Bug 1145405 - Add shutdown checks to main thread dispatches in ClearKey CDM - r=cpearce

This commit is contained in:
Edwin Flores 2015-03-23 07:59:42 +13:00
parent 66d02884ad
commit 38b1730747
4 changed files with 113 additions and 9 deletions

View File

@ -30,6 +30,7 @@ AudioDecoder::AudioDecoder(GMPAudioHost *aHostAPI)
, mWorkerThread(nullptr)
, mMutex(nullptr)
, mNumInputTasks(0)
, mHasShutdown(false)
{
}
@ -118,7 +119,7 @@ AudioDecoder::DecodeTask(GMPAudioSamples* aInput)
if (GMP_FAILED(rv)) {
CK_LOGE("Failed to decrypt with key id %08x...", *(uint32_t*)crypto->KeyId());
GetPlatform()->runonmainthread(WrapTask(mCallback, &GMPAudioDecoderCallback::Error, rv));
MaybeRunOnMainThread(WrapTask(mCallback, &GMPAudioDecoderCallback::Error, rv));
return;
}
}
@ -150,7 +151,7 @@ AudioDecoder::DecodeTask(GMPAudioSamples* aInput)
if (mNumInputTasks == 0) {
// We have run all input tasks. We *must* notify Gecko so that it will
// send us more data.
GetPlatform()->runonmainthread(WrapTask(mCallback, &GMPAudioDecoderCallback::InputDataExhausted));
MaybeRunOnMainThread(WrapTask(mCallback, &GMPAudioDecoderCallback::InputDataExhausted));
}
} else if (FAILED(hr)) {
LOG("AudioDecoder::DecodeTask() output failed hr=0x%x\n", hr);
@ -181,7 +182,7 @@ AudioDecoder::ReturnOutput(IMFSample* aSample)
}
ENSURE(SUCCEEDED(hr), /*void*/);
GetPlatform()->runonmainthread(WrapTask(mCallback, &GMPAudioDecoderCallback::Decoded, samples));
MaybeRunOnMainThread(WrapTask(mCallback, &GMPAudioDecoderCallback::Decoded, samples));
}
HRESULT
@ -241,7 +242,7 @@ AudioDecoder::DrainTask()
ReturnOutput(output);
}
}
GetPlatform()->runonmainthread(WrapTask(mCallback, &GMPAudioDecoderCallback::DrainComplete));
MaybeRunOnMainThread(WrapTask(mCallback, &GMPAudioDecoderCallback::DrainComplete));
}
void
@ -258,5 +259,48 @@ AudioDecoder::DecodingComplete()
if (mWorkerThread) {
mWorkerThread->Join();
}
mHasShutdown = true;
// Worker thread might have dispatched more tasks to the main thread that need this object.
// Append another task to delete |this|.
GetPlatform()->runonmainthread(WrapTask(this, &AudioDecoder::Destroy));
}
void
AudioDecoder::Destroy()
{
delete this;
}
void
AudioDecoder::MaybeRunOnMainThread(gmp_task_args_base* aTask)
{
class MaybeRunTask : public GMPTask
{
public:
MaybeRunTask(AudioDecoder* aDecoder, gmp_task_args_base* aTask)
: mDecoder(aDecoder), mTask(aTask)
{ }
virtual void Run(void) {
if (mDecoder->HasShutdown()) {
CK_LOGD("Trying to dispatch to main thread after AudioDecoder has shut down");
return;
}
mTask->Run();
}
virtual void Destroy()
{
mTask->Destroy();
delete this;
}
private:
AudioDecoder* mDecoder;
gmp_task_args_base* mTask;
};
GetPlatform()->runonmainthread(new MaybeRunTask(this, aTask));
}

View File

@ -19,6 +19,7 @@
#include "gmp-audio-decode.h"
#include "gmp-audio-host.h"
#include "gmp-task-utils.h"
#include "WMFAACDecoder.h"
#include "mfobjects.h"
@ -41,6 +42,8 @@ public:
virtual void DecodingComplete() override;
bool HasShutdown() { return mHasShutdown; }
private:
void EnsureWorker();
@ -53,6 +56,9 @@ private:
HRESULT MFToGMPSample(IMFSample* aSample,
GMPAudioSamples* aAudioFrame);
void MaybeRunOnMainThread(gmp_task_args_base* aTask);
void Destroy();
GMPAudioHost *mHostAPI; // host-owned, invalid at DecodingComplete
GMPAudioDecoderCallback* mCallback; // host-owned, invalid at DecodingComplete
GMPThread* mWorkerThread;
@ -60,6 +66,8 @@ private:
wmf::AutoPtr<wmf::WMFAACDecoder> mDecoder;
int32_t mNumInputTasks;
bool mHasShutdown;
};
#endif // __AudioDecoder_h__

View File

@ -34,6 +34,7 @@ VideoDecoder::VideoDecoder(GMPVideoHost *aHostAPI)
, mMutex(nullptr)
, mNumInputTasks(0)
, mSentExtraData(false)
, mHasShutdown(false)
{
}
@ -160,7 +161,7 @@ VideoDecoder::DecodeTask(GMPVideoEncodedFrame* aInput)
ClearKeyDecryptionManager::Get()->Decrypt(&buffer[0], buffer.size(), crypto);
if (GMP_FAILED(rv)) {
GetPlatform()->runonmainthread(WrapTask(mCallback, &GMPVideoDecoderCallback::Error, rv));
MaybeRunOnMainThread(WrapTask(mCallback, &GMPVideoDecoderCallback::Error, rv));
return;
}
}
@ -192,7 +193,7 @@ VideoDecoder::DecodeTask(GMPVideoEncodedFrame* aInput)
hr = mDecoder->Output(&output);
CK_LOGD("VideoDecoder::DecodeTask() output ret=0x%x\n", hr);
if (hr == S_OK) {
GetPlatform()->runonmainthread(
MaybeRunOnMainThread(
WrapTask(this,
&VideoDecoder::ReturnOutput,
CComPtr<IMFSample>(mozilla::Move(output)),
@ -206,7 +207,7 @@ VideoDecoder::DecodeTask(GMPVideoEncodedFrame* aInput)
if (mNumInputTasks == 0) {
// We have run all input tasks. We *must* notify Gecko so that it will
// send us more data.
GetPlatform()->runonmainthread(
MaybeRunOnMainThread(
WrapTask(mCallback,
&GMPVideoDecoderCallback::InputDataExhausted));
}
@ -347,7 +348,7 @@ VideoDecoder::DrainTask()
hr = mDecoder->Output(&output);
CK_LOGD("VideoDecoder::DrainTask() output ret=0x%x\n", hr);
if (hr == S_OK) {
GetPlatform()->runonmainthread(
MaybeRunOnMainThread(
WrapTask(this,
&VideoDecoder::ReturnOutput,
CComPtr<IMFSample>(mozilla::Move(output)),
@ -357,7 +358,7 @@ VideoDecoder::DrainTask()
assert(!output.Get());
}
}
GetPlatform()->runonmainthread(WrapTask(mCallback, &GMPVideoDecoderCallback::DrainComplete));
MaybeRunOnMainThread(WrapTask(mCallback, &GMPVideoDecoderCallback::DrainComplete));
}
void
@ -374,5 +375,48 @@ VideoDecoder::DecodingComplete()
if (mWorkerThread) {
mWorkerThread->Join();
}
mHasShutdown = true;
// Worker thread might have dispatched more tasks to the main thread that need this object.
// Append another task to delete |this|.
GetPlatform()->runonmainthread(WrapTask(this, &VideoDecoder::Destroy));
}
void
VideoDecoder::Destroy()
{
delete this;
}
void
VideoDecoder::MaybeRunOnMainThread(gmp_task_args_base* aTask)
{
class MaybeRunTask : public GMPTask
{
public:
MaybeRunTask(VideoDecoder* aDecoder, gmp_task_args_base* aTask)
: mDecoder(aDecoder), mTask(aTask)
{ }
virtual void Run(void) {
if (mDecoder->HasShutdown()) {
CK_LOGD("Trying to dispatch to main thread after VideoDecoder has shut down");
return;
}
mTask->Run();
}
virtual void Destroy()
{
mTask->Destroy();
delete this;
}
private:
VideoDecoder* mDecoder;
gmp_task_args_base* mTask;
};
GetPlatform()->runonmainthread(new MaybeRunTask(this, aTask));
}

View File

@ -17,6 +17,7 @@
#ifndef __VideoDecoder_h__
#define __VideoDecoder_h__
#include "gmp-task-utils.h"
#include "gmp-video-decode.h"
#include "gmp-video-host.h"
#include "WMFH264Decoder.h"
@ -48,6 +49,8 @@ public:
virtual void DecodingComplete() override;
bool HasShutdown() { return mHasShutdown; }
private:
void EnsureWorker();
@ -67,6 +70,9 @@ private:
int32_t aStride,
GMPVideoi420Frame* aVideoFrame);
void MaybeRunOnMainThread(gmp_task_args_base* aTask);
void Destroy();
GMPVideoHost *mHostAPI; // host-owned, invalid at DecodingComplete
GMPVideoDecoderCallback* mCallback; // host-owned, invalid at DecodingComplete
GMPThread* mWorkerThread;
@ -78,6 +84,8 @@ private:
int32_t mNumInputTasks;
bool mSentExtraData;
bool mHasShutdown;
};
#endif // __VideoDecoder_h__