mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-13 03:24:26 +00:00
Bug 1046756 - Wait until AudioInitTask finished before proceeding to Shutdown(). r=kinetik
This commit is contained in:
parent
1b49fb456b
commit
ab70178851
@ -17,6 +17,7 @@
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "soundtouch/SoundTouch.h"
|
||||
#include "Latency.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#ifdef XP_MACOSX
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
@ -254,6 +255,7 @@ AudioStream::AudioStream()
|
||||
, mState(INITIALIZED)
|
||||
, mNeedsStart(false)
|
||||
, mShouldDropFrames(false)
|
||||
, mPendingAudioInitTask(false)
|
||||
{
|
||||
// keep a ref in case we shut down later than nsLayoutStatics
|
||||
mLatencyLog = AsyncLatencyLogger::Get(true);
|
||||
@ -535,19 +537,24 @@ AudioStream::Init(int32_t aNumChannels, int32_t aRate,
|
||||
// cause us to move from INITIALIZED to RUNNING. Until then, we
|
||||
// can't access any cubeb functions.
|
||||
// Use a RefPtr to avoid leaks if Dispatch fails
|
||||
mPendingAudioInitTask = true;
|
||||
RefPtr<AudioInitTask> init = new AudioInitTask(this, aLatencyRequest, params);
|
||||
init->Dispatch();
|
||||
return NS_OK;
|
||||
nsresult rv = init->Dispatch();
|
||||
if (NS_FAILED(rv)) {
|
||||
mPendingAudioInitTask = false;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
// High latency - open synchronously
|
||||
nsresult rv = OpenCubeb(params, aLatencyRequest);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// See if we need to start() the stream, since we must do that from this
|
||||
// thread for now (cubeb API issue)
|
||||
{
|
||||
MonitorAutoLock mon(mMonitor);
|
||||
CheckForStart();
|
||||
}
|
||||
return rv;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// On certain MacBookPro, the microphone is located near the left speaker.
|
||||
@ -627,15 +634,9 @@ nsresult
|
||||
AudioStream::OpenCubeb(cubeb_stream_params &aParams,
|
||||
LatencyRequest aLatencyRequest)
|
||||
{
|
||||
{
|
||||
MonitorAutoLock mon(mMonitor);
|
||||
if (mState == AudioStream::SHUTDOWN) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
cubeb* cubebContext = GetCubebContext();
|
||||
if (!cubebContext) {
|
||||
NS_WARNING("Can't get cubeb context!");
|
||||
MonitorAutoLock mon(mMonitor);
|
||||
mState = AudioStream::ERRORED;
|
||||
return NS_ERROR_FAILURE;
|
||||
@ -658,21 +659,15 @@ AudioStream::OpenCubeb(cubeb_stream_params &aParams,
|
||||
if (cubeb_stream_init(cubebContext, &stream, "AudioStream", aParams,
|
||||
latency, DataCallback_S, StateCallback_S, this) == CUBEB_OK) {
|
||||
MonitorAutoLock mon(mMonitor);
|
||||
MOZ_ASSERT(mState != SHUTDOWN);
|
||||
mCubebStream.own(stream);
|
||||
// Make sure we weren't shut down while in flight!
|
||||
if (mState == SHUTDOWN) {
|
||||
mCubebStream.reset();
|
||||
LOG(("AudioStream::OpenCubeb() %p Shutdown while opening cubeb", this));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// We can't cubeb_stream_start() the thread from a transient thread due to
|
||||
// cubeb API requirements (init can be called from another thread, but
|
||||
// not start/stop/destroy/etc)
|
||||
} else {
|
||||
MonitorAutoLock mon(mMonitor);
|
||||
mState = ERRORED;
|
||||
LOG(("AudioStream::OpenCubeb() %p failed to init cubeb", this));
|
||||
NS_WARNING(nsPrintfCString("AudioStream::OpenCubeb() %p failed to init cubeb", this).get());
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
@ -693,6 +688,14 @@ AudioStream::OpenCubeb(cubeb_stream_params &aParams,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
AudioStream::AudioInitTaskFinished()
|
||||
{
|
||||
MonitorAutoLock mon(mMonitor);
|
||||
mPendingAudioInitTask = false;
|
||||
mon.NotifyAll();
|
||||
}
|
||||
|
||||
void
|
||||
AudioStream::CheckForStart()
|
||||
{
|
||||
@ -731,6 +734,7 @@ AudioInitTask::Run()
|
||||
}
|
||||
|
||||
nsresult rv = mAudioStream->OpenCubeb(mParams, mLatencyRequest);
|
||||
mAudioStream->AudioInitTaskFinished();
|
||||
|
||||
// and now kill this thread
|
||||
NS_DispatchToMainThread(this);
|
||||
@ -951,6 +955,10 @@ AudioStream::Shutdown()
|
||||
MonitorAutoLock mon(mMonitor);
|
||||
LOG(("AudioStream: Shutdown %p, state %d", this, mState));
|
||||
|
||||
while (mPendingAudioInitTask) {
|
||||
mon.Wait();
|
||||
}
|
||||
|
||||
if (mCubebStream) {
|
||||
MonitorAutoUnlock mon(mMonitor);
|
||||
// Force stop to put the cubeb stream in a stable state before deletion.
|
||||
|
@ -299,6 +299,7 @@ private:
|
||||
// So we can call it asynchronously from AudioInitTask
|
||||
nsresult OpenCubeb(cubeb_stream_params &aParams,
|
||||
LatencyRequest aLatencyRequest);
|
||||
void AudioInitTaskFinished();
|
||||
|
||||
void CheckForStart();
|
||||
|
||||
@ -425,6 +426,9 @@ private:
|
||||
// is not going to be called for a little while, simply drop incoming frames.
|
||||
// This is only on OSX for now, because other systems handle this gracefully.
|
||||
bool mShouldDropFrames;
|
||||
// True if there is a pending AudioInitTask. Shutdown() will wait until the
|
||||
// pending AudioInitTask is finished.
|
||||
bool mPendingAudioInitTask;
|
||||
|
||||
// This mutex protects the static members below.
|
||||
static StaticMutex sMutex;
|
||||
|
Loading…
x
Reference in New Issue
Block a user