mpeg4videoparse: set 0 duration when vop_coded is 0
authorMatej Knopp <matej.knopp@gmail.com>
Sat, 1 Sep 2012 19:46:19 +0000 (21:46 +0200)
committerTim-Philipp Müller <tim@centricular.net>
Sun, 2 Sep 2012 02:43:12 +0000 (03:43 +0100)
https://bugzilla.gnome.org/show_bug.cgi?id=683169

gst/videoparsers/gstmpeg4videoparse.c
gst/videoparsers/gstmpeg4videoparse.h

index 29caec7..f55f09e 100644 (file)
@@ -276,6 +276,44 @@ gst_mpeg4vparse_process_config (GstMpeg4VParse * mp4vparse,
   return TRUE;
 }
 
+static gboolean
+gst_mpeg4vparse_get_vop_coded (GstMpeg4VParse * mp4vparse, const guint8 * data,
+    gint vop_offset, gsize size, gsize frame_size)
+{
+  if (frame_size > 9) {         /* assuming bigger frame will always have vop_coded (saves some parsing) */
+    return TRUE;
+  } else if (size > vop_offset + 3) {
+    GstBitReader reader;
+    guint8 value;
+
+    gst_bit_reader_init (&reader, data + vop_offset + 1, size - vop_offset);
+    gst_bit_reader_skip (&reader, 2);   /* VOP_coding_type */
+
+    /* modulo_time_base (ends with 0) */
+    while (gst_bit_reader_get_bits_uint8 (&reader, &value, 1) && value);
+
+    /* marker_bit */
+    g_return_val_if_fail (gst_bit_reader_get_bits_uint8 (&reader, &value, 1)
+        && value, TRUE);
+
+    /* VOP_time_increment */
+    gst_bit_reader_skip (&reader, mp4vparse->vol.vop_time_increment_bits);
+
+    /* marker_bit */
+    g_return_val_if_fail (gst_bit_reader_get_bits_uint8 (&reader, &value, 1)
+        && value, TRUE);
+
+    /* VOP_coded */
+    if (!gst_bit_reader_get_bits_uint8 (&reader, &value, 1)) {
+      return FALSE;
+    }
+
+    return value;
+  }
+
+  return FALSE;
+}
+
 /* caller guarantees at least start code in @buf at @off */
 static gboolean
 gst_mpeg4vparse_process_sc (GstMpeg4VParse * mp4vparse, GstMpeg4Packet * packet,
@@ -295,8 +333,12 @@ gst_mpeg4vparse_process_sc (GstMpeg4VParse * mp4vparse, GstMpeg4Packet * packet,
       GST_WARNING_OBJECT (mp4vparse, "no data following VOP startcode");
       mp4vparse->intra_frame = FALSE;
     }
-    GST_LOG_OBJECT (mp4vparse, "ending frame of size %d, is intra %d",
-        packet->offset - 3, mp4vparse->intra_frame);
+    mp4vparse->vop_coded =
+        gst_mpeg4vparse_get_vop_coded (mp4vparse, packet->data,
+        mp4vparse->vop_offset, size, packet->offset - 3);
+    GST_LOG_OBJECT (mp4vparse,
+        "ending frame of size %d, is intra %d, vop_coded %d",
+        packet->offset - 3, mp4vparse->intra_frame, mp4vparse->vop_coded);
     return TRUE;
   }
 
@@ -567,6 +609,9 @@ gst_mpeg4vparse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
   else
     GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
 
+  if (!mp4vparse->vop_coded)    /* buffer without VOP_coded has no data */
+    GST_BUFFER_DURATION (buffer) = 0;
+
   if (G_UNLIKELY (mp4vparse->drop && !mp4vparse->config)) {
     GST_LOG_OBJECT (mp4vparse, "dropping frame as no config yet");
     return GST_BASE_PARSE_FLOW_DROPPED;
index 75d7d6c..7611749 100644 (file)
@@ -52,6 +52,7 @@ struct _GstMpeg4VParse {
   gint vop_offset;
   gboolean vo_found;
   gboolean intra_frame;
+  gboolean vop_coded;
   gboolean update_caps;
 
   GstBuffer *config;