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
This commit is contained in:
parent
b7938d24ee
commit
edda3b6c0f
17
ChangeLog
17
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>
|
2008-03-03 Peter Kjellerstedt <pkj@axis.com>
|
||||||
|
|
||||||
* configure.ac:
|
* configure.ac:
|
||||||
|
2
common
2
common
@ -1 +1 @@
|
|||||||
Subproject commit 668c3f0b72d50813c30eb04be7048f638037c571
|
Subproject commit 081a00a5e25d069b15bb7f6092c8f951462cd8eb
|
@ -266,8 +266,8 @@ gst_ebml_read_element_id (GstEbmlRead * ebml, guint32 * id, guint * level_up)
|
|||||||
guint64 pos = ebml->offset;
|
guint64 pos = ebml->offset;
|
||||||
|
|
||||||
GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL),
|
GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL),
|
||||||
("Invalid EBML ID size tag (0x%x) at position %llu (0x%llx)",
|
("Invalid EBML ID size tag (0x%x) at position %" G_GUINT64_FORMAT
|
||||||
(guint) b, pos, pos));
|
" (0x%" G_GINT64_MODIFIER "x)", (guint) b, pos, pos));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -318,8 +318,8 @@ gst_ebml_read_element_length (GstEbmlRead * ebml, guint64 * length)
|
|||||||
guint64 pos = ebml->offset;
|
guint64 pos = ebml->offset;
|
||||||
|
|
||||||
GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL),
|
GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL),
|
||||||
("Invalid EBML length size tag (0x%x) at position %llu (0x%llx)",
|
("Invalid EBML length size tag (0x%x) at position %" G_GUINT64_FORMAT
|
||||||
(guint) b, pos, pos));
|
" (0x%" G_GINT64_MODIFIER "x)", (guint) b, pos, pos));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -498,7 +498,8 @@ gst_ebml_read_uint (GstEbmlRead * ebml, guint32 * id, guint64 * num)
|
|||||||
|
|
||||||
if (size < 1 || size > 8) {
|
if (size < 1 || size > 8) {
|
||||||
GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL),
|
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));
|
size, ebml->offset - size, ebml->offset - size));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@ -528,8 +529,9 @@ gst_ebml_read_sint (GstEbmlRead * ebml, guint32 * id, gint64 * num)
|
|||||||
|
|
||||||
if (size < 1 || size > 8) {
|
if (size < 1 || size > 8) {
|
||||||
GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL),
|
GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL),
|
||||||
("Invalid integer element size %d at position %llu (0x%llx)",
|
("Invalid integer element size %d at position %" G_GUINT64_FORMAT
|
||||||
size, ebml->offset - size, ebml->offset - size));
|
" (0x%" G_GINT64_MODIFIER "x)", size, ebml->offset - size,
|
||||||
|
ebml->offset - size));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -570,8 +572,9 @@ gst_ebml_read_float (GstEbmlRead * ebml, guint32 * id, gdouble * num)
|
|||||||
|
|
||||||
if (size != 4 && size != 8 && size != 10) {
|
if (size != 4 && size != 8 && size != 10) {
|
||||||
GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL),
|
GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL),
|
||||||
("Invalid float element size %d at position %llu (0x%llx)",
|
("Invalid float element size %d at position %" G_GUINT64_FORMAT
|
||||||
size, ebml->offset - size, ebml->offset - size));
|
" (0x%" G_GINT64_MODIFIER "x)", size, ebml->offset - size,
|
||||||
|
ebml->offset - size));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -660,9 +660,11 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux)
|
|||||||
res = FALSE;
|
res = FALSE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
context->default_duration =
|
if (num != 0.0) {
|
||||||
gst_gdouble_to_guint64 ((gdouble) GST_SECOND * (1.0 / num));
|
context->default_duration =
|
||||||
videocontext->default_fps = num;
|
gst_gdouble_to_guint64 ((gdouble) GST_SECOND / num);
|
||||||
|
videocontext->default_fps = num;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1298,6 +1300,8 @@ gst_matroska_demux_send_event (GstMatroskaDemux * demux, GstEvent * event)
|
|||||||
gboolean ret = TRUE;
|
gboolean ret = TRUE;
|
||||||
gint i;
|
gint i;
|
||||||
|
|
||||||
|
g_return_val_if_fail (event != NULL, FALSE);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (demux, "Sending event of type %s to all source pads",
|
GST_DEBUG_OBJECT (demux, "Sending event of type %s to all source pads",
|
||||||
GST_EVENT_TYPE_NAME (event));
|
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);
|
GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (element);
|
||||||
gboolean res;
|
gboolean res;
|
||||||
|
|
||||||
|
g_return_val_if_fail (event != NULL, FALSE);
|
||||||
|
|
||||||
if (GST_EVENT_TYPE (event) == GST_EVENT_SEEK) {
|
if (GST_EVENT_TYPE (event) == GST_EVENT_SEEK) {
|
||||||
res = gst_matroska_demux_handle_seek_event (demux, event);
|
res = gst_matroska_demux_handle_seek_event (demux, event);
|
||||||
} else {
|
} else {
|
||||||
@ -1879,12 +1885,17 @@ gst_matroska_demux_parse_info (GstMatroskaDemux * demux)
|
|||||||
|
|
||||||
case GST_MATROSKA_ID_DURATION:{
|
case GST_MATROSKA_ID_DURATION:{
|
||||||
gdouble num;
|
gdouble num;
|
||||||
|
GstClockTime dur;
|
||||||
|
|
||||||
if (!gst_ebml_read_float (ebml, &id, &num)) {
|
if (!gst_ebml_read_float (ebml, &id, &num)) {
|
||||||
res = FALSE;
|
res = FALSE;
|
||||||
break;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3712,7 +3723,7 @@ gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext *
|
|||||||
|
|
||||||
g_value_init (&fps_double, G_TYPE_DOUBLE);
|
g_value_init (&fps_double, G_TYPE_DOUBLE);
|
||||||
g_value_init (&fps_fraction, GST_TYPE_FRACTION);
|
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));
|
gst_guint64_to_gdouble (context->default_duration));
|
||||||
g_value_transform (&fps_double, &fps_fraction);
|
g_value_transform (&fps_double, &fps_fraction);
|
||||||
|
|
||||||
|
@ -1185,13 +1185,17 @@ gst_matroska_mux_release_pad (GstElement * element, GstPad * pad)
|
|||||||
if (cdata->pad == pad) {
|
if (cdata->pad == pad) {
|
||||||
GstClockTime min_dur; /* observed minimum duration */
|
GstClockTime min_dur; /* observed minimum duration */
|
||||||
|
|
||||||
/* no need to check if start_ts and end_ts are set, in the worst case
|
if (GST_CLOCK_TIME_IS_VALID (collect_pad->start_ts) &&
|
||||||
* they're both -1 and we'll end up with a duration of 0 again */
|
GST_CLOCK_TIME_IS_VALID (collect_pad->end_ts)) {
|
||||||
min_dur = GST_CLOCK_DIFF (collect_pad->start_ts, collect_pad->end_ts);
|
min_dur = GST_CLOCK_DIFF (collect_pad->start_ts, collect_pad->end_ts);
|
||||||
if (collect_pad->duration < min_dur)
|
if (collect_pad->duration < min_dur)
|
||||||
collect_pad->duration = min_dur;
|
collect_pad->duration = min_dur;
|
||||||
if (collect_pad->duration > mux->duration)
|
}
|
||||||
|
|
||||||
|
if (GST_CLOCK_TIME_IS_VALID (collect_pad->duration) &&
|
||||||
|
mux->duration < collect_pad->duration)
|
||||||
mux->duration = collect_pad->duration;
|
mux->duration = collect_pad->duration;
|
||||||
|
|
||||||
gst_matroska_pad_free (collect_pad);
|
gst_matroska_pad_free (collect_pad);
|
||||||
gst_collect_pads_remove_pad (mux->collect, pad);
|
gst_collect_pads_remove_pad (mux->collect, pad);
|
||||||
gst_element_remove_pad (element, pad);
|
gst_element_remove_pad (element, pad);
|
||||||
@ -1321,7 +1325,7 @@ gst_matroska_mux_start (GstMatroskaMux * mux)
|
|||||||
GSList *collected;
|
GSList *collected;
|
||||||
int i;
|
int i;
|
||||||
guint tracknum = 1;
|
guint tracknum = 1;
|
||||||
gdouble duration = 0;
|
GstClockTime duration = 0;
|
||||||
guint32 *segment_uid = (guint32 *) g_malloc (16);
|
guint32 *segment_uid = (guint32 *) g_malloc (16);
|
||||||
GRand *rand = g_rand_new ();
|
GRand *rand = g_rand_new ();
|
||||||
GTimeVal time = { 0, 0 };
|
GTimeVal time = { 0, 0 };
|
||||||
@ -1376,14 +1380,15 @@ gst_matroska_mux_start (GstMatroskaMux * mux)
|
|||||||
if (gst_pad_query_peer_duration (thepad, &format, &trackduration)) {
|
if (gst_pad_query_peer_duration (thepad, &format, &trackduration)) {
|
||||||
GST_DEBUG_OBJECT (thepad, "duration: %" GST_TIME_FORMAT,
|
GST_DEBUG_OBJECT (thepad, "duration: %" GST_TIME_FORMAT,
|
||||||
GST_TIME_ARGS (trackduration));
|
GST_TIME_ARGS (trackduration));
|
||||||
if (trackduration != GST_CLOCK_TIME_NONE &&
|
if (trackduration != GST_CLOCK_TIME_NONE && trackduration > duration) {
|
||||||
(gdouble) trackduration > duration) {
|
duration = (GstClockTime) trackduration;
|
||||||
duration = (gdouble) trackduration;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gst_ebml_write_float (ebml, GST_MATROSKA_ID_DURATION,
|
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,
|
gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_MUXINGAPP,
|
||||||
"GStreamer plugin version " PACKAGE_VERSION);
|
"GStreamer plugin version " PACKAGE_VERSION);
|
||||||
if (mux->writing_app && mux->writing_app[0]) {
|
if (mux->writing_app && mux->writing_app[0]) {
|
||||||
@ -1617,14 +1622,23 @@ gst_matroska_mux_finish (GstMatroskaMux * mux)
|
|||||||
|
|
||||||
collect_pad = (GstMatroskaPad *) collected->data;
|
collect_pad = (GstMatroskaPad *) collected->data;
|
||||||
|
|
||||||
/* no need to check if start_ts and end_ts are set, in the worst case
|
GST_DEBUG_OBJECT (mux, "Pad %" GST_PTR_FORMAT " start ts %" GST_TIME_FORMAT
|
||||||
* they're both -1 and we'll end up with a duration of 0 again */
|
" end ts %" GST_TIME_FORMAT, collect_pad,
|
||||||
min_duration = GST_CLOCK_DIFF (collect_pad->start_ts, collect_pad->end_ts);
|
GST_TIME_ARGS (collect_pad->start_ts),
|
||||||
if (collect_pad->duration < min_duration)
|
GST_TIME_ARGS (collect_pad->end_ts));
|
||||||
collect_pad->duration = min_duration;
|
|
||||||
GST_DEBUG_OBJECT (collect_pad, "final track duration: %" GST_TIME_FORMAT,
|
if (GST_CLOCK_TIME_IS_VALID (collect_pad->start_ts) &&
|
||||||
GST_TIME_ARGS (collect_pad->duration));
|
GST_CLOCK_TIME_IS_VALID (collect_pad->end_ts)) {
|
||||||
if (collect_pad->duration > duration)
|
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;
|
duration = collect_pad->duration;
|
||||||
}
|
}
|
||||||
if (duration != 0) {
|
if (duration != 0) {
|
||||||
@ -1633,7 +1647,8 @@ gst_matroska_mux_finish (GstMatroskaMux * mux)
|
|||||||
pos = mux->ebml_write->pos;
|
pos = mux->ebml_write->pos;
|
||||||
gst_ebml_write_seek (ebml, mux->duration_pos);
|
gst_ebml_write_seek (ebml, mux->duration_pos);
|
||||||
gst_ebml_write_float (ebml, GST_MATROSKA_ID_DURATION,
|
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);
|
gst_ebml_write_seek (ebml, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1941,18 +1956,28 @@ gst_matroska_mux_collected (GstCollectPads * pads, gpointer user_data)
|
|||||||
ret = GST_FLOW_UNEXPECTED;
|
ret = GST_FLOW_UNEXPECTED;
|
||||||
break;
|
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
|
/* make note of first and last encountered timestamps, so we can calculate
|
||||||
* the actual duration later when we send an updated header on eos */
|
* the actual duration later when we send an updated header on eos */
|
||||||
best->end_ts = GST_BUFFER_TIMESTAMP (best->buffer);
|
if (GST_BUFFER_TIMESTAMP_IS_VALID (best->buffer)) {
|
||||||
if (GST_BUFFER_DURATION_IS_VALID (best->buffer))
|
GstClockTime start_ts = GST_BUFFER_TIMESTAMP (best->buffer);
|
||||||
best->end_ts += GST_BUFFER_DURATION (best->buffer);
|
GstClockTime end_ts = start_ts;
|
||||||
else if (best->track->default_duration)
|
|
||||||
best->end_ts += best->track->default_duration;
|
|
||||||
|
|
||||||
if (G_UNLIKELY (best->start_ts == GST_CLOCK_TIME_NONE)) {
|
if (GST_BUFFER_DURATION_IS_VALID (best->buffer))
|
||||||
best->start_ts = GST_BUFFER_TIMESTAMP (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 */
|
/* write one buffer */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user