mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1057908 - GeckoMediaPluginService needs to be proxied from Content processes to parent process. Part 2 - support asynchronous GMP API getters. r=jwwang,rjesup.
This commit is contained in:
parent
e98292c191
commit
ace406a462
@ -25,6 +25,7 @@ CDMProxy::CDMProxy(dom::MediaKeys* aKeys, const nsAString& aKeySystem)
|
|||||||
, mKeySystem(aKeySystem)
|
, mKeySystem(aKeySystem)
|
||||||
, mCDM(nullptr)
|
, mCDM(nullptr)
|
||||||
, mDecryptionJobCount(0)
|
, mDecryptionJobCount(0)
|
||||||
|
, mShutdownCalled(false)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
MOZ_COUNT_CTOR(CDMProxy);
|
MOZ_COUNT_CTOR(CDMProxy);
|
||||||
@ -70,7 +71,7 @@ CDMProxy::Init(PromiseId aPromiseId,
|
|||||||
nsCOMPtr<nsIRunnable> task(
|
nsCOMPtr<nsIRunnable> task(
|
||||||
NS_NewRunnableMethodWithArg<nsAutoPtr<InitData>>(this,
|
NS_NewRunnableMethodWithArg<nsAutoPtr<InitData>>(this,
|
||||||
&CDMProxy::gmp_Init,
|
&CDMProxy::gmp_Init,
|
||||||
data));
|
Move(data)));
|
||||||
mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
|
mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,14 +84,57 @@ CDMProxy::IsOnGMPThread()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
CDMProxy::gmp_Init(nsAutoPtr<InitData> aData)
|
CDMProxy::gmp_InitDone(GMPDecryptorProxy* aCDM, nsAutoPtr<InitData>&& aData)
|
||||||
|
{
|
||||||
|
EME_LOG("CDMProxy::gmp_InitDone");
|
||||||
|
if (!aCDM || mShutdownCalled) {
|
||||||
|
if (aCDM) {
|
||||||
|
aCDM->Close();
|
||||||
|
}
|
||||||
|
RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mCDM = aCDM;
|
||||||
|
mCallback = new CDMCallbackProxy(this);
|
||||||
|
mCDM->Init(mCallback);
|
||||||
|
nsCOMPtr<nsIRunnable> task(
|
||||||
|
NS_NewRunnableMethodWithArg<uint32_t>(this,
|
||||||
|
&CDMProxy::OnCDMCreated,
|
||||||
|
aData->mPromiseId));
|
||||||
|
NS_DispatchToMainThread(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
class gmp_InitDoneCallback : public GetGMPDecryptorCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
gmp_InitDoneCallback(CDMProxy* aCDMProxy,
|
||||||
|
nsAutoPtr<CDMProxy::InitData>&& aData)
|
||||||
|
: mCDMProxy(aCDMProxy),
|
||||||
|
mData(Move(aData))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Done(GMPDecryptorProxy* aCDM)
|
||||||
|
{
|
||||||
|
mCDMProxy->gmp_InitDone(aCDM, Move(mData));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
nsRefPtr<CDMProxy> mCDMProxy;
|
||||||
|
nsAutoPtr<CDMProxy::InitData> mData;
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
CDMProxy::gmp_Init(nsAutoPtr<InitData>&& aData)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(IsOnGMPThread());
|
MOZ_ASSERT(IsOnGMPThread());
|
||||||
|
|
||||||
|
uint32_t promiseID = aData->mPromiseId;
|
||||||
nsCOMPtr<mozIGeckoMediaPluginService> mps =
|
nsCOMPtr<mozIGeckoMediaPluginService> mps =
|
||||||
do_GetService("@mozilla.org/gecko-media-plugin-service;1");
|
do_GetService("@mozilla.org/gecko-media-plugin-service;1");
|
||||||
if (!mps) {
|
if (!mps) {
|
||||||
RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR);
|
RejectPromise(promiseID, NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,7 +144,7 @@ CDMProxy::gmp_Init(nsAutoPtr<InitData> aData)
|
|||||||
mNodeId);
|
mNodeId);
|
||||||
MOZ_ASSERT(!GetNodeId().IsEmpty());
|
MOZ_ASSERT(!GetNodeId().IsEmpty());
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR);
|
RejectPromise(promiseID, NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,17 +156,12 @@ CDMProxy::gmp_Init(nsAutoPtr<InitData> aData)
|
|||||||
|
|
||||||
nsTArray<nsCString> tags;
|
nsTArray<nsCString> tags;
|
||||||
tags.AppendElement(NS_ConvertUTF16toUTF8(mKeySystem));
|
tags.AppendElement(NS_ConvertUTF16toUTF8(mKeySystem));
|
||||||
rv = mps->GetGMPDecryptor(&tags, GetNodeId(), &mCDM);
|
|
||||||
if (NS_FAILED(rv) || !mCDM) {
|
UniquePtr<GetGMPDecryptorCallback> callback(new gmp_InitDoneCallback(this,
|
||||||
RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR);
|
Move(aData)));
|
||||||
} else {
|
rv = mps->GetGMPDecryptor(&tags, GetNodeId(), Move(callback));
|
||||||
mCallback = new CDMCallbackProxy(this);
|
if (NS_FAILED(rv)) {
|
||||||
mCDM->Init(mCallback);
|
RejectPromise(promiseID, NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||||
nsCOMPtr<nsIRunnable> task(
|
|
||||||
NS_NewRunnableMethodWithArg<uint32_t>(this,
|
|
||||||
&CDMProxy::OnCDMCreated,
|
|
||||||
aData->mPromiseId));
|
|
||||||
NS_DispatchToMainThread(task);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -341,6 +380,8 @@ CDMProxy::gmp_Shutdown()
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(IsOnGMPThread());
|
MOZ_ASSERT(IsOnGMPThread());
|
||||||
|
|
||||||
|
mShutdownCalled = true;
|
||||||
|
|
||||||
// Abort any pending decrypt jobs, to awaken any clients waiting on a job.
|
// Abort any pending decrypt jobs, to awaken any clients waiting on a job.
|
||||||
for (size_t i = 0; i < mDecryptionJobs.Length(); i++) {
|
for (size_t i = 0; i < mDecryptionJobs.Length(); i++) {
|
||||||
DecryptJob* job = mDecryptionJobs[i];
|
DecryptJob* job = mDecryptionJobs[i];
|
||||||
|
@ -174,6 +174,7 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
friend class gmp_InitDoneCallback;
|
||||||
|
|
||||||
struct InitData {
|
struct InitData {
|
||||||
uint32_t mPromiseId;
|
uint32_t mPromiseId;
|
||||||
@ -183,7 +184,8 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
// GMP thread only.
|
// GMP thread only.
|
||||||
void gmp_Init(nsAutoPtr<InitData> aData);
|
void gmp_Init(nsAutoPtr<InitData>&& aData);
|
||||||
|
void gmp_InitDone(GMPDecryptorProxy* aCDM, nsAutoPtr<InitData>&& aData);
|
||||||
|
|
||||||
// GMP thread only.
|
// GMP thread only.
|
||||||
void gmp_Shutdown();
|
void gmp_Shutdown();
|
||||||
@ -320,6 +322,10 @@ private:
|
|||||||
// from it.
|
// from it.
|
||||||
// GMP thread only.
|
// GMP thread only.
|
||||||
uint32_t mDecryptionJobCount;
|
uint32_t mDecryptionJobCount;
|
||||||
|
|
||||||
|
// True if CDMProxy::gmp_Shutdown was called.
|
||||||
|
// GMP thread only.
|
||||||
|
bool mShutdownCalled;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -133,6 +133,39 @@ GMPAudioDecoder::GetNodeId()
|
|||||||
return NS_LITERAL_CSTRING("");
|
return NS_LITERAL_CSTRING("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GMPAudioDecoder::GetGMPAPI(GMPInitDoneRunnable* aInitDone)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(IsOnGMPThread());
|
||||||
|
|
||||||
|
nsTArray<nsCString> tags;
|
||||||
|
InitTags(tags);
|
||||||
|
UniquePtr<GetGMPAudioDecoderCallback> callback(
|
||||||
|
new GMPInitDoneCallback(this, aInitDone));
|
||||||
|
if (NS_FAILED(mMPS->GetGMPAudioDecoder(&tags, GetNodeId(), Move(callback)))) {
|
||||||
|
aInitDone->Dispatch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GMPAudioDecoder::GMPInitDone(GMPAudioDecoderProxy* aGMP)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aGMP);
|
||||||
|
nsTArray<uint8_t> codecSpecific;
|
||||||
|
codecSpecific.AppendElements(mConfig.audio_specific_config->Elements(),
|
||||||
|
mConfig.audio_specific_config->Length());
|
||||||
|
|
||||||
|
nsresult rv = aGMP->InitDecode(kGMPAudioCodecAAC,
|
||||||
|
mConfig.channel_count,
|
||||||
|
mConfig.bits_per_sample,
|
||||||
|
mConfig.samples_per_second,
|
||||||
|
codecSpecific,
|
||||||
|
mAdapter);
|
||||||
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
mGMP = aGMP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
GMPAudioDecoder::Init()
|
GMPAudioDecoder::Init()
|
||||||
{
|
{
|
||||||
@ -141,25 +174,20 @@ GMPAudioDecoder::Init()
|
|||||||
mMPS = do_GetService("@mozilla.org/gecko-media-plugin-service;1");
|
mMPS = do_GetService("@mozilla.org/gecko-media-plugin-service;1");
|
||||||
MOZ_ASSERT(mMPS);
|
MOZ_ASSERT(mMPS);
|
||||||
|
|
||||||
nsTArray<nsCString> tags;
|
nsCOMPtr<nsIThread> gmpThread = NS_GetCurrentThread();
|
||||||
InitTags(tags);
|
|
||||||
nsresult rv = mMPS->GetGMPAudioDecoder(&tags, GetNodeId(), &mGMP);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
MOZ_ASSERT(mGMP);
|
|
||||||
|
|
||||||
nsTArray<uint8_t> codecSpecific;
|
nsRefPtr<GMPInitDoneRunnable> initDone(new GMPInitDoneRunnable());
|
||||||
codecSpecific.AppendElements(mConfig.audio_specific_config->Elements(),
|
gmpThread->Dispatch(
|
||||||
mConfig.audio_specific_config->Length());
|
NS_NewRunnableMethodWithArg<GMPInitDoneRunnable*>(this,
|
||||||
|
&GMPAudioDecoder::GetGMPAPI,
|
||||||
|
initDone),
|
||||||
|
NS_DISPATCH_NORMAL);
|
||||||
|
|
||||||
rv = mGMP->InitDecode(kGMPAudioCodecAAC,
|
while (!initDone->IsDone()) {
|
||||||
mConfig.channel_count,
|
NS_ProcessNextEvent(gmpThread, true);
|
||||||
mConfig.bits_per_sample,
|
}
|
||||||
mConfig.samples_per_second,
|
|
||||||
codecSpecific,
|
|
||||||
mAdapter);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
return NS_OK;
|
return mGMP ? NS_OK : NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
|
@ -80,6 +80,61 @@ protected:
|
|||||||
virtual nsCString GetNodeId();
|
virtual nsCString GetNodeId();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
class GMPInitDoneRunnable : public nsRunnable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GMPInitDoneRunnable()
|
||||||
|
: mInitDone(false),
|
||||||
|
mThread(do_GetCurrentThread())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHOD Run()
|
||||||
|
{
|
||||||
|
mInitDone = true;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Dispatch()
|
||||||
|
{
|
||||||
|
mThread->Dispatch(this, NS_DISPATCH_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsDone()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(nsCOMPtr<nsIThread>(do_GetCurrentThread()) == mThread);
|
||||||
|
return mInitDone;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool mInitDone;
|
||||||
|
nsCOMPtr<nsIThread> mThread;
|
||||||
|
};
|
||||||
|
void GetGMPAPI(GMPInitDoneRunnable* aInitDone);
|
||||||
|
class GMPInitDoneCallback : public GetGMPAudioDecoderCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GMPInitDoneCallback(GMPAudioDecoder* aDecoder,
|
||||||
|
GMPInitDoneRunnable* aGMPInitDone)
|
||||||
|
: mDecoder(aDecoder)
|
||||||
|
, mGMPInitDone(aGMPInitDone)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void Done(GMPAudioDecoderProxy* aGMP)
|
||||||
|
{
|
||||||
|
if (aGMP) {
|
||||||
|
mDecoder->GMPInitDone(aGMP);
|
||||||
|
}
|
||||||
|
mGMPInitDone->Dispatch();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
nsRefPtr<GMPAudioDecoder> mDecoder;
|
||||||
|
nsRefPtr<GMPInitDoneRunnable> mGMPInitDone;
|
||||||
|
};
|
||||||
|
void GMPInitDone(GMPAudioDecoderProxy* aGMP);
|
||||||
|
|
||||||
const mp4_demuxer::AudioDecoderConfig& mConfig;
|
const mp4_demuxer::AudioDecoderConfig& mConfig;
|
||||||
MediaDataDecoderCallbackProxy* mCallback;
|
MediaDataDecoderCallbackProxy* mCallback;
|
||||||
nsCOMPtr<mozIGeckoMediaPluginService> mMPS;
|
nsCOMPtr<mozIGeckoMediaPluginService> mMPS;
|
||||||
|
@ -157,29 +157,24 @@ GMPVideoDecoder::CreateFrame(mp4_demuxer::MP4Sample* aSample)
|
|||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
void
|
||||||
GMPVideoDecoder::Init()
|
GMPVideoDecoder::GetGMPAPI(GMPInitDoneRunnable* aInitDone)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(IsOnGMPThread());
|
MOZ_ASSERT(IsOnGMPThread());
|
||||||
|
|
||||||
mMPS = do_GetService("@mozilla.org/gecko-media-plugin-service;1");
|
|
||||||
MOZ_ASSERT(mMPS);
|
|
||||||
|
|
||||||
nsTArray<nsCString> tags;
|
nsTArray<nsCString> tags;
|
||||||
InitTags(tags);
|
InitTags(tags);
|
||||||
nsresult rv = mMPS->GetGMPVideoDecoder(&tags, GetNodeId(), &mHost, &mGMP);
|
UniquePtr<GetGMPVideoDecoderCallback> callback(
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
new GMPInitDoneCallback(this, aInitDone));
|
||||||
MOZ_ASSERT(mHost && mGMP);
|
if (NS_FAILED(mMPS->GetGMPVideoDecoder(&tags, GetNodeId(), Move(callback)))) {
|
||||||
|
aInitDone->Dispatch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// GMP implementations have interpreted the meaning of GMP_BufferLength32
|
void
|
||||||
// differently. The OpenH264 GMP expects GMP_BufferLength32 to behave as
|
GMPVideoDecoder::GMPInitDone(GMPVideoDecoderProxy* aGMP, GMPVideoHost* aHost)
|
||||||
// specified in the GMP API, where each buffer is prefixed by a 32-bit
|
{
|
||||||
// host-endian buffer length that includes the size of the buffer length
|
MOZ_ASSERT(aHost && aGMP);
|
||||||
// field. Other existing GMPs currently expect GMP_BufferLength32 (when
|
|
||||||
// combined with kGMPVideoCodecH264) to mean "like AVCC but restricted to
|
|
||||||
// 4-byte NAL lengths" (i.e. buffer lengths are specified in big-endian
|
|
||||||
// and do not include the length of the buffer length field.
|
|
||||||
mConvertNALUnitLengths = mGMP->GetDisplayName().EqualsLiteral("gmpopenh264");
|
|
||||||
|
|
||||||
GMPVideoCodec codec;
|
GMPVideoCodec codec;
|
||||||
memset(&codec, 0, sizeof(codec));
|
memset(&codec, 0, sizeof(codec));
|
||||||
@ -195,13 +190,48 @@ GMPVideoDecoder::Init()
|
|||||||
codecSpecific.AppendElements(mConfig.extra_data->Elements(),
|
codecSpecific.AppendElements(mConfig.extra_data->Elements(),
|
||||||
mConfig.extra_data->Length());
|
mConfig.extra_data->Length());
|
||||||
|
|
||||||
rv = mGMP->InitDecode(codec,
|
nsresult rv = aGMP->InitDecode(codec,
|
||||||
codecSpecific,
|
codecSpecific,
|
||||||
mAdapter,
|
mAdapter,
|
||||||
PR_GetNumberOfProcessors());
|
PR_GetNumberOfProcessors());
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
mGMP = aGMP;
|
||||||
|
mHost = aHost;
|
||||||
|
|
||||||
return NS_OK;
|
// GMP implementations have interpreted the meaning of GMP_BufferLength32
|
||||||
|
// differently. The OpenH264 GMP expects GMP_BufferLength32 to behave as
|
||||||
|
// specified in the GMP API, where each buffer is prefixed by a 32-bit
|
||||||
|
// host-endian buffer length that includes the size of the buffer length
|
||||||
|
// field. Other existing GMPs currently expect GMP_BufferLength32 (when
|
||||||
|
// combined with kGMPVideoCodecH264) to mean "like AVCC but restricted to
|
||||||
|
// 4-byte NAL lengths" (i.e. buffer lengths are specified in big-endian
|
||||||
|
// and do not include the length of the buffer length field.
|
||||||
|
mConvertNALUnitLengths = mGMP->GetDisplayName().EqualsLiteral("gmpopenh264");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
GMPVideoDecoder::Init()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(IsOnGMPThread());
|
||||||
|
|
||||||
|
mMPS = do_GetService("@mozilla.org/gecko-media-plugin-service;1");
|
||||||
|
MOZ_ASSERT(mMPS);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIThread> gmpThread = NS_GetCurrentThread();
|
||||||
|
|
||||||
|
nsRefPtr<GMPInitDoneRunnable> initDone(new GMPInitDoneRunnable());
|
||||||
|
gmpThread->Dispatch(
|
||||||
|
NS_NewRunnableMethodWithArg<GMPInitDoneRunnable*>(this,
|
||||||
|
&GMPVideoDecoder::GetGMPAPI,
|
||||||
|
initDone),
|
||||||
|
NS_DISPATCH_NORMAL);
|
||||||
|
|
||||||
|
while (!initDone->IsDone()) {
|
||||||
|
NS_ProcessNextEvent(gmpThread, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mGMP ? NS_OK : NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
|
@ -96,6 +96,61 @@ protected:
|
|||||||
virtual GMPUnique<GMPVideoEncodedFrame>::Ptr CreateFrame(mp4_demuxer::MP4Sample* aSample);
|
virtual GMPUnique<GMPVideoEncodedFrame>::Ptr CreateFrame(mp4_demuxer::MP4Sample* aSample);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
class GMPInitDoneRunnable : public nsRunnable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GMPInitDoneRunnable()
|
||||||
|
: mInitDone(false),
|
||||||
|
mThread(do_GetCurrentThread())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHOD Run()
|
||||||
|
{
|
||||||
|
mInitDone = true;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Dispatch()
|
||||||
|
{
|
||||||
|
mThread->Dispatch(this, NS_DISPATCH_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsDone()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(nsCOMPtr<nsIThread>(do_GetCurrentThread()) == mThread);
|
||||||
|
return mInitDone;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool mInitDone;
|
||||||
|
nsCOMPtr<nsIThread> mThread;
|
||||||
|
};
|
||||||
|
void GetGMPAPI(GMPInitDoneRunnable* aInitDone);
|
||||||
|
class GMPInitDoneCallback : public GetGMPVideoDecoderCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GMPInitDoneCallback(GMPVideoDecoder* aDecoder,
|
||||||
|
GMPInitDoneRunnable* aGMPInitDone)
|
||||||
|
: mDecoder(aDecoder)
|
||||||
|
, mGMPInitDone(aGMPInitDone)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void Done(GMPVideoDecoderProxy* aGMP, GMPVideoHost* aHost)
|
||||||
|
{
|
||||||
|
if (aGMP) {
|
||||||
|
mDecoder->GMPInitDone(aGMP, aHost);
|
||||||
|
}
|
||||||
|
mGMPInitDone->Dispatch();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
nsRefPtr<GMPVideoDecoder> mDecoder;
|
||||||
|
nsRefPtr<GMPInitDoneRunnable> mGMPInitDone;
|
||||||
|
};
|
||||||
|
void GMPInitDone(GMPVideoDecoderProxy* aGMP, GMPVideoHost* aHost);
|
||||||
|
|
||||||
const mp4_demuxer::VideoDecoderConfig& mConfig;
|
const mp4_demuxer::VideoDecoderConfig& mConfig;
|
||||||
MediaDataDecoderCallbackProxy* mCallback;
|
MediaDataDecoderCallbackProxy* mCallback;
|
||||||
nsCOMPtr<mozIGeckoMediaPluginService> mMPS;
|
nsCOMPtr<mozIGeckoMediaPluginService> mMPS;
|
||||||
|
@ -281,14 +281,33 @@ GeckoMediaPluginService::GetThread(nsIThread** aThread)
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class GetGMPParentForAudioDecoderDone
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit GetGMPParentForAudioDecoderDone(UniquePtr<GetGMPAudioDecoderCallback>&& aCallback)
|
||||||
|
: mCallback(Move(aCallback))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Done(GMPParent* aGMPParent)
|
||||||
|
{
|
||||||
|
GMPAudioDecoderParent* gmpADP = nullptr;
|
||||||
|
aGMPParent->GetGMPAudioDecoder(&gmpADP);
|
||||||
|
mCallback->Done(gmpADP);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
UniquePtr<GetGMPAudioDecoderCallback> mCallback;
|
||||||
|
};
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
GeckoMediaPluginService::GetGMPAudioDecoder(nsTArray<nsCString>* aTags,
|
GeckoMediaPluginService::GetGMPAudioDecoder(nsTArray<nsCString>* aTags,
|
||||||
const nsACString& aNodeId,
|
const nsACString& aNodeId,
|
||||||
GMPAudioDecoderProxy** aGMPAD)
|
UniquePtr<GetGMPAudioDecoderCallback>&& aCallback)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
|
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
|
||||||
NS_ENSURE_ARG(aTags && aTags->Length() > 0);
|
NS_ENSURE_ARG(aTags && aTags->Length() > 0);
|
||||||
NS_ENSURE_ARG(aGMPAD);
|
NS_ENSURE_ARG(aCallback);
|
||||||
|
|
||||||
if (mShuttingDownOnGMPThread) {
|
if (mShuttingDownOnGMPThread) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
@ -301,27 +320,42 @@ GeckoMediaPluginService::GetGMPAudioDecoder(nsTArray<nsCString>* aTags,
|
|||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
GMPAudioDecoderParent* gmpADP;
|
GetGMPParentForAudioDecoderDone(Move(aCallback)).Done(gmp);
|
||||||
nsresult rv = gmp->GetGMPAudioDecoder(&gmpADP);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
*aGMPAD = gmpADP;
|
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class GetGMPParentForVideoDecoderDone
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit GetGMPParentForVideoDecoderDone(UniquePtr<GetGMPVideoDecoderCallback>&& aCallback)
|
||||||
|
: mCallback(Move(aCallback))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Done(GMPParent* aGMPParent)
|
||||||
|
{
|
||||||
|
GMPVideoDecoderParent* gmpVDP = nullptr;
|
||||||
|
GMPVideoHostImpl* videoHost = nullptr;
|
||||||
|
nsresult rv = aGMPParent->GetGMPVideoDecoder(&gmpVDP);
|
||||||
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
videoHost = &gmpVDP->Host();
|
||||||
|
}
|
||||||
|
mCallback->Done(gmpVDP, videoHost);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
UniquePtr<GetGMPVideoDecoderCallback> mCallback;
|
||||||
|
};
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
GeckoMediaPluginService::GetGMPVideoDecoder(nsTArray<nsCString>* aTags,
|
GeckoMediaPluginService::GetGMPVideoDecoder(nsTArray<nsCString>* aTags,
|
||||||
const nsACString& aNodeId,
|
const nsACString& aNodeId,
|
||||||
GMPVideoHost** aOutVideoHost,
|
UniquePtr<GetGMPVideoDecoderCallback>&& aCallback)
|
||||||
GMPVideoDecoderProxy** aGMPVD)
|
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
|
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
|
||||||
NS_ENSURE_ARG(aTags && aTags->Length() > 0);
|
NS_ENSURE_ARG(aTags && aTags->Length() > 0);
|
||||||
NS_ENSURE_ARG(aOutVideoHost);
|
NS_ENSURE_ARG(aCallback);
|
||||||
NS_ENSURE_ARG(aGMPVD);
|
|
||||||
|
|
||||||
if (mShuttingDownOnGMPThread) {
|
if (mShuttingDownOnGMPThread) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
@ -339,28 +373,42 @@ GeckoMediaPluginService::GetGMPVideoDecoder(nsTArray<nsCString>* aTags,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
GMPVideoDecoderParent* gmpVDP;
|
GetGMPParentForVideoDecoderDone(Move(aCallback)).Done(gmp);
|
||||||
nsresult rv = gmp->GetGMPVideoDecoder(&gmpVDP);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
*aGMPVD = gmpVDP;
|
|
||||||
*aOutVideoHost = &gmpVDP->Host();
|
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class GetGMPParentForVideoEncoderDone
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit GetGMPParentForVideoEncoderDone(UniquePtr<GetGMPVideoEncoderCallback>&& aCallback)
|
||||||
|
: mCallback(Move(aCallback))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Done(GMPParent* aGMPParent)
|
||||||
|
{
|
||||||
|
GMPVideoEncoderParent* gmpVEP = nullptr;
|
||||||
|
GMPVideoHostImpl* videoHost = nullptr;
|
||||||
|
nsresult rv = aGMPParent->GetGMPVideoEncoder(&gmpVEP);
|
||||||
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
videoHost = &gmpVEP->Host();
|
||||||
|
}
|
||||||
|
mCallback->Done(gmpVEP, videoHost);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
UniquePtr<GetGMPVideoEncoderCallback> mCallback;
|
||||||
|
};
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
GeckoMediaPluginService::GetGMPVideoEncoder(nsTArray<nsCString>* aTags,
|
GeckoMediaPluginService::GetGMPVideoEncoder(nsTArray<nsCString>* aTags,
|
||||||
const nsACString& aNodeId,
|
const nsACString& aNodeId,
|
||||||
GMPVideoHost** aOutVideoHost,
|
UniquePtr<GetGMPVideoEncoderCallback>&& aCallback)
|
||||||
GMPVideoEncoderProxy** aGMPVE)
|
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
|
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
|
||||||
NS_ENSURE_ARG(aTags && aTags->Length() > 0);
|
NS_ENSURE_ARG(aTags && aTags->Length() > 0);
|
||||||
NS_ENSURE_ARG(aOutVideoHost);
|
NS_ENSURE_ARG(aCallback);
|
||||||
NS_ENSURE_ARG(aGMPVE);
|
|
||||||
|
|
||||||
if (mShuttingDownOnGMPThread) {
|
if (mShuttingDownOnGMPThread) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
@ -377,22 +425,34 @@ GeckoMediaPluginService::GetGMPVideoEncoder(nsTArray<nsCString>* aTags,
|
|||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
GMPVideoEncoderParent* gmpVEP;
|
GetGMPParentForVideoEncoderDone(Move(aCallback)).Done(gmp);
|
||||||
nsresult rv = gmp->GetGMPVideoEncoder(&gmpVEP);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
*aGMPVE = gmpVEP;
|
|
||||||
*aOutVideoHost = &gmpVEP->Host();
|
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class GetGMPParentForDecryptorDone
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit GetGMPParentForDecryptorDone(UniquePtr<GetGMPDecryptorCallback>&& aCallback)
|
||||||
|
: mCallback(Move(aCallback))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Done(GMPParent* aGMPParent)
|
||||||
|
{
|
||||||
|
GMPDecryptorParent* ksp = nullptr;
|
||||||
|
aGMPParent->GetGMPDecryptor(&ksp);
|
||||||
|
mCallback->Done(ksp);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
UniquePtr<GetGMPDecryptorCallback> mCallback;
|
||||||
|
};
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
GeckoMediaPluginService::GetGMPDecryptor(nsTArray<nsCString>* aTags,
|
GeckoMediaPluginService::GetGMPDecryptor(nsTArray<nsCString>* aTags,
|
||||||
const nsACString& aNodeId,
|
const nsACString& aNodeId,
|
||||||
GMPDecryptorProxy** aDecryptor)
|
UniquePtr<GetGMPDecryptorCallback>&& aCallback)
|
||||||
{
|
{
|
||||||
#if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX)
|
#if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX)
|
||||||
if (!SandboxInfo::Get().CanSandboxMedia()) {
|
if (!SandboxInfo::Get().CanSandboxMedia()) {
|
||||||
@ -404,7 +464,7 @@ GeckoMediaPluginService::GetGMPDecryptor(nsTArray<nsCString>* aTags,
|
|||||||
|
|
||||||
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
|
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
|
||||||
NS_ENSURE_ARG(aTags && aTags->Length() > 0);
|
NS_ENSURE_ARG(aTags && aTags->Length() > 0);
|
||||||
NS_ENSURE_ARG(aDecryptor);
|
NS_ENSURE_ARG(aCallback);
|
||||||
|
|
||||||
if (mShuttingDownOnGMPThread) {
|
if (mShuttingDownOnGMPThread) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
@ -417,13 +477,7 @@ GeckoMediaPluginService::GetGMPDecryptor(nsTArray<nsCString>* aTags,
|
|||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
GMPDecryptorParent* ksp;
|
GetGMPParentForDecryptorDone(Move(aCallback)).Done(gmp);
|
||||||
nsresult rv = gmp->GetGMPDecryptor(&ksp);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
*aDecryptor = static_cast<GMPDecryptorProxy*>(ksp);
|
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -44,18 +44,20 @@ public:
|
|||||||
bool *aRetVal) override;
|
bool *aRetVal) override;
|
||||||
NS_IMETHOD GetGMPVideoDecoder(nsTArray<nsCString>* aTags,
|
NS_IMETHOD GetGMPVideoDecoder(nsTArray<nsCString>* aTags,
|
||||||
const nsACString& aNodeId,
|
const nsACString& aNodeId,
|
||||||
GMPVideoHost** aOutVideoHost,
|
UniquePtr<GetGMPVideoDecoderCallback>&& aCallback)
|
||||||
GMPVideoDecoderProxy** aGMPVD) override;
|
override;
|
||||||
NS_IMETHOD GetGMPVideoEncoder(nsTArray<nsCString>* aTags,
|
NS_IMETHOD GetGMPVideoEncoder(nsTArray<nsCString>* aTags,
|
||||||
const nsACString& aNodeId,
|
const nsACString& aNodeId,
|
||||||
GMPVideoHost **aOutVideoHost,
|
UniquePtr<GetGMPVideoEncoderCallback>&& aCallback)
|
||||||
GMPVideoEncoderProxy** aGMPVE) override;
|
override;
|
||||||
NS_IMETHOD GetGMPAudioDecoder(nsTArray<nsCString>* aTags,
|
NS_IMETHOD GetGMPAudioDecoder(nsTArray<nsCString>* aTags,
|
||||||
const nsACString& aNodeId,
|
const nsACString& aNodeId,
|
||||||
GMPAudioDecoderProxy **aGMPAD) override;
|
UniquePtr<GetGMPAudioDecoderCallback>&& aCallback)
|
||||||
|
override;
|
||||||
NS_IMETHOD GetGMPDecryptor(nsTArray<nsCString>* aTags,
|
NS_IMETHOD GetGMPDecryptor(nsTArray<nsCString>* aTags,
|
||||||
const nsACString& aNodeId,
|
const nsACString& aNodeId,
|
||||||
GMPDecryptorProxy** aDecryptor) override;
|
UniquePtr<GetGMPDecryptorCallback>&& aCallback)
|
||||||
|
override;
|
||||||
|
|
||||||
int32_t AsyncShutdownTimeoutMs();
|
int32_t AsyncShutdownTimeoutMs();
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "nsIThread.idl"
|
#include "nsIThread.idl"
|
||||||
|
|
||||||
%{C++
|
%{C++
|
||||||
|
#include "mozilla/UniquePtr.h"
|
||||||
#include "nsTArray.h"
|
#include "nsTArray.h"
|
||||||
#include "nsStringGlue.h"
|
#include "nsStringGlue.h"
|
||||||
class GMPAudioDecoderProxy;
|
class GMPAudioDecoderProxy;
|
||||||
@ -14,16 +15,36 @@ class GMPDecryptorProxy;
|
|||||||
class GMPVideoDecoderProxy;
|
class GMPVideoDecoderProxy;
|
||||||
class GMPVideoEncoderProxy;
|
class GMPVideoEncoderProxy;
|
||||||
class GMPVideoHost;
|
class GMPVideoHost;
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
class GMPGetterCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GMPGetterCallback() { MOZ_COUNT_CTOR(GMPGetterCallback<T>); }
|
||||||
|
virtual ~GMPGetterCallback() { MOZ_COUNT_DTOR(GMPGetterCallback<T>); }
|
||||||
|
virtual void Done(T*) = 0;
|
||||||
|
};
|
||||||
|
template<class T>
|
||||||
|
class GMPVideoGetterCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GMPVideoGetterCallback() { MOZ_COUNT_CTOR(GMPVideoGetterCallback<T>); }
|
||||||
|
virtual ~GMPVideoGetterCallback() { MOZ_COUNT_DTOR(GMPVideoGetterCallback<T>); }
|
||||||
|
virtual void Done(T*, GMPVideoHost*) = 0;
|
||||||
|
};
|
||||||
|
typedef GMPGetterCallback<GMPDecryptorProxy> GetGMPDecryptorCallback;
|
||||||
|
typedef GMPGetterCallback<GMPAudioDecoderProxy> GetGMPAudioDecoderCallback;
|
||||||
|
typedef GMPVideoGetterCallback<GMPVideoDecoderProxy> GetGMPVideoDecoderCallback;
|
||||||
|
typedef GMPVideoGetterCallback<GMPVideoEncoderProxy> GetGMPVideoEncoderCallback;
|
||||||
%}
|
%}
|
||||||
|
|
||||||
[ptr] native GMPVideoDecoderProxy(GMPVideoDecoderProxy);
|
|
||||||
[ptr] native GMPVideoEncoderProxy(GMPVideoEncoderProxy);
|
|
||||||
[ptr] native GMPVideoHost(GMPVideoHost);
|
|
||||||
[ptr] native TagArray(nsTArray<nsCString>);
|
[ptr] native TagArray(nsTArray<nsCString>);
|
||||||
[ptr] native GMPDecryptorProxy(GMPDecryptorProxy);
|
native GetGMPDecryptorCallback(mozilla::UniquePtr<GetGMPDecryptorCallback>&&);
|
||||||
[ptr] native GMPAudioDecoderProxy(GMPAudioDecoderProxy);
|
native GetGMPAudioDecoderCallback(mozilla::UniquePtr<GetGMPAudioDecoderCallback>&&);
|
||||||
|
native GetGMPVideoDecoderCallback(mozilla::UniquePtr<GetGMPVideoDecoderCallback>&&);
|
||||||
|
native GetGMPVideoEncoderCallback(mozilla::UniquePtr<GetGMPVideoEncoderCallback>&&);
|
||||||
|
|
||||||
[scriptable, uuid(fed4d2d8-87d8-42fe-a141-98c15b5f7a1e)]
|
[scriptable, uuid(11bb248b-7a4b-4f62-bebb-8211551d8c20)]
|
||||||
interface mozIGeckoMediaPluginService : nsISupports
|
interface mozIGeckoMediaPluginService : nsISupports
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -52,35 +73,63 @@ interface mozIGeckoMediaPluginService : nsISupports
|
|||||||
* The array of tags should at least contain a codec tag, and optionally
|
* The array of tags should at least contain a codec tag, and optionally
|
||||||
* other tags such as for EME keysystem.
|
* other tags such as for EME keysystem.
|
||||||
* Callable only on GMP thread.
|
* Callable only on GMP thread.
|
||||||
|
* This is an asynchronous operation, the Done method of the callback object
|
||||||
|
* will be called on the GMP thread with the result (which might be null in
|
||||||
|
* the case of failure). This method always takes ownership of the callback
|
||||||
|
* object, but if this method returns an error then the Done method of the
|
||||||
|
* callback object will not be called at all.
|
||||||
*/
|
*/
|
||||||
[noscript]
|
[noscript]
|
||||||
GMPVideoDecoderProxy getGMPVideoDecoder(in TagArray tags,
|
void getGMPVideoDecoder(in TagArray tags,
|
||||||
[optional] in ACString nodeId,
|
[optional] in ACString nodeId,
|
||||||
out GMPVideoHost outVideoHost);
|
in GetGMPVideoDecoderCallback callback);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a video encoder that supports the specified tags.
|
* Get a video encoder that supports the specified tags.
|
||||||
* The array of tags should at least contain a codec tag, and optionally
|
* The array of tags should at least contain a codec tag, and optionally
|
||||||
* other tags.
|
* other tags.
|
||||||
* Callable only on GMP thread.
|
* Callable only on GMP thread.
|
||||||
|
* This is an asynchronous operation, the Done method of the callback object
|
||||||
|
* will be called on the GMP thread with the result (which might be null in
|
||||||
|
* the case of failure). This method always takes ownership of the callback
|
||||||
|
* object, but if this method returns an error then the Done method of the
|
||||||
|
* callback object will not be called at all.
|
||||||
*/
|
*/
|
||||||
[noscript]
|
[noscript]
|
||||||
GMPVideoEncoderProxy getGMPVideoEncoder(in TagArray tags,
|
void getGMPVideoEncoder(in TagArray tags,
|
||||||
[optional] in ACString nodeId,
|
[optional] in ACString nodeId,
|
||||||
out GMPVideoHost outVideoHost);
|
in GetGMPVideoEncoderCallback callback);
|
||||||
|
|
||||||
// Returns an audio decoder that supports the specified tags.
|
/**
|
||||||
// The array of tags should at least contain a codec tag, and optionally
|
* Returns an audio decoder that supports the specified tags.
|
||||||
// other tags such as for EME keysystem.
|
* The array of tags should at least contain a codec tag, and optionally
|
||||||
// Callable only on GMP thread.
|
* other tags such as for EME keysystem.
|
||||||
GMPAudioDecoderProxy getGMPAudioDecoder(in TagArray tags,
|
* Callable only on GMP thread.
|
||||||
[optional] in ACString nodeId);
|
* This is an asynchronous operation, the Done method of the callback object
|
||||||
|
* will be called on the GMP thread with the result (which might be null in
|
||||||
|
* the case of failure). This method always takes ownership of the callback
|
||||||
|
* object, but if this method returns an error then the Done method of the
|
||||||
|
* callback object will not be called at all.
|
||||||
|
*/
|
||||||
|
[noscript]
|
||||||
|
void getGMPAudioDecoder(in TagArray tags,
|
||||||
|
[optional] in ACString nodeId,
|
||||||
|
in GetGMPAudioDecoderCallback callback);
|
||||||
|
|
||||||
// Returns a decryption session manager that supports the specified tags.
|
/**
|
||||||
// The array of tags should at least contain a key system tag, and optionally
|
* Returns a decryption session manager that supports the specified tags.
|
||||||
// other tags.
|
* The array of tags should at least contain a key system tag, and optionally
|
||||||
// Callable only on GMP thread.
|
* other tags.
|
||||||
GMPDecryptorProxy getGMPDecryptor(in TagArray tags, in ACString nodeId);
|
* Callable only on GMP thread.
|
||||||
|
* This is an asynchronous operation, the Done method of the callback object
|
||||||
|
* will be called on the GMP thread with the result (which might be null in
|
||||||
|
* the case of failure). This method always takes ownership of the callback
|
||||||
|
* object, but if this method returns an error then the Done method of the
|
||||||
|
* callback object will not be called at all.
|
||||||
|
*/
|
||||||
|
[noscript]
|
||||||
|
void getGMPDecryptor(in TagArray tags, in ACString nodeId,
|
||||||
|
in GetGMPDecryptorCallback callback);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the NodeId for a (origin, urlbarOrigin, isInprivateBrowsing) tuple.
|
* Gets the NodeId for a (origin, urlbarOrigin, isInprivateBrowsing) tuple.
|
||||||
|
@ -28,87 +28,234 @@ using namespace std;
|
|||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
using namespace mozilla::gmp;
|
using namespace mozilla::gmp;
|
||||||
|
|
||||||
|
class GMPTestMonitor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GMPTestMonitor()
|
||||||
|
: mFinished(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void AwaitFinished()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
while (!mFinished) {
|
||||||
|
NS_ProcessNextEvent(nullptr, true);
|
||||||
|
}
|
||||||
|
mFinished = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void MarkFinished()
|
||||||
|
{
|
||||||
|
mFinished = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
void SetFinished()
|
||||||
|
{
|
||||||
|
NS_DispatchToMainThread(NS_NewNonOwningRunnableMethod(this,
|
||||||
|
&GMPTestMonitor::MarkFinished));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool mFinished;
|
||||||
|
};
|
||||||
|
|
||||||
struct GMPTestRunner
|
struct GMPTestRunner
|
||||||
{
|
{
|
||||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPTestRunner)
|
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPTestRunner)
|
||||||
|
|
||||||
void DoTest(void (GMPTestRunner::*aTestMethod)());
|
void DoTest(void (GMPTestRunner::*aTestMethod)(GMPTestMonitor&));
|
||||||
void RunTestGMPTestCodec();
|
void RunTestGMPTestCodec1(GMPTestMonitor& aMonitor);
|
||||||
void RunTestGMPCrossOrigin();
|
void RunTestGMPTestCodec2(GMPTestMonitor& aMonitor);
|
||||||
|
void RunTestGMPTestCodec3(GMPTestMonitor& aMonitor);
|
||||||
|
void RunTestGMPCrossOrigin1(GMPTestMonitor& aMonitor);
|
||||||
|
void RunTestGMPCrossOrigin2(GMPTestMonitor& aMonitor);
|
||||||
|
void RunTestGMPCrossOrigin3(GMPTestMonitor& aMonitor);
|
||||||
|
void RunTestGMPCrossOrigin4(GMPTestMonitor& aMonitor);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
~GMPTestRunner() { }
|
~GMPTestRunner() { }
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
template<class T, class Base,
|
||||||
GMPTestRunner::RunTestGMPTestCodec()
|
nsresult (NS_STDCALL GeckoMediaPluginService::*Getter)(nsTArray<nsCString>*,
|
||||||
|
const nsACString&,
|
||||||
|
UniquePtr<Base>&&)>
|
||||||
|
class RunTestGMPVideoCodec : public Base
|
||||||
{
|
{
|
||||||
nsRefPtr<GeckoMediaPluginService> service =
|
public:
|
||||||
GeckoMediaPluginService::GetGeckoMediaPluginService();
|
virtual void Done(T* aGMP, GMPVideoHost* aHost)
|
||||||
|
{
|
||||||
|
EXPECT_TRUE(aGMP);
|
||||||
|
EXPECT_TRUE(aHost);
|
||||||
|
if (aGMP) {
|
||||||
|
aGMP->Close();
|
||||||
|
}
|
||||||
|
mMonitor.SetFinished();
|
||||||
|
}
|
||||||
|
|
||||||
GMPVideoHost* host = nullptr;
|
static void Run(GMPTestMonitor& aMonitor, const nsCString& aOrigin)
|
||||||
GMPVideoDecoderProxy* decoder = nullptr;
|
{
|
||||||
GMPVideoDecoderProxy* decoder2 = nullptr;
|
UniquePtr<GMPCallbackType> callback(new RunTestGMPVideoCodec(aMonitor));
|
||||||
GMPVideoEncoderProxy* encoder = nullptr;
|
Get(aOrigin, Move(callback));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
typedef T GMPCodecType;
|
||||||
|
typedef Base GMPCallbackType;
|
||||||
|
|
||||||
|
explicit RunTestGMPVideoCodec(GMPTestMonitor& aMonitor)
|
||||||
|
: mMonitor(aMonitor)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static nsresult Get(const nsACString& aNodeId, UniquePtr<Base>&& aCallback)
|
||||||
|
{
|
||||||
nsTArray<nsCString> tags;
|
nsTArray<nsCString> tags;
|
||||||
tags.AppendElement(NS_LITERAL_CSTRING("h264"));
|
tags.AppendElement(NS_LITERAL_CSTRING("h264"));
|
||||||
|
|
||||||
service->GetGMPVideoDecoder(&tags, NS_LITERAL_CSTRING("o"), &host, &decoder2);
|
nsRefPtr<GeckoMediaPluginService> service =
|
||||||
service->GetGMPVideoDecoder(&tags, NS_LITERAL_CSTRING(""), &host, &decoder);
|
GeckoMediaPluginService::GetGeckoMediaPluginService();
|
||||||
|
return ((*service).*Getter)(&tags, aNodeId, Move(aCallback));
|
||||||
|
}
|
||||||
|
|
||||||
service->GetGMPVideoEncoder(&tags, NS_LITERAL_CSTRING(""), &host, &encoder);
|
protected:
|
||||||
|
GMPTestMonitor& mMonitor;
|
||||||
|
};
|
||||||
|
|
||||||
EXPECT_TRUE(host);
|
typedef RunTestGMPVideoCodec<GMPVideoDecoderProxy,
|
||||||
EXPECT_TRUE(decoder);
|
GetGMPVideoDecoderCallback,
|
||||||
EXPECT_TRUE(decoder2);
|
&GeckoMediaPluginService::GetGMPVideoDecoder>
|
||||||
EXPECT_TRUE(encoder);
|
RunTestGMPVideoDecoder;
|
||||||
|
typedef RunTestGMPVideoCodec<GMPVideoEncoderProxy,
|
||||||
|
GetGMPVideoEncoderCallback,
|
||||||
|
&GeckoMediaPluginService::GetGMPVideoEncoder>
|
||||||
|
RunTestGMPVideoEncoder;
|
||||||
|
|
||||||
if (decoder) decoder->Close();
|
void
|
||||||
if (decoder2) decoder2->Close();
|
GMPTestRunner::RunTestGMPTestCodec1(GMPTestMonitor& aMonitor)
|
||||||
if (encoder) encoder->Close();
|
{
|
||||||
|
RunTestGMPVideoDecoder::Run(aMonitor, NS_LITERAL_CSTRING("o"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
GMPTestRunner::RunTestGMPCrossOrigin()
|
GMPTestRunner::RunTestGMPTestCodec2(GMPTestMonitor& aMonitor)
|
||||||
{
|
{
|
||||||
nsRefPtr<GeckoMediaPluginService> service =
|
RunTestGMPVideoDecoder::Run(aMonitor, NS_LITERAL_CSTRING(""));
|
||||||
GeckoMediaPluginService::GetGeckoMediaPluginService();
|
}
|
||||||
|
|
||||||
GMPVideoHost* host = nullptr;
|
void
|
||||||
nsTArray<nsCString> tags;
|
GMPTestRunner::RunTestGMPTestCodec3(GMPTestMonitor& aMonitor)
|
||||||
tags.AppendElement(NS_LITERAL_CSTRING("h264"));
|
{
|
||||||
|
RunTestGMPVideoEncoder::Run(aMonitor, NS_LITERAL_CSTRING(""));
|
||||||
|
}
|
||||||
|
|
||||||
GMPVideoDecoderProxy* decoder1 = nullptr;
|
template<class Base>
|
||||||
GMPVideoDecoderProxy* decoder2 = nullptr;
|
class RunTestGMPCrossOrigin : public Base
|
||||||
GMPVideoEncoderProxy* encoder1 = nullptr;
|
{
|
||||||
GMPVideoEncoderProxy* encoder2 = nullptr;
|
public:
|
||||||
|
virtual void Done(typename Base::GMPCodecType* aGMP, GMPVideoHost* aHost)
|
||||||
|
{
|
||||||
|
EXPECT_TRUE(aGMP);
|
||||||
|
|
||||||
service->GetGMPVideoDecoder(&tags, NS_LITERAL_CSTRING("origin1"), &host, &decoder1);
|
UniquePtr<typename Base::GMPCallbackType> callback(
|
||||||
service->GetGMPVideoDecoder(&tags, NS_LITERAL_CSTRING("origin2"), &host, &decoder2);
|
new Step2(Base::mMonitor, aGMP, mShouldBeEqual));
|
||||||
EXPECT_TRUE(!!decoder1 && !!decoder2 &&
|
nsresult rv = Base::Get(mOrigin2, Move(callback));
|
||||||
decoder1->ParentID() != decoder2->ParentID());
|
EXPECT_TRUE(NS_SUCCEEDED(rv));
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
Base::mMonitor.SetFinished();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
service->GetGMPVideoEncoder(&tags, NS_LITERAL_CSTRING("origin1"), &host, &encoder1);
|
static void Run(GMPTestMonitor& aMonitor, const nsCString& aOrigin1,
|
||||||
service->GetGMPVideoEncoder(&tags, NS_LITERAL_CSTRING("origin2"), &host, &encoder2);
|
const nsCString& aOrigin2)
|
||||||
EXPECT_TRUE(!!encoder1 && !!encoder2 &&
|
{
|
||||||
encoder1->ParentID() != encoder2->ParentID());
|
UniquePtr<typename Base::GMPCallbackType> callback(
|
||||||
|
new RunTestGMPCrossOrigin<Base>(aMonitor, aOrigin1, aOrigin2));
|
||||||
|
nsresult rv = Base::Get(aOrigin1, Move(callback));
|
||||||
|
EXPECT_TRUE(NS_SUCCEEDED(rv));
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
aMonitor.SetFinished();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (decoder2) decoder2->Close();
|
private:
|
||||||
if (encoder2) encoder2->Close();
|
RunTestGMPCrossOrigin(GMPTestMonitor& aMonitor, const nsCString& aOrigin1,
|
||||||
|
const nsCString& aOrigin2)
|
||||||
|
: Base(aMonitor),
|
||||||
|
mGMP(nullptr),
|
||||||
|
mOrigin2(aOrigin2),
|
||||||
|
mShouldBeEqual(aOrigin1.Equals(aOrigin2))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
service->GetGMPVideoDecoder(&tags, NS_LITERAL_CSTRING("origin1"), &host, &decoder2);
|
class Step2 : public Base
|
||||||
EXPECT_TRUE(!!decoder1 && !!decoder2 &&
|
{
|
||||||
decoder1->ParentID() == decoder2->ParentID());
|
public:
|
||||||
|
Step2(GMPTestMonitor& aMonitor,
|
||||||
|
typename Base::GMPCodecType* aGMP,
|
||||||
|
bool aShouldBeEqual)
|
||||||
|
: Base(aMonitor),
|
||||||
|
mGMP(aGMP),
|
||||||
|
mShouldBeEqual(aShouldBeEqual)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
virtual void Done(typename Base::GMPCodecType* aGMP, GMPVideoHost* aHost)
|
||||||
|
{
|
||||||
|
EXPECT_TRUE(aGMP);
|
||||||
|
if (aGMP) {
|
||||||
|
EXPECT_TRUE(mGMP &&
|
||||||
|
(mGMP->ParentID() == aGMP->ParentID()) == mShouldBeEqual);
|
||||||
|
}
|
||||||
|
if (mGMP) {
|
||||||
|
mGMP->Close();
|
||||||
|
}
|
||||||
|
Base::Done(aGMP, aHost);
|
||||||
|
}
|
||||||
|
|
||||||
service->GetGMPVideoEncoder(&tags, NS_LITERAL_CSTRING("origin1"), &host, &encoder2);
|
private:
|
||||||
EXPECT_TRUE(!!encoder1 && !!encoder2 &&
|
typename Base::GMPCodecType* mGMP;
|
||||||
encoder1->ParentID() == encoder2->ParentID());
|
bool mShouldBeEqual;
|
||||||
|
};
|
||||||
|
|
||||||
if (decoder1) decoder1->Close();
|
typename Base::GMPCodecType* mGMP;
|
||||||
if (decoder2) decoder2->Close();
|
nsCString mOrigin2;
|
||||||
if (encoder1) encoder1->Close();
|
bool mShouldBeEqual;
|
||||||
if (encoder2) encoder2->Close();
|
};
|
||||||
|
|
||||||
|
typedef RunTestGMPCrossOrigin<RunTestGMPVideoDecoder>
|
||||||
|
RunTestGMPVideoDecoderCrossOrigin;
|
||||||
|
typedef RunTestGMPCrossOrigin<RunTestGMPVideoEncoder>
|
||||||
|
RunTestGMPVideoEncoderCrossOrigin;
|
||||||
|
|
||||||
|
void
|
||||||
|
GMPTestRunner::RunTestGMPCrossOrigin1(GMPTestMonitor& aMonitor)
|
||||||
|
{
|
||||||
|
RunTestGMPVideoDecoderCrossOrigin::Run(
|
||||||
|
aMonitor, NS_LITERAL_CSTRING("origin1"), NS_LITERAL_CSTRING("origin2"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GMPTestRunner::RunTestGMPCrossOrigin2(GMPTestMonitor& aMonitor)
|
||||||
|
{
|
||||||
|
RunTestGMPVideoEncoderCrossOrigin::Run(
|
||||||
|
aMonitor, NS_LITERAL_CSTRING("origin1"), NS_LITERAL_CSTRING("origin2"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GMPTestRunner::RunTestGMPCrossOrigin3(GMPTestMonitor& aMonitor)
|
||||||
|
{
|
||||||
|
RunTestGMPVideoDecoderCrossOrigin::Run(
|
||||||
|
aMonitor, NS_LITERAL_CSTRING("origin1"), NS_LITERAL_CSTRING("origin1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GMPTestRunner::RunTestGMPCrossOrigin4(GMPTestMonitor& aMonitor)
|
||||||
|
{
|
||||||
|
RunTestGMPVideoEncoderCrossOrigin::Run(
|
||||||
|
aMonitor, NS_LITERAL_CSTRING("origin1"), NS_LITERAL_CSTRING("origin1"));
|
||||||
}
|
}
|
||||||
|
|
||||||
static already_AddRefed<nsIThread>
|
static already_AddRefed<nsIThread>
|
||||||
@ -438,9 +585,73 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
|
|||||||
SetFinished();
|
SetFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class CreateDecryptorDone : public GetGMPDecryptorCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CreateDecryptorDone(GMPStorageTest* aRunner, nsIRunnable* aContinuation)
|
||||||
|
: mRunner(aRunner),
|
||||||
|
mContinuation(aContinuation)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void Done(GMPDecryptorProxy* aDecryptor) override
|
||||||
|
{
|
||||||
|
mRunner->mDecryptor = aDecryptor;
|
||||||
|
EXPECT_TRUE(!!mRunner->mDecryptor);
|
||||||
|
|
||||||
|
if (mRunner->mDecryptor) {
|
||||||
|
mRunner->mDecryptor->Init(mRunner);
|
||||||
|
}
|
||||||
|
nsCOMPtr<nsIThread> thread(GetGMPThread());
|
||||||
|
thread->Dispatch(mContinuation, NS_DISPATCH_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
nsRefPtr<GMPStorageTest> mRunner;
|
||||||
|
nsCOMPtr<nsIRunnable> mContinuation;
|
||||||
|
};
|
||||||
|
|
||||||
void CreateDecryptor(const nsAString& aOrigin,
|
void CreateDecryptor(const nsAString& aOrigin,
|
||||||
const nsAString& aTopLevelOrigin,
|
const nsAString& aTopLevelOrigin,
|
||||||
bool aInPBMode) {
|
bool aInPBMode,
|
||||||
|
const nsCString& aUpdate)
|
||||||
|
{
|
||||||
|
nsTArray<nsCString> updates;
|
||||||
|
updates.AppendElement(aUpdate);
|
||||||
|
CreateDecryptor(aOrigin, aTopLevelOrigin, aInPBMode, Move(updates));
|
||||||
|
}
|
||||||
|
class Updates : public nsRunnable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Updates(GMPStorageTest* aRunner, nsTArray<nsCString>&& aUpdates)
|
||||||
|
: mRunner(aRunner),
|
||||||
|
mUpdates(aUpdates)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHOD Run()
|
||||||
|
{
|
||||||
|
for (auto& update : mUpdates) {
|
||||||
|
mRunner->Update(update);
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
nsRefPtr<GMPStorageTest> mRunner;
|
||||||
|
nsTArray<nsCString> mUpdates;
|
||||||
|
};
|
||||||
|
void CreateDecryptor(const nsAString& aOrigin,
|
||||||
|
const nsAString& aTopLevelOrigin,
|
||||||
|
bool aInPBMode,
|
||||||
|
nsTArray<nsCString>&& aUpdates) {
|
||||||
|
nsCOMPtr<nsIRunnable> updates(new Updates(this, Move(aUpdates)));
|
||||||
|
CreateDecryptor(aOrigin, aTopLevelOrigin, aInPBMode, updates);
|
||||||
|
}
|
||||||
|
void CreateDecryptor(const nsAString& aOrigin,
|
||||||
|
const nsAString& aTopLevelOrigin,
|
||||||
|
bool aInPBMode,
|
||||||
|
nsIRunnable* aContinuation) {
|
||||||
nsRefPtr<GeckoMediaPluginService> service =
|
nsRefPtr<GeckoMediaPluginService> service =
|
||||||
GeckoMediaPluginService::GetGeckoMediaPluginService();
|
GeckoMediaPluginService::GetGeckoMediaPluginService();
|
||||||
EXPECT_TRUE(service);
|
EXPECT_TRUE(service);
|
||||||
@ -451,13 +662,11 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
|
|||||||
nsTArray<nsCString> tags;
|
nsTArray<nsCString> tags;
|
||||||
tags.AppendElement(NS_LITERAL_CSTRING("fake"));
|
tags.AppendElement(NS_LITERAL_CSTRING("fake"));
|
||||||
|
|
||||||
nsresult rv = service->GetGMPDecryptor(&tags, mNodeId, &mDecryptor);
|
UniquePtr<GetGMPDecryptorCallback> callback(
|
||||||
|
new CreateDecryptorDone(this, aContinuation));
|
||||||
|
nsresult rv =
|
||||||
|
service->GetGMPDecryptor(&tags, mNodeId, Move(callback));
|
||||||
EXPECT_TRUE(NS_SUCCEEDED(rv));
|
EXPECT_TRUE(NS_SUCCEEDED(rv));
|
||||||
EXPECT_TRUE(!!mDecryptor);
|
|
||||||
|
|
||||||
if (mDecryptor) {
|
|
||||||
mDecryptor->Init(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestBasicStorage() {
|
void TestBasicStorage() {
|
||||||
@ -467,16 +676,16 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
|
|||||||
nsRefPtr<GeckoMediaPluginService> service =
|
nsRefPtr<GeckoMediaPluginService> service =
|
||||||
GeckoMediaPluginService::GetGeckoMediaPluginService();
|
GeckoMediaPluginService::GetGeckoMediaPluginService();
|
||||||
|
|
||||||
CreateDecryptor(NS_LITERAL_STRING("example1.com"),
|
|
||||||
NS_LITERAL_STRING("example2.com"),
|
|
||||||
false);
|
|
||||||
|
|
||||||
// Send a message to the fake GMP for it to run its own tests internally.
|
// Send a message to the fake GMP for it to run its own tests internally.
|
||||||
// It sends us a "test-storage complete" message when its passed, or
|
// It sends us a "test-storage complete" message when its passed, or
|
||||||
// some other message if its tests fail.
|
// some other message if its tests fail.
|
||||||
Expect(NS_LITERAL_CSTRING("test-storage complete"),
|
Expect(NS_LITERAL_CSTRING("test-storage complete"),
|
||||||
NS_NewRunnableMethod(this, &GMPStorageTest::SetFinished));
|
NS_NewRunnableMethod(this, &GMPStorageTest::SetFinished));
|
||||||
Update(NS_LITERAL_CSTRING("test-storage"));
|
|
||||||
|
CreateDecryptor(NS_LITERAL_STRING("example1.com"),
|
||||||
|
NS_LITERAL_STRING("example2.com"),
|
||||||
|
false,
|
||||||
|
NS_LITERAL_CSTRING("test-storage"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -490,28 +699,28 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
|
|||||||
EXPECT_TRUE(IsGMPStorageIsEmpty());
|
EXPECT_TRUE(IsGMPStorageIsEmpty());
|
||||||
|
|
||||||
// Generate storage data for some site.
|
// Generate storage data for some site.
|
||||||
CreateDecryptor(NS_LITERAL_STRING("example1.com"),
|
|
||||||
NS_LITERAL_STRING("example2.com"),
|
|
||||||
false);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethod(
|
nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethod(
|
||||||
this, &GMPStorageTest::TestForgetThisSite_AnotherSite);
|
this, &GMPStorageTest::TestForgetThisSite_AnotherSite);
|
||||||
Expect(NS_LITERAL_CSTRING("test-storage complete"), r);
|
Expect(NS_LITERAL_CSTRING("test-storage complete"), r);
|
||||||
Update(NS_LITERAL_CSTRING("test-storage"));
|
|
||||||
|
CreateDecryptor(NS_LITERAL_STRING("example1.com"),
|
||||||
|
NS_LITERAL_STRING("example2.com"),
|
||||||
|
false,
|
||||||
|
NS_LITERAL_CSTRING("test-storage"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestForgetThisSite_AnotherSite() {
|
void TestForgetThisSite_AnotherSite() {
|
||||||
Shutdown();
|
Shutdown();
|
||||||
|
|
||||||
// Generate storage data for another site.
|
// Generate storage data for another site.
|
||||||
CreateDecryptor(NS_LITERAL_STRING("example3.com"),
|
|
||||||
NS_LITERAL_STRING("example4.com"),
|
|
||||||
false);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethod(
|
nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethod(
|
||||||
this, &GMPStorageTest::TestForgetThisSite_CollectSiteInfo);
|
this, &GMPStorageTest::TestForgetThisSite_CollectSiteInfo);
|
||||||
Expect(NS_LITERAL_CSTRING("test-storage complete"), r);
|
Expect(NS_LITERAL_CSTRING("test-storage complete"), r);
|
||||||
Update(NS_LITERAL_CSTRING("test-storage"));
|
|
||||||
|
CreateDecryptor(NS_LITERAL_STRING("example3.com"),
|
||||||
|
NS_LITERAL_STRING("example4.com"),
|
||||||
|
false,
|
||||||
|
NS_LITERAL_CSTRING("test-storage"));
|
||||||
}
|
}
|
||||||
|
|
||||||
struct NodeInfo {
|
struct NodeInfo {
|
||||||
@ -623,16 +832,15 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
|
|||||||
EXPECT_TRUE(IsGMPStorageIsEmpty());
|
EXPECT_TRUE(IsGMPStorageIsEmpty());
|
||||||
|
|
||||||
// Generate storage data for some site.
|
// Generate storage data for some site.
|
||||||
CreateDecryptor(NS_LITERAL_STRING("example1.com"),
|
|
||||||
NS_LITERAL_STRING("example2.com"),
|
|
||||||
false);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethod(
|
nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethod(
|
||||||
this, &GMPStorageTest::TestClearRecentHistory1_Clear);
|
this, &GMPStorageTest::TestClearRecentHistory1_Clear);
|
||||||
Expect(NS_LITERAL_CSTRING("test-storage complete"), r);
|
Expect(NS_LITERAL_CSTRING("test-storage complete"), r);
|
||||||
Update(NS_LITERAL_CSTRING("test-storage"));
|
|
||||||
|
|
||||||
}
|
CreateDecryptor(NS_LITERAL_STRING("example1.com"),
|
||||||
|
NS_LITERAL_STRING("example2.com"),
|
||||||
|
false,
|
||||||
|
NS_LITERAL_CSTRING("test-storage"));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 1. Generate some storage data.
|
* 1. Generate some storage data.
|
||||||
@ -646,15 +854,14 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
|
|||||||
EXPECT_TRUE(IsGMPStorageIsEmpty());
|
EXPECT_TRUE(IsGMPStorageIsEmpty());
|
||||||
|
|
||||||
// Generate storage data for some site.
|
// Generate storage data for some site.
|
||||||
CreateDecryptor(NS_LITERAL_STRING("example1.com"),
|
|
||||||
NS_LITERAL_STRING("example2.com"),
|
|
||||||
false);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethod(
|
nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethod(
|
||||||
this, &GMPStorageTest::TestClearRecentHistory2_Clear);
|
this, &GMPStorageTest::TestClearRecentHistory2_Clear);
|
||||||
Expect(NS_LITERAL_CSTRING("test-storage complete"), r);
|
Expect(NS_LITERAL_CSTRING("test-storage complete"), r);
|
||||||
Update(NS_LITERAL_CSTRING("test-storage"));
|
|
||||||
|
|
||||||
|
CreateDecryptor(NS_LITERAL_STRING("example1.com"),
|
||||||
|
NS_LITERAL_STRING("example2.com"),
|
||||||
|
false,
|
||||||
|
NS_LITERAL_CSTRING("test-storage"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -669,15 +876,14 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
|
|||||||
EXPECT_TRUE(IsGMPStorageIsEmpty());
|
EXPECT_TRUE(IsGMPStorageIsEmpty());
|
||||||
|
|
||||||
// Generate storage data for some site.
|
// Generate storage data for some site.
|
||||||
CreateDecryptor(NS_LITERAL_STRING("example1.com"),
|
|
||||||
NS_LITERAL_STRING("example2.com"),
|
|
||||||
false);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethod(
|
nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethod(
|
||||||
this, &GMPStorageTest::TestClearRecentHistory3_Clear);
|
this, &GMPStorageTest::TestClearRecentHistory3_Clear);
|
||||||
Expect(NS_LITERAL_CSTRING("test-storage complete"), r);
|
Expect(NS_LITERAL_CSTRING("test-storage complete"), r);
|
||||||
Update(NS_LITERAL_CSTRING("test-storage"));
|
|
||||||
|
|
||||||
|
CreateDecryptor(NS_LITERAL_STRING("example1.com"),
|
||||||
|
NS_LITERAL_STRING("example2.com"),
|
||||||
|
false,
|
||||||
|
NS_LITERAL_CSTRING("test-storage"));
|
||||||
}
|
}
|
||||||
|
|
||||||
class MaxMTimeFinder {
|
class MaxMTimeFinder {
|
||||||
@ -775,12 +981,6 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
|
|||||||
void TestCrossOriginStorage() {
|
void TestCrossOriginStorage() {
|
||||||
EXPECT_TRUE(!mDecryptor);
|
EXPECT_TRUE(!mDecryptor);
|
||||||
|
|
||||||
// Open decryptor on one, origin, write a record, and test that that
|
|
||||||
// record can't be read on another origin.
|
|
||||||
CreateDecryptor(NS_LITERAL_STRING("example3.com"),
|
|
||||||
NS_LITERAL_STRING("example4.com"),
|
|
||||||
false);
|
|
||||||
|
|
||||||
// Send the decryptor the message "store recordid $time"
|
// Send the decryptor the message "store recordid $time"
|
||||||
// Wait for the decrytor to send us "stored recordid $time"
|
// Wait for the decrytor to send us "stored recordid $time"
|
||||||
auto t = time(0);
|
auto t = time(0);
|
||||||
@ -791,7 +991,13 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
|
|||||||
|
|
||||||
nsCString update("store crossOriginTestRecordId ");
|
nsCString update("store crossOriginTestRecordId ");
|
||||||
update.AppendInt((int64_t)t);
|
update.AppendInt((int64_t)t);
|
||||||
Update(update);
|
|
||||||
|
// Open decryptor on one, origin, write a record, and test that that
|
||||||
|
// record can't be read on another origin.
|
||||||
|
CreateDecryptor(NS_LITERAL_STRING("example3.com"),
|
||||||
|
NS_LITERAL_STRING("example4.com"),
|
||||||
|
false,
|
||||||
|
update);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestCrossOriginStorage_RecordStoredContinuation() {
|
void TestCrossOriginStorage_RecordStoredContinuation() {
|
||||||
@ -799,87 +1005,102 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
|
|||||||
// and try to read the record.
|
// and try to read the record.
|
||||||
Shutdown();
|
Shutdown();
|
||||||
|
|
||||||
CreateDecryptor(NS_LITERAL_STRING("example5.com"),
|
|
||||||
NS_LITERAL_STRING("example6.com"),
|
|
||||||
false);
|
|
||||||
|
|
||||||
Expect(NS_LITERAL_CSTRING("retrieve crossOriginTestRecordId succeeded (length 0 bytes)"),
|
Expect(NS_LITERAL_CSTRING("retrieve crossOriginTestRecordId succeeded (length 0 bytes)"),
|
||||||
NS_NewRunnableMethod(this, &GMPStorageTest::SetFinished));
|
NS_NewRunnableMethod(this, &GMPStorageTest::SetFinished));
|
||||||
Update(NS_LITERAL_CSTRING("retrieve crossOriginTestRecordId"));
|
|
||||||
|
CreateDecryptor(NS_LITERAL_STRING("example5.com"),
|
||||||
|
NS_LITERAL_STRING("example6.com"),
|
||||||
|
false,
|
||||||
|
NS_LITERAL_CSTRING("retrieve crossOriginTestRecordId"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestPBStorage() {
|
void TestPBStorage() {
|
||||||
// Open decryptor on one, origin, write a record, close decryptor,
|
|
||||||
// open another, and test that record can be read, close decryptor,
|
|
||||||
// then send pb-last-context-closed notification, then open decryptor
|
|
||||||
// and check that it can't read that data; it should have been purged.
|
|
||||||
CreateDecryptor(NS_LITERAL_STRING("pb1.com"),
|
|
||||||
NS_LITERAL_STRING("pb2.com"),
|
|
||||||
true);
|
|
||||||
|
|
||||||
// Send the decryptor the message "store recordid $time"
|
// Send the decryptor the message "store recordid $time"
|
||||||
// Wait for the decrytor to send us "stored recordid $time"
|
// Wait for the decrytor to send us "stored recordid $time"
|
||||||
nsCString response("stored pbdata test-pb-data");
|
nsCString response("stored pbdata test-pb-data");
|
||||||
Expect(response, NS_NewRunnableMethod(this,
|
Expect(response, NS_NewRunnableMethod(this,
|
||||||
&GMPStorageTest::TestPBStorage_RecordStoredContinuation));
|
&GMPStorageTest::TestPBStorage_RecordStoredContinuation));
|
||||||
|
|
||||||
nsCString update("store pbdata test-pb-data");
|
// Open decryptor on one, origin, write a record, close decryptor,
|
||||||
Update(update);
|
// open another, and test that record can be read, close decryptor,
|
||||||
|
// then send pb-last-context-closed notification, then open decryptor
|
||||||
|
// and check that it can't read that data; it should have been purged.
|
||||||
|
CreateDecryptor(NS_LITERAL_STRING("pb1.com"),
|
||||||
|
NS_LITERAL_STRING("pb2.com"),
|
||||||
|
true,
|
||||||
|
NS_LITERAL_CSTRING("store pbdata test-pb-data"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestPBStorage_RecordStoredContinuation() {
|
void TestPBStorage_RecordStoredContinuation() {
|
||||||
Shutdown();
|
Shutdown();
|
||||||
|
|
||||||
CreateDecryptor(NS_LITERAL_STRING("pb1.com"),
|
|
||||||
NS_LITERAL_STRING("pb2.com"),
|
|
||||||
true);
|
|
||||||
|
|
||||||
Expect(NS_LITERAL_CSTRING("retrieve pbdata succeeded (length 12 bytes)"),
|
Expect(NS_LITERAL_CSTRING("retrieve pbdata succeeded (length 12 bytes)"),
|
||||||
NS_NewRunnableMethod(this,
|
NS_NewRunnableMethod(this,
|
||||||
&GMPStorageTest::TestPBStorage_RecordRetrievedContinuation));
|
&GMPStorageTest::TestPBStorage_RecordRetrievedContinuation));
|
||||||
Update(NS_LITERAL_CSTRING("retrieve pbdata"));
|
|
||||||
|
CreateDecryptor(NS_LITERAL_STRING("pb1.com"),
|
||||||
|
NS_LITERAL_STRING("pb2.com"),
|
||||||
|
true,
|
||||||
|
NS_LITERAL_CSTRING("retrieve pbdata"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestPBStorage_RecordRetrievedContinuation() {
|
void TestPBStorage_RecordRetrievedContinuation() {
|
||||||
Shutdown();
|
Shutdown();
|
||||||
SimulatePBModeExit();
|
SimulatePBModeExit();
|
||||||
|
|
||||||
CreateDecryptor(NS_LITERAL_STRING("pb1.com"),
|
|
||||||
NS_LITERAL_STRING("pb2.com"),
|
|
||||||
true);
|
|
||||||
|
|
||||||
Expect(NS_LITERAL_CSTRING("retrieve pbdata succeeded (length 0 bytes)"),
|
Expect(NS_LITERAL_CSTRING("retrieve pbdata succeeded (length 0 bytes)"),
|
||||||
NS_NewRunnableMethod(this,
|
NS_NewRunnableMethod(this,
|
||||||
&GMPStorageTest::SetFinished));
|
&GMPStorageTest::SetFinished));
|
||||||
Update(NS_LITERAL_CSTRING("retrieve pbdata"));
|
|
||||||
|
CreateDecryptor(NS_LITERAL_STRING("pb1.com"),
|
||||||
|
NS_LITERAL_STRING("pb2.com"),
|
||||||
|
true,
|
||||||
|
NS_LITERAL_CSTRING("retrieve pbdata"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void NextAsyncShutdownTimeoutTest(nsIRunnable* aContinuation)
|
||||||
|
{
|
||||||
|
if (mDecryptor) {
|
||||||
|
Update(NS_LITERAL_CSTRING("shutdown-mode timeout"));
|
||||||
|
Shutdown();
|
||||||
|
}
|
||||||
|
nsCOMPtr<nsIThread> thread(GetGMPThread());
|
||||||
|
thread->Dispatch(aContinuation, NS_DISPATCH_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateAsyncShutdownTimeoutGMP(const nsAString& aOrigin1,
|
void CreateAsyncShutdownTimeoutGMP(const nsAString& aOrigin1,
|
||||||
const nsAString& aOrigin2) {
|
const nsAString& aOrigin2,
|
||||||
CreateDecryptor(aOrigin1, aOrigin2, false);
|
void (GMPStorageTest::*aCallback)()) {
|
||||||
Update(NS_LITERAL_CSTRING("shutdown-mode timeout"));
|
nsCOMPtr<nsIRunnable> continuation(
|
||||||
Shutdown();
|
NS_NewRunnableMethodWithArg<nsCOMPtr<nsIRunnable>>(
|
||||||
|
this,
|
||||||
|
&GMPStorageTest::NextAsyncShutdownTimeoutTest,
|
||||||
|
NS_NewRunnableMethod(this, aCallback)));
|
||||||
|
|
||||||
|
CreateDecryptor(aOrigin1, aOrigin2, false, continuation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestAsyncShutdownTimeout() {
|
void TestAsyncShutdownTimeout() {
|
||||||
// Create decryptors that timeout in their async shutdown.
|
// Create decryptors that timeout in their async shutdown.
|
||||||
// If the gtest hangs on shutdown, test fails!
|
// If the gtest hangs on shutdown, test fails!
|
||||||
CreateAsyncShutdownTimeoutGMP(NS_LITERAL_STRING("example7.com"),
|
CreateAsyncShutdownTimeoutGMP(NS_LITERAL_STRING("example7.com"),
|
||||||
NS_LITERAL_STRING("example8.com"));
|
NS_LITERAL_STRING("example8.com"),
|
||||||
|
&GMPStorageTest::TestAsyncShutdownTimeout2);
|
||||||
|
};
|
||||||
|
|
||||||
|
void TestAsyncShutdownTimeout2() {
|
||||||
CreateAsyncShutdownTimeoutGMP(NS_LITERAL_STRING("example9.com"),
|
CreateAsyncShutdownTimeoutGMP(NS_LITERAL_STRING("example9.com"),
|
||||||
NS_LITERAL_STRING("example10.com"));
|
NS_LITERAL_STRING("example10.com"),
|
||||||
|
&GMPStorageTest::TestAsyncShutdownTimeout3);
|
||||||
|
};
|
||||||
|
|
||||||
|
void TestAsyncShutdownTimeout3() {
|
||||||
CreateAsyncShutdownTimeoutGMP(NS_LITERAL_STRING("example11.com"),
|
CreateAsyncShutdownTimeoutGMP(NS_LITERAL_STRING("example11.com"),
|
||||||
NS_LITERAL_STRING("example12.com"));
|
NS_LITERAL_STRING("example12.com"),
|
||||||
SetFinished();
|
&GMPStorageTest::SetFinished);
|
||||||
};
|
};
|
||||||
|
|
||||||
void TestAsyncShutdownStorage() {
|
void TestAsyncShutdownStorage() {
|
||||||
// Test that a GMP can write to storage during shutdown, and retrieve
|
|
||||||
// that written data in a subsequent session.
|
|
||||||
CreateDecryptor(NS_LITERAL_STRING("example13.com"),
|
|
||||||
NS_LITERAL_STRING("example14.com"),
|
|
||||||
false);
|
|
||||||
|
|
||||||
// Instruct the GMP to write a token (the current timestamp, so it's
|
// Instruct the GMP to write a token (the current timestamp, so it's
|
||||||
// unique) during async shutdown, then shutdown the plugin, re-create
|
// unique) during async shutdown, then shutdown the plugin, re-create
|
||||||
// it, and check that the token was successfully stored.
|
// it, and check that the token was successfully stored.
|
||||||
@ -896,7 +1117,12 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
|
|||||||
Expect(response, NS_NewRunnableMethodWithArg<nsCString>(this,
|
Expect(response, NS_NewRunnableMethodWithArg<nsCString>(this,
|
||||||
&GMPStorageTest::TestAsyncShutdownStorage_ReceivedShutdownToken, token));
|
&GMPStorageTest::TestAsyncShutdownStorage_ReceivedShutdownToken, token));
|
||||||
|
|
||||||
Update(update);
|
// Test that a GMP can write to storage during shutdown, and retrieve
|
||||||
|
// that written data in a subsequent session.
|
||||||
|
CreateDecryptor(NS_LITERAL_STRING("example13.com"),
|
||||||
|
NS_LITERAL_STRING("example14.com"),
|
||||||
|
false,
|
||||||
|
update);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestAsyncShutdownStorage_ReceivedShutdownToken(const nsCString& aToken) {
|
void TestAsyncShutdownStorage_ReceivedShutdownToken(const nsCString& aToken) {
|
||||||
@ -907,37 +1133,39 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
|
|||||||
void TestAsyncShutdownStorage_AsyncShutdownComplete(const nsCString& aToken) {
|
void TestAsyncShutdownStorage_AsyncShutdownComplete(const nsCString& aToken) {
|
||||||
// Create a new instance of the plugin, retrieve the token written
|
// Create a new instance of the plugin, retrieve the token written
|
||||||
// during shutdown and verify it is correct.
|
// during shutdown and verify it is correct.
|
||||||
CreateDecryptor(NS_LITERAL_STRING("example13.com"),
|
|
||||||
NS_LITERAL_STRING("example14.com"),
|
|
||||||
false);
|
|
||||||
nsCString response("retrieved shutdown-token ");
|
nsCString response("retrieved shutdown-token ");
|
||||||
response.Append(aToken);
|
response.Append(aToken);
|
||||||
Expect(response,
|
Expect(response,
|
||||||
NS_NewRunnableMethod(this, &GMPStorageTest::SetFinished));
|
NS_NewRunnableMethod(this, &GMPStorageTest::SetFinished));
|
||||||
Update(NS_LITERAL_CSTRING("retrieve-shutdown-token"));
|
|
||||||
|
CreateDecryptor(NS_LITERAL_STRING("example13.com"),
|
||||||
|
NS_LITERAL_STRING("example14.com"),
|
||||||
|
false,
|
||||||
|
NS_LITERAL_CSTRING("retrieve-shutdown-token"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(XP_WIN)
|
#if defined(XP_WIN)
|
||||||
void TestOutputProtection() {
|
void TestOutputProtection() {
|
||||||
Shutdown();
|
Shutdown();
|
||||||
|
|
||||||
CreateDecryptor(NS_LITERAL_STRING("example15.com"),
|
|
||||||
NS_LITERAL_STRING("example16.com"),
|
|
||||||
false);
|
|
||||||
|
|
||||||
Expect(NS_LITERAL_CSTRING("OP tests completed"),
|
Expect(NS_LITERAL_CSTRING("OP tests completed"),
|
||||||
NS_NewRunnableMethod(this, &GMPStorageTest::SetFinished));
|
NS_NewRunnableMethod(this, &GMPStorageTest::SetFinished));
|
||||||
Update(NS_LITERAL_CSTRING("test-op-apis"));
|
|
||||||
|
CreateDecryptor(NS_LITERAL_STRING("example15.com"),
|
||||||
|
NS_LITERAL_STRING("example16.com"),
|
||||||
|
false,
|
||||||
|
NS_LITERAL_CSTRING("test-op-apis"));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void TestPluginVoucher() {
|
void TestPluginVoucher() {
|
||||||
CreateDecryptor(NS_LITERAL_STRING("example17.com"),
|
|
||||||
NS_LITERAL_STRING("example18.com"),
|
|
||||||
false);
|
|
||||||
Expect(NS_LITERAL_CSTRING("retrieved plugin-voucher: gmp-fake placeholder voucher"),
|
Expect(NS_LITERAL_CSTRING("retrieved plugin-voucher: gmp-fake placeholder voucher"),
|
||||||
NS_NewRunnableMethod(this, &GMPStorageTest::SetFinished));
|
NS_NewRunnableMethod(this, &GMPStorageTest::SetFinished));
|
||||||
Update(NS_LITERAL_CSTRING("retrieve-plugin-voucher"));
|
|
||||||
|
CreateDecryptor(NS_LITERAL_STRING("example17.com"),
|
||||||
|
NS_LITERAL_STRING("example18.com"),
|
||||||
|
false,
|
||||||
|
NS_LITERAL_CSTRING("retrieve-plugin-voucher"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestGetRecordNamesInMemoryStorage() {
|
void TestGetRecordNamesInMemoryStorage() {
|
||||||
@ -954,12 +1182,9 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TestGetRecordNames(bool aPrivateBrowsing) {
|
void TestGetRecordNames(bool aPrivateBrowsing) {
|
||||||
CreateDecryptor(NS_LITERAL_STRING("foo.com"),
|
|
||||||
NS_LITERAL_STRING("bar.com"),
|
|
||||||
aPrivateBrowsing);
|
|
||||||
|
|
||||||
// Create a number of records of different names.
|
// Create a number of records of different names.
|
||||||
const uint32_t num = 100;
|
const uint32_t num = 100;
|
||||||
|
nsTArray<nsCString> updates(num);
|
||||||
for (uint32_t i = 0; i < num; i++) {
|
for (uint32_t i = 0; i < num; i++) {
|
||||||
nsAutoCString response;
|
nsAutoCString response;
|
||||||
response.AppendLiteral("stored data");
|
response.AppendLiteral("stored data");
|
||||||
@ -973,7 +1198,7 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
|
|||||||
mRecordNames.AppendLiteral("data");
|
mRecordNames.AppendLiteral("data");
|
||||||
AppendIntPadded(mRecordNames, i);
|
AppendIntPadded(mRecordNames, i);
|
||||||
|
|
||||||
nsAutoCString update;
|
nsCString& update = *updates.AppendElement();
|
||||||
update.AppendLiteral("store data");
|
update.AppendLiteral("store data");
|
||||||
AppendIntPadded(update, i);
|
AppendIntPadded(update, i);
|
||||||
update.AppendLiteral(" test-data");
|
update.AppendLiteral(" test-data");
|
||||||
@ -985,8 +1210,12 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
|
|||||||
NS_NewRunnableMethod(this, &GMPStorageTest::TestGetRecordNames_QueryNames);
|
NS_NewRunnableMethod(this, &GMPStorageTest::TestGetRecordNames_QueryNames);
|
||||||
}
|
}
|
||||||
Expect(response, continuation);
|
Expect(response, continuation);
|
||||||
Update(update);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CreateDecryptor(NS_LITERAL_STRING("foo.com"),
|
||||||
|
NS_LITERAL_STRING("bar.com"),
|
||||||
|
aPrivateBrowsing,
|
||||||
|
Move(updates));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestGetRecordNames_QueryNames() {
|
void TestGetRecordNames_QueryNames() {
|
||||||
@ -1026,10 +1255,6 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
|
|||||||
MOZ_ASSERT(longRecordName.Length() < GMP_MAX_RECORD_NAME_SIZE);
|
MOZ_ASSERT(longRecordName.Length() < GMP_MAX_RECORD_NAME_SIZE);
|
||||||
MOZ_ASSERT(longRecordName.Length() > 260); // Windows MAX_PATH
|
MOZ_ASSERT(longRecordName.Length() > 260); // Windows MAX_PATH
|
||||||
|
|
||||||
CreateDecryptor(NS_LITERAL_STRING("fuz.com"),
|
|
||||||
NS_LITERAL_STRING("baz.com"),
|
|
||||||
false);
|
|
||||||
|
|
||||||
nsCString response("stored ");
|
nsCString response("stored ");
|
||||||
response.Append(longRecordName);
|
response.Append(longRecordName);
|
||||||
response.AppendLiteral(" ");
|
response.AppendLiteral(" ");
|
||||||
@ -1040,7 +1265,10 @@ class GMPStorageTest : public GMPDecryptorProxyCallback
|
|||||||
update.Append(longRecordName);
|
update.Append(longRecordName);
|
||||||
update.AppendLiteral(" ");
|
update.AppendLiteral(" ");
|
||||||
update.Append(data);
|
update.Append(data);
|
||||||
Update(update);
|
CreateDecryptor(NS_LITERAL_STRING("fuz.com"),
|
||||||
|
NS_LITERAL_STRING("baz.com"),
|
||||||
|
false,
|
||||||
|
update);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Expect(const nsCString& aMessage, nsIRunnable* aContinuation) {
|
void Expect(const nsCString& aMessage, nsIRunnable* aContinuation) {
|
||||||
@ -1147,24 +1375,31 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
GMPTestRunner::DoTest(void (GMPTestRunner::*aTestMethod)())
|
GMPTestRunner::DoTest(void (GMPTestRunner::*aTestMethod)(GMPTestMonitor&))
|
||||||
{
|
{
|
||||||
nsRefPtr<GeckoMediaPluginService> service =
|
nsCOMPtr<nsIThread> thread(GetGMPThread());
|
||||||
GeckoMediaPluginService::GetGeckoMediaPluginService();
|
|
||||||
nsCOMPtr<nsIThread> thread;
|
|
||||||
|
|
||||||
service->GetThread(getter_AddRefs(thread));
|
GMPTestMonitor monitor;
|
||||||
thread->Dispatch(NS_NewRunnableMethod(this, aTestMethod), NS_DISPATCH_SYNC);
|
thread->Dispatch(NS_NewRunnableMethodWithArg<GMPTestMonitor&>(this,
|
||||||
|
aTestMethod,
|
||||||
|
monitor),
|
||||||
|
NS_DISPATCH_NORMAL);
|
||||||
|
monitor.AwaitFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(GeckoMediaPlugins, GMPTestCodec) {
|
TEST(GeckoMediaPlugins, GMPTestCodec) {
|
||||||
nsRefPtr<GMPTestRunner> runner = new GMPTestRunner();
|
nsRefPtr<GMPTestRunner> runner = new GMPTestRunner();
|
||||||
runner->DoTest(&GMPTestRunner::RunTestGMPTestCodec);
|
runner->DoTest(&GMPTestRunner::RunTestGMPTestCodec1);
|
||||||
|
runner->DoTest(&GMPTestRunner::RunTestGMPTestCodec2);
|
||||||
|
runner->DoTest(&GMPTestRunner::RunTestGMPTestCodec3);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(GeckoMediaPlugins, GMPCrossOrigin) {
|
TEST(GeckoMediaPlugins, GMPCrossOrigin) {
|
||||||
nsRefPtr<GMPTestRunner> runner = new GMPTestRunner();
|
nsRefPtr<GMPTestRunner> runner = new GMPTestRunner();
|
||||||
runner->DoTest(&GMPTestRunner::RunTestGMPCrossOrigin);
|
runner->DoTest(&GMPTestRunner::RunTestGMPCrossOrigin1);
|
||||||
|
runner->DoTest(&GMPTestRunner::RunTestGMPCrossOrigin2);
|
||||||
|
runner->DoTest(&GMPTestRunner::RunTestGMPCrossOrigin3);
|
||||||
|
runner->DoTest(&GMPTestRunner::RunTestGMPCrossOrigin4);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(GeckoMediaPlugins, GMPStorageGetNodeId) {
|
TEST(GeckoMediaPlugins, GMPStorageGetNodeId) {
|
||||||
|
@ -151,36 +151,57 @@ WebrtcGmpVideoEncoder::InitEncode(const webrtc::VideoCodec* aCodecSettings,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t ret;
|
nsCOMPtr<nsIThread> currentThread(do_GetCurrentThread());
|
||||||
mGMPThread->Dispatch(WrapRunnableRet(this,
|
MOZ_ASSERT(currentThread != mGMPThread);
|
||||||
|
|
||||||
|
nsRefPtr<InitDoneRunnable> initDone(new InitDoneRunnable());
|
||||||
|
mGMPThread->Dispatch(WrapRunnable(this,
|
||||||
&WebrtcGmpVideoEncoder::InitEncode_g,
|
&WebrtcGmpVideoEncoder::InitEncode_g,
|
||||||
aCodecSettings,
|
aCodecSettings,
|
||||||
aNumberOfCores,
|
aNumberOfCores,
|
||||||
aMaxPayloadSize,
|
aMaxPayloadSize,
|
||||||
&ret),
|
initDone),
|
||||||
NS_DISPATCH_SYNC);
|
NS_DISPATCH_NORMAL);
|
||||||
|
|
||||||
return ret;
|
|
||||||
|
while (!initDone->IsDone()) {
|
||||||
|
NS_ProcessNextEvent(currentThread, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return initDone->Result();
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t
|
void
|
||||||
WebrtcGmpVideoEncoder::InitEncode_g(const webrtc::VideoCodec* aCodecSettings,
|
WebrtcGmpVideoEncoder::InitEncode_g(const webrtc::VideoCodec* aCodecSettings,
|
||||||
int32_t aNumberOfCores,
|
int32_t aNumberOfCores,
|
||||||
uint32_t aMaxPayloadSize)
|
uint32_t aMaxPayloadSize,
|
||||||
|
InitDoneRunnable* aInitDone)
|
||||||
{
|
{
|
||||||
nsTArray<nsCString> tags;
|
nsTArray<nsCString> tags;
|
||||||
tags.AppendElement(NS_LITERAL_CSTRING("h264"));
|
tags.AppendElement(NS_LITERAL_CSTRING("h264"));
|
||||||
if (NS_WARN_IF(NS_FAILED(mMPS->GetGMPVideoEncoder(&tags,
|
UniquePtr<GetGMPVideoEncoderCallback> callback(
|
||||||
|
new InitDoneCallback(this, aInitDone, aCodecSettings, aMaxPayloadSize));
|
||||||
|
nsresult rv = mMPS->GetGMPVideoEncoder(&tags,
|
||||||
NS_LITERAL_CSTRING(""),
|
NS_LITERAL_CSTRING(""),
|
||||||
&mHost,
|
Move(callback));
|
||||||
&mGMP)))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
mMPS = nullptr;
|
mMPS = nullptr;
|
||||||
mGMP = nullptr;
|
mGMP = nullptr;
|
||||||
mGMPThread = nullptr;
|
mGMPThread = nullptr;
|
||||||
mHost = nullptr;
|
mHost = nullptr;
|
||||||
return WEBRTC_VIDEO_CODEC_ERROR;
|
aInitDone->Dispatch(WEBRTC_VIDEO_CODEC_ERROR);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t
|
||||||
|
WebrtcGmpVideoEncoder::GmpInitDone(GMPVideoEncoderProxy* aGMP,
|
||||||
|
GMPVideoHost* aHost,
|
||||||
|
const webrtc::VideoCodec* aCodecSettings,
|
||||||
|
uint32_t aMaxPayloadSize)
|
||||||
|
{
|
||||||
|
mGMP = aGMP;
|
||||||
|
mHost = aHost;
|
||||||
if (!mGMP || !mHost) {
|
if (!mGMP || !mHost) {
|
||||||
return WEBRTC_VIDEO_CODEC_ERROR;
|
return WEBRTC_VIDEO_CODEC_ERROR;
|
||||||
}
|
}
|
||||||
@ -189,8 +210,6 @@ WebrtcGmpVideoEncoder::InitEncode_g(const webrtc::VideoCodec* aCodecSettings,
|
|||||||
memset(&mCodecParams, 0, sizeof(mCodecParams));
|
memset(&mCodecParams, 0, sizeof(mCodecParams));
|
||||||
|
|
||||||
mCodecParams.mGMPApiVersion = 33;
|
mCodecParams.mGMPApiVersion = 33;
|
||||||
mCodecParams.mWidth = aCodecSettings->width;
|
|
||||||
mCodecParams.mHeight = aCodecSettings->height;
|
|
||||||
mCodecParams.mStartBitrate = aCodecSettings->startBitrate;
|
mCodecParams.mStartBitrate = aCodecSettings->startBitrate;
|
||||||
mCodecParams.mMinBitrate = aCodecSettings->minBitrate;
|
mCodecParams.mMinBitrate = aCodecSettings->minBitrate;
|
||||||
mCodecParams.mMaxBitrate = aCodecSettings->maxBitrate;
|
mCodecParams.mMaxBitrate = aCodecSettings->maxBitrate;
|
||||||
@ -206,6 +225,14 @@ WebrtcGmpVideoEncoder::InitEncode_g(const webrtc::VideoCodec* aCodecSettings,
|
|||||||
mCodecParams.mMode = kGMPRealtimeVideo;
|
mCodecParams.mMode = kGMPRealtimeVideo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return InitEncoderForSize(aCodecSettings->width, aCodecSettings->height);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t
|
||||||
|
WebrtcGmpVideoEncoder::InitEncoderForSize(unsigned short aWidth, unsigned short aHeight)
|
||||||
|
{
|
||||||
|
mCodecParams.mWidth = aWidth;
|
||||||
|
mCodecParams.mHeight = aHeight;
|
||||||
// Pass dummy codecSpecific data for now...
|
// Pass dummy codecSpecific data for now...
|
||||||
nsTArray<uint8_t> codecSpecific;
|
nsTArray<uint8_t> codecSpecific;
|
||||||
|
|
||||||
@ -223,8 +250,37 @@ WebrtcGmpVideoEncoder::Encode(const webrtc::I420VideoFrame& aInputImage,
|
|||||||
const webrtc::CodecSpecificInfo* aCodecSpecificInfo,
|
const webrtc::CodecSpecificInfo* aCodecSpecificInfo,
|
||||||
const std::vector<webrtc::VideoFrameType>* aFrameTypes)
|
const std::vector<webrtc::VideoFrameType>* aFrameTypes)
|
||||||
{
|
{
|
||||||
|
MOZ_ASSERT(mHost);
|
||||||
|
if (!mGMP) {
|
||||||
|
// destroyed via Terminate()
|
||||||
|
return WEBRTC_VIDEO_CODEC_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(aInputImage.width() >= 0 && aInputImage.height() >= 0);
|
||||||
|
if (static_cast<uint32_t>(aInputImage.width()) != mCodecParams.mWidth ||
|
||||||
|
static_cast<uint32_t>(aInputImage.height()) != mCodecParams.mHeight) {
|
||||||
|
LOGD(("GMP Encode: resolution change from %ux%u to %dx%d",
|
||||||
|
mCodecParams.mWidth, mCodecParams.mHeight, aInputImage.width(), aInputImage.height()));
|
||||||
|
|
||||||
|
nsRefPtr<InitDoneRunnable> initDone(new InitDoneRunnable());
|
||||||
|
nsCOMPtr<nsIRunnable> task(
|
||||||
|
WrapRunnable(this,
|
||||||
|
&WebrtcGmpVideoEncoder::RegetEncoderForResolutionChange,
|
||||||
|
&aInputImage,
|
||||||
|
initDone));
|
||||||
|
mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIThread> currentThread(do_GetCurrentThread());
|
||||||
|
while (!initDone->IsDone()) {
|
||||||
|
NS_ProcessNextEvent(currentThread, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (initDone->Result() != WEBRTC_VIDEO_CODEC_OK) {
|
||||||
|
return initDone->Result();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int32_t ret;
|
int32_t ret;
|
||||||
MOZ_ASSERT(mGMPThread);
|
|
||||||
mozilla::SyncRunnable::DispatchToThread(mGMPThread,
|
mozilla::SyncRunnable::DispatchToThread(mGMPThread,
|
||||||
WrapRunnableRet(this,
|
WrapRunnableRet(this,
|
||||||
&WebrtcGmpVideoEncoder::Encode_g,
|
&WebrtcGmpVideoEncoder::Encode_g,
|
||||||
@ -236,25 +292,17 @@ WebrtcGmpVideoEncoder::Encode(const webrtc::I420VideoFrame& aInputImage,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t
|
void
|
||||||
WebrtcGmpVideoEncoder::Encode_g(const webrtc::I420VideoFrame* aInputImage,
|
WebrtcGmpVideoEncoder::RegetEncoderForResolutionChange(const webrtc::I420VideoFrame* aInputImage,
|
||||||
const webrtc::CodecSpecificInfo* aCodecSpecificInfo,
|
InitDoneRunnable* aInitDone)
|
||||||
const std::vector<webrtc::VideoFrameType>* aFrameTypes)
|
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(mHost);
|
|
||||||
if (!mGMP) {
|
|
||||||
// destroyed via Terminate()
|
|
||||||
return WEBRTC_VIDEO_CODEC_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
MOZ_ASSERT(aInputImage->width() >= 0 && aInputImage->height() >= 0);
|
|
||||||
if (static_cast<uint32_t>(aInputImage->width()) != mCodecParams.mWidth ||
|
|
||||||
static_cast<uint32_t>(aInputImage->height()) != mCodecParams.mHeight) {
|
|
||||||
LOGD(("GMP Encode: resolution change from %ux%u to %dx%d",
|
|
||||||
mCodecParams.mWidth, mCodecParams.mHeight, aInputImage->width(), aInputImage->height()));
|
|
||||||
|
|
||||||
mGMP->Close();
|
mGMP->Close();
|
||||||
|
|
||||||
|
UniquePtr<GetGMPVideoEncoderCallback> callback(
|
||||||
|
new InitDoneForResolutionChangeCallback(this, aInitDone,
|
||||||
|
aInputImage->width(),
|
||||||
|
aInputImage->height()));
|
||||||
|
|
||||||
// OpenH264 codec (at least) can't handle dynamic input resolution changes
|
// OpenH264 codec (at least) can't handle dynamic input resolution changes
|
||||||
// re-init the plugin when the resolution changes
|
// re-init the plugin when the resolution changes
|
||||||
// XXX allow codec to indicate it doesn't need re-init!
|
// XXX allow codec to indicate it doesn't need re-init!
|
||||||
@ -262,23 +310,20 @@ WebrtcGmpVideoEncoder::Encode_g(const webrtc::I420VideoFrame* aInputImage,
|
|||||||
tags.AppendElement(NS_LITERAL_CSTRING("h264"));
|
tags.AppendElement(NS_LITERAL_CSTRING("h264"));
|
||||||
if (NS_WARN_IF(NS_FAILED(mMPS->GetGMPVideoEncoder(&tags,
|
if (NS_WARN_IF(NS_FAILED(mMPS->GetGMPVideoEncoder(&tags,
|
||||||
NS_LITERAL_CSTRING(""),
|
NS_LITERAL_CSTRING(""),
|
||||||
&mHost,
|
Move(callback))))) {
|
||||||
&mGMP)))) {
|
|
||||||
mGMP = nullptr;
|
mGMP = nullptr;
|
||||||
mHost = nullptr;
|
mHost = nullptr;
|
||||||
return WEBRTC_VIDEO_CODEC_ERROR;
|
aInitDone->Dispatch(WEBRTC_VIDEO_CODEC_ERROR);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mCodecParams.mWidth = aInputImage->width();
|
int32_t
|
||||||
mCodecParams.mHeight = aInputImage->height();
|
WebrtcGmpVideoEncoder::Encode_g(const webrtc::I420VideoFrame* aInputImage,
|
||||||
// Pass dummy codecSpecific data for now...
|
const webrtc::CodecSpecificInfo* aCodecSpecificInfo,
|
||||||
nsTArray<uint8_t> codecSpecific;
|
const std::vector<webrtc::VideoFrameType>* aFrameTypes)
|
||||||
|
{
|
||||||
GMPErr err = mGMP->InitEncode(mCodecParams, codecSpecific, this, 1, mMaxPayloadSize);
|
MOZ_ASSERT(mHost);
|
||||||
if (err != GMPNoErr) {
|
MOZ_ASSERT(mGMP);
|
||||||
return WEBRTC_VIDEO_CODEC_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GMPVideoFrame* ftmp = nullptr;
|
GMPVideoFrame* ftmp = nullptr;
|
||||||
GMPErr err = mHost->CreateFrame(kGMPI420VideoFrame, &ftmp);
|
GMPErr err = mHost->CreateFrame(kGMPI420VideoFrame, &ftmp);
|
||||||
@ -566,33 +611,48 @@ WebrtcGmpVideoDecoder::InitDecode(const webrtc::VideoCodec* aCodecSettings,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t ret;
|
nsRefPtr<InitDoneRunnable> initDone(new InitDoneRunnable());
|
||||||
mGMPThread->Dispatch(WrapRunnableRet(this,
|
mGMPThread->Dispatch(WrapRunnable(this,
|
||||||
&WebrtcGmpVideoDecoder::InitDecode_g,
|
&WebrtcGmpVideoDecoder::InitDecode_g,
|
||||||
aCodecSettings,
|
aCodecSettings,
|
||||||
aNumberOfCores,
|
aNumberOfCores,
|
||||||
&ret),
|
initDone.get()),
|
||||||
NS_DISPATCH_SYNC);
|
NS_DISPATCH_NORMAL);
|
||||||
|
|
||||||
return ret;
|
nsCOMPtr<nsIThread> currentThread(do_GetCurrentThread());
|
||||||
|
while (!initDone->IsDone()) {
|
||||||
|
NS_ProcessNextEvent(currentThread, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return initDone->Result();
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t
|
void
|
||||||
WebrtcGmpVideoDecoder::InitDecode_g(const webrtc::VideoCodec* aCodecSettings,
|
WebrtcGmpVideoDecoder::InitDecode_g(const webrtc::VideoCodec* aCodecSettings,
|
||||||
int32_t aNumberOfCores)
|
int32_t aNumberOfCores,
|
||||||
|
InitDoneRunnable* aInitDone)
|
||||||
{
|
{
|
||||||
nsTArray<nsCString> tags;
|
nsTArray<nsCString> tags;
|
||||||
tags.AppendElement(NS_LITERAL_CSTRING("h264"));
|
tags.AppendElement(NS_LITERAL_CSTRING("h264"));
|
||||||
|
UniquePtr<GetGMPVideoDecoderCallback> callback(
|
||||||
|
new InitDoneCallback(this, aInitDone));
|
||||||
if (NS_WARN_IF(NS_FAILED(mMPS->GetGMPVideoDecoder(&tags,
|
if (NS_WARN_IF(NS_FAILED(mMPS->GetGMPVideoDecoder(&tags,
|
||||||
NS_LITERAL_CSTRING(""),
|
NS_LITERAL_CSTRING(""),
|
||||||
&mHost,
|
Move(callback))))) {
|
||||||
&mGMP)))) {
|
|
||||||
mMPS = nullptr;
|
mMPS = nullptr;
|
||||||
mGMP = nullptr;
|
mGMP = nullptr;
|
||||||
mGMPThread = nullptr;
|
mGMPThread = nullptr;
|
||||||
mHost = nullptr;
|
mHost = nullptr;
|
||||||
return WEBRTC_VIDEO_CODEC_ERROR;
|
aInitDone->Dispatch(WEBRTC_VIDEO_CODEC_ERROR);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t
|
||||||
|
WebrtcGmpVideoDecoder::GmpInitDone(GMPVideoDecoderProxy* aGMP,
|
||||||
|
GMPVideoHost* aHost)
|
||||||
|
{
|
||||||
|
mGMP = aGMP;
|
||||||
|
mHost = aHost;
|
||||||
mMPS = nullptr;
|
mMPS = nullptr;
|
||||||
|
|
||||||
if (!mGMP || !mHost) {
|
if (!mGMP || !mHost) {
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
|
#include "mozilla/Monitor.h"
|
||||||
#include "mozilla/Mutex.h"
|
#include "mozilla/Mutex.h"
|
||||||
|
|
||||||
#include "mozIGeckoMediaPluginService.h"
|
#include "mozIGeckoMediaPluginService.h"
|
||||||
@ -77,13 +78,131 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual int32_t InitEncode_g(const webrtc::VideoCodec* aCodecSettings,
|
class InitDoneRunnable : public nsRunnable
|
||||||
int32_t aNumberOfCores,
|
{
|
||||||
uint32_t aMaxPayloadSize);
|
public:
|
||||||
|
InitDoneRunnable()
|
||||||
|
: mInitDone(false),
|
||||||
|
mResult(WEBRTC_VIDEO_CODEC_OK),
|
||||||
|
mThread(do_GetCurrentThread())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
virtual int32_t Encode_g(const webrtc::I420VideoFrame* aInputImage,
|
NS_IMETHOD Run()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mThread == nsCOMPtr<nsIThread>(do_GetCurrentThread()));
|
||||||
|
mInitDone = true;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Dispatch(int32_t aResult)
|
||||||
|
{
|
||||||
|
mResult = aResult;
|
||||||
|
mThread->Dispatch(this, NS_DISPATCH_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsDone()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(nsCOMPtr<nsIThread>(do_GetCurrentThread()) == mThread);
|
||||||
|
return mInitDone;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t Result()
|
||||||
|
{
|
||||||
|
return mResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool mInitDone;
|
||||||
|
int32_t mResult;
|
||||||
|
nsCOMPtr<nsIThread> mThread;
|
||||||
|
};
|
||||||
|
|
||||||
|
void InitEncode_g(const webrtc::VideoCodec* aCodecSettings,
|
||||||
|
int32_t aNumberOfCores,
|
||||||
|
uint32_t aMaxPayloadSize,
|
||||||
|
InitDoneRunnable* aInitDone);
|
||||||
|
int32_t GmpInitDone(GMPVideoEncoderProxy* aGMP, GMPVideoHost* aHost,
|
||||||
|
const webrtc::VideoCodec* aCodecSettings,
|
||||||
|
uint32_t aMaxPayloadSize);
|
||||||
|
int32_t InitEncoderForSize(unsigned short aWidth, unsigned short aHeight);
|
||||||
|
|
||||||
|
class InitDoneCallback : public GetGMPVideoEncoderCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
InitDoneCallback(WebrtcGmpVideoEncoder* aEncoder,
|
||||||
|
InitDoneRunnable* aInitDone,
|
||||||
|
const webrtc::VideoCodec* aCodecSettings,
|
||||||
|
uint32_t aMaxPayloadSize)
|
||||||
|
: mEncoder(aEncoder),
|
||||||
|
mInitDone(aInitDone),
|
||||||
|
mCodecSettings(aCodecSettings),
|
||||||
|
mMaxPayloadSize(aMaxPayloadSize)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void Done(GMPVideoEncoderProxy* aGMP, GMPVideoHost* aHost) override
|
||||||
|
{
|
||||||
|
mEncoder->mGMP = aGMP;
|
||||||
|
mEncoder->mHost = aHost;
|
||||||
|
int32_t result;
|
||||||
|
if (aGMP || aHost) {
|
||||||
|
result = mEncoder->GmpInitDone(aGMP, aHost, mCodecSettings,
|
||||||
|
mMaxPayloadSize);
|
||||||
|
} else {
|
||||||
|
result = WEBRTC_VIDEO_CODEC_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
mInitDone->Dispatch(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
WebrtcGmpVideoEncoder* mEncoder;
|
||||||
|
nsRefPtr<InitDoneRunnable> mInitDone;
|
||||||
|
const webrtc::VideoCodec* mCodecSettings;
|
||||||
|
uint32_t mMaxPayloadSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
int32_t Encode_g(const webrtc::I420VideoFrame* aInputImage,
|
||||||
const webrtc::CodecSpecificInfo* aCodecSpecificInfo,
|
const webrtc::CodecSpecificInfo* aCodecSpecificInfo,
|
||||||
const std::vector<webrtc::VideoFrameType>* aFrameTypes);
|
const std::vector<webrtc::VideoFrameType>* aFrameTypes);
|
||||||
|
void RegetEncoderForResolutionChange(const webrtc::I420VideoFrame* aInputImage,
|
||||||
|
InitDoneRunnable* aInitDone);
|
||||||
|
|
||||||
|
class InitDoneForResolutionChangeCallback : public GetGMPVideoEncoderCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
InitDoneForResolutionChangeCallback(WebrtcGmpVideoEncoder* aEncoder,
|
||||||
|
InitDoneRunnable* aInitDone,
|
||||||
|
uint32_t aWidth,
|
||||||
|
uint32_t aHeight)
|
||||||
|
: mEncoder(aEncoder),
|
||||||
|
mInitDone(aInitDone),
|
||||||
|
mWidth(aWidth),
|
||||||
|
mHeight(aHeight)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void Done(GMPVideoEncoderProxy* aGMP, GMPVideoHost* aHost) override
|
||||||
|
{
|
||||||
|
mEncoder->mGMP = aGMP;
|
||||||
|
mEncoder->mHost = aHost;
|
||||||
|
int32_t result;
|
||||||
|
if (aGMP && aHost) {
|
||||||
|
result = mEncoder->InitEncoderForSize(mWidth, mHeight);
|
||||||
|
} else {
|
||||||
|
result = WEBRTC_VIDEO_CODEC_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
mInitDone->Dispatch(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
WebrtcGmpVideoEncoder* mEncoder;
|
||||||
|
nsRefPtr<InitDoneRunnable> mInitDone;
|
||||||
|
uint32_t mWidth;
|
||||||
|
uint32_t mHeight;
|
||||||
|
};
|
||||||
|
|
||||||
virtual int32_t SetRates_g(uint32_t aNewBitRate,
|
virtual int32_t SetRates_g(uint32_t aNewBitRate,
|
||||||
uint32_t aFrameRate);
|
uint32_t aFrameRate);
|
||||||
@ -151,8 +270,72 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual int32_t InitDecode_g(const webrtc::VideoCodec* aCodecSettings,
|
class InitDoneRunnable : public nsRunnable
|
||||||
int32_t aNumberOfCores);
|
{
|
||||||
|
public:
|
||||||
|
InitDoneRunnable()
|
||||||
|
: mInitDone(false),
|
||||||
|
mResult(WEBRTC_VIDEO_CODEC_OK),
|
||||||
|
mThread(do_GetCurrentThread())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHOD Run()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mThread == nsCOMPtr<nsIThread>(do_GetCurrentThread()));
|
||||||
|
mInitDone = true;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Dispatch(int32_t aResult)
|
||||||
|
{
|
||||||
|
mResult = aResult;
|
||||||
|
mThread->Dispatch(this, NS_DISPATCH_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsDone()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(nsCOMPtr<nsIThread>(do_GetCurrentThread()) == mThread);
|
||||||
|
return mInitDone;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t Result()
|
||||||
|
{
|
||||||
|
return mResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool mInitDone;
|
||||||
|
int32_t mResult;
|
||||||
|
nsCOMPtr<nsIThread> mThread;
|
||||||
|
};
|
||||||
|
|
||||||
|
void InitDecode_g(const webrtc::VideoCodec* aCodecSettings,
|
||||||
|
int32_t aNumberOfCores,
|
||||||
|
InitDoneRunnable* aInitDone);
|
||||||
|
int32_t GmpInitDone(GMPVideoDecoderProxy* aGMP, GMPVideoHost* aHost);
|
||||||
|
|
||||||
|
class InitDoneCallback : public GetGMPVideoDecoderCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit InitDoneCallback(WebrtcGmpVideoDecoder* aDecoder,
|
||||||
|
InitDoneRunnable* aInitDone)
|
||||||
|
: mDecoder(aDecoder),
|
||||||
|
mInitDone(aInitDone)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void Done(GMPVideoDecoderProxy* aGMP, GMPVideoHost* aHost)
|
||||||
|
{
|
||||||
|
int32_t result = mDecoder->GmpInitDone(aGMP, aHost);
|
||||||
|
|
||||||
|
mInitDone->Dispatch(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
WebrtcGmpVideoDecoder* mDecoder;
|
||||||
|
nsRefPtr<InitDoneRunnable> mInitDone;
|
||||||
|
};
|
||||||
|
|
||||||
virtual int32_t Decode_g(const webrtc::EncodedImage& aInputImage,
|
virtual int32_t Decode_g(const webrtc::EncodedImage& aInputImage,
|
||||||
bool aMissingFrames,
|
bool aMissingFrames,
|
||||||
|
Loading…
Reference in New Issue
Block a user