From 5d0657d4aecad854fe9ab39dd336403c5a28b691 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Sebastian=20Dr=C3=B6ge?= Date: Tue, 15 May 2018 18:26:16 +0300 Subject: [PATCH] matroska-demux: Send instant-rate-change event if requested in the SEEK event Short-circuit instant rate change events by generating a downstream instant-rate-change event and doing no further seek processing. --- gst/matroska/matroska-demux.c | 73 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 65 insertions(+), 8 deletions(-) diff --git a/gst/matroska/matroska-demux.c b/gst/matroska/matroska-demux.c index ddeb193..883ac28 100644 --- a/gst/matroska/matroska-demux.c +++ b/gst/matroska/matroska-demux.c @@ -2730,7 +2730,8 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux, GstSeekFlags flags; GstSeekType cur_type, stop_type; GstFormat format; - gboolean flush, keyunit, before, after, accurate, snap_next; + gboolean flush, keyunit, instant_rate_change, before, after, accurate, + snap_next; gdouble rate; gint64 cur, stop; GstMatroskaTrackContext *track = NULL; @@ -2758,6 +2759,40 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux, return FALSE; } + GST_DEBUG_OBJECT (demux, "configuring seek"); + + flush = ! !(flags & GST_SEEK_FLAG_FLUSH); + keyunit = ! !(flags & GST_SEEK_FLAG_KEY_UNIT); + after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER); + before = ! !(flags & GST_SEEK_FLAG_SNAP_BEFORE); + accurate = ! !(flags & GST_SEEK_FLAG_ACCURATE); + instant_rate_change = ! !(flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE); + + /* Directly send the instant-rate-change event here before taking the + * stream-lock so that it can be applied as soon as possible */ + if (instant_rate_change) { + GstEvent *ev; + + /* instant rate change only supported if direction does not change. All + * other requirements are already checked before creating the seek event + * but let's double-check here to be sure */ + if ((rate > 0 && demux->common.segment.rate < 0) || + (rate < 0 && demux->common.segment.rate > 0) || + cur_type != GST_SEEK_TYPE_NONE || + stop_type != GST_SEEK_TYPE_NONE || flush) { + GST_ERROR_OBJECT (demux, + "Instant rate change seeks only supported in the " + "same direction, without flushing and position change"); + return FALSE; + } + + ev = gst_event_new_instant_rate_change (rate / + demux->common.segment.rate, (GstSegmentFlags) flags); + gst_event_set_seqnum (ev, seqnum); + gst_matroska_demux_send_event (demux, ev); + return TRUE; + } + /* copy segment, we need this because we still need the old * segment when we close the current segment. */ memcpy (&seeksegment, &demux->common.segment, sizeof (GstSegment)); @@ -2770,7 +2805,6 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux, seeksegment.duration = GST_CLOCK_TIME_NONE; } - GST_DEBUG_OBJECT (demux, "configuring seek"); /* Subtract stream_start_time so we always seek on a segment * in stream time */ if (GST_CLOCK_TIME_IS_VALID (demux->stream_start_time)) { @@ -2799,12 +2833,6 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux, * would be determined again when parsing, but anyway ... */ seeksegment.duration = demux->common.segment.duration; - flush = ! !(flags & GST_SEEK_FLAG_FLUSH); - keyunit = ! !(flags & GST_SEEK_FLAG_KEY_UNIT); - after = ! !(flags & GST_SEEK_FLAG_SNAP_AFTER); - before = ! !(flags & GST_SEEK_FLAG_SNAP_BEFORE); - accurate = ! !(flags & GST_SEEK_FLAG_ACCURATE); - /* always do full update if flushing, * otherwise problems might arise downstream with missing keyframes etc */ update = update || flush; @@ -3023,6 +3051,35 @@ gst_matroska_demux_handle_seek_push (GstMatroskaDemux * demux, GstPad * pad, gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur, &stop_type, &stop); + /* Directly send the instant-rate-change event here before taking the + * stream-lock so that it can be applied as soon as possible */ + if (flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE) { + guint32 seqnum; + GstEvent *ev; + + /* instant rate change only supported if direction does not change. All + * other requirements are already checked before creating the seek event + * but let's double-check here to be sure */ + if ((rate > 0 && demux->common.segment.rate < 0) || + (rate < 0 && demux->common.segment.rate > 0) || + cur_type != GST_SEEK_TYPE_NONE || + stop_type != GST_SEEK_TYPE_NONE || (flags & GST_SEEK_FLAG_FLUSH)) { + GST_ERROR_OBJECT (demux, + "Instant rate change seeks only supported in the " + "same direction, without flushing and position change"); + return FALSE; + } + + seqnum = gst_event_get_seqnum (event); + ev = gst_event_new_instant_rate_change (rate / demux->common.segment.rate, + (GstSegmentFlags) flags); + gst_event_set_seqnum (ev, seqnum); + gst_matroska_demux_send_event (demux, ev); + return TRUE; + } + + + /* sanity checks */ /* we can only seek on time */ -- 2.7.4