Open Bug 1242332 Opened 9 years ago Updated 2 years ago

libcubeb's PulseAudio backend sometimes calls data_callback prematurely

Categories

(Core :: Audio/Video: cubeb, defect, P3)

defect

Tracking

()

Tracking Status
firefox46 --- affected

People

(Reporter: kinetik, Unassigned)

References

Details

jwwang added the following work-around for a cubeb_pulse bug:

641   // FIXME: cubeb_pulse sometimes calls us before cubeb_stream_start() is called.
642   // We don't want to consume audio data until Start() is called by the client.
643   if (mState == INITIALIZED) {
644     NS_WARNING("data callback fires before cubeb_stream_start() is called");
645     mAudioClock.UpdateFrameHistory(0, aFrames);
646     return writer.WriteZeros(aFrames);
647   }

in http://mxr.mozilla.org/mozilla-central/source/dom/media/AudioStream.cpp#641

We create streams with PA_STREAM_START_CORKED and wait for them to be ready by checking for PA_STREAM_READY and looping on pa_threaded_mainloop_wait.  The assumption I made when I wrote the code was that a corked stream wouldn't start requesting data until it was uncorked, which we do in via cubeb_stream_start.

Looking at pulseaudio/src/pulse/stream.c, the write_callback is generally driven off of pa_command_request being received, which also updates s->requested_bytes.

But it looks like s->requested_bytes can be updated in pa_create_stream_callback and the write_callback would then be called from create_stream_complete while we're still waiting for the stream to be set up.

I'm wondering what circumstances that happens in, and if it can happen with a PA_STREAM_START_CORKED stream at all.

Perhaps we should be creating the stream with pa_buffer_attr.prebuf = 0 and triggering the buffering manually?
Looking at the code, even in create_stream_complete(), we call pa_stream_set_state(READY) which causes the state callback to be called before we call the write callback. I've modified one of our test cases to assert if we see the write callback before ready and have it running in a loop. Will report if I see breakage.
Thanks.

Reading IRC scrollback in #media, I saw you also said:

00:00 < Ford_Prefect> But you will get data callbacks to buffer up tlength bytes of data so when
                      you uncork playback starts smoothly, and you will get more data requests to
                      fill up the buffer

which I think means my assumption about not receiving callbacks until uncork when creating a corked stream is wrong.

I suspect the callback timing from libcubeb is somewhat inconsistent between platforms anyway, since the WinMM backend will also call the data callback during stream creation to prefill buffers, so the warning jwwang added applies to multiple backends.

Obviously prefilling is valuable to ensure smooth playback, but libcubeb's current behaviour doesn't provide enough control to the caller, causing it to be called for data before it's ready.
At least on the PulesAudio side, the only way to avoid the data callback altogether is to not connect the stream until you're ready to feed data. Not sure if that makes more sense than what you have now in the libcubeb context.
Rank: 25
Priority: -- → P2
Depends on: 1286041
Mass change P2->P3 to align with new Mozilla triage process.
Priority: P2 → P3
Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.