зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1860954 replace AsyncCubebTask with NS_NewRunnableFunction() r=pehrsons
Differential Revision: https://phabricator.services.mozilla.com/D191919
This commit is contained in:
Родитель
c91ee34d5b
Коммит
726438b26a
|
@ -47,6 +47,8 @@ GraphDriver::GraphDriver(GraphInterface* aGraphInterface,
|
|||
void GraphDriver::SetStreamName(const nsACString& aStreamName) {
|
||||
MOZ_ASSERT(InIteration() || (!ThreadRunning() && NS_IsMainThread()));
|
||||
mStreamName = aStreamName;
|
||||
LOG(LogLevel::Debug, ("%p: GraphDriver::SetStreamName driver=%p %s", Graph(),
|
||||
this, mStreamName.get()));
|
||||
}
|
||||
|
||||
void GraphDriver::SetState(const nsACString& aStreamName,
|
||||
|
@ -123,10 +125,14 @@ class MediaTrackGraphInitThreadRunnable : public Runnable {
|
|||
("%p releasing an AudioCallbackDriver(%p), for graph %p",
|
||||
mDriver.get(), previousDriver, mDriver->Graph()));
|
||||
MOZ_ASSERT(!mDriver->AsAudioCallbackDriver());
|
||||
RefPtr<AsyncCubebTask> releaseEvent =
|
||||
new AsyncCubebTask(previousDriver->AsAudioCallbackDriver(),
|
||||
AsyncCubebOperation::SHUTDOWN);
|
||||
releaseEvent->Dispatch();
|
||||
AudioCallbackDriver* audioCallbackDriver =
|
||||
previousDriver->AsAudioCallbackDriver();
|
||||
audioCallbackDriver->mCubebOperationThread->Dispatch(
|
||||
NS_NewRunnableFunction(
|
||||
"ThreadedDriver previousDriver::Stop()",
|
||||
[audioCallbackDriver = RefPtr{audioCallbackDriver}] {
|
||||
audioCallbackDriver->Stop();
|
||||
}));
|
||||
mDriver->SetPreviousDriver(nullptr);
|
||||
}
|
||||
|
||||
|
@ -294,54 +300,6 @@ MediaTime OfflineClockDriver::GetIntervalForIteration() {
|
|||
return MillisecondsToMediaTime(mSlice);
|
||||
}
|
||||
|
||||
AsyncCubebTask::AsyncCubebTask(AudioCallbackDriver* aDriver,
|
||||
AsyncCubebOperation aOperation,
|
||||
const nsACString& aName)
|
||||
: Runnable("AsyncCubebTask"),
|
||||
mDriver(aDriver),
|
||||
mOperation(aOperation),
|
||||
mName(aName) {
|
||||
MOZ_ASSERT((aOperation == AsyncCubebOperation::SHUTDOWN) == aName.IsVoid());
|
||||
MOZ_ASSERT(aOperation != AsyncCubebOperation::INIT ||
|
||||
mDriver->mAudioStreamState ==
|
||||
AudioCallbackDriver::AudioStreamState::Pending,
|
||||
"Replacing active stream!");
|
||||
}
|
||||
|
||||
AsyncCubebTask::~AsyncCubebTask() = default;
|
||||
|
||||
NS_IMETHODIMP
|
||||
AsyncCubebTask::Run() {
|
||||
MOZ_ASSERT(mDriver);
|
||||
|
||||
switch (mOperation) {
|
||||
case AsyncCubebOperation::INIT: {
|
||||
LOG(LogLevel::Debug, ("%p: AsyncCubebOperation::INIT driver=%p",
|
||||
mDriver->Graph(), mDriver.get()));
|
||||
mDriver->Init(mName);
|
||||
break;
|
||||
}
|
||||
case AsyncCubebOperation::NAME_CHANGE: {
|
||||
LOG(LogLevel::Debug, ("%p: AsyncCubebOperation::NAME_CHANGE driver=%p",
|
||||
mDriver->Graph(), mDriver.get()));
|
||||
mDriver->SetCubebStreamName(mName);
|
||||
break;
|
||||
}
|
||||
case AsyncCubebOperation::SHUTDOWN: {
|
||||
LOG(LogLevel::Debug, ("%p: AsyncCubebOperation::SHUTDOWN driver=%p",
|
||||
mDriver->Graph(), mDriver.get()));
|
||||
mDriver->Stop();
|
||||
mDriver = nullptr;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
MOZ_CRASH("Operation not implemented.");
|
||||
}
|
||||
|
||||
// The thread will kill itself after a bit
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
TrackAndPromiseForOperation::TrackAndPromiseForOperation(
|
||||
MediaTrack* aTrack, dom::AudioContextOperation aOperation,
|
||||
AbstractThread* aMainThread,
|
||||
|
@ -500,7 +458,7 @@ AudioCallbackDriver::AudioCallbackDriver(
|
|||
mOutputDeviceID(aOutputDeviceID),
|
||||
mInputDeviceID(aInputDeviceID),
|
||||
mIterationDurationMS(MEDIA_GRAPH_TARGET_PERIOD_MS),
|
||||
mInitShutdownThread(CUBEB_TASK_THREAD),
|
||||
mCubebOperationThread(CUBEB_TASK_THREAD),
|
||||
mAudioThreadId(ProfilerThreadId{}),
|
||||
mAudioThreadIdInCb(std::thread::id()),
|
||||
mFallback("AudioCallbackDriver::mFallback"),
|
||||
|
@ -515,7 +473,7 @@ AudioCallbackDriver::AudioCallbackDriver(
|
|||
MOZ_ASSERT(mOutputChannelCount <= 8);
|
||||
|
||||
const uint32_t kIdleThreadTimeoutMs = 2000;
|
||||
mInitShutdownThread->SetIdleThreadTimeout(
|
||||
mCubebOperationThread->SetIdleThreadTimeout(
|
||||
PR_MillisecondsToInterval(kIdleThreadTimeoutMs));
|
||||
|
||||
if (aAudioInputType == AudioInputType::Voice) {
|
||||
|
@ -559,6 +517,8 @@ bool IsMacbookOrMacbookAir() {
|
|||
}
|
||||
|
||||
void AudioCallbackDriver::Init(const nsCString& aStreamName) {
|
||||
LOG(LogLevel::Debug,
|
||||
("%p: AudioCallbackDriver::Init driver=%p", Graph(), this));
|
||||
TRACE("AudioCallbackDriver::Init");
|
||||
MOZ_ASSERT(OnCubebOperationThread());
|
||||
MOZ_ASSERT(mAudioStreamState == AudioStreamState::Pending);
|
||||
|
@ -731,12 +691,14 @@ void AudioCallbackDriver::Start() {
|
|||
}
|
||||
|
||||
if (mPreviousDriver) {
|
||||
if (mPreviousDriver->AsAudioCallbackDriver()) {
|
||||
if (AudioCallbackDriver* previousAudioCallback =
|
||||
mPreviousDriver->AsAudioCallbackDriver()) {
|
||||
LOG(LogLevel::Debug, ("Releasing audio driver off main thread."));
|
||||
RefPtr<AsyncCubebTask> releaseEvent =
|
||||
new AsyncCubebTask(mPreviousDriver->AsAudioCallbackDriver(),
|
||||
AsyncCubebOperation::SHUTDOWN);
|
||||
releaseEvent->Dispatch();
|
||||
mCubebOperationThread->Dispatch(NS_NewRunnableFunction(
|
||||
"AudioCallbackDriver previousDriver::Stop()",
|
||||
[previousDriver = RefPtr{previousAudioCallback}] {
|
||||
previousDriver->Stop();
|
||||
}));
|
||||
} else {
|
||||
LOG(LogLevel::Debug,
|
||||
("Dropping driver reference for SystemClockDriver."));
|
||||
|
@ -747,9 +709,11 @@ void AudioCallbackDriver::Start() {
|
|||
|
||||
LOG(LogLevel::Debug, ("Starting new audio driver off main thread, "
|
||||
"to ensure it runs after previous shutdown."));
|
||||
RefPtr<AsyncCubebTask> initEvent = new AsyncCubebTask(
|
||||
AsAudioCallbackDriver(), AsyncCubebOperation::INIT, mStreamName);
|
||||
initEvent->Dispatch();
|
||||
mCubebOperationThread->Dispatch(
|
||||
NS_NewRunnableFunction("AudioCallbackDriver Init()",
|
||||
[self = RefPtr{this}, streamName = mStreamName] {
|
||||
self->Init(streamName);
|
||||
}));
|
||||
}
|
||||
|
||||
bool AudioCallbackDriver::StartStream() {
|
||||
|
@ -768,6 +732,8 @@ bool AudioCallbackDriver::StartStream() {
|
|||
}
|
||||
|
||||
void AudioCallbackDriver::Stop() {
|
||||
LOG(LogLevel::Debug,
|
||||
("%p: AudioCallbackDriver::Stop driver=%p", Graph(), this));
|
||||
TRACE("AudioCallbackDriver::Stop");
|
||||
MOZ_ASSERT(OnCubebOperationThread());
|
||||
cubeb_stream_register_device_changed_callback(mAudioStream, nullptr);
|
||||
|
@ -796,10 +762,11 @@ void AudioCallbackDriver::Shutdown() {
|
|||
("%p: Releasing audio driver off main thread (GraphDriver::Shutdown).",
|
||||
Graph()));
|
||||
|
||||
RefPtr<AsyncCubebTask> releaseEvent =
|
||||
new AsyncCubebTask(this, AsyncCubebOperation::SHUTDOWN);
|
||||
releaseEvent->DispatchAndSpinEventLoopUntilComplete(
|
||||
"AudioCallbackDriver::Shutdown"_ns);
|
||||
nsLiteralCString reason("AudioCallbackDriver::Shutdown");
|
||||
NS_DispatchAndSpinEventLoopUntilComplete(
|
||||
reason, mCubebOperationThread,
|
||||
NS_NewRunnableFunction(reason.get(),
|
||||
[self = RefPtr{this}] { self->Stop(); }));
|
||||
}
|
||||
|
||||
void AudioCallbackDriver::SetStreamName(const nsACString& aStreamName) {
|
||||
|
@ -821,9 +788,11 @@ void AudioCallbackDriver::SetStreamName(const nsACString& aStreamName) {
|
|||
AudioStreamState streamState = mAudioStreamState;
|
||||
if (streamState != AudioStreamState::None &&
|
||||
streamState != AudioStreamState::Stopping) {
|
||||
RefPtr<AsyncCubebTask> nameChange = new AsyncCubebTask(
|
||||
AsAudioCallbackDriver(), AsyncCubebOperation::NAME_CHANGE, mStreamName);
|
||||
nameChange->Dispatch();
|
||||
mCubebOperationThread->Dispatch(
|
||||
NS_NewRunnableFunction("AudioCallbackDriver SetStreamName()",
|
||||
[self = RefPtr{this}, streamName = mStreamName] {
|
||||
self->SetCubebStreamName(streamName);
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -538,7 +538,6 @@ struct TrackAndPromiseForOperation {
|
|||
MozPromiseHolder<MediaTrackGraph::AudioContextOperationPromise> mHolder;
|
||||
};
|
||||
|
||||
enum class AsyncCubebOperation { INIT, NAME_CHANGE, SHUTDOWN };
|
||||
enum class AudioInputType { Unknown, Voice };
|
||||
|
||||
/**
|
||||
|
@ -669,7 +668,7 @@ class AudioCallbackDriver : public GraphDriver, public MixerCallbackReceiver {
|
|||
void DeviceChangedCallback();
|
||||
/* Start the cubeb stream */
|
||||
bool StartStream();
|
||||
friend class AsyncCubebTask;
|
||||
friend class MediaTrackGraphInitThreadRunnable;
|
||||
void Init(const nsCString& aStreamName);
|
||||
void SetCubebStreamName(const nsCString& aStreamName);
|
||||
void Stop();
|
||||
|
@ -692,7 +691,7 @@ class AudioCallbackDriver : public GraphDriver, public MixerCallbackReceiver {
|
|||
|
||||
/* This is true when the method is executed on CubebOperation thread pool. */
|
||||
bool OnCubebOperationThread() {
|
||||
return mInitShutdownThread->IsOnCurrentThreadInfallible();
|
||||
return mCubebOperationThread->IsOnCurrentThreadInfallible();
|
||||
}
|
||||
|
||||
/* MediaTrackGraphs are always down/up mixed to output channels. */
|
||||
|
@ -730,8 +729,9 @@ class AudioCallbackDriver : public GraphDriver, public MixerCallbackReceiver {
|
|||
};
|
||||
|
||||
/* Shared thread pool with up to one thread for off-main-thread
|
||||
* initialization and shutdown of the audio stream via AsyncCubebTask. */
|
||||
const RefPtr<SharedThreadPool> mInitShutdownThread;
|
||||
* initialization and shutdown of the audio stream and for other tasks that
|
||||
* must run serially for access to mAudioStream. */
|
||||
const RefPtr<SharedThreadPool> mCubebOperationThread;
|
||||
cubeb_device_pref mInputDevicePreference;
|
||||
/* The mixer that the graph mixes into during an iteration. Audio thread only.
|
||||
*/
|
||||
|
@ -745,10 +745,10 @@ class AudioCallbackDriver : public GraphDriver, public MixerCallbackReceiver {
|
|||
/* State of the audio stream, see inline comments. */
|
||||
enum class AudioStreamState {
|
||||
/* There is no cubeb_stream or mAudioStream is in CUBEB_STATE_ERROR or
|
||||
* CUBEB_STATE_STOPPED and no pending AsyncCubebTask exists to INIT a new
|
||||
* CUBEB_STATE_STOPPED and no pending task exists to Init() a new
|
||||
* cubeb_stream. */
|
||||
None,
|
||||
/* An AsyncCubebTask to INIT a new cubeb_stream is pending. */
|
||||
/* A task to Init() a new cubeb_stream is pending. */
|
||||
Pending,
|
||||
/* cubeb_start_stream() is about to be or has been called on mAudioStream.
|
||||
* Any previous cubeb_streams have been destroyed. */
|
||||
|
@ -793,33 +793,6 @@ class AudioCallbackDriver : public GraphDriver, public MixerCallbackReceiver {
|
|||
const bool mSandboxed = false;
|
||||
};
|
||||
|
||||
class AsyncCubebTask : public Runnable {
|
||||
public:
|
||||
// aName is not required for AsyncCubebOperation::SHUTDOWN
|
||||
AsyncCubebTask(AudioCallbackDriver* aDriver, AsyncCubebOperation aOperation,
|
||||
const nsACString& aName = VoidCString());
|
||||
|
||||
nsresult Dispatch(uint32_t aFlags = NS_DISPATCH_NORMAL) {
|
||||
return mDriver->mInitShutdownThread->Dispatch(this, aFlags);
|
||||
}
|
||||
|
||||
nsresult DispatchAndSpinEventLoopUntilComplete(
|
||||
const nsACString& aVeryGoodReasonToDoThis) {
|
||||
return NS_DispatchAndSpinEventLoopUntilComplete(
|
||||
aVeryGoodReasonToDoThis, mDriver->mInitShutdownThread, do_AddRef(this));
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ~AsyncCubebTask();
|
||||
|
||||
private:
|
||||
NS_IMETHOD Run() final;
|
||||
|
||||
RefPtr<AudioCallbackDriver> mDriver;
|
||||
AsyncCubebOperation mOperation;
|
||||
nsCString mName;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // GRAPHDRIVER_H_
|
||||
|
|
Загрузка…
Ссылка в новой задаче