qtdemux: Add support for version 1 cslg boxes
authorSebastian Dröge <sebastian@centricular.com>
Tue, 2 Nov 2021 15:41:01 +0000 (17:41 +0200)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Fri, 12 Nov 2021 17:51:03 +0000 (17:51 +0000)
They use 64 bit fields instead of 32 bit.

Also parse offset as a signed integer (in both versions) and clamp it to
a positive value as negative values don't really interest us here.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1294>

subprojects/gst-plugins-good/gst/isomp4/qtdemux.c
subprojects/gst-plugins-good/gst/isomp4/qtdemux.h
subprojects/gst-plugins-good/gst/isomp4/qtdemux_dump.c

index ae30290..ccbc68b 100644 (file)
@@ -9385,9 +9385,31 @@ qtdemux_stbl_init (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * stbl)
 
     /* This is optional, if missing we iterate the ctts */
     if (qtdemux_tree_get_child_by_type_full (stbl, FOURCC_cslg, &cslg)) {
-      if (!gst_byte_reader_skip (&cslg, 1 + 3)
-          || !gst_byte_reader_get_uint32_be (&cslg, &stream->cslg_shift))
+      guint8 cslg_version;
+
+      /* cslg version 1 has 64 bit fields */
+      if (!gst_byte_reader_get_uint8 (&cslg, &cslg_version))
+        goto corrupt_file;
+
+      /* skip flags */
+      if (!gst_byte_reader_skip (&cslg, 3))
         goto corrupt_file;
+
+      if (cslg_version == 0) {
+        gint32 composition_to_dts_shift;
+
+        if (!gst_byte_reader_get_int32_be (&cslg, &composition_to_dts_shift))
+          goto corrupt_file;
+
+        stream->cslg_shift = MAX (0, composition_to_dts_shift);
+      } else {
+        gint64 composition_to_dts_shift;
+
+        if (!gst_byte_reader_get_int64_be (&cslg, &composition_to_dts_shift))
+          goto corrupt_file;
+
+        stream->cslg_shift = MAX (0, composition_to_dts_shift);
+      }
     } else {
       gint32 cslg_least = 0;
       guint num_entries, pos;
index 742915c..e61deb6 100644 (file)
@@ -478,7 +478,7 @@ struct _QtDemuxStream
   gint32 ctts_soffset;
 
   /* cslg */
-  guint32 cslg_shift;
+  guint64 cslg_shift;
 
   /* fragmented */
   gboolean parsed_trex;
index 25921df..7f1aaa5 100644 (file)
@@ -577,21 +577,37 @@ qtdemux_dump_ctts (GstQTDemux * qtdemux, GstByteReader * data, int depth)
 gboolean
 qtdemux_dump_cslg (GstQTDemux * qtdemux, GstByteReader * data, int depth)
 {
-  guint32 ver_flags = 0, shift = 0;
-  gint32 least_offset = 0, start_time = 0, end_time = 0;
+  guint32 ver_flags = 0;
 
-  if (!gst_byte_reader_get_uint32_be (data, &ver_flags) ||
-      !gst_byte_reader_get_uint32_be (data, &shift) ||
-      !gst_byte_reader_get_int32_be (data, &least_offset) ||
-      !gst_byte_reader_get_int32_be (data, &start_time) ||
-      !gst_byte_reader_get_int32_be (data, &end_time))
+  if (!gst_byte_reader_get_uint32_be (data, &ver_flags))
     return FALSE;
 
   GST_LOG ("%*s  version/flags: %08x", depth, "", ver_flags);
-  GST_LOG ("%*s  shift:         %u", depth, "", shift);
-  GST_LOG ("%*s  least offset:  %d", depth, "", least_offset);
-  GST_LOG ("%*s  start time:    %d", depth, "", start_time);
-  GST_LOG ("%*s  end time:      %d", depth, "", end_time);
+
+  if (ver_flags >> 24 == 0) {
+    gint32 shift = 0, least_offset = 0, start_time = 0, end_time = 0;
+    if (!gst_byte_reader_get_int32_be (data, &shift) ||
+        !gst_byte_reader_get_int32_be (data, &least_offset) ||
+        !gst_byte_reader_get_int32_be (data, &start_time) ||
+        !gst_byte_reader_get_int32_be (data, &end_time))
+      return FALSE;
+    GST_LOG ("%*s  shift:         %d", depth, "", shift);
+    GST_LOG ("%*s  least offset:  %d", depth, "", least_offset);
+    GST_LOG ("%*s  start time:    %d", depth, "", start_time);
+    GST_LOG ("%*s  end time:      %d", depth, "", end_time);
+  } else {
+    gint64 shift = 0, least_offset = 0, start_time = 0, end_time = 0;
+    if (!gst_byte_reader_get_int64_be (data, &shift) ||
+        !gst_byte_reader_get_int64_be (data, &least_offset) ||
+        !gst_byte_reader_get_int64_be (data, &start_time) ||
+        !gst_byte_reader_get_int64_be (data, &end_time))
+      return FALSE;
+
+    GST_LOG ("%*s  shift:         %" G_GINT64_FORMAT, depth, "", shift);
+    GST_LOG ("%*s  least offset:  %" G_GINT64_FORMAT, depth, "", least_offset);
+    GST_LOG ("%*s  start time:    %" G_GINT64_FORMAT, depth, "", start_time);
+    GST_LOG ("%*s  end time:      %" G_GINT64_FORMAT, depth, "", end_time);
+  }
 
   return TRUE;
 }