adaptivedemux: Handle instant rate change requests directly
authorJan Schmidt <jan@centricular.com>
Wed, 18 Mar 2020 01:30:51 +0000 (12:30 +1100)
committerGStreamer Merge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Thu, 2 Apr 2020 11:26:46 +0000 (11:26 +0000)
Downstream demuxers will first send seek events upstream to us.
Do the right thing with instant rate change requests by handling them
immediately.

gst-libs/gst/adaptivedemux/gstadaptivedemux.c

index c9ca405..65d7157 100644 (file)
@@ -1560,13 +1560,6 @@ gst_adaptive_demux_handle_seek_event (GstAdaptiveDemux * demux, GstPad * pad,
   GST_API_LOCK (demux);
   GST_MANIFEST_LOCK (demux);
 
-  if (!gst_adaptive_demux_can_seek (demux)) {
-    GST_MANIFEST_UNLOCK (demux);
-    GST_API_UNLOCK (demux);
-    gst_event_unref (event);
-    return FALSE;
-  }
-
   gst_event_parse_seek (event, &rate, &format, &flags, &start_type, &start,
       &stop_type, &stop);
 
@@ -1589,6 +1582,48 @@ gst_adaptive_demux_handle_seek_event (GstAdaptiveDemux * demux, GstPad * pad,
 
   seqnum = gst_event_get_seqnum (event);
 
+  if (flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE) {
+    /* For instant rate seeks, reply directly and update
+     * our segment so the new rate is reflected in any future
+     * fragments */
+    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 ((demux->segment.rate > 0 && rate < 0) ||
+        (demux->segment.rate < 0 && rate > 0) ||
+        start_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");
+      GST_MANIFEST_UNLOCK (demux);
+      GST_API_UNLOCK (demux);
+      return FALSE;
+    }
+
+    ev = gst_event_new_instant_rate_change (rate / demux->segment.rate,
+        (GstSegmentFlags) flags);
+    gst_event_set_seqnum (ev, seqnum);
+
+    GST_MANIFEST_UNLOCK (demux);
+
+    ret = gst_adaptive_demux_push_src_event (demux, ev);
+
+    GST_API_UNLOCK (demux);
+    gst_event_unref (event);
+
+    return ret;
+  }
+
+  if (!gst_adaptive_demux_can_seek (demux)) {
+    GST_MANIFEST_UNLOCK (demux);
+    GST_API_UNLOCK (demux);
+    gst_event_unref (event);
+    return FALSE;
+  }
+
   if (gst_adaptive_demux_is_live (demux)) {
     gint64 range_start, range_stop;
     gboolean changed = FALSE;