mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-24 01:00:37 +00:00
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.
This commit is contained in:
parent
fe1f47aa17
commit
8596ec23cb
1 changed files with 26 additions and 12 deletions
|
@ -676,7 +676,7 @@ gst_ogg_demux_chain_peer (GstOggPad * pad, ogg_packet * packet,
|
||||||
packet->granulepos);
|
packet->granulepos);
|
||||||
GST_DEBUG_OBJECT (ogg, "new granule %" G_GUINT64_FORMAT,
|
GST_DEBUG_OBJECT (ogg, "new granule %" G_GUINT64_FORMAT,
|
||||||
pad->current_granule);
|
pad->current_granule);
|
||||||
} else if (ogg->segment.rate > 0.0 && pad->current_granule != -1) {
|
} else if (pad->current_granule != -1) {
|
||||||
pad->current_granule += duration;
|
pad->current_granule += duration;
|
||||||
if (!delta_unit) {
|
if (!delta_unit) {
|
||||||
pad->keyframe_granule = pad->current_granule;
|
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,
|
GST_DEBUG_OBJECT (ogg, "interpolating granule %" G_GUINT64_FORMAT,
|
||||||
pad->current_granule);
|
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_timestamp = -1;
|
||||||
out_duration = -1;
|
out_duration = -1;
|
||||||
out_offset = -1;
|
out_offset = -1;
|
||||||
out_offset_end = -1;
|
out_offset_end = -1;
|
||||||
|
pad->prev_granule = -1;
|
||||||
} else {
|
} else {
|
||||||
/* we only push buffers after we have a valid granule. This is done so that
|
/* 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
|
* 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. */
|
* timestamp. */
|
||||||
if (pad->current_granule == -1)
|
if (pad->current_granule == -1) {
|
||||||
|
pad->prev_granule = -1;
|
||||||
goto no_timestamp;
|
goto no_timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
if (pad->map.is_ogm) {
|
if (pad->map.is_ogm) {
|
||||||
out_timestamp = gst_ogg_stream_granule_to_time (&pad->map,
|
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 */
|
/* Mark discont on the buffer */
|
||||||
if (pad->discont) {
|
if (pad->discont) {
|
||||||
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
|
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
|
||||||
if GST_BUFFER_TIMESTAMP_IS_VALID
|
if (ogg->segment.rate < 0.0 || GST_BUFFER_TIMESTAMP_IS_VALID (buf))
|
||||||
(buf)
|
pad->discont = FALSE;
|
||||||
pad->discont = FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* don't push the header packets when we are asked to skip them */
|
/* 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
|
static void
|
||||||
gst_ogg_pad_mark_discont (GstOggPad * pad)
|
gst_ogg_pad_mark_discont (GstOggPad * pad)
|
||||||
{
|
{
|
||||||
|
GST_LOG_OBJECT (pad, "Marking discont on pad");
|
||||||
pad->discont = TRUE;
|
pad->discont = TRUE;
|
||||||
pad->map.last_size = 0;
|
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,
|
granule_time = gst_ogg_stream_get_end_time_for_granulepos (&pad->map,
|
||||||
granulepos);
|
granulepos);
|
||||||
|
|
||||||
|
/* Convert to stream time */
|
||||||
|
granule_time -= pad->start_time;
|
||||||
|
granule_time += chain->begin_time;
|
||||||
|
|
||||||
GST_LOG_OBJECT (ogg,
|
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_FORMAT, GST_TIME_ARGS (granule_time),
|
||||||
GST_TIME_ARGS (target));
|
GST_TIME_ARGS (target));
|
||||||
if (granule_time < target)
|
if (granule_time < target)
|
||||||
|
@ -4435,7 +4443,7 @@ gst_ogg_demux_update_chunk_size (GstOggDemux * ogg, ogg_page * page)
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
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;
|
GstOggPad *pad;
|
||||||
gint64 granule;
|
gint64 granule;
|
||||||
|
@ -4517,6 +4525,10 @@ gst_ogg_demux_handle_page (GstOggDemux * ogg, ogg_page * page)
|
||||||
pad = gst_ogg_demux_find_pad (ogg, serialno);
|
pad = gst_ogg_demux_find_pad (ogg, serialno);
|
||||||
}
|
}
|
||||||
if (pad) {
|
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);
|
result = gst_ogg_pad_submit_page (pad, page);
|
||||||
} else {
|
} else {
|
||||||
GST_PUSH_LOCK (ogg);
|
GST_PUSH_LOCK (ogg);
|
||||||
|
@ -4595,7 +4607,7 @@ gst_ogg_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
|
||||||
/* discontinuity in the pages */
|
/* discontinuity in the pages */
|
||||||
GST_DEBUG_OBJECT (ogg, "discont in page found, continuing");
|
GST_DEBUG_OBJECT (ogg, "discont in page found, continuing");
|
||||||
} else {
|
} else {
|
||||||
result = gst_ogg_demux_handle_page (ogg, &page);
|
result = gst_ogg_demux_handle_page (ogg, &page, FALSE);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
GST_DEBUG_OBJECT (ogg, "gst_ogg_demux_handle_page returned %d", result);
|
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;
|
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:
|
done:
|
||||||
return ret;
|
return ret;
|
||||||
|
|
Loading…
Reference in a new issue