From 45c16599ff4a3d674bd651cdb3babbc00af8d06c Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Fri, 15 Nov 2013 08:54:07 -0300 Subject: [PATCH] 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 --- gst/isomp4/qtdemux.c | 46 +++++++++++++++++++++++++++++++++++++++++--- gst/isomp4/qtdemux.h | 1 + 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/gst/isomp4/qtdemux.c b/gst/isomp4/qtdemux.c index 0604ac9d77..78d4f45109 100644 --- a/gst/isomp4/qtdemux.c +++ b/gst/isomp4/qtdemux.c @@ -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 */ diff --git a/gst/isomp4/qtdemux.h b/gst/isomp4/qtdemux.h index 3fb43daea7..a6b9768f58 100644 --- a/gst/isomp4/qtdemux.h +++ b/gst/isomp4/qtdemux.h @@ -106,6 +106,7 @@ struct _GstQTDemux { guint64 mdatoffset; guint64 first_mdat; gboolean got_moov; + guint64 last_moov_offset; guint header_size; GstTagList *tag_list;