Bug 1200614 - Protect the capture engines array from concurrent access (during shutdown). r=jesup

This commit is contained in:
Gian-Carlo Pascutto 2015-09-02 18:41:06 +02:00
parent deee8c45c6
commit 95f412e884
2 changed files with 73 additions and 51 deletions

View File

@ -324,21 +324,24 @@ CamerasParent::CloseEngines()
}
}
for (int i = 0; i < CaptureEngine::MaxEngine; i++) {
if (mEngines[i].mEngineIsRunning) {
LOG(("Being closed down while engine %d is running!", i));
}
if (mEngines[i].mPtrViERender) {
mEngines[i].mPtrViERender->Release();
mEngines[i].mPtrViERender = nullptr;
}
if (mEngines[i].mPtrViECapture) {
mEngines[i].mPtrViECapture->Release();
mEngines[i].mPtrViECapture = nullptr;
}
if(mEngines[i].mPtrViEBase) {
mEngines[i].mPtrViEBase->Release();
mEngines[i].mPtrViEBase = nullptr;
{
MutexAutoLock lock(mEngineMutex);
for (int i = 0; i < CaptureEngine::MaxEngine; i++) {
if (mEngines[i].mEngineIsRunning) {
LOG(("Being closed down while engine %d is running!", i));
}
if (mEngines[i].mPtrViERender) {
mEngines[i].mPtrViERender->Release();
mEngines[i].mPtrViERender = nullptr;
}
if (mEngines[i].mPtrViECapture) {
mEngines[i].mPtrViECapture->Release();
mEngines[i].mPtrViECapture = nullptr;
}
if(mEngines[i].mPtrViEBase) {
mEngines[i].mPtrViEBase->Release();
mEngines[i].mPtrViEBase = nullptr;
}
}
}
}
@ -373,6 +376,7 @@ CamerasParent::RecvNumberOfCaptureDevices(const int& aCapEngine)
nsRefPtr<CamerasParent> self(this);
nsRefPtr<nsRunnable> webrtc_runnable =
media::NewRunnableFrom([self, aCapEngine]() -> nsresult {
MutexAutoLock lock(self->mEngineMutex);
int num = self->mEngines[aCapEngine].mPtrViECapture->NumberOfCaptureDevices();
nsRefPtr<nsIRunnable> ipc_runnable =
media::NewRunnableFrom([self, num]() -> nsresult {
@ -412,6 +416,7 @@ CamerasParent::RecvNumberOfCapabilities(const int& aCapEngine,
nsRefPtr<CamerasParent> self(this);
nsRefPtr<nsRunnable> webrtc_runnable =
media::NewRunnableFrom([self, unique_id, aCapEngine]() -> nsresult {
MutexAutoLock lock(self->mEngineMutex);
int num =
self->mEngines[aCapEngine].mPtrViECapture->NumberOfCapabilities(
unique_id.get(),
@ -456,6 +461,7 @@ CamerasParent::RecvGetCaptureCapability(const int &aCapEngine,
nsRefPtr<nsRunnable> webrtc_runnable =
media::NewRunnableFrom([self, unique_id, aCapEngine, num]() -> nsresult {
webrtc::CaptureCapability webrtcCaps;
MutexAutoLock lock(self->mEngineMutex);
int error = self->mEngines[aCapEngine].mPtrViECapture->GetCaptureCapability(
unique_id.get(), MediaEngineSource::kMaxUniqueIdLength, num, webrtcCaps);
nsRefPtr<nsIRunnable> ipc_runnable =
@ -510,7 +516,7 @@ CamerasParent::RecvGetCaptureDevice(const int& aCapEngine,
char deviceUniqueId[MediaEngineSource::kMaxUniqueIdLength];
nsCString name;
nsCString uniqueId;
MutexAutoLock lock(self->mEngineMutex);
int error =
self->mEngines[aCapEngine].mPtrViECapture->GetCaptureDevice(aListNumber,
deviceName,
@ -559,6 +565,7 @@ CamerasParent::RecvAllocateCaptureDevice(const int& aCapEngine,
nsRefPtr<nsRunnable> webrtc_runnable =
media::NewRunnableFrom([self, aCapEngine, unique_id]() -> nsresult {
int numdev;
MutexAutoLock lock(self->mEngineMutex);
int error = self->mEngines[aCapEngine].mPtrViECapture->AllocateCaptureDevice(
unique_id.get(), MediaEngineSource::kMaxUniqueIdLength, numdev);
nsRefPtr<nsIRunnable> ipc_runnable =
@ -597,6 +604,7 @@ CamerasParent::RecvReleaseCaptureDevice(const int& aCapEngine,
nsRefPtr<nsRunnable> webrtc_runnable =
media::NewRunnableFrom([self, aCapEngine, numdev]() -> nsresult {
LOG(("RecvReleaseCamera device nr %d", numdev));
MutexAutoLock lock(self->mEngineMutex);
int error = self->mEngines[aCapEngine].mPtrViECapture->ReleaseCaptureDevice(numdev);
nsRefPtr<nsIRunnable> ipc_runnable =
media::NewRunnableFrom([self, error, numdev]() -> nsresult {
@ -639,35 +647,41 @@ CamerasParent::RecvStartCapture(const int& aCapEngine,
nsRefPtr<CamerasParent> self(this);
nsRefPtr<nsRunnable> webrtc_runnable =
media::NewRunnableFrom([self, aCapEngine, capnum, ipcCaps]() -> nsresult {
MutexAutoLock lock(self->mCallbackMutex);
auto cbh = self->mCallbacks.AppendElement(
new CallbackHelper(static_cast<CaptureEngine>(aCapEngine), capnum, self));
auto render = static_cast<webrtc::ExternalRenderer*>(*cbh);
EngineHelper* helper = &self->mEngines[aCapEngine];
int error =
helper->mPtrViERender->AddRenderer(capnum, webrtc::kVideoI420, render);
if (!error) {
error = helper->mPtrViERender->StartRender(capnum);
CallbackHelper** cbh;
webrtc::ExternalRenderer* render;
EngineHelper* helper;
int error;
{
MutexAutoLock lockCallback(self->mCallbackMutex);
cbh = self->mCallbacks.AppendElement(
new CallbackHelper(static_cast<CaptureEngine>(aCapEngine), capnum, self));
render = static_cast<webrtc::ExternalRenderer*>(*cbh);
}
{
MutexAutoLock lockEngine(self->mEngineMutex);
helper = &self->mEngines[aCapEngine];
error =
helper->mPtrViERender->AddRenderer(capnum, webrtc::kVideoI420, render);
webrtc::CaptureCapability capability;
capability.width = ipcCaps.width();
capability.height = ipcCaps.height();
capability.maxFPS = ipcCaps.maxFPS();
capability.expectedCaptureDelay = ipcCaps.expectedCaptureDelay();
capability.rawType = static_cast<webrtc::RawVideoType>(ipcCaps.rawType());
capability.codecType = static_cast<webrtc::VideoCodecType>(ipcCaps.codecType());
capability.interlaced = ipcCaps.interlaced();
if (!error) {
error = helper->mPtrViERender->StartRender(capnum);
}
if (!error) {
error = helper->mPtrViECapture->StartCapture(capnum, capability);
}
webrtc::CaptureCapability capability;
capability.width = ipcCaps.width();
capability.height = ipcCaps.height();
capability.maxFPS = ipcCaps.maxFPS();
capability.expectedCaptureDelay = ipcCaps.expectedCaptureDelay();
capability.rawType = static_cast<webrtc::RawVideoType>(ipcCaps.rawType());
capability.codecType = static_cast<webrtc::VideoCodecType>(ipcCaps.codecType());
capability.interlaced = ipcCaps.interlaced();
if (!error) {
helper->mEngineIsRunning = true;
if (!error) {
error = helper->mPtrViECapture->StartCapture(capnum, capability);
}
if (!error) {
helper->mEngineIsRunning = true;
}
}
nsRefPtr<nsIRunnable> ipc_runnable =
@ -704,11 +718,13 @@ CamerasParent::RecvStopCapture(const int& aCapEngine,
nsRefPtr<CamerasParent> self(this);
nsRefPtr<nsRunnable> webrtc_runnable =
media::NewRunnableFrom([self, aCapEngine, capnum]() -> nsresult {
self->mEngines[aCapEngine].mPtrViECapture->StopCapture(capnum);
self->mEngines[aCapEngine].mPtrViERender->StopRender(capnum);
self->mEngines[aCapEngine].mPtrViERender->RemoveRenderer(capnum);
self->mEngines[aCapEngine].mEngineIsRunning = false;
{
MutexAutoLock lock(self->mEngineMutex);
self->mEngines[aCapEngine].mPtrViECapture->StopCapture(capnum);
self->mEngines[aCapEngine].mPtrViERender->StopRender(capnum);
self->mEngines[aCapEngine].mPtrViERender->RemoveRenderer(capnum);
self->mEngines[aCapEngine].mEngineIsRunning = false;
}
MutexAutoLock lock(self->mCallbackMutex);
for (unsigned int i = 0; i < self->mCallbacks.Length(); i++) {
if (self->mCallbacks[i]->mCapEngine == aCapEngine
@ -739,11 +755,14 @@ void CamerasParent::DoShutdown()
LOG((__PRETTY_FUNCTION__));
CloseEngines();
for (int i = 0; i < CaptureEngine::MaxEngine; i++) {
if (mEngines[i].mEngine) {
mEngines[i].mEngine->SetTraceCallback(nullptr);
webrtc::VideoEngine::Delete(mEngines[i].mEngine);
mEngines[i].mEngine = nullptr;
{
MutexAutoLock lock(mEngineMutex);
for (int i = 0; i < CaptureEngine::MaxEngine; i++) {
if (mEngines[i].mEngine) {
mEngines[i].mEngine->SetTraceCallback(nullptr);
webrtc::VideoEngine::Delete(mEngines[i].mEngine);
mEngines[i].mEngine = nullptr;
}
}
}
@ -774,6 +793,7 @@ CamerasParent::ActorDestroy(ActorDestroyReason aWhy)
CamerasParent::CamerasParent()
: mCallbackMutex("CamerasParent.mCallbackMutex"),
mEngineMutex("CamerasParent.mEngineMutex"),
mShmemPool(CaptureEngine::MaxEngine),
mVideoCaptureThread(nullptr),
mChildIsAlive(true),

View File

@ -122,6 +122,8 @@ protected:
nsTArray<CallbackHelper*> mCallbacks;
// Protects the callback arrays
Mutex mCallbackMutex;
// Protects the engines array
Mutex mEngineMutex;
// image buffers
mozilla::ShmemPool mShmemPool;