jpegdec: discard incomplete image
authorMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
Mon, 6 Dec 2010 17:16:19 +0000 (18:16 +0100)
committerMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
Mon, 6 Dec 2010 18:14:52 +0000 (19:14 +0100)
... as determined when finding SOI next image before an EOI.

Based on patch by David Hoyt <david.hoyt@llnl.gov>

Fixes #635734.

ext/jpeg/gstjpegdec.c

index fedf25e..987827b 100644 (file)
@@ -382,9 +382,10 @@ gst_jpeg_dec_parse_tag_has_entropy_segment (guint8 tag)
   return FALSE;
 }
 
-/* returns image length in bytes if parsed
- * successfully, otherwise 0 */
-static guint
+/* returns image length in bytes if parsed successfully,
+ * otherwise 0 if more data needed,
+ * if < 0 the absolute value needs to be flushed */
+static gint
 gst_jpeg_dec_parse_image_data (GstJpegDec * dec)
 {
   guint size;
@@ -445,8 +446,15 @@ gst_jpeg_dec_parse_image_data (GstJpegDec * dec)
       dec->parse_resync = FALSE;
       dec->parse_offset = 0;
       return (offset + 4);
+    } else if (value == 0xd8) {
+      /* Skip this frame if we found another SOI marker */
+      GST_DEBUG ("0x%08x: SOI marker before EOI, skipping", offset + 2);
+      dec->parse_resync = FALSE;
+      dec->parse_offset = 0;
+      return -(offset + 2);
     }
 
+
     if (value >= 0xd0 && value <= 0xd7)
       frame_len = 0;
     else {
@@ -1149,7 +1157,8 @@ gst_jpeg_dec_chain (GstPad * pad, GstBuffer * buf)
 #endif
   guchar *outdata;
   guchar *base[3], *last[3];
-  guint img_len, outsize;
+  gint img_len;
+  guint outsize;
   gint width, height;
   gint r_h, r_v;
   guint code, hdr_ok;
@@ -1187,6 +1196,7 @@ gst_jpeg_dec_chain (GstPad * pad, GstBuffer * buf)
     goto need_more_data;
   }
 
+again:
   if (!gst_jpeg_dec_ensure_header (dec))
     goto need_more_data;
 
@@ -1201,8 +1211,12 @@ gst_jpeg_dec_chain (GstPad * pad, GstBuffer * buf)
      * is not aligned to buffer boundaries */
     img_len = gst_jpeg_dec_parse_image_data (dec);
 
-    if (img_len == 0)
+    if (img_len == 0) {
       goto need_more_data;
+    } else if (img_len < 0) {
+      gst_adapter_flush (dec->adapter, -img_len);
+      goto again;
+    }
   }
 
   dec->rem_img_len = img_len;