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.
This commit is contained in:
Thiago Santos 2015-05-23 14:36:41 -03:00
parent d3997773fc
commit fc0a184592

View file

@ -2149,6 +2149,28 @@ gst_qtdemux_stbl_free (QtDemuxStream * stream)
stream->ctts.data = NULL;
}
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)
{
@ -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);