summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Hervey <bilboed@bilboed.com>2014-11-21 17:14:29 +0100
committerEdward Hervey <bilboed@bilboed.com>2015-02-18 12:17:31 +0100
commitd35869988c241020df003763b5017f0909d2282e (patch)
tree06ee61f0abc86a3117ce557778f22c9a0f07d1a5
parentc27471eb9e998455931b044c6d7927f442db2c4c (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.c76
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;
}