Index: ext/jpeg/gstjpegdec.h
===================================================================
--- ext/jpeg/gstjpegdec.h	Fri Aug 13 07:24:00 2010
+++ ext/jpeg/gstjpegdec.h	Mon Aug 16 14:45:55 2010
@@ -113,6 +113,10 @@
 
   /* properties */
   gint     idct_method;
+  gint     max_errors;
+ 
+  /* number of errors we're currently at before reporting GST_FLOW_ERROR */
+  gint     error_count;
 
   struct jpeg_decompress_struct cinfo;
   struct GstJpegDecErrorMgr     jerr;
Index: ext/jpeg/gstjpegdec.c
===================================================================
--- ext/jpeg/gstjpegdec.c	Fri Aug 13 07:24:00 2010
+++ ext/jpeg/gstjpegdec.c	Mon Aug 16 16:15:15 2010
@@ -52,11 +52,13 @@
         (((struct GstJpegDecSourceMgr*)((cinfo_ptr)->src))->dec)
 
 #define JPEG_DEFAULT_IDCT_METHOD	JDCT_FASTEST
+#define JPEG_DEFAULT_MAX_ERRORS	-1
 
 enum
 {
   PROP_0,
-  PROP_IDCT_METHOD
+  PROP_IDCT_METHOD, 
+  PROP_MAX_ERRORS
 };
 
 /* *INDENT-OFF* */
@@ -190,6 +192,11 @@
       g_param_spec_enum ("idct-method", "IDCT Method",
           "The IDCT algorithm to use", GST_TYPE_IDCT_METHOD,
           JPEG_DEFAULT_IDCT_METHOD, G_PARAM_READWRITE));
+ 
+  g_object_class_install_property (gobject_class, PROP_MAX_ERRORS,
+      g_param_spec_int ("max-errors", "Maximum Consecutive Decoding Errors", "Error out after receiving N consecutive decoding errors (-1 = fail on first error)",
+          -1, G_MAXINT, JPEG_DEFAULT_MAX_ERRORS,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   gstelement_class->change_state =
       GST_DEBUG_FUNCPTR (gst_jpeg_dec_change_state);
@@ -340,6 +347,7 @@
 
   /* init properties */
   dec->idct_method = JPEG_DEFAULT_IDCT_METHOD;
+  dec->max_errors = JPEG_DEFAULT_MAX_ERRORS;
 
   dec->adapter = gst_adapter_new ();
 }
@@ -932,15 +940,28 @@
       GST_INFO_OBJECT (dec, "jpeg_read_raw_data() returned 0");
     }
   }
+
+  /* reset error count on good buffers */
+  if (dec->max_errors >= 0) {
+    dec->error_count = 0;
+  }
   return GST_FLOW_OK;
 
 format_not_supported:
   {
-    GST_ELEMENT_ERROR (dec, STREAM, DECODE,
-        (_("Failed to decode JPEG image")),
-        ("Unsupported subsampling schema: v_samp factors: %u %u %u",
-            v_samp[0], v_samp[1], v_samp[2]));
-    return GST_FLOW_ERROR;
+    if (dec->max_errors >= 0 && (++dec->error_count) < dec->max_errors) {
+      GST_ELEMENT_WARNING (dec, STREAM, DECODE,
+          (_("Failed to decode JPEG image. Error count: %d"), dec->error_count),
+          ("Unsupported subsampling schema: v_samp factors: %u %u %u",
+              v_samp[0], v_samp[1], v_samp[2]));
+      return GST_FLOW_OK;
+    } else {
+      GST_ELEMENT_ERROR (dec, STREAM, DECODE,
+          (_("Failed to decode JPEG image. Error count: %d"), dec->error_count),
+          ("Unsupported subsampling schema: v_samp factors: %u %u %u",
+              v_samp[0], v_samp[1], v_samp[2]));
+      return GST_FLOW_ERROR;
+    }
   }
 }
 
@@ -1420,6 +1441,11 @@
       GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)));
 
   ret = gst_pad_push (dec->srcpad, outbuf);
+ 
+  /* reset error count on good buffers */
+  if (dec->max_errors >= 0) {
+    dec->error_count = 0;
+  }
 
 skip_decoding:
 done:
@@ -1443,11 +1469,22 @@
   /* ERRORS */
 wrong_size:
   {
-    GST_ELEMENT_ERROR (dec, STREAM, DECODE,
-        ("Picture is too small or too big (%ux%u)", width, height),
-        ("Picture is too small or too big (%ux%u)", width, height));
-    ret = GST_FLOW_ERROR;
-    goto done;
+    if (dec->max_errors >= 0 && (++dec->error_count) < dec->max_errors) {
+      GST_ELEMENT_WARNING (dec, STREAM, DECODE,
+          ("Picture is too small or too big (%ux%u). Error count: %d", width, height, dec->error_count),
+          ("Picture is too small or too big (%ux%u)", width, height));
+      if (outbuf) {
+        gst_buffer_unref (outbuf);
+      }
+      ret = GST_FLOW_OK;
+      goto exit;
+    } else {
+      GST_ELEMENT_ERROR (dec, STREAM, DECODE,
+          ("Picture is too small or too big (%ux%u). Error count: %d", width, height, dec->error_count),
+          ("Picture is too small or too big (%ux%u)", width, height));
+      ret = GST_FLOW_ERROR;
+      goto done;
+    }
   }
 decode_error:
   {
@@ -1455,14 +1492,24 @@
 
     dec->jerr.pub.format_message ((j_common_ptr) (&dec->cinfo), err_msg);
 
-    GST_ELEMENT_ERROR (dec, STREAM, DECODE,
-        (_("Failed to decode JPEG image")), ("Error #%u: %s", code, err_msg));
-    if (outbuf) {
-      gst_buffer_unref (outbuf);
-      outbuf = NULL;
+    if (dec->max_errors >= 0 && (++dec->error_count) < dec->max_errors) {
+      GST_ELEMENT_WARNING (dec, STREAM, DECODE,
+          (_("Failed to decode JPEG image. Error count: %d"), dec->error_count), ("Error #%u: %s", code, err_msg));
+      if (outbuf) {
+        gst_buffer_unref (outbuf);
+      }
+      ret = GST_FLOW_OK;
+      goto exit;
+    } else {
+      GST_ELEMENT_ERROR (dec, STREAM, DECODE,
+          (_("Failed to decode JPEG image. Error count: %d"), dec->error_count), ("Error #%u: %s", code, err_msg));
+      if (outbuf) {
+        gst_buffer_unref (outbuf);
+        outbuf = NULL;
+      }
+      ret = GST_FLOW_ERROR;
+      goto done;
     }
-    ret = GST_FLOW_ERROR;
-    goto done;
   }
 decode_direct_failed:
   {
@@ -1489,6 +1536,11 @@
   }
 drop_buffer:
   {
+    /* reset error count on good buffers */
+    /* not sure about this one -- should late buffers be essentially a no-op? */
+    if (dec->max_errors >= 0) {
+      dec->error_count = 0;
+    }
     GST_WARNING_OBJECT (dec, "Outgoing buffer is outside configured segment");
     gst_buffer_unref (outbuf);
     ret = GST_FLOW_OK;
@@ -1496,24 +1548,45 @@
   }
 components_not_supported:
   {
-    GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL),
-        ("more components than supported: %d > 3", dec->cinfo.num_components));
-    ret = GST_FLOW_ERROR;
-    goto done;
+    if (dec->max_errors >= 0 && (++dec->error_count) < dec->max_errors) {
+      GST_ELEMENT_WARNING (dec, STREAM, DECODE, (NULL),
+          ("More components than supported: %d > 3. Error count: ", dec->cinfo.num_components, dec->error_count));
+      ret = GST_FLOW_OK;
+      goto exit;
+    } else {
+      GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL),
+          ("More components than supported: %d > 3. Error count: ", dec->cinfo.num_components, dec->error_count));
+      ret = GST_FLOW_ERROR;
+      goto done;
+    }
   }
 unsupported_colorspace:
   {
-    GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL),
-        ("Picture has unknown or unsupported colourspace"));
-    ret = GST_FLOW_ERROR;
-    goto done;
+    if (dec->max_errors >= 0 && (++dec->error_count) < dec->max_errors) {
+      GST_ELEMENT_WARNING (dec, STREAM, DECODE, (NULL),
+          ("Picture has unknown or unsupported colourspace. Error count: %d", dec->error_count));
+      ret = GST_FLOW_OK;
+      goto exit;
+    } else {
+      GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL),
+          ("Picture has unknown or unsupported colourspace. Error count: %d", dec->error_count));
+      ret = GST_FLOW_ERROR;
+      goto done;
+    }
   }
 invalid_yuvrgbgrayscale:
   {
-    GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL),
-        ("Picture is corrupt or unhandled YUV/RGB/grayscale layout"));
-    ret = GST_FLOW_ERROR;
-    goto done;
+    if (dec->max_errors >= 0 && (++dec->error_count) < dec->max_errors) {
+      GST_ELEMENT_WARNING (dec, STREAM, DECODE, (NULL),
+          ("Picture is corrupt or unhandled YUV/RGB/grayscale layout. Error count: %d", dec->error_count));
+      ret = GST_FLOW_OK;
+      goto exit;
+    } else {
+      GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL),
+          ("Picture is corrupt or unhandled YUV/RGB/grayscale layout. Error count: %d", dec->error_count));
+      ret = GST_FLOW_ERROR;
+      goto done;
+    }
   }
 }
 
@@ -1606,6 +1679,10 @@
     case PROP_IDCT_METHOD:
       dec->idct_method = g_value_get_enum (value);
       break;
+    case PROP_MAX_ERRORS:
+      /* FIXME: not thread-safe */
+      dec->max_errors = g_value_get_int(value);
+      break;
 
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -1625,6 +1702,10 @@
     case PROP_IDCT_METHOD:
       g_value_set_enum (value, dec->idct_method);
       break;
+    case PROP_MAX_ERRORS:
+      /* FIXME: not thread-safe */
+      g_value_set_int (value, dec->max_errors);
+      break;
 
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -1642,6 +1723,7 @@
 
   switch (transition) {
     case GST_STATE_CHANGE_READY_TO_PAUSED:
+      dec->error_count = dec->max_errors;
       dec->framerate_numerator = 0;
       dec->framerate_denominator = 1;
       dec->caps_framerate_numerator = dec->caps_framerate_denominator = 0;
