summaryrefslogtreecommitdiffstats
path: root/dom/media/AudioInputSource.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/media/AudioInputSource.cpp')
-rw-r--r--dom/media/AudioInputSource.cpp105
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,