Bug 1351953 - Send Data to CDM for decrypt and or decode in shmems. r=gerald
MozReview-Commit-ID: 2UdGimoOLKr
--- a/dom/media/gmp/ChromiumCDMChild.cpp
+++ b/dom/media/gmp/ChromiumCDMChild.cpp
@@ -9,16 +9,17 @@
#include "WidevineFileIO.h"
#include "WidevineVideoFrame.h"
#include "GMPLog.h"
#include "GMPPlatform.h"
#include "mozilla/Unused.h"
#include "nsPrintfCString.h"
#include "base/time.h"
#include "GMPUtils.h"
+#include "mozilla/ScopeExit.h"
namespace mozilla {
namespace gmp {
ChromiumCDMChild::ChromiumCDMChild(GMPContentChild* aPlugin)
: mPlugin(aPlugin)
{
MOZ_ASSERT(IsOnMessageLoopThread());
@@ -383,18 +384,18 @@ ChromiumCDMChild::DecryptFailed(uint32_t
Unused << SendDecrypted(aId, aStatus, nsTArray<uint8_t>());
}
static void
InitInputBuffer(const CDMInputBuffer& aBuffer,
nsTArray<cdm::SubsampleEntry>& aSubSamples,
cdm::InputBuffer& aInputBuffer)
{
- aInputBuffer.data = aBuffer.mData().Elements();
- aInputBuffer.data_size = aBuffer.mData().Length();
+ aInputBuffer.data = aBuffer.mData().get<uint8_t>();
+ aInputBuffer.data_size = aBuffer.mData().Size<uint8_t>();
if (aBuffer.mIsEncrypted()) {
aInputBuffer.key_id = aBuffer.mKeyId().Elements();
aInputBuffer.key_id_size = aBuffer.mKeyId().Length();
aInputBuffer.iv = aBuffer.mIV().Elements();
aInputBuffer.iv_size = aBuffer.mIV().Length();
@@ -410,16 +411,21 @@ InitInputBuffer(const CDMInputBuffer& aB
}
mozilla::ipc::IPCResult
ChromiumCDMChild::RecvDecrypt(const uint32_t& aId,
const CDMInputBuffer& aBuffer)
{
MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild::RecvDecrypt()");
+
+ auto autoDeallocateShmem = MakeScopeExit([&,this] {
+ this->DeallocShmem(aBuffer.mData());
+ });
+
if (!mCDM) {
GMP_LOG("ChromiumCDMChild::RecvDecrypt() no CDM");
DecryptFailed(aId, cdm::kDecryptError);
return IPC_OK();
}
if (aBuffer.mClearBytes().Length() != aBuffer.mCipherBytes().Length()) {
GMP_LOG("ChromiumCDMChild::RecvDecrypt() clear/cipher bytes length doesn't "
"match");
@@ -435,17 +441,17 @@ ChromiumCDMChild::RecvDecrypt(const uint
cdm::Status status = mCDM->Decrypt(input, &output);
if (status != cdm::kSuccess) {
DecryptFailed(aId, status);
return IPC_OK();
}
if (!output.DecryptedBuffer() ||
- output.DecryptedBuffer()->Size() != aBuffer.mData().Length()) {
+ output.DecryptedBuffer()->Size() != aBuffer.mData().Size<uint8_t>()) {
// The sizes of the input and output should exactly match.
DecryptFailed(aId, cdm::kDecryptError);
return IPC_OK();
}
nsTArray<uint8_t> buf =
static_cast<WidevineBuffer*>(output.DecryptedBuffer())->ExtractBuffer();
Unused << SendDecrypted(aId, cdm::kSuccess, buf);
@@ -505,16 +511,20 @@ ChromiumCDMChild::RecvResetVideoDecoder(
mozilla::ipc::IPCResult
ChromiumCDMChild::RecvDecryptAndDecodeFrame(const CDMInputBuffer& aBuffer)
{
MOZ_ASSERT(IsOnMessageLoopThread());
GMP_LOG("ChromiumCDMChild::RecvDecryptAndDecodeFrame() t=%" PRId64 ")",
aBuffer.mTimestamp());
MOZ_ASSERT(mDecoderInitialized);
+ auto autoDeallocateShmem = MakeScopeExit([&, this] {
+ this->DeallocShmem(aBuffer.mData());
+ });
+
// The output frame may not have the same timestamp as the frame we put in.
// We may need to input a number of frames before we receive output. The
// CDM's decoder reorders to ensure frames output are in presentation order.
// So we need to store the durations of the frames input, and retrieve them
// on output.
mFrameDurations.Insert(aBuffer.mTimestamp(), aBuffer.mDuration());
cdm::InputBuffer input;
--- a/dom/media/gmp/ChromiumCDMParent.cpp
+++ b/dom/media/gmp/ChromiumCDMParent.cpp
@@ -164,29 +164,32 @@ ChromiumCDMParent::RemoveSession(const n
if (!SendRemoveSession(aPromiseId, aSessionId)) {
RejectPromise(
aPromiseId,
NS_ERROR_DOM_INVALID_STATE_ERR,
NS_LITERAL_CSTRING("Failed to send removeSession to CDM process"));
}
}
-static bool
-InitCDMInputBuffer(gmp::CDMInputBuffer& aBuffer, MediaRawData* aSample)
+bool
+ChromiumCDMParent::InitCDMInputBuffer(gmp::CDMInputBuffer& aBuffer, MediaRawData* aSample)
{
const CryptoSample& crypto = aSample->mCrypto;
if (crypto.mEncryptedSizes.Length() != crypto.mPlainSizes.Length()) {
GMP_LOG("InitCDMInputBuffer clear/cipher subsamples don't match");
return false;
}
- nsTArray<uint8_t> data;
- data.AppendElements(aSample->Data(), aSample->Size());
+ Shmem shmem;
+ if (!AllocShmem(aSample->Size(), Shmem::SharedMemory::TYPE_BASIC, &shmem)) {
+ return false;
+ }
+ memcpy(shmem.get<uint8_t>(), aSample->Data(), aSample->Size());
- aBuffer = gmp::CDMInputBuffer(data,
+ aBuffer = gmp::CDMInputBuffer(shmem,
crypto.mKeyId,
crypto.mIV,
aSample->mTime,
aSample->mDuration,
crypto.mPlainSizes,
crypto.mEncryptedSizes,
crypto.mValid);
return true;
@@ -204,16 +207,17 @@ ChromiumCDMParent::Decrypt(MediaRawData*
return DecryptPromise::CreateAndReject(DecryptResult(GenericErr, aSample),
__func__);
}
RefPtr<DecryptJob> job = new DecryptJob(aSample);
if (!SendDecrypt(job->mId, buffer)) {
GMP_LOG(
"ChromiumCDMParent::Decrypt(this=%p) failed to send decrypt message",
this);
+ DeallocShmem(buffer.mData());
return DecryptPromise::CreateAndReject(DecryptResult(GenericErr, aSample),
__func__);
}
RefPtr<DecryptPromise> promise = job->Ensure();
mDecrypts.AppendElement(job);
return promise;
}
@@ -716,16 +720,17 @@ ChromiumCDMParent::DecryptAndDecodeFrame
}
mLastStreamOffset = aSample->mOffset;
if (!SendDecryptAndDecodeFrame(buffer)) {
GMP_LOG(
"ChromiumCDMParent::Decrypt(this=%p) failed to send decrypt message.",
this);
+ DeallocShmem(buffer.mData());
return MediaDataDecoder::DecodePromise::CreateAndReject(
MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
"Failed to send decrypt to CDM process."),
__func__);
}
return mDecodePromise.Ensure(__func__);
}
--- a/dom/media/gmp/ChromiumCDMParent.h
+++ b/dom/media/gmp/ChromiumCDMParent.h
@@ -122,16 +122,18 @@ protected:
void ActorDestroy(ActorDestroyReason aWhy) override;
void RejectPromise(uint32_t aPromiseId,
nsresult aError,
const nsCString& aErrorMessage);
void ResolvePromise(uint32_t aPromiseId);
+ bool InitCDMInputBuffer(gmp::CDMInputBuffer& aBuffer, MediaRawData* aSample);
+
const uint32_t mPluginId;
GMPContentParent* mContentParent;
// Note: this pointer is a weak reference because otherwise it would cause
// a cycle, as ChromiumCDMProxy has a strong reference to the
// ChromiumCDMParent.
ChromiumCDMProxy* mProxy = nullptr;
nsDataHashtable<nsUint32HashKey, uint32_t> mPromiseToCreateSessionToken;
nsTArray<RefPtr<DecryptJob>> mDecrypts;
--- a/dom/media/gmp/GMPTypes.ipdlh
+++ b/dom/media/gmp/GMPTypes.ipdlh
@@ -56,17 +56,17 @@ struct GMPVideoi420FrameData
};
struct GMPKeyInformation {
uint8_t[] keyId;
GMPMediaKeyStatus status;
};
struct CDMInputBuffer {
- uint8_t[] mData;
+ Shmem mData;
uint8_t[] mKeyId;
uint8_t[] mIV;
int64_t mTimestamp;
int64_t mDuration;
uint16_t[] mClearBytes;
uint32_t[] mCipherBytes;
bool mIsEncrypted;
};
--- a/dom/media/gmp/PChromiumCDM.ipdl
+++ b/dom/media/gmp/PChromiumCDM.ipdl
@@ -82,17 +82,17 @@ parent:
async OnLegacySessionError(nsCString aSessionId,
uint32_t aError,
uint32_t aSystemCode,
nsCString aMessage);
async ResolveLoadSessionPromise(uint32_t aPromiseId, bool aSuccessful);
// Return values of cdm::ContentDecryptionModule8::Decrypt
- async Decrypted(uint32_t aId, uint32_t aStatus, uint8_t[] aData);
+ async Decrypted(uint32_t aId, uint32_t aStatus, Shmem aData);
async OnDecoderInitDone(uint32_t aStatus);
// Return values of cdm::ContentDecryptionModule8::DecryptAndDecodeFrame
async Decoded(CDMVideoFrame aFrame);
async DecodeFailed(uint32_t aStatus);
async ResetVideoDecoderComplete();