From 54260af4c9042d98531907c3a149eea03b5283cd Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Wed, 11 Apr 2007 09:53:38 +0000 Subject: gst/qtdemux/: Handle version 1 mdhd atoms to get extended precision durations. Original commit message from CVS: * gst/qtdemux/qtdemux.c: (gst_qtdemux_get_duration), (qtdemux_parse_samples), (qtdemux_parse_segments), (qtdemux_parse_trak), (qtdemux_parse_tree): * gst/qtdemux/qtdemux_dump.c: (qtdemux_dump_mdhd): Handle version 1 mdhd atoms to get extended precision durations. Fixes #426972. --- gst/qtdemux/qtdemux.c | 37 +++++++++++++++++++++++-------------- gst/qtdemux/qtdemux_dump.c | 36 +++++++++++++++++++++++++++++------- 2 files changed, 52 insertions(+), 21 deletions(-) (limited to 'gst') diff --git a/gst/qtdemux/qtdemux.c b/gst/qtdemux/qtdemux.c index aca5bd32..1cd0f3b8 100644 --- a/gst/qtdemux/qtdemux.c +++ b/gst/qtdemux/qtdemux.c @@ -116,8 +116,8 @@ struct _QtDemuxStream guint32 fourcc; /* duration/scale */ - guint32 duration; /* in timescale */ - guint32 timescale; + guint64 duration; /* in timescale */ + guint64 timescale; /* our samples */ guint32 n_samples; @@ -401,7 +401,7 @@ gst_qtdemux_get_duration (GstQTDemux * qtdemux, gint64 * duration) if (qtdemux->duration != 0) { if (qtdemux->duration != G_MAXINT32 && qtdemux->timescale != 0) { - *duration = gst_util_uint64_scale_int (qtdemux->duration, + *duration = gst_util_uint64_scale (qtdemux->duration, GST_SECOND, qtdemux->timescale); } } @@ -2385,8 +2385,7 @@ qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, stream->min_duration = duration; /* add non-scaled values to avoid rounding errors */ time += duration; - timestamp = gst_util_uint64_scale_int (time, - GST_SECOND, stream->timescale); + timestamp = gst_util_uint64_scale (time, GST_SECOND, stream->timescale); samples[index].duration = timestamp - samples[index].timestamp; index++; @@ -2481,7 +2480,7 @@ qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream, samples[j].timestamp = timestamp; sample_index += samples_per_chunk; - timestamp = gst_util_uint64_scale_int (sample_index, + timestamp = gst_util_uint64_scale (sample_index, GST_SECOND, stream->timescale); samples[j].duration = timestamp - samples[j].timestamp; @@ -2572,12 +2571,12 @@ qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream, segment->time = stime; /* add non scaled values so we don't cause roundoff errors */ time += duration; - stime = gst_util_uint64_scale_int (time, GST_SECOND, qtdemux->timescale); + stime = gst_util_uint64_scale (time, GST_SECOND, qtdemux->timescale); segment->stop_time = stime; segment->duration = stime - segment->time; /* media_time expressed in stream timescale */ segment->media_start = - gst_util_uint64_scale_int (media_time, GST_SECOND, stream->timescale); + gst_util_uint64_scale (media_time, GST_SECOND, stream->timescale); segment->media_stop = segment->media_start + segment->duration; segment->rate = QT_FP32 (buffer + 24 + i * 12); @@ -2636,6 +2635,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak) GstTagList *list = NULL; const gchar *codec = NULL; const guint8 *stsd_data; + guint32 version; /* new streams always need a discont */ stream = g_new0 (QtDemuxStream, 1); @@ -2657,11 +2657,20 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak) if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd))) goto corrupt_file; - stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20); - stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24); + version = QT_UINT32 ((guint8 *) mdhd->data + 8); + GST_LOG_OBJECT (qtdemux, "track version/flags: %08x", version); + if (version == 0x01000000) { + stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 28); + stream->duration = QT_UINT64 ((guint8 *) mdhd->data + 32); + } else { + stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20); + stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24); + } - GST_LOG_OBJECT (qtdemux, "track timescale: %d", stream->timescale); - GST_LOG_OBJECT (qtdemux, "track duration: %d", stream->duration); + GST_LOG_OBJECT (qtdemux, "track timescale: %" G_GUINT64_FORMAT, + stream->timescale); + GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT, + stream->duration); if (qtdemux->duration != G_MAXINT32 && stream->duration != G_MAXINT32) { guint64 tdur1, tdur2; @@ -3501,8 +3510,8 @@ qtdemux_parse_tree (GstQTDemux * qtdemux) qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20); qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24); - GST_INFO_OBJECT (qtdemux, "timescale: %d", qtdemux->timescale); - GST_INFO_OBJECT (qtdemux, "duration: %d", qtdemux->duration); + GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale); + GST_INFO_OBJECT (qtdemux, "duration: %u", qtdemux->duration); /* set duration in the segment info */ gst_qtdemux_get_duration (qtdemux, &duration); diff --git a/gst/qtdemux/qtdemux_dump.c b/gst/qtdemux/qtdemux_dump.c index 357a5b15..391d67a0 100644 --- a/gst/qtdemux/qtdemux_dump.c +++ b/gst/qtdemux/qtdemux_dump.c @@ -83,14 +83,36 @@ qtdemux_dump_elst (GstQTDemux * qtdemux, guint8 * buffer, int depth) void qtdemux_dump_mdhd (GstQTDemux * qtdemux, guint8 * buffer, int depth) { - GST_LOG ("%*s version/flags: %08x", depth, "", QT_UINT32 (buffer + 8)); - GST_LOG ("%*s creation time: %u", depth, "", QT_UINT32 (buffer + 12)); - GST_LOG ("%*s modify time: %u", depth, "", QT_UINT32 (buffer + 16)); - GST_LOG ("%*s time scale: 1/%u sec", depth, "", QT_UINT32 (buffer + 20)); - GST_LOG ("%*s duration: %u", depth, "", QT_UINT32 (buffer + 24)); - GST_LOG ("%*s language: %u", depth, "", QT_UINT16 (buffer + 28)); - GST_LOG ("%*s quality: %u", depth, "", QT_UINT16 (buffer + 30)); + guint32 version; + guint64 duration, ctime, mtime; + guint32 time_scale; + guint16 language, quality; + + version = QT_UINT32 (buffer + 8); + GST_LOG ("%*s version/flags: %08x", depth, "", version); + + if (version == 0x01000000) { + ctime = QT_UINT64 (buffer + 12); + mtime = QT_UINT64 (buffer + 20); + time_scale = QT_UINT32 (buffer + 28); + duration = QT_UINT64 (buffer + 32); + language = QT_UINT16 (buffer + 40); + quality = QT_UINT16 (buffer + 42); + } else { + ctime = QT_UINT32 (buffer + 12); + mtime = QT_UINT32 (buffer + 16); + time_scale = QT_UINT32 (buffer + 20); + duration = QT_UINT32 (buffer + 24); + language = QT_UINT16 (buffer + 28); + quality = QT_UINT16 (buffer + 30); + } + GST_LOG ("%*s creation time: %" G_GUINT64_FORMAT, depth, "", ctime); + GST_LOG ("%*s modify time: %" G_GUINT64_FORMAT, depth, "", mtime); + GST_LOG ("%*s time scale: 1/%u sec", depth, "", time_scale); + GST_LOG ("%*s duration: %" G_GUINT64_FORMAT, depth, "", duration); + GST_LOG ("%*s language: %u", depth, "", language); + GST_LOG ("%*s quality: %u", depth, "", quality); } void -- cgit v1.2.1