qtdemux: avoid re-reading the same moov and entering into loop

In the scenario of "mdat | moov (with fragmented artifacts)" qtdemux
could read the moov again after the mdat because it was considering the
media as a fragmented one.

To avoid this loop this patch makes it store
the last processed moov_offset to avoid parsing it again.
And it also checks if there are any samples to play before
resturning to the mdat, so that it knows there is new data to be played.

https://bugzilla.gnome.org/show_bug.cgi?id=691570
This commit is contained in:
Thiago Santos 2013-11-15 08:54:07 -03:00
parent fcc78aa3bd
commit 45c16599ff
2 changed files with 44 additions and 3 deletions

View file

@ -1819,6 +1819,7 @@ gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
if (qtdemux->comp_brands)
gst_buffer_unref (qtdemux->comp_brands);
qtdemux->comp_brands = NULL;
qtdemux->last_moov_offset = -1;
if (qtdemux->moov_node)
g_node_destroy (qtdemux->moov_node);
qtdemux->moov_node = NULL;
@ -4412,6 +4413,39 @@ pause:
}
}
/*
* has_next_entry
*
* Returns if there are samples to be played.
*/
static gboolean
has_next_entry (GstQTDemux * demux)
{
QtDemuxStream *stream;
int i;
GST_DEBUG_OBJECT (demux, "Checking if there are samples not played yet");
for (i = 0; i < demux->n_streams; i++) {
stream = demux->streams[i];
if (stream->sample_index == -1) {
stream->sample_index = 0;
stream->offset_in_sample = 0;
}
if (stream->sample_index >= stream->n_samples) {
GST_LOG_OBJECT (demux, "stream %d samples exhausted", i);
continue;
}
GST_DEBUG_OBJECT (demux, "Found a sample");
return TRUE;
}
GST_DEBUG_OBJECT (demux, "There wasn't any next sample");
return FALSE;
}
/*
* next_entry_size
*
@ -4704,9 +4738,11 @@ gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
if (fourcc == FOURCC_moov) {
/* in usual fragmented setup we could try to scan for more
* and end up at the the moov (after mdat) again */
if (demux->got_moov && demux->n_streams > 0 && !demux->fragmented) {
if (demux->got_moov && demux->n_streams > 0 &&
(!demux->fragmented
|| demux->last_moov_offset == demux->offset)) {
GST_DEBUG_OBJECT (demux,
"Skipping moov atom as we have one already");
"Skipping moov atom as we have (this) one already");
} else {
GST_DEBUG_OBJECT (demux, "Parsing [moov]");
@ -4724,6 +4760,8 @@ gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
gst_event_new_segment (&demux->segment);
}
demux->last_moov_offset = demux->offset;
qtdemux_parse_moov (demux, data, demux->neededbytes);
qtdemux_node_dump (demux, demux->moov_node);
qtdemux_parse_tree (demux);
@ -4817,7 +4855,9 @@ gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf)
GST_DEBUG_OBJECT (demux, "Carrying on normally");
gst_adapter_flush (demux->adapter, demux->neededbytes);
if (demux->got_moov && demux->first_mdat != -1) {
/* only go back to the mdat if there are samples to play */
if (demux->got_moov && demux->first_mdat != -1
&& has_next_entry (demux)) {
gboolean res;
/* we need to seek back */

View file

@ -106,6 +106,7 @@ struct _GstQTDemux {
guint64 mdatoffset;
guint64 first_mdat;
gboolean got_moov;
guint64 last_moov_offset;
guint header_size;
GstTagList *tag_list;