audiodecoder: Handle instant-rate-change event
authorJan Schmidt <jan@centricular.com>
Fri, 30 Nov 2018 12:10:55 +0000 (23:10 +1100)
committerSebastian Dröge <slomo@coaxion.net>
Wed, 1 Apr 2020 21:01:38 +0000 (21:01 +0000)
When receiving an instant-rate-change event, store the updated
seek flags and replace the flags in any input segments with them
to allow for instant switching between trickmodes and not.

gst-libs/gst/audio/gstaudiodecoder.c

index 33d086f..0288247 100644 (file)
@@ -214,6 +214,10 @@ struct _GstAudioDecoderPrivate
   gboolean force;
   /* input_segment are output_segment identical */
   gboolean in_out_segment_sync;
+  /* TRUE if we have an active set of instant rate flags */
+  gboolean decode_flags_override;
+  GstSegmentFlags decode_flags;
+
   /* expecting the buffer with DISCONT flag */
   gboolean expecting_discont_buf;
 
@@ -519,6 +523,7 @@ gst_audio_decoder_reset (GstAudioDecoder * dec, gboolean full)
       gst_object_unref (dec->priv->ctx.allocator);
 
     GST_OBJECT_LOCK (dec);
+    dec->priv->decode_flags_override = FALSE;
     gst_caps_replace (&dec->priv->ctx.input_caps, NULL);
     gst_caps_replace (&dec->priv->ctx.caps, NULL);
     gst_caps_replace (&dec->priv->ctx.allocation_caps, NULL);
@@ -2373,9 +2378,19 @@ gst_audio_decoder_sink_eventfunc (GstAudioDecoder * dec, GstEvent * event)
         dec->priv->samples = 0;
       }
 
+      /* Update the decode flags in the segment if we have an instant-rate
+       * override active */
+      GST_OBJECT_LOCK (dec);
+      if (dec->priv->decode_flags_override) {
+        seg.flags &= ~GST_SEGMENT_INSTANT_FLAGS;
+        seg.flags |= dec->priv->decode_flags & GST_SEGMENT_INSTANT_FLAGS;
+      }
+
       /* and follow along with segment */
       dec->priv->in_out_segment_sync = FALSE;
       dec->input_segment = seg;
+      GST_OBJECT_UNLOCK (dec);
+
       dec->priv->pending_events =
           g_list_append (dec->priv->pending_events, event);
       GST_AUDIO_DECODER_STREAM_UNLOCK (dec);
@@ -2383,6 +2398,27 @@ gst_audio_decoder_sink_eventfunc (GstAudioDecoder * dec, GstEvent * event)
       ret = TRUE;
       break;
     }
+    case GST_EVENT_INSTANT_RATE_CHANGE:
+    {
+      GstSegmentFlags flags;
+      GstSegment *seg;
+
+      gst_event_parse_instant_rate_change (event, NULL, &flags);
+
+      GST_OBJECT_LOCK (dec);
+      dec->priv->decode_flags_override = TRUE;
+      dec->priv->decode_flags = flags;
+
+      /* Update the input segment flags */
+      seg = &dec->input_segment;
+      seg->flags &= ~GST_SEGMENT_INSTANT_FLAGS;
+      seg->flags |= dec->priv->decode_flags & GST_SEGMENT_INSTANT_FLAGS;
+      GST_OBJECT_UNLOCK (dec);
+
+      /* Forward downstream */
+      ret = gst_pad_event_default (dec->sinkpad, GST_OBJECT_CAST (dec), event);
+      break;
+    }
     case GST_EVENT_GAP:
       ret = gst_audio_decoder_handle_gap (dec, event);
       break;