2017-02-23 01:51:00 +03:00
|
|
|
/* -*- 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_
|
|
|
|
|
2017-03-13 03:26:13 +03:00
|
|
|
#include "content_decryption_module.h"
|
2017-03-07 06:37:21 +03:00
|
|
|
#include "mozilla/gmp/PChromiumCDMChild.h"
|
2017-03-09 01:32:15 +03:00
|
|
|
#include "SimpleMap.h"
|
2017-03-07 06:37:21 +03:00
|
|
|
#include "WidevineVideoFrame.h"
|
2017-02-23 01:51:00 +03:00
|
|
|
|
|
|
|
namespace mozilla {
|
|
|
|
namespace gmp {
|
|
|
|
|
|
|
|
class GMPContentChild;
|
|
|
|
|
|
|
|
class ChromiumCDMChild : public PChromiumCDMChild
|
2017-03-13 03:26:13 +03:00
|
|
|
, public cdm::Host_8
|
2017-02-23 01:51:00 +03:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ChromiumCDMChild);
|
|
|
|
|
|
|
|
explicit ChromiumCDMChild(GMPContentChild* aPlugin);
|
|
|
|
|
2017-03-13 06:59:34 +03:00
|
|
|
void Init(cdm::ContentDecryptionModule_8* aCDM);
|
2017-03-13 03:26:13 +03:00
|
|
|
|
|
|
|
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;
|
Bug 1351953 - Pre-allocate shmems for the CDM process to use for storing decrypted and audio samples. r=gerald
Makes transfer of samples between the content and CDM processes use shmems.
The Chromium CDM API requires us to implement a synchronous interface to supply
buffers to the CDM for it to write decrypted samples into. We want our buffers
to be backed by shmems, in order to reduce the overhead of transferring decoded
frames. However due to sandboxing restrictions, the CDM process cannot allocate
shmems itself. We don't want to be doing synchronous IPC to request shmems
from the content process, nor do we want to have to do intr IPC or make async
IPC conform to the sync allocation interface. So instead we have the content
process pre-allocate a set of shmems and give them to the CDM process in
advance of them being needed.
When the CDM needs to allocate a buffer for storing a decrypted sample, the CDM
host gives it one of these shmems' buffers. When this is sent back to the
content process, we copy the result out (uploading to a GPU surface for video
frames), and send the shmem back to the CDM process so it can reuse it.
We predict the size of buffer the CDM will allocate, and prepopulate the CDM's
list of shmems with shmems of at least that size, plus a bit of padding for
safety. We pad frames out to be the next multiple of 16, as we've seen some
decoders do that.
Normally the CDM won't allocate more than one buffer at once, but we've seen
cases where it allocates two buffers, returns one and holds onto the other. So
the minimum number of shmems we give to the CDM must be at least two, and the
default is three for safety.
MozReview-Commit-ID: 5FaWAst3aeh
--HG--
extra : rebase_source : a0cb126e72bfb2905bcdf02e864dc654e8340410
2017-03-28 08:59:11 +03:00
|
|
|
|
|
|
|
void GiveBuffer(ipc::Shmem&& aBuffer);
|
|
|
|
|
2017-02-23 01:51:00 +03:00
|
|
|
protected:
|
Bug 1351953 - Pre-allocate shmems for the CDM process to use for storing decrypted and audio samples. r=gerald
Makes transfer of samples between the content and CDM processes use shmems.
The Chromium CDM API requires us to implement a synchronous interface to supply
buffers to the CDM for it to write decrypted samples into. We want our buffers
to be backed by shmems, in order to reduce the overhead of transferring decoded
frames. However due to sandboxing restrictions, the CDM process cannot allocate
shmems itself. We don't want to be doing synchronous IPC to request shmems
from the content process, nor do we want to have to do intr IPC or make async
IPC conform to the sync allocation interface. So instead we have the content
process pre-allocate a set of shmems and give them to the CDM process in
advance of them being needed.
When the CDM needs to allocate a buffer for storing a decrypted sample, the CDM
host gives it one of these shmems' buffers. When this is sent back to the
content process, we copy the result out (uploading to a GPU surface for video
frames), and send the shmem back to the CDM process so it can reuse it.
We predict the size of buffer the CDM will allocate, and prepopulate the CDM's
list of shmems with shmems of at least that size, plus a bit of padding for
safety. We pad frames out to be the next multiple of 16, as we've seen some
decoders do that.
Normally the CDM won't allocate more than one buffer at once, but we've seen
cases where it allocates two buffers, returns one and holds onto the other. So
the minimum number of shmems we give to the CDM must be at least two, and the
default is three for safety.
MozReview-Commit-ID: 5FaWAst3aeh
--HG--
extra : rebase_source : a0cb126e72bfb2905bcdf02e864dc654e8340410
2017-03-28 08:59:11 +03:00
|
|
|
~ChromiumCDMChild();
|
2017-02-23 01:51:00 +03:00
|
|
|
|
2017-03-09 08:17:50 +03:00
|
|
|
bool IsOnMessageLoopThread();
|
|
|
|
|
Bug 1351953 - Pre-allocate shmems for the CDM process to use for storing decrypted and audio samples. r=gerald
Makes transfer of samples between the content and CDM processes use shmems.
The Chromium CDM API requires us to implement a synchronous interface to supply
buffers to the CDM for it to write decrypted samples into. We want our buffers
to be backed by shmems, in order to reduce the overhead of transferring decoded
frames. However due to sandboxing restrictions, the CDM process cannot allocate
shmems itself. We don't want to be doing synchronous IPC to request shmems
from the content process, nor do we want to have to do intr IPC or make async
IPC conform to the sync allocation interface. So instead we have the content
process pre-allocate a set of shmems and give them to the CDM process in
advance of them being needed.
When the CDM needs to allocate a buffer for storing a decrypted sample, the CDM
host gives it one of these shmems' buffers. When this is sent back to the
content process, we copy the result out (uploading to a GPU surface for video
frames), and send the shmem back to the CDM process so it can reuse it.
We predict the size of buffer the CDM will allocate, and prepopulate the CDM's
list of shmems with shmems of at least that size, plus a bit of padding for
safety. We pad frames out to be the next multiple of 16, as we've seen some
decoders do that.
Normally the CDM won't allocate more than one buffer at once, but we've seen
cases where it allocates two buffers, returns one and holds onto the other. So
the minimum number of shmems we give to the CDM must be at least two, and the
default is three for safety.
MozReview-Commit-ID: 5FaWAst3aeh
--HG--
extra : rebase_source : a0cb126e72bfb2905bcdf02e864dc654e8340410
2017-03-28 08:59:11 +03:00
|
|
|
ipc::IPCResult RecvGiveBuffer(ipc::Shmem&& aShmem) override;
|
|
|
|
|
2017-02-23 01:51:00 +03:00
|
|
|
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;
|
2017-03-09 09:09:43 +03:00
|
|
|
ipc::IPCResult RecvLoadSession(const uint32_t& aPromiseId,
|
|
|
|
const uint32_t& aSessionType,
|
|
|
|
const nsCString& aSessionId) override;
|
2017-02-23 01:51:00 +03:00
|
|
|
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;
|
2017-03-09 01:31:07 +03:00
|
|
|
ipc::IPCResult RecvDecrypt(const uint32_t& aId,
|
|
|
|
const CDMInputBuffer& aBuffer) override;
|
2017-02-23 01:51:00 +03:00
|
|
|
ipc::IPCResult RecvInitializeVideoDecoder(
|
|
|
|
const CDMVideoDecoderConfig& aConfig) override;
|
|
|
|
ipc::IPCResult RecvDeinitializeVideoDecoder() override;
|
|
|
|
ipc::IPCResult RecvResetVideoDecoder() override;
|
|
|
|
ipc::IPCResult RecvDecryptAndDecodeFrame(
|
|
|
|
const CDMInputBuffer& aBuffer) override;
|
2017-03-07 06:37:21 +03:00
|
|
|
ipc::IPCResult RecvDrain() override;
|
2017-02-23 01:51:00 +03:00
|
|
|
ipc::IPCResult RecvDestroy() override;
|
|
|
|
|
2017-03-07 06:37:21 +03:00
|
|
|
void ReturnOutput(WidevineVideoFrame& aFrame);
|
Bug 1351953 - Pre-allocate shmems for the CDM process to use for storing decrypted and audio samples. r=gerald
Makes transfer of samples between the content and CDM processes use shmems.
The Chromium CDM API requires us to implement a synchronous interface to supply
buffers to the CDM for it to write decrypted samples into. We want our buffers
to be backed by shmems, in order to reduce the overhead of transferring decoded
frames. However due to sandboxing restrictions, the CDM process cannot allocate
shmems itself. We don't want to be doing synchronous IPC to request shmems
from the content process, nor do we want to have to do intr IPC or make async
IPC conform to the sync allocation interface. So instead we have the content
process pre-allocate a set of shmems and give them to the CDM process in
advance of them being needed.
When the CDM needs to allocate a buffer for storing a decrypted sample, the CDM
host gives it one of these shmems' buffers. When this is sent back to the
content process, we copy the result out (uploading to a GPU surface for video
frames), and send the shmem back to the CDM process so it can reuse it.
We predict the size of buffer the CDM will allocate, and prepopulate the CDM's
list of shmems with shmems of at least that size, plus a bit of padding for
safety. We pad frames out to be the next multiple of 16, as we've seen some
decoders do that.
Normally the CDM won't allocate more than one buffer at once, but we've seen
cases where it allocates two buffers, returns one and holds onto the other. So
the minimum number of shmems we give to the CDM must be at least two, and the
default is three for safety.
MozReview-Commit-ID: 5FaWAst3aeh
--HG--
extra : rebase_source : a0cb126e72bfb2905bcdf02e864dc654e8340410
2017-03-28 08:59:11 +03:00
|
|
|
bool HasShmemOfSize(size_t aSize) const;
|
2017-03-09 01:31:07 +03:00
|
|
|
|
2017-03-13 06:59:34 +03:00
|
|
|
GMPContentChild* mPlugin = nullptr;
|
|
|
|
cdm::ContentDecryptionModule_8* mCDM = nullptr;
|
2017-03-09 08:17:50 +03:00
|
|
|
|
2017-03-09 01:32:15 +03:00
|
|
|
typedef SimpleMap<uint64_t> DurationMap;
|
|
|
|
DurationMap mFrameDurations;
|
2017-03-09 09:09:43 +03:00
|
|
|
nsTArray<uint32_t> mLoadSessionPromiseIds;
|
2017-03-09 01:32:15 +03:00
|
|
|
|
2017-03-14 07:17:05 +03:00
|
|
|
cdm::Size mCodedSize;
|
Bug 1351953 - Pre-allocate shmems for the CDM process to use for storing decrypted and audio samples. r=gerald
Makes transfer of samples between the content and CDM processes use shmems.
The Chromium CDM API requires us to implement a synchronous interface to supply
buffers to the CDM for it to write decrypted samples into. We want our buffers
to be backed by shmems, in order to reduce the overhead of transferring decoded
frames. However due to sandboxing restrictions, the CDM process cannot allocate
shmems itself. We don't want to be doing synchronous IPC to request shmems
from the content process, nor do we want to have to do intr IPC or make async
IPC conform to the sync allocation interface. So instead we have the content
process pre-allocate a set of shmems and give them to the CDM process in
advance of them being needed.
When the CDM needs to allocate a buffer for storing a decrypted sample, the CDM
host gives it one of these shmems' buffers. When this is sent back to the
content process, we copy the result out (uploading to a GPU surface for video
frames), and send the shmem back to the CDM process so it can reuse it.
We predict the size of buffer the CDM will allocate, and prepopulate the CDM's
list of shmems with shmems of at least that size, plus a bit of padding for
safety. We pad frames out to be the next multiple of 16, as we've seen some
decoders do that.
Normally the CDM won't allocate more than one buffer at once, but we've seen
cases where it allocates two buffers, returns one and holds onto the other. So
the minimum number of shmems we give to the CDM must be at least two, and the
default is three for safety.
MozReview-Commit-ID: 5FaWAst3aeh
--HG--
extra : rebase_source : a0cb126e72bfb2905bcdf02e864dc654e8340410
2017-03-28 08:59:11 +03:00
|
|
|
nsTArray<ipc::Shmem> mBuffers;
|
2017-03-14 07:17:05 +03:00
|
|
|
|
2017-03-09 08:17:50 +03:00
|
|
|
bool mDecoderInitialized = false;
|
2017-03-22 06:30:54 +03:00
|
|
|
bool mPersistentStateAllowed = false;
|
2017-02-23 01:51:00 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace gmp
|
|
|
|
} // namespace mozilla
|
|
|
|
|
|
|
|
#endif // ChromiumCDMChild_h_
|