gst/matroska/ebml-read.c: Use GINT64 formatting constants from GLIB.
authorJan Schmidt <thaytan@mad.scientist.com>
Mon, 3 Mar 2008 22:01:56 +0000 (22:01 +0000)
committerJan Schmidt <thaytan@mad.scientist.com>
Mon, 3 Mar 2008 22:01:56 +0000 (22:01 +0000)
Original commit message from CVS:
* gst/matroska/ebml-read.c:
Use GINT64 formatting constants from GLIB.
* gst/matroska/matroska-demux.c:
Add some guards to avoid a possible division by 0 and crashing
with NULL events on some systems.
Use gst_gdouble_to_guint64 somewhere instead of an implicit
conversion.
* gst/matroska/matroska-mux.c:
Check for invalid timestamps in a bunch of places to avoid
writing bogus durations into the output file.
Fix some double<->gint64 conversions that weren't using
gst_guint64_to_gdouble

ChangeLog
common
gst/matroska/ebml-read.c
gst/matroska/matroska-demux.c
gst/matroska/matroska-mux.c

index e81807c..2d02f73 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2008-03-03  Jan Schmidt  <jan.schmidt@sun.com>
+
+       * gst/matroska/ebml-read.c:
+       Use GINT64 formatting constants from GLIB.
+
+       * gst/matroska/matroska-demux.c:
+       Add some guards to avoid a possible division by 0 and crashing
+       with NULL events on some systems.
+       Use gst_gdouble_to_guint64 somewhere instead of an implicit
+       conversion. 
+
+       * gst/matroska/matroska-mux.c:
+       Check for invalid timestamps in a bunch of places to avoid
+       writing bogus durations into the output file.
+       Fix some double<->gint64 conversions that weren't using
+       gst_guint64_to_gdouble
+
 2008-03-03  Peter Kjellerstedt  <pkj@axis.com>
 
        * configure.ac:
diff --git a/common b/common
index 668c3f0..081a00a 160000 (submodule)
--- a/common
+++ b/common
@@ -1 +1 @@
-Subproject commit 668c3f0b72d50813c30eb04be7048f638037c571
+Subproject commit 081a00a5e25d069b15bb7f6092c8f951462cd8eb
index 8343910..9c5ae4a 100644 (file)
@@ -266,8 +266,8 @@ gst_ebml_read_element_id (GstEbmlRead * ebml, guint32 * id, guint * level_up)
     guint64 pos = ebml->offset;
 
     GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL),
-        ("Invalid EBML ID size tag (0x%x) at position %llu (0x%llx)",
-            (guint) b, pos, pos));
+        ("Invalid EBML ID size tag (0x%x) at position %" G_GUINT64_FORMAT
+            " (0x%" G_GINT64_MODIFIER "x)", (guint) b, pos, pos));
     return FALSE;
   }
 
@@ -318,8 +318,8 @@ gst_ebml_read_element_length (GstEbmlRead * ebml, guint64 * length)
     guint64 pos = ebml->offset;
 
     GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL),
-        ("Invalid EBML length size tag (0x%x) at position %llu (0x%llx)",
-            (guint) b, pos, pos));
+        ("Invalid EBML length size tag (0x%x) at position %" G_GUINT64_FORMAT
+            " (0x%" G_GINT64_MODIFIER "x)", (guint) b, pos, pos));
     return -1;
   }
 
@@ -498,7 +498,8 @@ gst_ebml_read_uint (GstEbmlRead * ebml, guint32 * id, guint64 * num)
 
   if (size < 1 || size > 8) {
     GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL),
-        ("Invalid integer element size %d at position %llu (0x%llu)",
+        ("Invalid integer element size %d at position %" G_GUINT64_FORMAT
+            " (0x%" G_GINT64_MODIFIER "x)",
             size, ebml->offset - size, ebml->offset - size));
     return FALSE;
   }
@@ -528,8 +529,9 @@ gst_ebml_read_sint (GstEbmlRead * ebml, guint32 * id, gint64 * num)
 
   if (size < 1 || size > 8) {
     GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL),
-        ("Invalid integer element size %d at position %llu (0x%llx)",
-            size, ebml->offset - size, ebml->offset - size));
+        ("Invalid integer element size %d at position %" G_GUINT64_FORMAT
+            " (0x%" G_GINT64_MODIFIER "x)", size, ebml->offset - size,
+            ebml->offset - size));
     return FALSE;
   }
 
@@ -570,8 +572,9 @@ gst_ebml_read_float (GstEbmlRead * ebml, guint32 * id, gdouble * num)
 
   if (size != 4 && size != 8 && size != 10) {
     GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL),
-        ("Invalid float element size %d at position %llu (0x%llx)",
-            size, ebml->offset - size, ebml->offset - size));
+        ("Invalid float element size %d at position %" G_GUINT64_FORMAT
+            " (0x%" G_GINT64_MODIFIER "x)", size, ebml->offset - size,
+            ebml->offset - size));
     return FALSE;
   }
 
index 7f0f48f..5fe16e3 100644 (file)
@@ -660,9 +660,11 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
                 res = FALSE;
                 break;
               }
-              context->default_duration =
-                  gst_gdouble_to_guint64 ((gdouble) GST_SECOND * (1.0 / num));
-              videocontext->default_fps = num;
+              if (num != 0.0) {
+                context->default_duration =
+                    gst_gdouble_to_guint64 ((gdouble) GST_SECOND / num);
+                videocontext->default_fps = num;
+              }
               break;
             }
 
@@ -1298,6 +1300,8 @@ gst_matroska_demux_send_event (GstMatroskaDemux * demux, GstEvent * event)
   gboolean ret = TRUE;
   gint i;
 
+  g_return_val_if_fail (event != NULL, FALSE);
+
   GST_DEBUG_OBJECT (demux, "Sending event of type %s to all source pads",
       GST_EVENT_TYPE_NAME (event));
 
@@ -1324,6 +1328,8 @@ gst_matroska_demux_element_send_event (GstElement * element, GstEvent * event)
   GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (element);
   gboolean res;
 
+  g_return_val_if_fail (event != NULL, FALSE);
+
   if (GST_EVENT_TYPE (event) == GST_EVENT_SEEK) {
     res = gst_matroska_demux_handle_seek_event (demux, event);
   } else {
@@ -1879,12 +1885,17 @@ gst_matroska_demux_parse_info (GstMatroskaDemux * demux)
 
       case GST_MATROSKA_ID_DURATION:{
         gdouble num;
+        GstClockTime dur;
 
         if (!gst_ebml_read_float (ebml, &id, &num)) {
           res = FALSE;
           break;
         }
-        demux->duration = num * gst_guint64_to_gdouble (demux->time_scale);
+
+        dur = gst_gdouble_to_guint64 (num *
+            gst_guint64_to_gdouble (demux->time_scale));
+        if (GST_CLOCK_TIME_IS_VALID (dur) && dur <= G_MAXINT64)
+          demux->duration = dur;
         break;
       }
 
@@ -3712,7 +3723,7 @@ gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext *
 
         g_value_init (&fps_double, G_TYPE_DOUBLE);
         g_value_init (&fps_fraction, GST_TYPE_FRACTION);
-        g_value_set_double (&fps_double, (gdouble) GST_SECOND * 1.0 /
+        g_value_set_double (&fps_double, (gdouble) GST_SECOND /
             gst_guint64_to_gdouble (context->default_duration));
         g_value_transform (&fps_double, &fps_fraction);
 
index d1794e5..098b2fc 100644 (file)
@@ -1185,13 +1185,17 @@ gst_matroska_mux_release_pad (GstElement * element, GstPad * pad)
     if (cdata->pad == pad) {
       GstClockTime min_dur;     /* observed minimum duration */
 
-      /* no need to check if start_ts and end_ts are set, in the worst case
-       * they're both -1 and we'll end up with a duration of 0 again */
-      min_dur = GST_CLOCK_DIFF (collect_pad->start_ts, collect_pad->end_ts);
-      if (collect_pad->duration < min_dur)
-        collect_pad->duration = min_dur;
-      if (collect_pad->duration > mux->duration)
+      if (GST_CLOCK_TIME_IS_VALID (collect_pad->start_ts) &&
+          GST_CLOCK_TIME_IS_VALID (collect_pad->end_ts)) {
+        min_dur = GST_CLOCK_DIFF (collect_pad->start_ts, collect_pad->end_ts);
+        if (collect_pad->duration < min_dur)
+          collect_pad->duration = min_dur;
+      }
+
+      if (GST_CLOCK_TIME_IS_VALID (collect_pad->duration) &&
+          mux->duration < collect_pad->duration)
         mux->duration = collect_pad->duration;
+
       gst_matroska_pad_free (collect_pad);
       gst_collect_pads_remove_pad (mux->collect, pad);
       gst_element_remove_pad (element, pad);
@@ -1321,7 +1325,7 @@ gst_matroska_mux_start (GstMatroskaMux * mux)
   GSList *collected;
   int i;
   guint tracknum = 1;
-  gdouble duration = 0;
+  GstClockTime duration = 0;
   guint32 *segment_uid = (guint32 *) g_malloc (16);
   GRand *rand = g_rand_new ();
   GTimeVal time = { 0, 0 };
@@ -1376,14 +1380,15 @@ gst_matroska_mux_start (GstMatroskaMux * mux)
     if (gst_pad_query_peer_duration (thepad, &format, &trackduration)) {
       GST_DEBUG_OBJECT (thepad, "duration: %" GST_TIME_FORMAT,
           GST_TIME_ARGS (trackduration));
-      if (trackduration != GST_CLOCK_TIME_NONE &&
-          (gdouble) trackduration > duration) {
-        duration = (gdouble) trackduration;
+      if (trackduration != GST_CLOCK_TIME_NONE && trackduration > duration) {
+        duration = (GstClockTime) trackduration;
       }
     }
   }
   gst_ebml_write_float (ebml, GST_MATROSKA_ID_DURATION,
-      duration / gst_guint64_to_gdouble (mux->time_scale));
+      gst_guint64_to_gdouble (duration) /
+      gst_guint64_to_gdouble (mux->time_scale));
+
   gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_MUXINGAPP,
       "GStreamer plugin version " PACKAGE_VERSION);
   if (mux->writing_app && mux->writing_app[0]) {
@@ -1617,14 +1622,23 @@ gst_matroska_mux_finish (GstMatroskaMux * mux)
 
     collect_pad = (GstMatroskaPad *) collected->data;
 
-    /* no need to check if start_ts and end_ts are set, in the worst case
-     * they're both -1 and we'll end up with a duration of 0 again */
-    min_duration = GST_CLOCK_DIFF (collect_pad->start_ts, collect_pad->end_ts);
-    if (collect_pad->duration < min_duration)
-      collect_pad->duration = min_duration;
-    GST_DEBUG_OBJECT (collect_pad, "final track duration: %" GST_TIME_FORMAT,
-        GST_TIME_ARGS (collect_pad->duration));
-    if (collect_pad->duration > duration)
+    GST_DEBUG_OBJECT (mux, "Pad %" GST_PTR_FORMAT " start ts %" GST_TIME_FORMAT
+        " end ts %" GST_TIME_FORMAT, collect_pad,
+        GST_TIME_ARGS (collect_pad->start_ts),
+        GST_TIME_ARGS (collect_pad->end_ts));
+
+    if (GST_CLOCK_TIME_IS_VALID (collect_pad->start_ts) &&
+        GST_CLOCK_TIME_IS_VALID (collect_pad->end_ts)) {
+      min_duration =
+          GST_CLOCK_DIFF (collect_pad->start_ts, collect_pad->end_ts);
+      if (collect_pad->duration < min_duration)
+        collect_pad->duration = min_duration;
+      GST_DEBUG_OBJECT (collect_pad, "final track duration: %" GST_TIME_FORMAT,
+          GST_TIME_ARGS (collect_pad->duration));
+    }
+
+    if (GST_CLOCK_TIME_IS_VALID (collect_pad->duration) &&
+        duration < collect_pad->duration)
       duration = collect_pad->duration;
   }
   if (duration != 0) {
@@ -1633,7 +1647,8 @@ gst_matroska_mux_finish (GstMatroskaMux * mux)
     pos = mux->ebml_write->pos;
     gst_ebml_write_seek (ebml, mux->duration_pos);
     gst_ebml_write_float (ebml, GST_MATROSKA_ID_DURATION,
-        gst_guint64_to_gdouble (duration / mux->time_scale));
+        gst_guint64_to_gdouble (duration) /
+        gst_guint64_to_gdouble (mux->time_scale));
     gst_ebml_write_seek (ebml, pos);
   }
 
@@ -1941,18 +1956,28 @@ gst_matroska_mux_collected (GstCollectPads * pads, gpointer user_data)
       ret = GST_FLOW_UNEXPECTED;
       break;
     }
-    GST_DEBUG_OBJECT (best->collect.pad, "best pad");
+    GST_DEBUG_OBJECT (best->collect.pad, "best pad - buffer ts %"
+        GST_TIME_FORMAT " dur %" GST_TIME_FORMAT,
+        GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (best->buffer)),
+        GST_TIME_ARGS (GST_BUFFER_DURATION (best->buffer)));
 
     /* make note of first and last encountered timestamps, so we can calculate
      * the actual duration later when we send an updated header on eos */
-    best->end_ts = GST_BUFFER_TIMESTAMP (best->buffer);
-    if (GST_BUFFER_DURATION_IS_VALID (best->buffer))
-      best->end_ts += GST_BUFFER_DURATION (best->buffer);
-    else if (best->track->default_duration)
-      best->end_ts += best->track->default_duration;
-
-    if (G_UNLIKELY (best->start_ts == GST_CLOCK_TIME_NONE)) {
-      best->start_ts = GST_BUFFER_TIMESTAMP (best->buffer);
+    if (GST_BUFFER_TIMESTAMP_IS_VALID (best->buffer)) {
+      GstClockTime start_ts = GST_BUFFER_TIMESTAMP (best->buffer);
+      GstClockTime end_ts = start_ts;
+
+      if (GST_BUFFER_DURATION_IS_VALID (best->buffer))
+        end_ts += GST_BUFFER_DURATION (best->buffer);
+      else if (best->track->default_duration)
+        end_ts += best->track->default_duration;
+
+      if (end_ts > best->end_ts)
+        best->end_ts = end_ts;
+
+      if (G_UNLIKELY (best->start_ts == GST_CLOCK_TIME_NONE ||
+              start_ts < best->start_ts))
+        best->start_ts = start_ts;
     }
 
     /* write one buffer */