gst/mpeg4videoparse/mpeg4videoparse.c: Move some code around to integrate the startco...
authorSjoerd Simons <sjoerd@luon.net>
Thu, 22 May 2008 14:03:05 +0000 (14:03 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Thu, 22 May 2008 14:03:05 +0000 (14:03 +0000)
Original commit message from CVS:
Patch by: Sjoerd Simons <sjoerd at luon dot net>
* gst/mpeg4videoparse/mpeg4videoparse.c: (gst_mpeg4vparse_push),
(gst_mpeg4vparse_drain), (gst_mpeg4vparse_chain),
(gst_mpeg4vparse_change_state):
Move some code around to integrate the startcode searching with the
other bits of parsing, avoid a whole bunch of peeks.
Get rid of invalid data that should not happen according to the specs.
Fixes #533559.

ChangeLog
common
gst/mpeg4videoparse/mpeg4videoparse.c

index 89322f3..76d20e3 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2008-05-22  Wim Taymans  <wim.taymans@collabora.co.uk>
+
+       Patch by: Sjoerd Simons <sjoerd at luon dot net>
+
+       * gst/mpeg4videoparse/mpeg4videoparse.c: (gst_mpeg4vparse_push),
+       (gst_mpeg4vparse_drain), (gst_mpeg4vparse_chain),
+       (gst_mpeg4vparse_change_state):
+       Move some code around to integrate the startcode searching with the
+       other bits of parsing, avoid a whole bunch of peeks.
+       Get rid of invalid data that should not happen according to the specs.
+       Fixes #533559.
+
 2008-05-20  Sebastian Dröge  <slomo@circular-chaos.org>
 
        Patch by: Bastien Nocera <hadess at hadess dot net>
diff --git a/common b/common
index e365978..5e77192 160000 (submodule)
--- a/common
+++ b/common
@@ -1 +1 @@
-Subproject commit e365978c480a8fffa4bdb61568fb2cd989d1b197
+Subproject commit 5e771924d59d9ac912237ea466d0c60ad95df5ab
index fc43f01..ce027ee 100644 (file)
@@ -121,32 +121,6 @@ gst_mpeg4vparse_set_new_caps (GstMpeg4VParse * parse,
   return res;
 }
 
-static void
-gst_mpeg4vparse_align (GstMpeg4VParse * parse)
-{
-  guint flushed = 0;
-
-  /* Searching for a start code */
-  while (gst_adapter_available (parse->adapter) >= 4) {
-    /* If we have enough data, ensure we're aligned to a start code */
-    const guint8 *data = gst_adapter_peek (parse->adapter, 4);
-
-    if (G_LIKELY (data[0] == 0 && data[1] == 0 && data[2] == 1)) {
-      GST_LOG_OBJECT (parse, "found start code with type %02X", data[3]);
-      parse->state = PARSE_START_FOUND;
-      break;
-    } else {
-      gst_adapter_flush (parse->adapter, 1);
-      flushed++;
-      parse->state = PARSE_NEED_START;
-    }
-  }
-
-  if (G_UNLIKELY (flushed)) {
-    GST_LOG_OBJECT (parse, "flushed %u bytes while aligning", flushed);
-  }
-}
-
 #define VOS_STARTCODE                   0xB0
 #define VOS_ENDCODE                     0xB1
 #define USER_DATA_STARTCODE             0xB2
@@ -440,7 +414,7 @@ gst_mpeg4vparse_push (GstMpeg4VParse * parse, gsize size)
 
   /* Restart now that we flushed data */
   parse->offset = 0;
-  parse->state = PARSE_START_FOUND;
+  parse->state = PARSE_NEED_START;
   parse->intra_frame = FALSE;
 }
 
@@ -452,15 +426,39 @@ gst_mpeg4vparse_drain (GstMpeg4VParse * parse, GstBuffer * last_buffer)
   guint available = 0;
 
   available = gst_adapter_available (parse->adapter);
+  /* We do a quick check here to avoid the _peek() below. */
+  if (G_UNLIKELY (available < 5)) {
+    GST_DEBUG_OBJECT (parse, "we need more data, %d < 5", available);
+    goto beach;
+  }
   data = gst_adapter_peek (parse->adapter, available);
 
   /* Need at least 5 more bytes, 4 for the startcode, 1 to optionally determine
    * the VOP frame type */
-  while (parse->offset < available - 5) {
+  while (available >= 5 && parse->offset < available - 5) {
     if (data[parse->offset] == 0 && data[parse->offset + 1] == 0 &&
         data[parse->offset + 2] == 1) {
 
       switch (parse->state) {
+        case PARSE_NEED_START:
+          switch (data[parse->offset + 3]) {
+            case VOP_STARTCODE:
+            case VOS_STARTCODE:
+            case GOP_STARTCODE:
+              /* valid starts of a frame */
+              parse->state = PARSE_START_FOUND;
+              if (parse->offset > 0) {
+                GST_LOG_OBJECT (parse, "Flushing %u bytes", parse->offset);
+                gst_adapter_flush (parse->adapter, parse->offset);
+                parse->offset = 0;
+                available = gst_adapter_available (parse->adapter);
+                data = gst_adapter_peek (parse->adapter, available);
+              }
+              break;
+            default:
+              parse->offset += 4;
+          }
+          break;
         case PARSE_START_FOUND:
           switch (data[parse->offset + 3]) {
             case VOP_STARTCODE:
@@ -498,15 +496,6 @@ gst_mpeg4vparse_drain (GstMpeg4VParse * parse, GstBuffer * last_buffer)
           break;
         case PARSE_VOP_FOUND:
         {                       /* We were in a VOP already, any start code marks the end of it */
-          if (data[parse->offset + 3] == USER_DATA_STARTCODE) {
-            /* Userdata shouldn't come directly after a VOP, but some
-             * implementation do it anyways :( This prevents pushing 
-             * USER_DATA as the initial bit of a buffer, which causes confusing
-             * with other elements */
-            parse->offset += 4;
-            break;
-          }
-
           GST_LOG_OBJECT (parse, "found VOP end marker at %u", parse->offset);
 
           gst_mpeg4vparse_push (parse, parse->offset);
@@ -543,27 +532,9 @@ gst_mpeg4vparse_chain (GstPad * pad, GstBuffer * buffer)
 
   gst_adapter_push (parse->adapter, buffer);
 
-  /* We need to get aligned on a start code */
-  if (G_UNLIKELY (parse->state == PARSE_NEED_START)) {
-    gst_mpeg4vparse_align (parse);
-    /* No start code found in that buffer */
-    if (G_UNLIKELY (parse->state == PARSE_NEED_START)) {
-      GST_DEBUG_OBJECT (parse, "start code not found, need more data");
-      goto beach;
-    }
-  }
-
-  /* We need at least 8 bytes to find the next start code which marks the end
-     of the one we just found */
-  if (G_UNLIKELY (gst_adapter_available (parse->adapter) < 8)) {
-    GST_DEBUG_OBJECT (parse, "start code found, need more data to find next");
-    goto beach;
-  }
-
   /* Drain the accumulated blocks frame per frame */
   ret = gst_mpeg4vparse_drain (parse, buffer);
 
-beach:
   gst_object_unref (parse);
 
   return ret;
@@ -702,7 +673,6 @@ gst_mpeg4vparse_change_state (GstElement * element, GstStateChange transition)
     default:
       break;
   }
-
   return ret;
 }