From: Jan Schmidt Date: Mon, 3 Mar 2008 22:01:56 +0000 (+0000) Subject: gst/matroska/ebml-read.c: Use GINT64 formatting constants from GLIB. X-Git-Tag: RELEASE-0_10_8~84 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=edda3b6c0f721bb2085de7e76abf761b3f691326;p=platform%2Fupstream%2Fgst-plugins-good.git gst/matroska/ebml-read.c: Use GINT64 formatting constants from GLIB. 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 --- diff --git a/ChangeLog b/ChangeLog index e81807c..2d02f73 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2008-03-03 Jan Schmidt + + * 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 * configure.ac: diff --git a/common b/common index 668c3f0..081a00a 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit 668c3f0b72d50813c30eb04be7048f638037c571 +Subproject commit 081a00a5e25d069b15bb7f6092c8f951462cd8eb diff --git a/gst/matroska/ebml-read.c b/gst/matroska/ebml-read.c index 8343910..9c5ae4a 100644 --- a/gst/matroska/ebml-read.c +++ b/gst/matroska/ebml-read.c @@ -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; } diff --git a/gst/matroska/matroska-demux.c b/gst/matroska/matroska-demux.c index 7f0f48f..5fe16e3 100644 --- a/gst/matroska/matroska-demux.c +++ b/gst/matroska/matroska-demux.c @@ -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); diff --git a/gst/matroska/matroska-mux.c b/gst/matroska/matroska-mux.c index d1794e5..098b2fc 100644 --- a/gst/matroska/matroska-mux.c +++ b/gst/matroska/matroska-mux.c @@ -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 */