Bug 1545079 - Execute revive logic in operation thread. r=padenot

`IsStarted` may not be updated at the time `Revive()` method is executed since the update of the flag happens on the async operation. This will be the case if `Revive` is executed right after `Start`. When that happens the revive method asserts that the stream is started.

Differential Revision: https://phabricator.services.mozilla.com/D30889

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Alex Chronopoulos 2019-05-14 16:00:22 +00:00
Родитель 77b1b7585c
Коммит 75d6afdf3b
2 изменённых файлов: 22 добавлений и 23 удалений

Просмотреть файл

@ -442,9 +442,12 @@ AsyncCubebTask::Run() {
mDriver->CompleteAudioContextOperations(mOperation); mDriver->CompleteAudioContextOperations(mOperation);
break; break;
} }
case AsyncCubebOperation::START: { case AsyncCubebOperation::REVIVE: {
LOG(LogLevel::Debug, ("%p: AsyncCubebOperation::START driver=%p", LOG(LogLevel::Debug, ("%p: AsyncCubebOperation::REVIVE driver=%p",
mDriver->GraphImpl(), mDriver.get())); mDriver->GraphImpl(), mDriver.get()));
if (mDriver->IsStarted()) {
mDriver->Stop();
}
if (!mDriver->StartStream()) { if (!mDriver->StartStream()) {
LOG(LogLevel::Warning, LOG(LogLevel::Warning,
("%p: AsyncCubebOperation couldn't start the driver=%p.", ("%p: AsyncCubebOperation couldn't start the driver=%p.",
@ -452,12 +455,6 @@ AsyncCubebTask::Run() {
} }
break; break;
} }
case AsyncCubebOperation::STOP: {
LOG(LogLevel::Debug, ("%p: AsyncCubebOperation::STOP driver=%p",
mDriver->GraphImpl(), mDriver.get()));
mDriver->Stop();
break;
}
case AsyncCubebOperation::SHUTDOWN: { case AsyncCubebOperation::SHUTDOWN: {
LOG(LogLevel::Debug, ("%p: AsyncCubebOperation::SHUTDOWN driver=%p", LOG(LogLevel::Debug, ("%p: AsyncCubebOperation::SHUTDOWN driver=%p",
mDriver->GraphImpl(), mDriver.get())); mDriver->GraphImpl(), mDriver.get()));
@ -745,19 +742,9 @@ void AudioCallbackDriver::Revive() {
if (NextDriver()) { if (NextDriver()) {
SwitchToNextDriver(); SwitchToNextDriver();
} else { } else {
LOG(LogLevel::Debug, RefPtr<AsyncCubebTask> reviveEvent =
("Starting audio threads for MediaStreamGraph %p from a new thread.", new AsyncCubebTask(this, AsyncCubebOperation::REVIVE);
mGraphImpl.get())); reviveEvent->Dispatch();
if (IsStarted()) {
RefPtr<AsyncCubebTask> stopEvent =
new AsyncCubebTask(this, AsyncCubebOperation::STOP);
// This dispatches to a thread pool with a maximum of one thread thus it
// is guaranteed to be executed before the start event, right below.
stopEvent->Dispatch();
}
RefPtr<AsyncCubebTask> startEvent =
new AsyncCubebTask(this, AsyncCubebOperation::START);
startEvent->Dispatch();
} }
} }
@ -985,9 +972,20 @@ long AudioCallbackDriver::DataCallback(const AudioDataValue* aInputBuffer,
return aFrames; return aFrames;
} }
static const char* StateToString(cubeb_state aState) {
switch (aState) {
case CUBEB_STATE_STARTED: return "STARTED";
case CUBEB_STATE_STOPPED: return "STOPPED";
case CUBEB_STATE_DRAINED: return "DRAINED";
case CUBEB_STATE_ERROR: return "ERROR";
default:
MOZ_CRASH("Unexpected state!");
}
}
void AudioCallbackDriver::StateCallback(cubeb_state aState) { void AudioCallbackDriver::StateCallback(cubeb_state aState) {
MOZ_ASSERT(!OnGraphThread()); MOZ_ASSERT(!OnGraphThread());
LOG(LogLevel::Debug, ("AudioCallbackDriver State: %d", aState)); LOG(LogLevel::Debug, ("AudioCallbackDriver State: %s", StateToString(aState)));
// Clear the flag for the not running // Clear the flag for the not running
// states: stopped, drained, error. // states: stopped, drained, error.

Просмотреть файл

@ -12,6 +12,7 @@
#include "AudioSegment.h" #include "AudioSegment.h"
#include "SelfRef.h" #include "SelfRef.h"
#include "mozilla/Atomics.h" #include "mozilla/Atomics.h"
#include "mozilla/dom/AudioContext.h"
#include "mozilla/SharedThreadPool.h" #include "mozilla/SharedThreadPool.h"
#include "mozilla/StaticPtr.h" #include "mozilla/StaticPtr.h"
@ -322,7 +323,7 @@ struct StreamAndPromiseForOperation {
dom::AudioContextOperationFlags mFlags; dom::AudioContextOperationFlags mFlags;
}; };
enum class AsyncCubebOperation { INIT, START, STOP, SHUTDOWN }; enum class AsyncCubebOperation { INIT, REVIVE, SHUTDOWN };
enum class AudioInputType { Unknown, Voice }; enum class AudioInputType { Unknown, Voice };
/** /**