gecko-dev/dom/media/gmp/ChromiumCDMChild.h
Chris Pearce 5fe1464d84 Bug 1357133 - Recover from incorrectly guessing the CDM's shmem sizes. r=gerald
We are pre-allocating shmems in the content process for use by the CDM in the
GMP process. We guess the size of shmem required. However if we guess wrong,
currently we always end up taking the non-shmem path for video frames to
return to the content process, which results in us sending another shmem
(of the wrong size) to the CDM, and this continues until we hit the limit
on the number of shmems that we tolerate the CDM asking for.

So in this patch, I change our behaviour to detect when we're allocating
shmems that are too small, whereupon we purge the existing shmems and switch
to allocating them at the size being requested by the CDM.

This means we recover from incorrectly guessing the size of shmems required
by the CDM. The overhead of an incorrect guess should be one video frame
transferred via the nsTArray path.


MozReview-Commit-ID: 8o1s7FI2UBd

--HG--
extra : rebase_source : 0612d199686278612e8c58dc97e96a9304ea3ee9
2017-04-28 08:55:28 +12:00

139 lines
5.6 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef ChromiumCDMChild_h_
#define ChromiumCDMChild_h_
#include "content_decryption_module.h"
#include "mozilla/gmp/PChromiumCDMChild.h"
#include "SimpleMap.h"
#include "WidevineVideoFrame.h"
namespace mozilla {
namespace gmp {
class GMPContentChild;
class ChromiumCDMChild : public PChromiumCDMChild
, public cdm::Host_8
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ChromiumCDMChild);
explicit ChromiumCDMChild(GMPContentChild* aPlugin);
void Init(cdm::ContentDecryptionModule_8* aCDM);
void TimerExpired(void* aContext);
// cdm::Host_8
cdm::Buffer* Allocate(uint32_t aCapacity) override;
void SetTimer(int64_t aDelayMs, void* aContext) override;
cdm::Time GetCurrentWallTime() override;
void OnResolveNewSessionPromise(uint32_t aPromiseId,
const char* aSessionId,
uint32_t aSessionIdSize) override;
void OnResolvePromise(uint32_t aPromiseId) override;
void OnRejectPromise(uint32_t aPromiseId,
cdm::Error aError,
uint32_t aSystemCode,
const char* aErrorMessage,
uint32_t aErrorMessageSize) override;
void OnSessionMessage(const char* aSessionId,
uint32_t aSessionIdSize,
cdm::MessageType aMessageType,
const char* aMessage,
uint32_t aMessageSize,
const char* aLegacyDestinationUrl,
uint32_t aLegacyDestinationUrlLength) override;
void OnSessionKeysChange(const char* aSessionId,
uint32_t aSessionIdSize,
bool aHasAdditionalUsableKey,
const cdm::KeyInformation* aKeysInfo,
uint32_t aKeysInfoCount) override;
void OnExpirationChange(const char* aSessionId,
uint32_t aSessionIdSize,
cdm::Time aNewExpiryTime) override;
void OnSessionClosed(const char* aSessionId,
uint32_t aSessionIdSize) override;
void OnLegacySessionError(const char* aSessionId,
uint32_t aSessionIdLength,
cdm::Error aError,
uint32_t aSystemCode,
const char* aErrorMessage,
uint32_t aErrorMessageLength) override;
void SendPlatformChallenge(const char* aServiceId,
uint32_t aServiceIdSize,
const char* aChallenge,
uint32_t aChallengeSize) override {}
void EnableOutputProtection(uint32_t aDesiredProtectionMask) override {}
void QueryOutputProtectionStatus() override {}
void OnDeferredInitializationDone(cdm::StreamType aStreamType,
cdm::Status aDecoderStatus) override {}
cdm::FileIO* CreateFileIO(cdm::FileIOClient* aClient) override;
void GiveBuffer(ipc::Shmem&& aBuffer);
protected:
~ChromiumCDMChild();
bool IsOnMessageLoopThread();
ipc::IPCResult RecvGiveBuffer(ipc::Shmem&& aShmem) override;
ipc::IPCResult RecvPurgeShmems() override;
void PurgeShmems();
ipc::IPCResult RecvInit(const bool& aAllowDistinctiveIdentifier,
const bool& aAllowPersistentState) override;
ipc::IPCResult RecvSetServerCertificate(
const uint32_t& aPromiseId,
nsTArray<uint8_t>&& aServerCert) override;
ipc::IPCResult RecvCreateSessionAndGenerateRequest(
const uint32_t& aPromiseId,
const uint32_t& aSessionType,
const uint32_t& aInitDataType,
nsTArray<uint8_t>&& aInitData) override;
ipc::IPCResult RecvLoadSession(const uint32_t& aPromiseId,
const uint32_t& aSessionType,
const nsCString& aSessionId) override;
ipc::IPCResult RecvUpdateSession(const uint32_t& aPromiseId,
const nsCString& aSessionId,
nsTArray<uint8_t>&& aResponse) override;
ipc::IPCResult RecvCloseSession(const uint32_t& aPromiseId,
const nsCString& aSessionId) override;
ipc::IPCResult RecvRemoveSession(const uint32_t& aPromiseId,
const nsCString& aSessionId) override;
ipc::IPCResult RecvDecrypt(const uint32_t& aId,
const CDMInputBuffer& aBuffer) override;
ipc::IPCResult RecvInitializeVideoDecoder(
const CDMVideoDecoderConfig& aConfig) override;
ipc::IPCResult RecvDeinitializeVideoDecoder() override;
ipc::IPCResult RecvResetVideoDecoder() override;
ipc::IPCResult RecvDecryptAndDecodeFrame(
const CDMInputBuffer& aBuffer) override;
ipc::IPCResult RecvDrain() override;
ipc::IPCResult RecvDestroy() override;
void ReturnOutput(WidevineVideoFrame& aFrame);
bool HasShmemOfSize(size_t aSize) const;
GMPContentChild* mPlugin = nullptr;
cdm::ContentDecryptionModule_8* mCDM = nullptr;
typedef SimpleMap<uint64_t> DurationMap;
DurationMap mFrameDurations;
nsTArray<uint32_t> mLoadSessionPromiseIds;
cdm::Size mCodedSize;
nsTArray<ipc::Shmem> mBuffers;
bool mDecoderInitialized = false;
bool mPersistentStateAllowed = false;
};
} // namespace gmp
} // namespace mozilla
#endif // ChromiumCDMChild_h_