dashdemux: fix error calculating large presentationTimeOffset values
authorAlex Ashley <bugzilla@ashley-family.net>
Thu, 11 Jun 2015 16:25:49 +0000 (17:25 +0100)
committerSebastian Dröge <sebastian@centricular.com>
Thu, 11 Jun 2015 17:41:11 +0000 (19:41 +0200)
If the presentationTimeOffset attribute of a DASH manifest contains
a value that is larger than 2^32, gstmpdparser incorrectly calculates
the stream's presentation time offset. This is due to two bugs:

1: Using gst_mpdparser_get_xml_prop_unsigned_integer rather than
   gst_mpdparser_get_xml_prop_unsigned_integer_64 to parse the
   attribute
2: gst_mpd_client_setup_representation multiplying the value by
   GST_SECOND and then dividing by timescale

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

ext/dash/gstmpdparser.c
ext/dash/gstmpdparser.h

index 4a66e16..fe9e939 100644 (file)
@@ -1162,6 +1162,7 @@ gst_mpdparser_parse_seg_base_type_ext (GstSegmentBaseType ** pointer,
   xmlNode *cur_node;
   GstSegmentBaseType *seg_base_type;
   guint intval;
+  guint64 int64val;
   gboolean boolval;
   GstRange *rangeval;
 
@@ -1194,9 +1195,9 @@ gst_mpdparser_parse_seg_base_type_ext (GstSegmentBaseType ** pointer,
           &intval)) {
     seg_base_type->timescale = intval;
   }
-  if (gst_mpdparser_get_xml_prop_unsigned_integer (a_node,
-          "presentationTimeOffset", 0, &intval)) {
-    seg_base_type->presentationTimeOffset = intval;
+  if (gst_mpdparser_get_xml_prop_unsigned_integer_64 (a_node,
+          "presentationTimeOffset", 0, &int64val)) {
+    seg_base_type->presentationTimeOffset = int64val;
   }
   if (gst_mpdparser_get_xml_prop_range (a_node, "indexRange", &rangeval)) {
     if (seg_base_type->indexRange) {
@@ -3283,13 +3284,17 @@ gst_mpd_client_setup_representation (GstMpdClient * client,
 
       GST_LOG ("Building media segment list using this template: %s",
           stream->cur_seg_template->media);
-      stream->presentationTimeOffset =
-          mult_seg->SegBaseType->presentationTimeOffset * GST_SECOND;
-
-      /* Avoid dividing by zero */
-      if (mult_seg->SegBaseType->timescale)
-        stream->presentationTimeOffset /= mult_seg->SegBaseType->timescale;
 
+      /* Avoid dividing by zero and avoid overflows */
+      if (mult_seg->SegBaseType->timescale) {
+        stream->presentationTimeOffset =
+            gst_util_uint64_scale (mult_seg->
+            SegBaseType->presentationTimeOffset, GST_SECOND,
+            mult_seg->SegBaseType->timescale);
+      } else {
+        stream->presentationTimeOffset =
+            mult_seg->SegBaseType->presentationTimeOffset * GST_SECOND;
+      }
       GST_LOG ("Setting stream's presentation time offset to %" GST_TIME_FORMAT,
           GST_TIME_ARGS (stream->presentationTimeOffset));
 
index 43c454b..31e630c 100644 (file)
@@ -143,7 +143,7 @@ struct _GstURLType
 struct _GstSegmentBaseType
 {
   guint timescale;
-  guint presentationTimeOffset;
+  guint64 presentationTimeOffset;
   GstRange *indexRange;
   gboolean indexRangeExact;
   /* Initialization node */