mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-17 03:35:21 +00:00
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.
This commit is contained in:
parent
acddbd83ff
commit
2f97f23897
2 changed files with 52 additions and 21 deletions
|
@ -116,8 +116,8 @@ struct _QtDemuxStream
|
||||||
guint32 fourcc;
|
guint32 fourcc;
|
||||||
|
|
||||||
/* duration/scale */
|
/* duration/scale */
|
||||||
guint32 duration; /* in timescale */
|
guint64 duration; /* in timescale */
|
||||||
guint32 timescale;
|
guint64 timescale;
|
||||||
|
|
||||||
/* our samples */
|
/* our samples */
|
||||||
guint32 n_samples;
|
guint32 n_samples;
|
||||||
|
@ -401,7 +401,7 @@ gst_qtdemux_get_duration (GstQTDemux * qtdemux, gint64 * duration)
|
||||||
|
|
||||||
if (qtdemux->duration != 0) {
|
if (qtdemux->duration != 0) {
|
||||||
if (qtdemux->duration != G_MAXINT32 && qtdemux->timescale != 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);
|
GST_SECOND, qtdemux->timescale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2385,8 +2385,7 @@ qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream,
|
||||||
stream->min_duration = duration;
|
stream->min_duration = duration;
|
||||||
/* add non-scaled values to avoid rounding errors */
|
/* add non-scaled values to avoid rounding errors */
|
||||||
time += duration;
|
time += duration;
|
||||||
timestamp = gst_util_uint64_scale_int (time,
|
timestamp = gst_util_uint64_scale (time, GST_SECOND, stream->timescale);
|
||||||
GST_SECOND, stream->timescale);
|
|
||||||
samples[index].duration = timestamp - samples[index].timestamp;
|
samples[index].duration = timestamp - samples[index].timestamp;
|
||||||
|
|
||||||
index++;
|
index++;
|
||||||
|
@ -2481,7 +2480,7 @@ qtdemux_parse_samples (GstQTDemux * qtdemux, QtDemuxStream * stream,
|
||||||
samples[j].timestamp = timestamp;
|
samples[j].timestamp = timestamp;
|
||||||
sample_index += samples_per_chunk;
|
sample_index += samples_per_chunk;
|
||||||
|
|
||||||
timestamp = gst_util_uint64_scale_int (sample_index,
|
timestamp = gst_util_uint64_scale (sample_index,
|
||||||
GST_SECOND, stream->timescale);
|
GST_SECOND, stream->timescale);
|
||||||
samples[j].duration = timestamp - samples[j].timestamp;
|
samples[j].duration = timestamp - samples[j].timestamp;
|
||||||
|
|
||||||
|
@ -2572,12 +2571,12 @@ qtdemux_parse_segments (GstQTDemux * qtdemux, QtDemuxStream * stream,
|
||||||
segment->time = stime;
|
segment->time = stime;
|
||||||
/* add non scaled values so we don't cause roundoff errors */
|
/* add non scaled values so we don't cause roundoff errors */
|
||||||
time += duration;
|
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->stop_time = stime;
|
||||||
segment->duration = stime - segment->time;
|
segment->duration = stime - segment->time;
|
||||||
/* media_time expressed in stream timescale */
|
/* media_time expressed in stream timescale */
|
||||||
segment->media_start =
|
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->media_stop = segment->media_start + segment->duration;
|
||||||
segment->rate = QT_FP32 (buffer + 24 + i * 12);
|
segment->rate = QT_FP32 (buffer + 24 + i * 12);
|
||||||
|
|
||||||
|
@ -2636,6 +2635,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
|
||||||
GstTagList *list = NULL;
|
GstTagList *list = NULL;
|
||||||
const gchar *codec = NULL;
|
const gchar *codec = NULL;
|
||||||
const guint8 *stsd_data;
|
const guint8 *stsd_data;
|
||||||
|
guint32 version;
|
||||||
|
|
||||||
/* new streams always need a discont */
|
/* new streams always need a discont */
|
||||||
stream = g_new0 (QtDemuxStream, 1);
|
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)))
|
if (!(mdhd = qtdemux_tree_get_child_by_type (mdia, FOURCC_mdhd)))
|
||||||
goto corrupt_file;
|
goto corrupt_file;
|
||||||
|
|
||||||
stream->timescale = QT_UINT32 ((guint8 *) mdhd->data + 20);
|
version = QT_UINT32 ((guint8 *) mdhd->data + 8);
|
||||||
stream->duration = QT_UINT32 ((guint8 *) mdhd->data + 24);
|
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 timescale: %" G_GUINT64_FORMAT,
|
||||||
GST_LOG_OBJECT (qtdemux, "track duration: %d", stream->duration);
|
stream->timescale);
|
||||||
|
GST_LOG_OBJECT (qtdemux, "track duration: %" G_GUINT64_FORMAT,
|
||||||
|
stream->duration);
|
||||||
|
|
||||||
if (qtdemux->duration != G_MAXINT32 && stream->duration != G_MAXINT32) {
|
if (qtdemux->duration != G_MAXINT32 && stream->duration != G_MAXINT32) {
|
||||||
guint64 tdur1, tdur2;
|
guint64 tdur1, tdur2;
|
||||||
|
@ -3501,8 +3510,8 @@ qtdemux_parse_tree (GstQTDemux * qtdemux)
|
||||||
qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
|
qtdemux->timescale = QT_UINT32 ((guint8 *) mvhd->data + 20);
|
||||||
qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
|
qtdemux->duration = QT_UINT32 ((guint8 *) mvhd->data + 24);
|
||||||
|
|
||||||
GST_INFO_OBJECT (qtdemux, "timescale: %d", qtdemux->timescale);
|
GST_INFO_OBJECT (qtdemux, "timescale: %u", qtdemux->timescale);
|
||||||
GST_INFO_OBJECT (qtdemux, "duration: %d", qtdemux->duration);
|
GST_INFO_OBJECT (qtdemux, "duration: %u", qtdemux->duration);
|
||||||
|
|
||||||
/* set duration in the segment info */
|
/* set duration in the segment info */
|
||||||
gst_qtdemux_get_duration (qtdemux, &duration);
|
gst_qtdemux_get_duration (qtdemux, &duration);
|
||||||
|
|
|
@ -83,14 +83,36 @@ qtdemux_dump_elst (GstQTDemux * qtdemux, guint8 * buffer, int depth)
|
||||||
void
|
void
|
||||||
qtdemux_dump_mdhd (GstQTDemux * qtdemux, guint8 * buffer, int depth)
|
qtdemux_dump_mdhd (GstQTDemux * qtdemux, guint8 * buffer, int depth)
|
||||||
{
|
{
|
||||||
GST_LOG ("%*s version/flags: %08x", depth, "", QT_UINT32 (buffer + 8));
|
guint32 version;
|
||||||
GST_LOG ("%*s creation time: %u", depth, "", QT_UINT32 (buffer + 12));
|
guint64 duration, ctime, mtime;
|
||||||
GST_LOG ("%*s modify time: %u", depth, "", QT_UINT32 (buffer + 16));
|
guint32 time_scale;
|
||||||
GST_LOG ("%*s time scale: 1/%u sec", depth, "", QT_UINT32 (buffer + 20));
|
guint16 language, quality;
|
||||||
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));
|
|
||||||
|
|
||||||
|
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
|
void
|
||||||
|
|
Loading…
Reference in a new issue