Bug 1277037 - Make AudioCallbackDriver::StartStream fallible. r?jesup
Avoid crashing in the case that cubeb stream start fails and report
an error instead.
MozReview-Commit-ID: 75M392POyHo
--- a/dom/media/GraphDriver.cpp
+++ b/dom/media/GraphDriver.cpp
@@ -510,17 +510,19 @@ AsyncCubebTask::EnsureThread()
NS_IMETHODIMP
AsyncCubebTask::Run()
{
MOZ_ASSERT(mDriver);
switch(mOperation) {
case AsyncCubebOperation::INIT: {
LIFECYCLE_LOG("AsyncCubebOperation::INIT driver=%p\n", mDriver.get());
- mDriver->Init();
+ if (!mDriver->Init()) {
+ return NS_ERROR_FAILURE;
+ }
mDriver->CompleteAudioContextOperations(mOperation);
break;
}
case AsyncCubebOperation::SHUTDOWN: {
LIFECYCLE_LOG("AsyncCubebOperation::SHUTDOWN driver=%p\n", mDriver.get());
mDriver->Stop();
mDriver->CompleteAudioContextOperations(mOperation);
@@ -589,26 +591,26 @@ bool IsMacbookOrMacbookAir()
}
}
return false;
}
#endif
return false;
}
-void
+bool
AudioCallbackDriver::Init()
{
cubeb* cubebContext = CubebUtils::GetCubebContext();
if (!cubebContext) {
NS_WARNING("Could not get cubeb context.");
if (!mFromFallback) {
CubebUtils::ReportCubebStreamInitFailure(true);
}
- return;
+ return false;
}
cubeb_stream_params output;
cubeb_stream_params input;
uint32_t latency_frames;
bool firstStream = CubebUtils::GetFirstStream();
MOZ_ASSERT(!NS_IsMainThread(),
@@ -619,17 +621,17 @@ AudioCallbackDriver::Init()
#if defined(__ANDROID__)
#if defined(MOZ_B2G)
output.stream_type = CubebUtils::ConvertChannelToCubebType(mAudioChannel);
#else
output.stream_type = CUBEB_STREAM_TYPE_MUSIC;
#endif
if (output.stream_type == CUBEB_STREAM_TYPE_MAX) {
NS_WARNING("Bad stream type");
- return;
+ return false;
}
#else
(void)mAudioChannel;
#endif
output.channels = mGraphImpl->AudioChannelCount();
if (AUDIO_OUTPUT_FORMAT == AUDIO_FORMAT_S16) {
output.format = CUBEB_SAMPLE_S16NE;
@@ -638,17 +640,17 @@ AudioCallbackDriver::Init()
}
Maybe<uint32_t> latencyPref = CubebUtils::GetCubebMSGLatencyInFrames();
if (latencyPref) {
latency_frames = latencyPref.value();
} else {
if (cubeb_get_min_latency(cubebContext, output, &latency_frames) != CUBEB_OK) {
NS_WARNING("Could not get minimal latency from cubeb.");
- return;
+ return false;
}
}
// Macbook and MacBook air don't have enough CPU to run very low latency
// MediaStreamGraphs, cap the minimal latency to 512 frames int this case.
if (IsMacbookOrMacbookAir()) {
latency_frames = std::max((uint32_t) 512, latency_frames);
}
@@ -707,29 +709,33 @@ AudioCallbackDriver::Init()
// Fall back to a driver using a normal thread.
MonitorAutoLock lock(GraphImpl()->GetMonitor());
SystemClockDriver* nextDriver = new SystemClockDriver(GraphImpl());
SetNextDriver(nextDriver);
nextDriver->MarkAsFallback();
nextDriver->SetGraphTime(this, mIterationStart, mIterationEnd);
mGraphImpl->SetCurrentDriver(nextDriver);
nextDriver->Start();
- return;
+ return true;
}
}
bool aec;
Unused << mGraphImpl->AudioTrackPresent(aec);
SetMicrophoneActive(aec);
cubeb_stream_register_device_changed_callback(mAudioStream,
AudioCallbackDriver::DeviceChangedCallback_s);
- StartStream();
+ if (!StartStream()) {
+ STREAM_LOG(LogLevel::Warning, ("AudioCallbackDriver couldn't start stream."));
+ return false;
+ }
STREAM_LOG(LogLevel::Debug, ("AudioCallbackDriver started."));
+ return true;
}
void
AudioCallbackDriver::Destroy()
{
STREAM_LOG(LogLevel::Debug, ("AudioCallbackDriver destroyed."));
mAudioInput = nullptr;
@@ -766,28 +772,30 @@ AudioCallbackDriver::Start()
LIFECYCLE_LOG("Starting new audio driver off main thread, "
"to ensure it runs after previous shutdown.");
RefPtr<AsyncCubebTask> initEvent =
new AsyncCubebTask(AsAudioCallbackDriver(), AsyncCubebOperation::INIT);
initEvent->Dispatch();
}
-void
+bool
AudioCallbackDriver::StartStream()
{
if (cubeb_stream_start(mAudioStream) != CUBEB_OK) {
- MOZ_CRASH("Could not start cubeb stream for MSG.");
+ NS_WARNING("Could not start cubeb stream for MSG.");
+ return false;
}
{
MonitorAutoLock mon(mGraphImpl->GetMonitor());
mStarted = true;
mWaitState = WAITSTATE_RUNNING;
}
+ return true;
}
void
AudioCallbackDriver::Stop()
{
if (cubeb_stream_stop(mAudioStream) != CUBEB_OK) {
NS_WARNING("Could not stop cubeb stream for MSG.");
}
--- a/dom/media/GraphDriver.h
+++ b/dom/media/GraphDriver.h
@@ -462,19 +462,19 @@ private:
* On certain MacBookPro, the microphone is located near the left speaker.
* We need to pan the sound output to the right speaker if we are using the
* mic and the built-in speaker, or we will have terrible echo. */
void PanOutputIfNeeded(bool aMicrophoneActive);
/**
* This is called when the output device used by the cubeb stream changes. */
void DeviceChangedCallback();
/* Start the cubeb stream */
- void StartStream();
+ bool StartStream();
friend class AsyncCubebTask;
- void Init();
+ bool Init();
/* MediaStreamGraphs are always down/up mixed to stereo for now. */
static const uint32_t ChannelCount = 2;
/* The size of this buffer comes from the fact that some audio backends can
* call back with a number of frames lower than one block (128 frames), so we
* need to keep at most two block in the SpillBuffer, because we always round
* up to block boundaries during an iteration.
* This is only ever accessed on the audio callback thread. */
SpillBuffer<AudioDataValue, WEBAUDIO_BLOCK_SIZE * 2, ChannelCount> mScratchBuffer;