diff --git a/.clang-format-ignore b/.clang-format-ignore index 6a49ae1d9271..83276e002601 100644 --- a/.clang-format-ignore +++ b/.clang-format-ignore @@ -82,7 +82,6 @@ dom/media/gmp/rlz/.* dom/media/gmp/widevine-adapter/content_decryption_module.h dom/media/gmp/widevine-adapter/content_decryption_module_export.h dom/media/gmp/widevine-adapter/content_decryption_module_ext.h -dom/media/gmp/widevine-adapter/content_decryption_module_proxy.h dom/media/platforms/ffmpeg/ffmpeg57/.* dom/media/platforms/ffmpeg/ffmpeg58/.* dom/media/platforms/ffmpeg/ffmpeg59/.* diff --git a/.prettierignore b/.prettierignore index 6e32c02f6568..afc0abd0d7a3 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1273,7 +1273,6 @@ dom/media/gmp/rlz/ dom/media/gmp/widevine-adapter/content_decryption_module_export.h dom/media/gmp/widevine-adapter/content_decryption_module_ext.h dom/media/gmp/widevine-adapter/content_decryption_module.h -dom/media/gmp/widevine-adapter/content_decryption_module_proxy.h dom/media/platforms/ffmpeg/ffmpeg57/ dom/media/platforms/ffmpeg/ffmpeg58/ dom/media/platforms/ffmpeg/ffmpeg59/ diff --git a/dom/media/gmp/ChromiumCDMChild.cpp b/dom/media/gmp/ChromiumCDMChild.cpp index 343622d37f87..c6ca64d3819f 100644 --- a/dom/media/gmp/ChromiumCDMChild.cpp +++ b/dom/media/gmp/ChromiumCDMChild.cpp @@ -783,12 +783,12 @@ void ChromiumCDMChild::ReturnOutput(WidevineVideoFrame& aFrame) { output.mFormat() = static_cast(aFrame.Format()); output.mImageWidth() = aFrame.Size().width; output.mImageHeight() = aFrame.Size().height; - output.mYPlane() = {aFrame.PlaneOffset(cdm::VideoPlane::kYPlane), - aFrame.Stride(cdm::VideoPlane::kYPlane)}; - output.mUPlane() = {aFrame.PlaneOffset(cdm::VideoPlane::kUPlane), - aFrame.Stride(cdm::VideoPlane::kUPlane)}; - output.mVPlane() = {aFrame.PlaneOffset(cdm::VideoPlane::kVPlane), - aFrame.Stride(cdm::VideoPlane::kVPlane)}; + output.mYPlane() = {aFrame.PlaneOffset(cdm::kYPlane), + aFrame.Stride(cdm::kYPlane)}; + output.mUPlane() = {aFrame.PlaneOffset(cdm::kUPlane), + aFrame.Stride(cdm::kUPlane)}; + output.mVPlane() = {aFrame.PlaneOffset(cdm::kVPlane), + aFrame.Stride(cdm::kVPlane)}; output.mTimestamp() = aFrame.Timestamp(); uint64_t duration = 0; diff --git a/dom/media/gmp/moz.build b/dom/media/gmp/moz.build index 744209fa1c37..679c97fb249e 100644 --- a/dom/media/gmp/moz.build +++ b/dom/media/gmp/moz.build @@ -62,10 +62,6 @@ EXPORTS += [ "GMPVideoHost.h", "GMPVideoi420FrameImpl.h", "GMPVideoPlaneImpl.h", - "widevine-adapter/content_decryption_module.h", - "widevine-adapter/content_decryption_module_export.h", - "widevine-adapter/content_decryption_module_ext.h", - "widevine-adapter/content_decryption_module_proxy.h", ] UNIFIED_SOURCES += [ diff --git a/dom/media/gmp/widevine-adapter/WidevineVideoFrame.cpp b/dom/media/gmp/widevine-adapter/WidevineVideoFrame.cpp index 3f136c4ac805..6d34f0a4e69f 100644 --- a/dom/media/gmp/widevine-adapter/WidevineVideoFrame.cpp +++ b/dom/media/gmp/widevine-adapter/WidevineVideoFrame.cpp @@ -127,14 +127,14 @@ bool WidevineVideoFrame::InitToBlack(int32_t aWidth, int32_t aHeight, SetFormat(cdm::VideoFormat::kI420); SetSize(cdm::Size{aWidth, aHeight}); SetFrameBuffer(buffer); - SetPlaneOffset(cdm::VideoPlane::kYPlane, 0); - SetStride(cdm::VideoPlane::kYPlane, aWidth); + SetPlaneOffset(cdm::kYPlane, 0); + SetStride(cdm::kYPlane, aWidth); // Note: U and V planes are stored at the same place in order to // save memory since their contents are the same. - SetPlaneOffset(cdm::VideoPlane::kUPlane, ySize); - SetStride(cdm::VideoPlane::kUPlane, halfWidth); - SetPlaneOffset(cdm::VideoPlane::kVPlane, ySize); - SetStride(cdm::VideoPlane::kVPlane, halfWidth); + SetPlaneOffset(cdm::kUPlane, ySize); + SetStride(cdm::kUPlane, halfWidth); + SetPlaneOffset(cdm::kVPlane, ySize); + SetStride(cdm::kVPlane, halfWidth); SetTimestamp(aTimeStamp); return true; } diff --git a/dom/media/gmp/widevine-adapter/WidevineVideoFrame.h b/dom/media/gmp/widevine-adapter/WidevineVideoFrame.h index 0ae65ac1e5e4..b6abb416046f 100644 --- a/dom/media/gmp/widevine-adapter/WidevineVideoFrame.h +++ b/dom/media/gmp/widevine-adapter/WidevineVideoFrame.h @@ -44,8 +44,8 @@ class WidevineVideoFrame : public cdm::VideoFrame { cdm::VideoFormat mFormat; cdm::Size mSize; cdm::Buffer* mBuffer; - uint32_t mPlaneOffsets[cdm::VideoPlane::kMaxPlanes]; - uint32_t mPlaneStrides[cdm::VideoPlane::kMaxPlanes]; + uint32_t mPlaneOffsets[cdm::kMaxPlanes]; + uint32_t mPlaneStrides[cdm::kMaxPlanes]; int64_t mTimestamp; }; diff --git a/dom/media/gmp/widevine-adapter/content_decryption_module.h b/dom/media/gmp/widevine-adapter/content_decryption_module.h index b132eabf9261..37ef4724af01 100644 --- a/dom/media/gmp/widevine-adapter/content_decryption_module.h +++ b/dom/media/gmp/widevine-adapter/content_decryption_module.h @@ -8,7 +8,6 @@ #include #include "content_decryption_module_export.h" -#include "content_decryption_module_proxy.h" #if defined(_MSC_VER) typedef unsigned char uint8_t; @@ -16,7 +15,7 @@ typedef unsigned int uint32_t; typedef int int32_t; typedef __int64 int64_t; #else -# include +#include #endif #include "mozilla/DefineEnum.h" @@ -413,6 +412,7 @@ CHECK_TYPE(InitDataType, 4, 4); enum SessionType : uint32_t { kTemporary = 0, kPersistentLicense = 1, + kPersistentUsageRecord = 2 }; CHECK_TYPE(SessionType, 4, 4); @@ -481,12 +481,13 @@ class CDM_CLASS_API DecryptedBlock { virtual ~DecryptedBlock() {} }; -enum VideoPlane : uint32_t { - kYPlane = 0, - kUPlane = 1, - kVPlane = 2, - kMaxPlanes = 3, -}; +// This intentionally avoids using an enum, since it will be used to do math +// with other enums, which is deprecated in C++20. +using VideoPlane = uint32_t; +constexpr VideoPlane kYPlane = 0; +constexpr VideoPlane kUPlane = 1; +constexpr VideoPlane kVPlane = 2; +constexpr VideoPlane kMaxPlanes = 3; CHECK_TYPE(VideoPlane, 4, 4); class CDM_CLASS_API VideoFrame { @@ -624,7 +625,8 @@ class CDM_CLASS_API FileIOClient { // - kInUse indicates that there are other read/write operations pending. // - kError indicates read failure, e.g. the storage is not open or cannot be // fully read. - virtual void OnReadComplete(Status status, const uint8_t* data, + virtual void OnReadComplete(Status status, + const uint8_t* data, uint32_t data_size) = 0; // Response to a FileIO::Write() call. @@ -641,8 +643,21 @@ class CDM_CLASS_API FileIOClient { virtual ~FileIOClient() {} }; +// Metrics that will be reported from the CDM through the ReportMetrics() +// function. To add a new metric, please add it to the end of this enum list +// without changing any existing enum values. +// Note: For forward compatibility, Host implementations must gracefully handle +// unexpected (new) enum values, e.g. no-op. +enum MetricName : uint32_t { + kSdkVersion, + kCertificateSerialNumber, + kDecoderBypassBlockCount, +}; +CHECK_TYPE(MetricName, 4, 4); + class CDM_CLASS_API Host_10; class CDM_CLASS_API Host_11; +class CDM_CLASS_API Host_12; // ContentDecryptionModule interface that all CDMs need to implement. // The interface is versioned for backward compatibility. @@ -710,28 +725,33 @@ class CDM_CLASS_API ContentDecryptionModule_10 { // The CDM must respond by calling either Host::OnResolveNewSessionPromise() // or Host::OnRejectPromise(). If the session is not found, call // Host::OnResolveNewSessionPromise() with session_id = NULL. - virtual void LoadSession(uint32_t promise_id, SessionType session_type, + virtual void LoadSession(uint32_t promise_id, + SessionType session_type, const char* session_id, uint32_t session_id_size) = 0; // Updates the session with |response|. The CDM must respond by calling // either Host::OnResolvePromise() or Host::OnRejectPromise(). - virtual void UpdateSession(uint32_t promise_id, const char* session_id, - uint32_t session_id_size, const uint8_t* response, + virtual void UpdateSession(uint32_t promise_id, + const char* session_id, + uint32_t session_id_size, + const uint8_t* response, uint32_t response_size) = 0; // Requests that the CDM close the session. The CDM must respond by calling // either Host::OnResolvePromise() or Host::OnRejectPromise() when the request // has been processed. This may be before the session is closed. Once the // session is closed, Host::OnSessionClosed() must also be called. - virtual void CloseSession(uint32_t promise_id, const char* session_id, + virtual void CloseSession(uint32_t promise_id, + const char* session_id, uint32_t session_id_size) = 0; // Removes any stored session data associated with this session. Will only be // called for persistent sessions. The CDM must respond by calling either // Host::OnResolvePromise() or Host::OnRejectPromise() when the request has // been processed. - virtual void RemoveSession(uint32_t promise_id, const char* session_id, + virtual void RemoveSession(uint32_t promise_id, + const char* session_id, uint32_t session_id_size) = 0; // Performs scheduled operation with |context| when the timer fires. @@ -835,7 +855,8 @@ class CDM_CLASS_API ContentDecryptionModule_10 { // then |link_mask| and |output_protection_mask| are undefined and should // be ignored. virtual void OnQueryOutputProtectionStatus( - QueryResult result, uint32_t link_mask, + QueryResult result, + uint32_t link_mask, uint32_t output_protection_mask) = 0; // Called by the host after a call to Host::RequestStorageId(). If the @@ -846,7 +867,8 @@ class CDM_CLASS_API ContentDecryptionModule_10 { // If the requested version is not available, null/zero will be provided as // |storage_id| and |storage_id_size|, respectively, and |version| should be // ignored. - virtual void OnStorageId(uint32_t version, const uint8_t* storage_id, + virtual void OnStorageId(uint32_t version, + const uint8_t* storage_id, uint32_t storage_id_size) = 0; // Destroys the object in the same context as it was created. @@ -857,8 +879,6 @@ class CDM_CLASS_API ContentDecryptionModule_10 { virtual ~ContentDecryptionModule_10() {} }; -// ----- Note: CDM interface(s) below still in development and not stable! ----- - // ContentDecryptionModule interface that all CDMs need to implement. // The interface is versioned for backward compatibility. // Note: ContentDecryptionModule implementations must use the allocator @@ -868,7 +888,7 @@ class CDM_CLASS_API ContentDecryptionModule_10 { class CDM_CLASS_API ContentDecryptionModule_11 { public: static const int kVersion = 11; - static const bool kIsStable = false; + static const bool kIsStable = true; typedef Host_11 Host; // Initializes the CDM instance, providing information about permitted @@ -925,21 +945,247 @@ class CDM_CLASS_API ContentDecryptionModule_11 { // The CDM must respond by calling either Host::OnResolveNewSessionPromise() // or Host::OnRejectPromise(). If the session is not found, call // Host::OnResolveNewSessionPromise() with session_id = NULL. - virtual void LoadSession(uint32_t promise_id, SessionType session_type, + virtual void LoadSession(uint32_t promise_id, + SessionType session_type, const char* session_id, uint32_t session_id_size) = 0; // Updates the session with |response|. The CDM must respond by calling // either Host::OnResolvePromise() or Host::OnRejectPromise(). - virtual void UpdateSession(uint32_t promise_id, const char* session_id, - uint32_t session_id_size, const uint8_t* response, + virtual void UpdateSession(uint32_t promise_id, + const char* session_id, + uint32_t session_id_size, + const uint8_t* response, uint32_t response_size) = 0; // Requests that the CDM close the session. The CDM must respond by calling // either Host::OnResolvePromise() or Host::OnRejectPromise() when the request // has been processed. This may be before the session is closed. Once the // session is closed, Host::OnSessionClosed() must also be called. - virtual void CloseSession(uint32_t promise_id, const char* session_id, + virtual void CloseSession(uint32_t promise_id, + const char* session_id, + uint32_t session_id_size) = 0; + + // Removes any stored session data associated with this session. Will only be + // called for persistent sessions. The CDM must respond by calling either + // Host::OnResolvePromise() or Host::OnRejectPromise() when the request has + // been processed. + virtual void RemoveSession(uint32_t promise_id, + const char* session_id, + uint32_t session_id_size) = 0; + + // Performs scheduled operation with |context| when the timer fires. + virtual void TimerExpired(void* context) = 0; + + // Decrypts the |encrypted_buffer|. + // + // Returns kSuccess if decryption succeeded, in which case the callee + // should have filled the |decrypted_buffer| and passed the ownership of + // |data| in |decrypted_buffer| to the caller. + // Returns kNoKey if the CDM did not have the necessary decryption key + // to decrypt. + // Returns kDecryptError if any other error happened. + // If the return value is not kSuccess, |decrypted_buffer| should be ignored + // by the caller. + virtual Status Decrypt(const InputBuffer_2& encrypted_buffer, + DecryptedBlock* decrypted_buffer) = 0; + + // Initializes the CDM audio decoder with |audio_decoder_config|. This + // function must be called before DecryptAndDecodeSamples() is called. + // + // Returns kSuccess if the |audio_decoder_config| is supported and the CDM + // audio decoder is successfully initialized. + // Returns kInitializationError if |audio_decoder_config| is not supported. + // The CDM may still be able to do Decrypt(). + // Returns kDeferredInitialization if the CDM is not ready to initialize the + // decoder at this time. Must call Host::OnDeferredInitializationDone() once + // initialization is complete. + virtual Status InitializeAudioDecoder( + const AudioDecoderConfig_2& audio_decoder_config) = 0; + + // Initializes the CDM video decoder with |video_decoder_config|. This + // function must be called before DecryptAndDecodeFrame() is called. + // + // Returns kSuccess if the |video_decoder_config| is supported and the CDM + // video decoder is successfully initialized. + // Returns kInitializationError if |video_decoder_config| is not supported. + // The CDM may still be able to do Decrypt(). + // Returns kDeferredInitialization if the CDM is not ready to initialize the + // decoder at this time. Must call Host::OnDeferredInitializationDone() once + // initialization is complete. + virtual Status InitializeVideoDecoder( + const VideoDecoderConfig_2& video_decoder_config) = 0; + + // De-initializes the CDM decoder and sets it to an uninitialized state. The + // caller can initialize the decoder again after this call to re-initialize + // it. This can be used to reconfigure the decoder if the configuration + // changes. + virtual void DeinitializeDecoder(StreamType decoder_type) = 0; + + // Resets the CDM decoder to an initialized clean state. All internal buffers + // MUST be flushed. + virtual void ResetDecoder(StreamType decoder_type) = 0; + + // Decrypts the |encrypted_buffer| and decodes the decrypted buffer into a + // |video_frame|. Upon end-of-stream, the caller should call this function + // repeatedly with empty |encrypted_buffer| (|data| == NULL) until + // kNeedMoreData is returned. + // + // Returns kSuccess if decryption and decoding both succeeded, in which case + // the callee will have filled the |video_frame| and passed the ownership of + // |frame_buffer| in |video_frame| to the caller. + // Returns kNoKey if the CDM did not have the necessary decryption key + // to decrypt. + // Returns kNeedMoreData if more data was needed by the decoder to generate + // a decoded frame (e.g. during initialization and end-of-stream). + // Returns kDecryptError if any decryption error happened. + // Returns kDecodeError if any decoding error happened. + // If the return value is not kSuccess, |video_frame| should be ignored by + // the caller. + virtual Status DecryptAndDecodeFrame(const InputBuffer_2& encrypted_buffer, + VideoFrame* video_frame) = 0; + + // Decrypts the |encrypted_buffer| and decodes the decrypted buffer into + // |audio_frames|. Upon end-of-stream, the caller should call this function + // repeatedly with empty |encrypted_buffer| (|data| == NULL) until only empty + // |audio_frames| is produced. + // + // Returns kSuccess if decryption and decoding both succeeded, in which case + // the callee will have filled |audio_frames| and passed the ownership of + // |data| in |audio_frames| to the caller. + // Returns kNoKey if the CDM did not have the necessary decryption key + // to decrypt. + // Returns kNeedMoreData if more data was needed by the decoder to generate + // audio samples (e.g. during initialization and end-of-stream). + // Returns kDecryptError if any decryption error happened. + // Returns kDecodeError if any decoding error happened. + // If the return value is not kSuccess, |audio_frames| should be ignored by + // the caller. + virtual Status DecryptAndDecodeSamples(const InputBuffer_2& encrypted_buffer, + AudioFrames* audio_frames) = 0; + + // Called by the host after a platform challenge was initiated via + // Host::SendPlatformChallenge(). + virtual void OnPlatformChallengeResponse( + const PlatformChallengeResponse& response) = 0; + + // Called by the host after a call to Host::QueryOutputProtectionStatus(). The + // |link_mask| is a bit mask of OutputLinkTypes and |output_protection_mask| + // is a bit mask of OutputProtectionMethods. If |result| is kQueryFailed, + // then |link_mask| and |output_protection_mask| are undefined and should + // be ignored. + virtual void OnQueryOutputProtectionStatus( + QueryResult result, + uint32_t link_mask, + uint32_t output_protection_mask) = 0; + + // Called by the host after a call to Host::RequestStorageId(). If the + // version of the storage ID requested is available, |storage_id| and + // |storage_id_size| are set appropriately. |version| will be the same as + // what was requested, unless 0 (latest) was requested, in which case + // |version| will be the actual version number for the |storage_id| returned. + // If the requested version is not available, null/zero will be provided as + // |storage_id| and |storage_id_size|, respectively, and |version| should be + // ignored. + virtual void OnStorageId(uint32_t version, + const uint8_t* storage_id, + uint32_t storage_id_size) = 0; + + // Destroys the object in the same context as it was created. + virtual void Destroy() = 0; + + protected: + ContentDecryptionModule_11() {} + virtual ~ContentDecryptionModule_11() {} +}; + +// ----- Note: CDM interface(s) below still in development and not stable! ----- + +// ContentDecryptionModule interface that all CDMs need to implement. +// The interface is versioned for backward compatibility. +// Note: ContentDecryptionModule implementations must use the allocator +// provided in CreateCdmInstance() to allocate any Buffer that needs to +// be passed back to the caller. Implementations must call Buffer::Destroy() +// when a Buffer is created that will never be returned to the caller. +class CDM_CLASS_API ContentDecryptionModule_12 { + public: + static const int kVersion = 12; + static const bool kIsStable = false; + typedef Host_12 Host; + + // Initializes the CDM instance, providing information about permitted + // functionalities. The CDM must respond by calling Host::OnInitialized() + // with whether the initialization succeeded. No other calls will be made by + // the host before Host::OnInitialized() returns. + // If |allow_distinctive_identifier| is false, messages from the CDM, + // such as message events, must not contain a Distinctive Identifier, + // even in an encrypted form. + // If |allow_persistent_state| is false, the CDM must not attempt to + // persist state. Calls to CreateFileIO() will fail. + // If |use_hw_secure_codecs| is true, the CDM must ensure the decryption key + // and video buffers (compressed and uncompressed) are securely protected by + // hardware. + virtual void Initialize(bool allow_distinctive_identifier, + bool allow_persistent_state, + bool use_hw_secure_codecs) = 0; + + // Gets the key status if the CDM has a hypothetical key with the |policy|. + // The CDM must respond by calling either Host::OnResolveKeyStatusPromise() + // with the result key status or Host::OnRejectPromise() if an unexpected + // error happened or this method is not supported. + virtual void GetStatusForPolicy(uint32_t promise_id, + const Policy& policy) = 0; + + // SetServerCertificate(), CreateSessionAndGenerateRequest(), LoadSession(), + // UpdateSession(), CloseSession(), and RemoveSession() all accept a + // |promise_id|, which must be passed to the completion Host method + // (e.g. Host::OnResolveNewSessionPromise()). + + // Provides a server certificate to be used to encrypt messages to the + // license server. The CDM must respond by calling either + // Host::OnResolvePromise() or Host::OnRejectPromise(). + // If the CDM does not support server certificates, the promise should be + // rejected with kExceptionNotSupportedError. If |server_certificate_data| + // is empty, reject with kExceptionTypeError. Any other error should be + // rejected with kExceptionInvalidStateError or kExceptionQuotaExceededError. + // TODO(crbug.com/796417): Add support for the promise to return true or + // false, rather than using kExceptionNotSupportedError to mean false. + virtual void SetServerCertificate(uint32_t promise_id, + const uint8_t* server_certificate_data, + uint32_t server_certificate_data_size) = 0; + + // Creates a session given |session_type|, |init_data_type|, and |init_data|. + // The CDM must respond by calling either Host::OnResolveNewSessionPromise() + // or Host::OnRejectPromise(). + virtual void CreateSessionAndGenerateRequest(uint32_t promise_id, + SessionType session_type, + InitDataType init_data_type, + const uint8_t* init_data, + uint32_t init_data_size) = 0; + + // Loads the session of type |session_type| specified by |session_id|. + // The CDM must respond by calling either Host::OnResolveNewSessionPromise() + // or Host::OnRejectPromise(). If the session is not found, call + // Host::OnResolveNewSessionPromise() with session_id = NULL. + virtual void LoadSession(uint32_t promise_id, + SessionType session_type, + const char* session_id, + uint32_t session_id_size) = 0; + + // Updates the session with |response|. The CDM must respond by calling + // either Host::OnResolvePromise() or Host::OnRejectPromise(). + virtual void UpdateSession(uint32_t promise_id, + const char* session_id, + uint32_t session_id_size, + const uint8_t* response, + uint32_t response_size) = 0; + + // Requests that the CDM close the session. The CDM must respond by calling + // either Host::OnResolvePromise() or Host::OnRejectPromise() when the request + // has been processed. This may be before the session is closed. Once the + // session is closed, Host::OnSessionClosed() must also be called. + virtual void CloseSession(uint32_t promise_id, + const char* session_id, uint32_t session_id_size) = 0; // Removes any stored session data associated with this session. Removes all @@ -950,7 +1196,8 @@ class CDM_CLASS_API ContentDecryptionModule_11 { // processed by UpdateSession(). The CDM must respond by calling either // Host::OnResolvePromise() or Host::OnRejectPromise() when the request has // been processed. - virtual void RemoveSession(uint32_t promise_id, const char* session_id, + virtual void RemoveSession(uint32_t promise_id, + const char* session_id, uint32_t session_id_size) = 0; // Performs scheduled operation with |context| when the timer fires. @@ -1054,7 +1301,8 @@ class CDM_CLASS_API ContentDecryptionModule_11 { // then |link_mask| and |output_protection_mask| are undefined and should // be ignored. virtual void OnQueryOutputProtectionStatus( - QueryResult result, uint32_t link_mask, + QueryResult result, + uint32_t link_mask, uint32_t output_protection_mask) = 0; // Called by the host after a call to Host::RequestStorageId(). If the @@ -1065,15 +1313,16 @@ class CDM_CLASS_API ContentDecryptionModule_11 { // If the requested version is not available, null/zero will be provided as // |storage_id| and |storage_id_size|, respectively, and |version| should be // ignored. - virtual void OnStorageId(uint32_t version, const uint8_t* storage_id, + virtual void OnStorageId(uint32_t version, + const uint8_t* storage_id, uint32_t storage_id_size) = 0; // Destroys the object in the same context as it was created. virtual void Destroy() = 0; protected: - ContentDecryptionModule_11() {} - virtual ~ContentDecryptionModule_11() {} + ContentDecryptionModule_12() {} + virtual ~ContentDecryptionModule_12() {} }; class CDM_CLASS_API Host_10 { @@ -1120,15 +1369,18 @@ class CDM_CLASS_API Host_10 { // ContentDecryptionModule calls that accept a |promise_id|. // |exception| must be specified. |error_message| and |system_code| // are optional. |error_message_size| should not include null termination. - virtual void OnRejectPromise(uint32_t promise_id, Exception exception, - uint32_t system_code, const char* error_message, + virtual void OnRejectPromise(uint32_t promise_id, + Exception exception, + uint32_t system_code, + const char* error_message, uint32_t error_message_size) = 0; // Called by the CDM when it has a message for session |session_id|. // Size parameters should not include null termination. virtual void OnSessionMessage(const char* session_id, uint32_t session_id_size, - MessageType message_type, const char* message, + MessageType message_type, + const char* message, uint32_t message_size) = 0; // Called by the CDM when there has been a change in keys or their status for @@ -1253,15 +1505,18 @@ class CDM_CLASS_API Host_11 { // ContentDecryptionModule calls that accept a |promise_id|. // |exception| must be specified. |error_message| and |system_code| // are optional. |error_message_size| should not include null termination. - virtual void OnRejectPromise(uint32_t promise_id, Exception exception, - uint32_t system_code, const char* error_message, + virtual void OnRejectPromise(uint32_t promise_id, + Exception exception, + uint32_t system_code, + const char* error_message, uint32_t error_message_size) = 0; // Called by the CDM when it has a message for session |session_id|. // Size parameters should not include null termination. virtual void OnSessionMessage(const char* session_id, uint32_t session_id_size, - MessageType message_type, const char* message, + MessageType message_type, + const char* message, uint32_t message_size) = 0; // Called by the CDM when there has been a change in keys or their status for @@ -1328,18 +1583,146 @@ class CDM_CLASS_API Host_11 { // CDM can call this method multiple times to operate on different files. virtual FileIO* CreateFileIO(FileIOClient* client) = 0; - // Requests a CdmProxy that proxies part of CDM functionalities to a different - // entity, e.g. a hardware CDM module. A CDM instance can have at most one - // CdmProxy throughout its lifetime, which must be requested and initialized - // during CDM instance initialization time, i.e. in or after CDM::Initialize() - // and before OnInitialized() is called, to ensure proper connection of the - // CdmProxy and the media player (e.g. hardware decoder). The CdmProxy is - // owned by the host and is guaranteed to be valid throughout the CDM - // instance's lifetime. The CDM must ensure that the |client| remain valid - // before the CDM instance is destroyed. Returns null if CdmProxy is not - // supported, called before CDM::Initialize(), RequestCdmProxy() is called - // more than once, or called after the CDM instance has been initialized. - virtual CdmProxy* RequestCdmProxy(CdmProxyClient* client) = 0; + // Requests a specific version of the storage ID. A storage ID is a stable, + // device specific ID used by the CDM to securely store persistent data. The + // ID will be returned by the host via ContentDecryptionModule::OnStorageId(). + // If |version| is 0, the latest version will be returned. All |version|s + // that are greater than or equal to 0x80000000 are reserved for the CDM and + // should not be supported or returned by the host. The CDM must not expose + // the ID outside the client device, even in encrypted form. + virtual void RequestStorageId(uint32_t version) = 0; + + // Reports the metric |metric_name| with value |value| to the host. Can be + // called by the CDM at any time. May report the same metric multiple times + // during the lifetime of the CDM. + virtual void ReportMetrics(MetricName metric_name, uint64_t value) = 0; + + protected: + Host_11() {} + virtual ~Host_11() {} +}; + +class CDM_CLASS_API Host_12 { + public: + static const int kVersion = 12; + + // Returns a Buffer* containing non-zero members upon success, or NULL on + // failure. The caller owns the Buffer* after this call. The buffer is not + // guaranteed to be zero initialized. The capacity of the allocated Buffer + // is guaranteed to be not less than |capacity|. + virtual Buffer* Allocate(uint32_t capacity) = 0; + + // Requests the host to call ContentDecryptionModule::TimerFired() |delay_ms| + // from now with |context|. + virtual void SetTimer(int64_t delay_ms, void* context) = 0; + + // Returns the current wall time. + virtual Time GetCurrentWallTime() = 0; + + // Called by the CDM with the result after the CDM instance was initialized. + virtual void OnInitialized(bool success) = 0; + + // Called by the CDM when a key status is available in response to + // GetStatusForPolicy(). + virtual void OnResolveKeyStatusPromise(uint32_t promise_id, + KeyStatus key_status) = 0; + + // Called by the CDM when a session is created or loaded and the value for the + // MediaKeySession's sessionId attribute is available (|session_id|). + // This must be called before OnSessionMessage() or + // OnSessionKeysChange() is called for the same session. |session_id_size| + // should not include null termination. + // When called in response to LoadSession(), the |session_id| must be the + // same as the |session_id| passed in LoadSession(), or NULL if the + // session could not be loaded. + virtual void OnResolveNewSessionPromise(uint32_t promise_id, + const char* session_id, + uint32_t session_id_size) = 0; + + // Called by the CDM when a session is updated or released. + virtual void OnResolvePromise(uint32_t promise_id) = 0; + + // Called by the CDM when an error occurs as a result of one of the + // ContentDecryptionModule calls that accept a |promise_id|. + // |exception| must be specified. |error_message| and |system_code| + // are optional. |error_message_size| should not include null termination. + virtual void OnRejectPromise(uint32_t promise_id, + Exception exception, + uint32_t system_code, + const char* error_message, + uint32_t error_message_size) = 0; + + // Called by the CDM when it has a message for session |session_id|. + // Size parameters should not include null termination. + virtual void OnSessionMessage(const char* session_id, + uint32_t session_id_size, + MessageType message_type, + const char* message, + uint32_t message_size) = 0; + + // Called by the CDM when there has been a change in keys or their status for + // session |session_id|. |has_additional_usable_key| should be set if a + // key is newly usable (e.g. new key available, previously expired key has + // been renewed, etc.) and the browser should attempt to resume playback. + // |keys_info| is the list of key IDs for this session along with their + // current status. |keys_info_count| is the number of entries in |keys_info|. + // Size parameter for |session_id| should not include null termination. + virtual void OnSessionKeysChange(const char* session_id, + uint32_t session_id_size, + bool has_additional_usable_key, + const KeyInformation* keys_info, + uint32_t keys_info_count) = 0; + + // Called by the CDM when there has been a change in the expiration time for + // session |session_id|. This can happen as the result of an Update() call + // or some other event. If this happens as a result of a call to Update(), + // it must be called before resolving the Update() promise. |new_expiry_time| + // represents the time after which the key(s) in the session will no longer + // be usable for decryption. It can be 0 if no such time exists or if the + // license explicitly never expires. Size parameter should not include null + // termination. + virtual void OnExpirationChange(const char* session_id, + uint32_t session_id_size, + Time new_expiry_time) = 0; + + // Called by the CDM when session |session_id| is closed. Size + // parameter should not include null termination. + virtual void OnSessionClosed(const char* session_id, + uint32_t session_id_size) = 0; + + // The following are optional methods that may not be implemented on all + // platforms. + + // Sends a platform challenge for the given |service_id|. |challenge| is at + // most 256 bits of data to be signed. Once the challenge has been completed, + // the host will call ContentDecryptionModule::OnPlatformChallengeResponse() + // with the signed challenge response and platform certificate. Size + // parameters should not include null termination. + virtual void SendPlatformChallenge(const char* service_id, + uint32_t service_id_size, + const char* challenge, + uint32_t challenge_size) = 0; + + // Attempts to enable output protection (e.g. HDCP) on the display link. The + // |desired_protection_mask| is a bit mask of OutputProtectionMethods. No + // status callback is issued, the CDM must call QueryOutputProtectionStatus() + // periodically to ensure the desired protections are applied. + virtual void EnableOutputProtection(uint32_t desired_protection_mask) = 0; + + // Requests the current output protection status. Once the host has the status + // it will call ContentDecryptionModule::OnQueryOutputProtectionStatus(). + virtual void QueryOutputProtectionStatus() = 0; + + // Must be called by the CDM if it returned kDeferredInitialization during + // InitializeAudioDecoder() or InitializeVideoDecoder(). + virtual void OnDeferredInitializationDone(StreamType stream_type, + Status decoder_status) = 0; + + // Creates a FileIO object from the host to do file IO operation. Returns NULL + // if a FileIO object cannot be obtained. Once a valid FileIO object is + // returned, |client| must be valid until FileIO::Close() is called. The + // CDM can call this method multiple times to operate on different files. + virtual FileIO* CreateFileIO(FileIOClient* client) = 0; // Requests a specific version of the storage ID. A storage ID is a stable, // device specific ID used by the CDM to securely store persistent data. The @@ -1350,9 +1733,14 @@ class CDM_CLASS_API Host_11 { // the ID outside the client device, even in encrypted form. virtual void RequestStorageId(uint32_t version) = 0; + // Reports the metric |metric_name| with value |value| to the host. Can be + // called by the CDM at any time. May report the same metric multiple times + // during the lifetime of the CDM. + virtual void ReportMetrics(MetricName metric_name, uint64_t value) = 0; + protected: - Host_11() {} - virtual ~Host_11() {} + Host_12() {} + virtual ~Host_12() {} }; } // namespace cdm diff --git a/dom/media/gmp/widevine-adapter/content_decryption_module_proxy.h b/dom/media/gmp/widevine-adapter/content_decryption_module_proxy.h deleted file mode 100644 index d3edff8b37d5..000000000000 --- a/dom/media/gmp/widevine-adapter/content_decryption_module_proxy.h +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CDM_CONTENT_DECRYPTION_MODULE_PROXY_H_ -#define CDM_CONTENT_DECRYPTION_MODULE_PROXY_H_ - -#include "content_decryption_module_export.h" - -#if defined(_MSC_VER) -typedef unsigned char uint8_t; -typedef unsigned int uint32_t; -typedef unsigned __int64 uint64_t; -#else -# include -#endif - -namespace cdm { - -class CDM_CLASS_API CdmProxyClient; - -// A proxy class for the CDM. -// In general, the interpretation of the CdmProxy and CdmProxyClient method -// parameters are protocol dependent. For enum parameters, values outside the -// enum range may not work. -class CDM_CLASS_API CdmProxy { - public: - enum Function : uint32_t { - // For Intel Negotiate Crypto SessionKey Exchange (CSME) path to call - // ID3D11VideoContext::NegotiateCryptoSessionKeyExchange. - kIntelNegotiateCryptoSessionKeyExchange = 1, - // There will be more values in the future e.g. for D3D11 RSA method. - }; - - enum KeyType : uint32_t { - kDecryptOnly = 0, - kDecryptAndDecode = 1, - }; - - // Initializes the proxy. The results will be returned in - // CdmProxyClient::OnInitialized(). - virtual void Initialize() = 0; - - // Processes and updates the state of the proxy. - // |output_data_size| is required by some protocol to set up the output data. - // The operation may fail if the |output_data_size| is wrong. The results will - // be returned in CdmProxyClient::OnProcessed(). - virtual void Process(Function function, uint32_t crypto_session_id, - const uint8_t* input_data, uint32_t input_data_size, - uint32_t output_data_size) = 0; - - // Creates a crypto session for handling media. - // If extra data has to be passed to further setup the media crypto session, - // pass the data as |input_data|. The results will be returned in - // CdmProxyClient::OnMediaCryptoSessionCreated(). - virtual void CreateMediaCryptoSession(const uint8_t* input_data, - uint32_t input_data_size) = 0; - - // Sets a key for the session identified by |crypto_session_id|. - virtual void SetKey(uint32_t crypto_session_id, const uint8_t* key_id, - uint32_t key_id_size, KeyType key_type, - const uint8_t* key_blob, uint32_t key_blob_size) = 0; - - // Removes a key for the session identified by |crypto_session_id|. - virtual void RemoveKey(uint32_t crypto_session_id, const uint8_t* key_id, - uint32_t key_id_size) = 0; - - protected: - CdmProxy() {} - virtual ~CdmProxy() {} -}; - -// Responses to CdmProxy calls. All responses will be called asynchronously. -class CDM_CLASS_API CdmProxyClient { - public: - enum Status : uint32_t { - kOk, - kFail, - }; - - enum Protocol : uint32_t { - kNone = 0, // No protocol supported. Can be used in failure cases. - kIntel, // Method using Intel CSME. - // There will be more values in the future e.g. kD3D11RsaHardware, - // kD3D11RsaSoftware to use the D3D11 RSA method. - }; - - // Callback for Initialize(). If the proxy created a crypto session, then the - // ID for the crypto session is |crypto_session_id|. - virtual void OnInitialized(Status status, Protocol protocol, - uint32_t crypto_session_id) = 0; - - // Callback for Process(). |output_data| is the output of processing. - virtual void OnProcessed(Status status, const uint8_t* output_data, - uint32_t output_data_size) = 0; - - // Callback for CreateMediaCryptoSession(). On success: - // - |crypto_session_id| is the ID for the created crypto session. - // - |output_data| is extra value, if any. - // Otherwise, |crypto_session_id| and |output_data| should be ignored. - virtual void OnMediaCryptoSessionCreated(Status status, - uint32_t crypto_session_id, - uint64_t output_data) = 0; - - // Callback for SetKey(). - virtual void OnKeySet(Status status) = 0; - - // Callback for RemoveKey(). - virtual void OnKeyRemoved(Status status) = 0; - - // Called when there is a hardware reset and all the hardware context is lost. - virtual void NotifyHardwareReset() = 0; - - protected: - CdmProxyClient() {} - virtual ~CdmProxyClient() {} -}; - -} // namespace cdm - -#endif // CDM_CONTENT_DECRYPTION_MODULE_PROXY_H_ diff --git a/dom/media/gmp/widevine-adapter/moz.build b/dom/media/gmp/widevine-adapter/moz.build index b1b75824076d..992837fdf4f6 100644 --- a/dom/media/gmp/widevine-adapter/moz.build +++ b/dom/media/gmp/widevine-adapter/moz.build @@ -10,7 +10,14 @@ SOURCES += [ "WidevineVideoFrame.cpp", ] -EXPORTS += ["WidevineFileIO.h", "WidevineUtils.h", "WidevineVideoFrame.h"] +EXPORTS += [ + "content_decryption_module.h", + "content_decryption_module_export.h", + "content_decryption_module_ext.h", + "WidevineFileIO.h", + "WidevineUtils.h", + "WidevineVideoFrame.h", +] FINAL_LIBRARY = "xul" diff --git a/media/gmp-clearkey/0.1/VideoDecoder.cpp b/media/gmp-clearkey/0.1/VideoDecoder.cpp index 6417defdafdb..697f7ba37bb9 100644 --- a/media/gmp-clearkey/0.1/VideoDecoder.cpp +++ b/media/gmp-clearkey/0.1/VideoDecoder.cpp @@ -219,9 +219,9 @@ VideoDecoder::SampleToVideoFrame(IMFSample* aSample, int32_t aPictureWidth, uint32_t srcUVSize = stride * (aFrameHeight + padding) / 4; uint32_t halfStride = (stride + 1) / 2; - aVideoFrame->SetStride(cdm::VideoPlane::kYPlane, stride); - aVideoFrame->SetStride(cdm::VideoPlane::kUPlane, halfStride); - aVideoFrame->SetStride(cdm::VideoPlane::kVPlane, halfStride); + aVideoFrame->SetStride(cdm::kYPlane, stride); + aVideoFrame->SetStride(cdm::kUPlane, halfStride); + aVideoFrame->SetStride(cdm::kVPlane, halfStride); aVideoFrame->SetSize(cdm::Size{aPictureWidth, aPictureHeight}); @@ -252,17 +252,17 @@ VideoDecoder::SampleToVideoFrame(IMFSample* aSample, int32_t aPictureWidth, uint8_t* outBuffer = buffer->Data(); - aVideoFrame->SetPlaneOffset(cdm::VideoPlane::kYPlane, 0); + aVideoFrame->SetPlaneOffset(cdm::kYPlane, 0); // Offset of U plane is the size of the Y plane, excluding the padding that // WMF adds. uint32_t dstUOffset = stride * aPictureHeight; - aVideoFrame->SetPlaneOffset(cdm::VideoPlane::kUPlane, dstUOffset); + aVideoFrame->SetPlaneOffset(cdm::kUPlane, dstUOffset); // Offset of the V plane is the size of the Y plane + the size of the U plane, // excluding any padding WMF adds. uint32_t dstVOffset = stride * aPictureHeight + (stride * aPictureHeight) / 4; - aVideoFrame->SetPlaneOffset(cdm::VideoPlane::kVPlane, dstVOffset); + aVideoFrame->SetPlaneOffset(cdm::kVPlane, dstVOffset); // Copy the pixel data, excluding WMF's padding. memcpy(outBuffer, data, stride * aPictureHeight); diff --git a/tools/rewriting/ThirdPartyPaths.txt b/tools/rewriting/ThirdPartyPaths.txt index a5f2c72587fe..dbb81b8a8573 100644 --- a/tools/rewriting/ThirdPartyPaths.txt +++ b/tools/rewriting/ThirdPartyPaths.txt @@ -30,7 +30,6 @@ dom/media/gmp/rlz/ dom/media/gmp/widevine-adapter/content_decryption_module_export.h dom/media/gmp/widevine-adapter/content_decryption_module_ext.h dom/media/gmp/widevine-adapter/content_decryption_module.h -dom/media/gmp/widevine-adapter/content_decryption_module_proxy.h dom/media/platforms/ffmpeg/ffmpeg57/ dom/media/platforms/ffmpeg/ffmpeg58/ dom/media/platforms/ffmpeg/ffmpeg59/