From: Jan Schmidt Date: Fri, 3 Mar 2017 13:27:30 +0000 (+1100) Subject: oggdemux: Fix reverse playback X-Git-Tag: 1.12.2~99 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8596ec23cbf74a46b34ff3541718a1cdf311f370;p=platform%2Fupstream%2Fgst-plugins-base.git oggdemux: Fix reverse playback Fix various issues with reverse playback by clearing tracking vars when working in reverse, and where possible using the timestamp interpolation code to generate timestamps for outgoing buffers. Make sure to mark things as discontinuous only when looping backward to a new position and fix seeking to the next page when starting. --- diff --git a/ext/ogg/gstoggdemux.c b/ext/ogg/gstoggdemux.c index ff2cc61..51c5509 100644 --- a/ext/ogg/gstoggdemux.c +++ b/ext/ogg/gstoggdemux.c @@ -676,7 +676,7 @@ gst_ogg_demux_chain_peer (GstOggPad * pad, ogg_packet * packet, packet->granulepos); GST_DEBUG_OBJECT (ogg, "new granule %" G_GUINT64_FORMAT, pad->current_granule); - } else if (ogg->segment.rate > 0.0 && pad->current_granule != -1) { + } else if (pad->current_granule != -1) { pad->current_granule += duration; if (!delta_unit) { pad->keyframe_granule = pad->current_granule; @@ -684,19 +684,23 @@ gst_ogg_demux_chain_peer (GstOggPad * pad, ogg_packet * packet, GST_DEBUG_OBJECT (ogg, "interpolating granule %" G_GUINT64_FORMAT, pad->current_granule); } - if (ogg->segment.rate < 0.0 && packet->granulepos == -1) { - /* negative rates, only set timestamp on the packets with a granulepos */ + + if (ogg->segment.rate < 0.0 && pad->current_granule == -1) { + /* negative rates, allow output of packets with no timestamp, let downstream reconstruct */ out_timestamp = -1; out_duration = -1; out_offset = -1; out_offset_end = -1; + pad->prev_granule = -1; } else { /* we only push buffers after we have a valid granule. This is done so that * we nicely skip packets without a timestamp after a seek. This is ok - * because we base or seek on the packet after the page with the smaller + * because we base our seek on the packet after the page with the smaller * timestamp. */ - if (pad->current_granule == -1) + if (pad->current_granule == -1) { + pad->prev_granule = -1; goto no_timestamp; + } if (pad->map.is_ogm) { out_timestamp = gst_ogg_stream_granule_to_time (&pad->map, @@ -802,9 +806,8 @@ gst_ogg_demux_chain_peer (GstOggPad * pad, ogg_packet * packet, /* Mark discont on the buffer */ if (pad->discont) { GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT); - if GST_BUFFER_TIMESTAMP_IS_VALID - (buf) - pad->discont = FALSE; + if (ogg->segment.rate < 0.0 || GST_BUFFER_TIMESTAMP_IS_VALID (buf)) + pad->discont = FALSE; } /* don't push the header packets when we are asked to skip them */ @@ -2100,6 +2103,7 @@ gst_ogg_chain_free (GstOggChain * chain) static void gst_ogg_pad_mark_discont (GstOggPad * pad) { + GST_LOG_OBJECT (pad, "Marking discont on pad"); pad->discont = TRUE; pad->map.last_size = 0; } @@ -3341,8 +3345,12 @@ gst_ogg_demux_do_seek (GstOggDemux * ogg, GstSegment * segment, granule_time = gst_ogg_stream_get_end_time_for_granulepos (&pad->map, granulepos); + /* Convert to stream time */ + granule_time -= pad->start_time; + granule_time += chain->begin_time; + GST_LOG_OBJECT (ogg, - "looking at page with ts %" GST_TIME_FORMAT ", target %" + "looking at page with time %" GST_TIME_FORMAT ", target %" GST_TIME_FORMAT, GST_TIME_ARGS (granule_time), GST_TIME_ARGS (target)); if (granule_time < target) @@ -4435,7 +4443,7 @@ gst_ogg_demux_update_chunk_size (GstOggDemux * ogg, ogg_page * page) } static GstFlowReturn -gst_ogg_demux_handle_page (GstOggDemux * ogg, ogg_page * page) +gst_ogg_demux_handle_page (GstOggDemux * ogg, ogg_page * page, gboolean discont) { GstOggPad *pad; gint64 granule; @@ -4517,6 +4525,10 @@ gst_ogg_demux_handle_page (GstOggDemux * ogg, ogg_page * page) pad = gst_ogg_demux_find_pad (ogg, serialno); } if (pad) { + /* Reset granule interpolation if chaining in reverse (discont = TRUE) */ + if (discont) + pad->current_granule = -1; + result = gst_ogg_pad_submit_page (pad, page); } else { GST_PUSH_LOCK (ogg); @@ -4595,7 +4607,7 @@ gst_ogg_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) /* discontinuity in the pages */ GST_DEBUG_OBJECT (ogg, "discont in page found, continuing"); } else { - result = gst_ogg_demux_handle_page (ogg, &page); + result = gst_ogg_demux_handle_page (ogg, &page, FALSE); if (result < 0) { GST_DEBUG_OBJECT (ogg, "gst_ogg_demux_handle_page returned %d", result); } @@ -4718,7 +4730,9 @@ gst_ogg_demux_loop_reverse (GstOggDemux * ogg) ogg->newsegment = NULL; } - ret = gst_ogg_demux_handle_page (ogg, &page); + GST_LOG_OBJECT (ogg, "Handling page at offset %" G_GINT64_FORMAT, + ogg->offset); + ret = gst_ogg_demux_handle_page (ogg, &page, TRUE); done: return ret;