From fc0a1845920f4fe6c21e0fe5edf87c43e222f51d Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Sat, 23 May 2015 14:36:41 -0300 Subject: [PATCH] qtdemux: fix reverse playback of fragmented media qtdemux creates a samples array and gets the timestamps for buffers by accumulating their durations. When doing reverse playback of fragments, accumulating samples will lead to wrong timestamps as the timestamps should go decreasing from fragment to fragment and the accumulation will produce wrong results. In this case, when receiving a discont for fragmented reverse playback, the previous samples information should be flushed before new data is processed. --- gst/isomp4/qtdemux.c | 53 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/gst/isomp4/qtdemux.c b/gst/isomp4/qtdemux.c index f50ff20..5adad74 100644 --- a/gst/isomp4/qtdemux.c +++ b/gst/isomp4/qtdemux.c @@ -2150,6 +2150,28 @@ gst_qtdemux_stbl_free (QtDemuxStream * stream) } static void +gst_qtdemux_stream_flush_samples_data (GstQTDemux * qtdemux, + QtDemuxStream * stream) +{ + g_free (stream->samples); + stream->samples = NULL; + g_free (stream->segments); + stream->segments = NULL; + gst_qtdemux_stbl_free (stream); + + /* fragments */ + g_free (stream->ra_entries); + stream->ra_entries = NULL; + stream->n_ra_entries = 0; + + stream->sample_index = -1; + stream->stbl_index = -1; + stream->n_samples = 0; + stream->time_position = 0; + stream->segment_index = -1; +} + +static void gst_qtdemux_stream_clear (GstQTDemux * qtdemux, QtDemuxStream * stream) { if (stream->allocator) @@ -2162,29 +2184,16 @@ gst_qtdemux_stream_clear (GstQTDemux * qtdemux, QtDemuxStream * stream) gst_memory_unref (stream->rgb8_palette); stream->rgb8_palette = NULL; } - g_free (stream->samples); - stream->samples = NULL; - g_free (stream->segments); - stream->segments = NULL; + if (stream->pending_tags) gst_tag_list_unref (stream->pending_tags); stream->pending_tags = NULL; g_free (stream->redirect_uri); stream->redirect_uri = NULL; - /* free stbl sub-atoms */ - gst_qtdemux_stbl_free (stream); - /* fragments */ - g_free (stream->ra_entries); - stream->ra_entries = NULL; - stream->n_ra_entries = 0; - stream->sent_eos = FALSE; - stream->segment_index = -1; - stream->time_position = 0; - stream->sample_index = -1; - stream->stbl_index = -1; - stream->n_samples = 0; stream->sparse = FALSE; + + gst_qtdemux_stream_flush_samples_data (qtdemux, stream); } static void @@ -5010,6 +5019,18 @@ gst_qtdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * inbuf) for (i = 0; i < demux->n_streams; i++) { demux->streams[i]->discont = TRUE; } + + /* Reverse fragmented playback, need to flush all we have before + * consuming a new fragment. + * The samples array have the timestamps calculated by accumulating the + * durations but this won't work for reverse playback of fragments as + * the timestamps of a subsequent fragment should be smaller than the + * previously received one. */ + if (demux->fragmented && demux->segment.rate < 0) { + gst_qtdemux_process_adapter (demux, TRUE); + for (i = 0; i < demux->n_streams; i++) + gst_qtdemux_stream_flush_samples_data (demux, demux->streams[i]); + } } gst_adapter_push (demux->adapter, inbuf); -- 2.7.4