summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog17
m---------common0
-rw-r--r--gst/matroska/ebml-read.c21
-rw-r--r--gst/matroska/matroska-demux.c21
-rw-r--r--gst/matroska/matroska-mux.c83
5 files changed, 99 insertions, 43 deletions
diff --git a/ChangeLog b/ChangeLog
index e81807ca..2d02f73e 100644
--- 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
-Subproject 668c3f0b72d50813c30eb04be7048f638037c57
+Subproject 081a00a5e25d069b15bb7f6092c8f951462cd8e
diff --git a/gst/matroska/ebml-read.c b/gst/matroska/ebml-read.c
index 83439104..9c5ae4a6 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 7f0f48f8..5fe16e32 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 d1794e52..098b2fc0 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 */