Handling rate change in a live audio source element

Hi all,

I am trying to implement a source element relying on audiosrc (in GStreamer 1.26.9) and have some troubles handling rate changes with no related state change.

My source SDK advices any change of rate through a callback. The problem I’m facing is that on a rate transition, gst-launch-1.0 pipeline would hang for a certain time: displayed running time would freeze after the call to prepare(). Stream would eventually restart but I don’t quite get what goes wrong in the meantime. When analyzing the logs:

  • My read() function seems to be correctly called the whole time

  • I see audioringbuffer’s read() function display a diff value which decrements, audio seems to start playing when that value reaches 0.

I would expect running time to reset or continue gradually on rate change but it seems to wait for the previous running time to elapse and then start streaming (with the previous rate running time x2).

I test my pipeline with an identity element, PTS seems to increment consistently and duration correctly adjust to any rate.

I don’t know what my source is supposed to do or what are the steps that I’m missing: I’v tried flushing and sending a new segment in prepare() or reset() function but that wasn’t a success.

Noteworthy:

- at init(), I use a src pad template with an inclusive range of supported rates, not fixed. No caps change expected other than that at this stage.

GST_STATIC_PAD_TEMPLATE ("src",
      GST_PAD_SRC,
      GST_PAD_ALWAYS,
      GST_STATIC_CAPS (
          "audio/x-raw, "
          "layout = (string) interleaved, "
          "format = (string) S32LE, "
          "rate = (int) { 44100, 48000, 88200, 96000 }, "
          "channels = (int) [ 1, 128 ]"));

- when a new rate is detected, my source SDK will callback my reset() function, which will cache the new caps. There I call a pad_reconfigure to advice subclasses of the changes.

if (audio_sample_rate != 0 && rate_changed) {
    gst_pad_mark_reconfigure(self->srcpad);

}

- get_caps() and set_caps() returns template when source is not yet opened, cached caps otherwise.

- in prepare() function, I force AudioRingBufferSpec segize and segtotal. This is done to minimize latency (inspired by pulsesrc source code)

// Forcing AudioRingBufferSpec segment size to Source samples per period, in bytes (PCM 32bits)
spec->segsize = num_channels * 4 * samples_per_period;
// Segments number minimal value is 2
spec->segtotal = 2;

Of course, don’t hesitate if you need some more details.

Many thanks for your help!