diff options
author | Edward Hervey <bilboed@bilboed.com> | 2014-11-21 17:14:29 +0100 |
---|---|---|
committer | Edward Hervey <bilboed@bilboed.com> | 2015-02-18 12:17:31 +0100 |
commit | d35869988c241020df003763b5017f0909d2282e (patch) | |
tree | 06ee61f0abc86a3117ce557778f22c9a0f07d1a5 | |
parent | c27471eb9e998455931b044c6d7927f442db2c4c (diff) |
qtdemux: Detect badly interleaved files
When working in push-based with broken files, error out if the interleaving
is greater than 10s (which is already awful).
-rw-r--r-- | gst/isomp4/qtdemux.c | 76 |
1 files changed, 73 insertions, 3 deletions
diff --git a/gst/isomp4/qtdemux.c b/gst/isomp4/qtdemux.c index 0ac2d6983..daf977eaa 100644 --- a/gst/isomp4/qtdemux.c +++ b/gst/isomp4/qtdemux.c @@ -3454,8 +3454,9 @@ gst_qtdemux_loop_state_header (GstQTDemux * qtdemux) beach: if (ret == GST_FLOW_EOS && (qtdemux->got_moov || qtdemux->media_caps)) { /* digested all data, show what we have */ - qtdemux_prepare_streams (qtdemux); - ret = qtdemux_expose_streams (qtdemux); + ret = qtdemux_prepare_streams (qtdemux); + if (ret == GST_FLOW_OK) + ret = qtdemux_expose_streams (qtdemux); qtdemux->state = QTDEMUX_STATE_MOVIE; GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)", @@ -5192,7 +5193,7 @@ gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force) qtdemux_parse_moov (demux, data, demux->neededbytes); qtdemux_node_dump (demux, demux->moov_node); qtdemux_parse_tree (demux); - qtdemux_prepare_streams (demux); + ret = qtdemux_prepare_streams (demux); if (!demux->got_moov) qtdemux_expose_streams (demux); else { @@ -9490,6 +9491,75 @@ qtdemux_prepare_streams (GstQTDemux * qtdemux) } } + /* Check interleave in push-mode */ + /* For each first sample of each track: + * * Remember the one with the lowest offset (remember that early_track) + * * Remember the one with the highest offset + * + * Calculate what sample from the early_track corresponds to the highest offset + * (use gst_qtdemux_find_index_for_given_media_offset_linear) + * => That will be the interleave in time + */ + if (!qtdemux->pullbased && ret == GST_FLOW_OK) { + gint64 low_offs = -1; + gint64 high_offs = -1; + gint early_track = -1; + QtDemuxSample *first_sample; + QtDemuxStream *stream; + GstClockTime low_ts = 0; + + for (i = 0; i < qtdemux->n_streams; i++) { + stream = qtdemux->streams[i]; + + /* skip empty tracks */ + if (stream->n_samples == 0) + continue; + first_sample = stream->samples; + if (low_offs == -1 || first_sample->offset < low_offs) { + GST_DEBUG ("Low offset on track %d (offs:%" G_GUINT64_FORMAT ")", + i, first_sample->offset); + low_offs = first_sample->offset; + low_ts = + gst_util_uint64_scale (first_sample->timestamp, GST_SECOND, + stream->timescale); + early_track = i; + } else if (high_offs == -1 || first_sample->offset > high_offs) { + GST_DEBUG ("High offset on track %d (offs:%" G_GUINT64_FORMAT ")", + i, first_sample->offset); + high_offs = first_sample->offset; + } + } + if (high_offs != -1 && low_offs != -1) { + guint32 int_idx; + GST_DEBUG_OBJECT (qtdemux, + "Initial interleave in bytes %" G_GINT64_FORMAT, + high_offs - low_offs); + GST_DEBUG_OBJECT (qtdemux, "First track is %d", early_track); + stream = qtdemux->streams[early_track]; + int_idx = + gst_qtdemux_find_index_for_given_media_offset_linear (qtdemux, stream, + high_offs); + if (int_idx != -1) { + GstClockTime interleave; + + first_sample = stream->samples + int_idx; + interleave = + gst_util_uint64_scale (first_sample->timestamp, GST_SECOND, + stream->timescale) - low_ts; + GST_DEBUG_OBJECT (qtdemux, + "Corresponding sample (%d) on early_track is at %" GST_TIME_FORMAT, + int_idx, GST_TIME_ARGS (interleave)); + + /* ERROR OUT if interleave is greater than 10s */ + if (interleave > 10 * GST_SECOND) { + GST_ERROR_OBJECT (qtdemux, + "File has interleave greater than 10s, cannot be played correctly"); + ret = GST_FLOW_ERROR; + } + } + } + } + return ret; } |