diff options
Diffstat (limited to 'dom/media/AudioInputSource.cpp')
-rw-r--r-- | dom/media/AudioInputSource.cpp | 105 |
1 files changed, 87 insertions, 18 deletions
diff --git a/dom/media/AudioInputSource.cpp b/dom/media/AudioInputSource.cpp index 1ba2d81938..ef471530d6 100644 --- a/dom/media/AudioInputSource.cpp +++ b/dom/media/AudioInputSource.cpp @@ -55,46 +55,63 @@ AudioInputSource::AudioInputSource(RefPtr<EventListener>&& aListener, mSandboxed(CubebUtils::SandboxEnabled()), mAudioThreadId(ProfilerThreadId{}), mEventListener(std::move(aListener)), - mTaskThread(CUBEB_TASK_THREAD), + mTaskThread(CubebUtils::GetCubebOperationThread()), mDriftCorrector(static_cast<uint32_t>(aSourceRate), static_cast<uint32_t>(aTargetRate), aPrincipalHandle) { MOZ_ASSERT(mChannelCount > 0); MOZ_ASSERT(mEventListener); } -void AudioInputSource::Start() { +void AudioInputSource::Init() { // This is called on MediaTrackGraph's graph thread, which can be the cubeb // stream's callback thread. Running cubeb operations within cubeb stream // callback thread can cause the deadlock on Linux, so we dispatch those // operations to the task thread. MOZ_ASSERT(mTaskThread); - LOG("AudioInputSource %p, start", this); + LOG("AudioInputSource %p, init", this); MOZ_ALWAYS_SUCCEEDS(mTaskThread->Dispatch( - NS_NewRunnableFunction(__func__, [self = RefPtr(this)]() mutable { - self->mStream = CubebInputStream::Create( - self->mDeviceId, self->mChannelCount, - static_cast<uint32_t>(self->mRate), self->mIsVoice, self.get()); - if (!self->mStream) { + NS_NewRunnableFunction(__func__, [this, self = RefPtr(this)]() mutable { + mStream = CubebInputStream::Create(mDeviceId, mChannelCount, + static_cast<uint32_t>(mRate), + mIsVoice, this); + if (!mStream) { LOGE("AudioInputSource %p, cannot create an audio input stream!", self.get()); return; } + }))); +} - if (uint32_t latency = 0; - self->mStream->Latency(&latency) == CUBEB_OK) { - Data data(LatencyChangeData{media::TimeUnit(latency, self->mRate)}); - if (self->mSPSCQueue.Enqueue(data) == 0) { +void AudioInputSource::Start() { + // This is called on MediaTrackGraph's graph thread, which can be the cubeb + // stream's callback thread. Running cubeb operations within cubeb stream + // callback thread can cause the deadlock on Linux, so we dispatch those + // operations to the task thread. + MOZ_ASSERT(mTaskThread); + + LOG("AudioInputSource %p, start", this); + MOZ_ALWAYS_SUCCEEDS(mTaskThread->Dispatch( + NS_NewRunnableFunction(__func__, [this, self = RefPtr(this)]() mutable { + if (!mStream) { + LOGE("AudioInputSource %p, no audio input stream!", self.get()); + return; + } + + if (uint32_t latency = 0; mStream->Latency(&latency) == CUBEB_OK) { + Data data(LatencyChangeData{media::TimeUnit(latency, mRate)}); + if (mSPSCQueue.Enqueue(data) == 0) { LOGE("AudioInputSource %p, failed to enqueue latency change", self.get()); } } - if (int r = self->mStream->Start(); r != CUBEB_OK) { + if (int r = mStream->Start(); r != CUBEB_OK) { LOGE( "AudioInputSource %p, cannot start its audio input stream! The " "stream is destroyed directly!", self.get()); - self->mStream = nullptr; + mStream = nullptr; + mConfiguredProcessingParams = CUBEB_INPUT_PROCESSING_PARAM_NONE; } }))); } @@ -108,20 +125,72 @@ void AudioInputSource::Stop() { LOG("AudioInputSource %p, stop", this); MOZ_ALWAYS_SUCCEEDS(mTaskThread->Dispatch( - NS_NewRunnableFunction(__func__, [self = RefPtr(this)]() mutable { - if (!self->mStream) { + NS_NewRunnableFunction(__func__, [this, self = RefPtr(this)]() mutable { + if (!mStream) { LOGE("AudioInputSource %p, has no audio input stream to stop!", self.get()); return; } - if (int r = self->mStream->Stop(); r != CUBEB_OK) { + if (int r = mStream->Stop(); r != CUBEB_OK) { LOGE( "AudioInputSource %p, cannot stop its audio input stream! The " "stream is going to be destroyed forcefully", self.get()); } - self->mStream = nullptr; + mStream = nullptr; + mConfiguredProcessingParams = CUBEB_INPUT_PROCESSING_PARAM_NONE; + }))); +} + +auto AudioInputSource::SetRequestedProcessingParams( + cubeb_input_processing_params aParams) + -> RefPtr<SetRequestedProcessingParamsPromise> { + // This is called on MediaTrackGraph's graph thread, which can be the cubeb + // stream's callback thread. Running cubeb operations within cubeb stream + // callback thread can cause the deadlock on Linux, so we dispatch those + // operations to the task thread. + MOZ_ASSERT(mTaskThread); + + LOG("AudioInputSource %p, SetProcessingParams(%s)", this, + CubebUtils::ProcessingParamsToString(aParams).get()); + using ProcessingPromise = SetRequestedProcessingParamsPromise; + MozPromiseHolder<ProcessingPromise> holder; + RefPtr<ProcessingPromise> p = holder.Ensure(__func__); + MOZ_ALWAYS_SUCCEEDS(mTaskThread->Dispatch(NS_NewRunnableFunction( + __func__, [this, self = RefPtr(this), holder = std::move(holder), + aParams]() mutable { + if (!mStream) { + LOGE( + "AudioInputSource %p, has no audio input stream to set " + "processing params on!", + this); + holder.Reject(CUBEB_ERROR, + "AudioInputSource::SetProcessingParams no stream"); + return; + } + cubeb_input_processing_params supportedParams; + auto handle = CubebUtils::GetCubeb(); + int r = cubeb_get_supported_input_processing_params(handle->Context(), + &supportedParams); + if (r != CUBEB_OK) { + holder.Reject(CUBEB_ERROR_NOT_SUPPORTED, + "AudioInputSource::SetProcessingParams"); + return; + } + aParams &= supportedParams; + if (aParams == mConfiguredProcessingParams) { + holder.Resolve(aParams, "AudioInputSource::SetProcessingParams"); + return; + } + mConfiguredProcessingParams = aParams; + r = mStream->SetProcessingParams(aParams); + if (r == CUBEB_OK) { + holder.Resolve(aParams, "AudioInputSource::SetProcessingParams"); + return; + } + holder.Reject(r, "AudioInputSource::SetProcessingParams"); }))); + return p; } AudioSegment AudioInputSource::GetAudioSegment(TrackTime aDuration, |