qtdemux: support for cenc auxiliary info parsing outside of moof box
authorPhilippe Normand <philn@igalia.com>
Wed, 12 Aug 2015 11:35:40 +0000 (13:35 +0200)
committerTim-Philipp Müller <tim@centricular.com>
Wed, 4 Nov 2015 15:29:10 +0000 (15:29 +0000)
When the cenc aux info index is out of moof boundaries, keep track of
it and parse the beginning of the mdat box, before the first sample.

https://bugzilla.gnome.org/show_bug.cgi?id=755614

gst/isomp4/qtdemux.c
gst/isomp4/qtdemux.h

index ec830c3..7945495 100644 (file)
@@ -602,6 +602,9 @@ gst_qtdemux_init (GstQTDemux * qtdemux)
   qtdemux->upstream_format_is_time = FALSE;
   qtdemux->have_group_id = FALSE;
   qtdemux->group_id = G_MAXUINT;
+  qtdemux->cenc_aux_info_offset = 0;
+  qtdemux->cenc_aux_info_sizes = NULL;
+  qtdemux->cenc_aux_sample_count = 0;
   qtdemux->protection_system_ids = NULL;
   g_queue_init (&qtdemux->protection_event_queue);
   gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
@@ -624,6 +627,9 @@ gst_qtdemux_dispose (GObject * object)
       NULL);
   g_queue_clear (&qtdemux->protection_event_queue);
 
+  g_free (qtdemux->cenc_aux_info_sizes);
+  qtdemux->cenc_aux_info_sizes = NULL;
+
   G_OBJECT_CLASS (parent_class)->dispose (object);
 }
 
@@ -3386,15 +3392,16 @@ qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
         qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_saiz,
         &saiz_data);
     if (saiz_node) {
-      guint8 *info_sizes;
-      guint32 sample_count;
       guint32 info_type = 0;
       guint64 offset = 0;
       guint32 info_type_parameter = 0;
 
-      info_sizes = qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
-          &sample_count);
-      if (G_UNLIKELY (info_sizes == NULL)) {
+      g_free (qtdemux->cenc_aux_info_sizes);
+
+      qtdemux->cenc_aux_info_sizes =
+          qtdemux_parse_saiz (qtdemux, stream, &saiz_data,
+          &qtdemux->cenc_aux_sample_count);
+      if (qtdemux->cenc_aux_info_sizes == NULL) {
         GST_ERROR_OBJECT (qtdemux, "failed to parse saiz box");
         goto fail;
       }
@@ -3403,13 +3410,16 @@ qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
           &saio_data);
       if (!saio_node) {
         GST_ERROR_OBJECT (qtdemux, "saiz box without a corresponding saio box");
+        g_free (qtdemux->cenc_aux_info_sizes);
+        qtdemux->cenc_aux_info_sizes = NULL;
         goto fail;
       }
 
       if (G_UNLIKELY (!qtdemux_parse_saio (qtdemux, stream, &saio_data,
                   &info_type, &info_type_parameter, &offset))) {
         GST_ERROR_OBJECT (qtdemux, "failed to parse saio box");
-        g_free (info_sizes);
+        g_free (qtdemux->cenc_aux_info_sizes);
+        qtdemux->cenc_aux_info_sizes = NULL;
         goto fail;
       }
       if (base_offset > qtdemux->moof_offset)
@@ -3417,19 +3427,20 @@ qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
       if (info_type == FOURCC_cenc && info_type_parameter == 0U) {
         GstByteReader br;
         if (offset > length) {
-          GST_ERROR_OBJECT (qtdemux, "cenc auxiliary info outside moof "
-              "boxes is not supported");
-          g_free (info_sizes);
-          goto fail;
-        }
-        gst_byte_reader_init (&br, buffer + offset, length - offset);
-        if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
-                info_sizes, sample_count)) {
-          GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
-          goto fail;
+          GST_DEBUG_OBJECT (qtdemux, "cenc auxiliary info stored out of moof");
+          qtdemux->cenc_aux_info_offset = offset;
+        } else {
+          gst_byte_reader_init (&br, buffer + offset, length - offset);
+          if (!qtdemux_parse_cenc_aux_info (qtdemux, stream, &br,
+                  qtdemux->cenc_aux_info_sizes,
+                  qtdemux->cenc_aux_sample_count)) {
+            GST_ERROR_OBJECT (qtdemux, "failed to parse cenc auxiliary info");
+            g_free (qtdemux->cenc_aux_info_sizes);
+            qtdemux->cenc_aux_info_sizes = NULL;
+            goto fail;
+          }
         }
       }
-      g_free (info_sizes);
     }
 
     tfdt_node =
@@ -5928,6 +5939,27 @@ gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
         }
 
         if (demux->todrop) {
+          if (demux->cenc_aux_info_offset > 0) {
+            GstByteReader br;
+            const guint8 *data;
+
+            GST_DEBUG_OBJECT (demux, "parsing cenc auxiliary info");
+            data = gst_adapter_map (demux->adapter, demux->todrop);
+            gst_byte_reader_init (&br, data + 8, demux->todrop);
+            if (!qtdemux_parse_cenc_aux_info (demux, demux->streams[0], &br,
+                    demux->cenc_aux_info_sizes, demux->cenc_aux_sample_count)) {
+              GST_ERROR_OBJECT (demux, "failed to parse cenc auxiliary info");
+              ret = GST_FLOW_ERROR;
+              gst_adapter_unmap (demux->adapter);
+              g_free (demux->cenc_aux_info_sizes);
+              demux->cenc_aux_info_sizes = NULL;
+              goto done;
+            }
+            demux->cenc_aux_info_offset = 0;
+            g_free (demux->cenc_aux_info_sizes);
+            demux->cenc_aux_info_sizes = NULL;
+            gst_adapter_unmap (demux->adapter);
+          }
           gst_qtdemux_drop_data (demux, demux->todrop);
         }
 
index 8f0553b..05cd806 100644 (file)
@@ -149,6 +149,10 @@ struct _GstQTDemux {
   /* protection support */
   GPtrArray *protection_system_ids; /* Holds identifiers of all content protection systems for all tracks */
   GQueue protection_event_queue; /* holds copy of upstream protection events */
+  guint64 cenc_aux_info_offset;
+  guint8 *cenc_aux_info_sizes;
+  guint32 cenc_aux_sample_count;
+
 };
 
 struct _GstQTDemuxClass {