diff --git a/inputstream.adaptive/resources/settings.xml.in b/inputstream.adaptive/resources/settings.xml.in index 9100783ba..1f4e36629 100755 --- a/inputstream.adaptive/resources/settings.xml.in +++ b/inputstream.adaptive/resources/settings.xml.in @@ -83,7 +83,7 @@ 4 - 9 + 10 diff --git a/wvdecrypter/cdm/media/cdm/api/content_decryption_module.h b/wvdecrypter/cdm/media/cdm/api/content_decryption_module.h index 5788dc225..8d839e4d0 100755 --- a/wvdecrypter/cdm/media/cdm/api/content_decryption_module.h +++ b/wvdecrypter/cdm/media/cdm/api/content_decryption_module.h @@ -5,6 +5,11 @@ #ifndef CDM_CONTENT_DECRYPTION_MODULE_H_ #define CDM_CONTENT_DECRYPTION_MODULE_H_ +#include + +#include "content_decryption_module_export.h" +#include "content_decryption_module_proxy.h" + #if defined(_MSC_VER) typedef unsigned char uint8_t; typedef unsigned int uint32_t; @@ -14,8 +19,6 @@ typedef __int64 int64_t; #include #endif -#include "content_decryption_module_export.h" - // The version number must be rolled when the exported functions are updated! // If the CDM and the adapter use different versions of these functions, the // adapter will fail to load or crash! @@ -29,159 +32,78 @@ typedef __int64 int64_t; BUILD_ENTRYPOINT_NO_EXPANSION(name, version) #define BUILD_ENTRYPOINT_NO_EXPANSION(name, version) name##_##version +// Macro to check that |type| does the following: +// 1. is a standard layout. +// 2. is trivial. +// 3. sizeof(type) matches the expected size in bytes. As some types contain +// pointers, the size is specified for both 32 and 64 bit. +#define CHECK_TYPE(type, size_32, size_64) \ + static_assert(std::is_standard_layout(), \ + #type " not standard_layout"); \ + static_assert(std::is_trivial(), #type " not trivial"); \ + static_assert((sizeof(void*) == 4 && sizeof(type) == size_32) || \ + (sizeof(void*) == 8 && sizeof(type) == size_64), \ + #type " size mismatch") + extern "C" { -CDM_API void INITIALIZE_CDM_MODULE(); - -CDM_API void DeinitializeCdmModule(); - -// Returns a pointer to the requested CDM Host interface upon success. -// Returns NULL if the requested CDM Host interface is not supported. -// The caller should cast the returned pointer to the type matching -// |host_interface_version|. -typedef void* (*GetCdmHostFunc)(int host_interface_version, void* user_data); - -// Returns a pointer to the requested CDM upon success. -// Returns NULL if an error occurs or the requested |cdm_interface_version| or -// |key_system| is not supported or another error occurs. -// The caller should cast the returned pointer to the type matching -// |cdm_interface_version|. -// Caller retains ownership of arguments and must call Destroy() on the returned -// object. -CDM_API void* CreateCdmInstance( - int cdm_interface_version, - const char* key_system, uint32_t key_system_size, - GetCdmHostFunc get_cdm_host_func, void* user_data); - -CDM_API const char* GetCdmVersion(); -} + + CDM_API void INITIALIZE_CDM_MODULE(); + + CDM_API void DeinitializeCdmModule(); + + // Returns a pointer to the requested CDM Host interface upon success. + // Returns NULL if the requested CDM Host interface is not supported. + // The caller should cast the returned pointer to the type matching + // |host_interface_version|. + typedef void* (*GetCdmHostFunc)(int host_interface_version, void* user_data); + + // Returns a pointer to the requested CDM upon success. + // Returns NULL if an error occurs or the requested |cdm_interface_version| or + // |key_system| is not supported or another error occurs. + // The caller should cast the returned pointer to the type matching + // |cdm_interface_version|. + // Caller retains ownership of arguments and must call Destroy() on the returned + // object. + CDM_API void* CreateCdmInstance(int cdm_interface_version, + const char* key_system, + uint32_t key_system_size, + GetCdmHostFunc get_cdm_host_func, + void* user_data); + + CDM_API const char* GetCdmVersion(); + +} // extern "C" namespace cdm { -class CDM_CLASS_API AudioFrames; -class CDM_CLASS_API DecryptedBlock; -class CDM_CLASS_API VideoFrame; - -class CDM_CLASS_API Host_8; -class CDM_CLASS_API Host_9; -class CDM_CLASS_API Host_10; - -enum Status { - kSuccess = 0, - kNeedMoreData, // Decoder needs more data to produce a decoded frame/sample. - kNoKey, // The required decryption key is not available. - kSessionError, // Session management error. - kDecryptError, // Decryption failed. - kDecodeError, // Error decoding audio or video. - kDeferredInitialization // Decoder is not ready for initialization. -}; - -// This must at least contain the exceptions defined in the spec: -// https://w3c.github.io/encrypted-media/#exceptions -// The following starts with the list of DOM4 exceptions from: -// http://www.w3.org/TR/dom/#domexception -// Some DOM4 exceptions are not included as they are not expected to be used. -enum Error { - kNotSupportedError = 9, - kInvalidStateError = 11, - kInvalidAccessError = 15, - kQuotaExceededError = 22, - - // Additional exceptions that do not have assigned codes. - // There are other non-EME-specific values, not included in this list. - kUnknownError = 30, - - // Additional values from previous EME versions. They currently have no - // matching DOMException. - kClientError = 100, - kOutputError = 101 -}; - -// Exceptions used by the CDM to reject promises. -// https://w3c.github.io/encrypted-media/#exceptions -enum Exception : uint32_t { - kExceptionTypeError, - kExceptionNotSupportedError, - kExceptionInvalidStateError, - kExceptionQuotaExceededError -}; - -// The encryption scheme. The definitions are from ISO/IEC 23001-7:2016. -enum class EncryptionScheme : uint32_t { - kUnencrypted = 0, - kCenc, // 'cenc' subsample encryption using AES-CTR mode. - kCbcs // 'cbcs' pattern encryption using AES-CBC mode. -}; - -// Time is defined as the number of seconds since the -// Epoch (00:00:00 UTC, January 1, 1970). -typedef double Time; - -// An input buffer can be split into several continuous subsamples. -// A SubsampleEntry specifies the number of clear and cipher bytes in each -// subsample. For example, the following buffer has three subsamples: -// -// |<----- subsample1 ----->|<----- subsample2 ----->|<----- subsample3 ----->| -// | clear1 | cipher1 | clear2 | cipher2 | clear3 | cipher3 | -// -// For decryption, all of the cipher bytes in a buffer should be concatenated -// (in the subsample order) into a single logical stream. The clear bytes should -// not be considered as part of decryption. -// -// Stream to decrypt: | cipher1 | cipher2 | cipher3 | -// Decrypted stream: | decrypted1| decrypted2 | decrypted3 | -// -// After decryption, the decrypted bytes should be copied over the position -// of the corresponding cipher bytes in the original buffer to form the output -// buffer. Following the above example, the decrypted buffer should be: -// -// |<----- subsample1 ----->|<----- subsample2 ----->|<----- subsample3 ----->| -// | clear1 | decrypted1| clear2 | decrypted2 | clear3 | decrypted3 | -// -struct SubsampleEntry { - SubsampleEntry(uint32_t clear_bytes, uint32_t cipher_bytes) - : clear_bytes(clear_bytes), cipher_bytes(cipher_bytes) {} - - uint32_t clear_bytes; - uint32_t cipher_bytes; -}; - -// Represents an input buffer to be decrypted (and possibly decoded). It does -// not own any pointers in this struct. If |iv_size| = 0, the data is -// unencrypted. -struct InputBuffer { - InputBuffer() - : data(NULL), - data_size(0), - key_id(NULL), - key_id_size(0), - iv(NULL), - iv_size(0), - subsamples(NULL), - num_subsamples(0), - timestamp(0) {} - - const uint8_t* data; // Pointer to the beginning of the input data. - uint32_t data_size; // Size (in bytes) of |data|. - - const uint8_t* key_id; // Key ID to identify the decryption key. - uint32_t key_id_size; // Size (in bytes) of |key_id|. - - const uint8_t* iv; // Initialization vector. - uint32_t iv_size; // Size (in bytes) of |iv|. - - const struct SubsampleEntry* subsamples; - uint32_t num_subsamples; // Number of subsamples in |subsamples|. - - int64_t timestamp; // Presentation timestamp in microseconds. -}; - -// Represents an input buffer to be decrypted (and possibly decoded). It does -// not own any pointers in this struct. If |encryption_scheme| = kUnencrypted, -// the data is unencrypted. -// Note that this struct is organized so that sizeof(InputBuffer_2) -// equals the sum of sizeof() all members in both 32-bit and 64-bit compiles. -// Padding has been added to keep the fields aligned. -struct InputBuffer_2 { + enum Status : uint32_t { + kSuccess = 0, + kNeedMoreData, // Decoder needs more data to produce a decoded frame/sample. + kNoKey, // The required decryption key is not available. + kInitializationError, // Initialization error. + kDecryptError, // Decryption failed. + kDecodeError, // Error decoding audio or video. + kDeferredInitialization // Decoder is not ready for initialization. + }; + CHECK_TYPE(Status, 4, 4); + + // Exceptions used by the CDM to reject promises. + // https://w3c.github.io/encrypted-media/#exceptions + enum Exception : uint32_t { + kExceptionTypeError, + kExceptionNotSupportedError, + kExceptionInvalidStateError, + kExceptionQuotaExceededError + }; + CHECK_TYPE(Exception, 4, 4); + + // The encryption scheme. The definitions are from ISO/IEC 23001-7:2016. + enum class EncryptionScheme : uint32_t { + kUnencrypted = 0, + kCenc, // 'cenc' subsample encryption using AES-CTR mode. + kCbcs // 'cbcs' pattern encryption using AES-CBC mode. + }; + CHECK_TYPE(EncryptionScheme, 4, 4); // The pattern used for pattern encryption. Note that ISO/IEC 23001-7:2016 // defines each block to be 16-bytes. @@ -189,1552 +111,1667 @@ struct InputBuffer_2 { uint32_t crypt_byte_block; // Count of the encrypted blocks. uint32_t skip_byte_block; // Count of the unencrypted blocks. }; + CHECK_TYPE(Pattern, 8, 8); - InputBuffer_2() - : data(NULL) - , data_size(0) - , encryption_scheme(EncryptionScheme::kCenc) - , key_id(NULL) - , key_id_size(0) - , iv(NULL) - , iv_size(0) - , subsamples(NULL) - , num_subsamples(0) - , timestamp(0) { - pattern.crypt_byte_block = pattern.skip_byte_block = 0; + enum class ColorRange : uint8_t { + kInvalid, + kLimited, // 709 color range with RGB values ranging from 16 to 235. + kFull, // Full RGB color range with RGB values from 0 to 255. + kDerived // Range is defined by |transfer_id| and |matrix_id|. + }; + CHECK_TYPE(ColorRange, 1, 1); + + // Described in ISO 23001-8:2016, section 7. All the IDs are in the range + // [0, 255] so 8-bit integer is sufficient. An unspecified ColorSpace should be + // {2, 2, 2, ColorRange::kInvalid}, where value 2 means "Unspecified" for all + // the IDs, as defined by the spec. + struct ColorSpace { + uint8_t primary_id; // 7.1 colour primaries, table 2 + uint8_t transfer_id; // 7.2 transfer characteristics, table 3 + uint8_t matrix_id; // 7.3 matrix coefficients, table 4 + ColorRange range; + }; + CHECK_TYPE(ColorSpace, 4, 4); + + // Time is defined as the number of seconds since the Epoch + // (00:00:00 UTC, January 1, 1970), not including any added leap second. + // Also see Time definition in spec: https://w3c.github.io/encrypted-media/#time + // Note that Time is defined in millisecond accuracy in the spec but in second + // accuracy here. + typedef double Time; + + // An input buffer can be split into several continuous subsamples. + // A SubsampleEntry specifies the number of clear and cipher bytes in each + // subsample. For example, the following buffer has three subsamples: + // + // |<----- subsample1 ----->|<----- subsample2 ----->|<----- subsample3 ----->| + // | clear1 | cipher1 | clear2 | cipher2 | clear3 | cipher3 | + // + // For decryption, all of the cipher bytes in a buffer should be concatenated + // (in the subsample order) into a single logical stream. The clear bytes should + // not be considered as part of decryption. + // + // Stream to decrypt: | cipher1 | cipher2 | cipher3 | + // Decrypted stream: | decrypted1| decrypted2 | decrypted3 | + // + // After decryption, the decrypted bytes should be copied over the position + // of the corresponding cipher bytes in the original buffer to form the output + // buffer. Following the above example, the decrypted buffer should be: + // + // |<----- subsample1 ----->|<----- subsample2 ----->|<----- subsample3 ----->| + // | clear1 | decrypted1| clear2 | decrypted2 | clear3 | decrypted3 | + // + struct SubsampleEntry { + uint32_t clear_bytes; + uint32_t cipher_bytes; }; + CHECK_TYPE(SubsampleEntry, 8, 8); + + // Represents an input buffer to be decrypted (and possibly decoded). It does + // not own any pointers in this struct. If |iv_size| = 0, the data is + // unencrypted. + // Deprecated: New CDM implementations should use InputBuffer_2. + struct InputBuffer_1 { + const uint8_t* data; // Pointer to the beginning of the input data. + uint32_t data_size; // Size (in bytes) of |data|. + + const uint8_t* key_id; // Key ID to identify the decryption key. + uint32_t key_id_size; // Size (in bytes) of |key_id|. + + const uint8_t* iv; // Initialization vector. + uint32_t iv_size; // Size (in bytes) of |iv|. - InputBuffer_2(const InputBuffer &other) - : data(other.data) - , data_size(other.data_size) - , encryption_scheme(EncryptionScheme::kCenc) - , key_id(other.key_id) - , key_id_size(other.key_id_size) - , iv(other.iv) - , iv_size(other.iv_size) - , subsamples(other.subsamples) - , num_subsamples(other.num_subsamples) - , timestamp(other.timestamp) - { - pattern.crypt_byte_block = pattern.skip_byte_block = 0; + const struct SubsampleEntry* subsamples; + uint32_t num_subsamples; // Number of subsamples in |subsamples|. + + int64_t timestamp; // Presentation timestamp in microseconds. }; + CHECK_TYPE(InputBuffer_1, 40, 72); - const uint8_t* data; // Pointer to the beginning of the input data. - uint32_t data_size; // Size (in bytes) of |data|. - - EncryptionScheme encryption_scheme; - - const uint8_t* key_id; // Key ID to identify the decryption key. - uint32_t key_id_size; // Size (in bytes) of |key_id|. - uint32_t : 32; // Padding. - - const uint8_t* iv; // Initialization vector. - uint32_t iv_size; // Size (in bytes) of |iv|. - uint32_t : 32; // Padding. - - const struct SubsampleEntry* subsamples; - uint32_t num_subsamples; // Number of subsamples in |subsamples|. - uint32_t : 32; // Padding. - - // |pattern| is required if |encryption_scheme| specifies pattern encryption. - Pattern pattern; - - int64_t timestamp; // Presentation timestamp in microseconds. -}; - -enum AudioCodec { - kUnknownAudioCodec = 0, - kCodecVorbis, - kCodecAac -}; - -struct AudioDecoderConfig { - AudioDecoderConfig() - : codec(kUnknownAudioCodec), - channel_count(0), - bits_per_channel(0), - samples_per_second(0), - extra_data(NULL), - extra_data_size(0) {} - - AudioCodec codec; - int32_t channel_count; - int32_t bits_per_channel; - int32_t samples_per_second; - - // Optional byte data required to initialize audio decoders, such as the - // vorbis setup header. - uint8_t* extra_data; - uint32_t extra_data_size; -}; - -struct AudioDecoderConfig_2 { - - AudioDecoderConfig_2() - : codec(kUnknownAudioCodec) - , channel_count(0) - , bits_per_channel(0) - , samples_per_second(0) - , extra_data(NULL) - , extra_data_size(0) - , encryption_scheme(EncryptionScheme::kCenc) - {} - - AudioDecoderConfig_2(const AudioDecoderConfig &other) - : codec(other.codec) - , channel_count(other.channel_count) - , bits_per_channel(other.bits_per_channel) - , samples_per_second(other.samples_per_second) - , extra_data(other.extra_data) - , extra_data_size(other.extra_data_size) - , encryption_scheme(EncryptionScheme::kCenc) - {}; - - AudioCodec codec; - int32_t channel_count; - int32_t bits_per_channel; - int32_t samples_per_second; - - // Optional byte data required to initialize audio decoders, such as the - // vorbis setup header. - uint8_t* extra_data; - uint32_t extra_data_size; - - // Encryption scheme. - EncryptionScheme encryption_scheme; -}; - -// Supported sample formats for AudioFrames. -enum AudioFormat { - kUnknownAudioFormat = 0, // Unknown format value. Used for error reporting. - kAudioFormatU8, // Interleaved unsigned 8-bit w/ bias of 128. - kAudioFormatS16, // Interleaved signed 16-bit. - kAudioFormatS32, // Interleaved signed 32-bit. - kAudioFormatF32, // Interleaved float 32-bit. - kAudioFormatPlanarS16, // Signed 16-bit planar. - kAudioFormatPlanarF32, // Float 32-bit planar. -}; - -// Surface formats based on FOURCC labels, see: http://www.fourcc.org/yuv.php -enum VideoFormat { - kUnknownVideoFormat = 0, // Unknown format value. Used for error reporting. - kYv12, // 12bpp YVU planar 1x1 Y, 2x2 VU samples. - kI420 // 12bpp YVU planar 1x1 Y, 2x2 UV samples. -}; - -struct Size { - Size() : width(0), height(0) {} - Size(int32_t width, int32_t height) : width(width), height(height) {} - - int32_t width; - int32_t height; -}; - -enum VideoCodec { - kUnknownVideoCodec = 0, - kCodecVp8, - kCodecH264, - kCodecVp9 -}; - -enum VideoCodecProfile { - kUnknownVideoCodecProfile = 0, - kProfileNotNeeded, - kH264ProfileBaseline, - kH264ProfileMain, - kH264ProfileExtended, - kH264ProfileHigh, - kH264ProfileHigh10, - kH264ProfileHigh422, - kH264ProfileHigh444Predictive -}; - -struct VideoDecoderConfig { - VideoDecoderConfig() - : codec(kUnknownVideoCodec), - profile(kUnknownVideoCodecProfile), - format(kUnknownVideoFormat), - extra_data(NULL), - extra_data_size(0) {} - - VideoCodec codec; - VideoCodecProfile profile; - VideoFormat format; - - // Width and height of video frame immediately post-decode. Not all pixels - // in this region are valid. - Size coded_size; - - // Optional byte data required to initialize video decoders, such as H.264 - // AAVC data. - uint8_t* extra_data; - uint32_t extra_data_size; -}; - -// Note that this struct is organized so that sizeof(VideoDecoderConfig_2) -// equals the sum of sizeof() all members in both 32-bit and 64-bit compiles. -// Padding has been added to keep the fields aligned. -struct VideoDecoderConfig_2 { - VideoDecoderConfig_2() - : codec(kUnknownVideoCodec) - , profile(kUnknownVideoCodecProfile) - , format(kUnknownVideoFormat) - , extra_data(NULL) - , extra_data_size(0) - , encryption_scheme(EncryptionScheme::kCenc) - {} - - VideoDecoderConfig_2(const VideoDecoderConfig &other) - : codec(other.codec) - , profile(other.profile) - , format(other.format) - , extra_data(other.extra_data) - , extra_data_size(other.extra_data_size) - , encryption_scheme(EncryptionScheme::kCenc) - {} - - VideoCodec codec; - VideoCodecProfile profile; - VideoFormat format; - uint32_t : 32; // Padding. - - // Width and height of video frame immediately post-decode. Not all pixels - // in this region are valid. - Size coded_size; - - // Optional byte data required to initialize video decoders, such as H.264 - // AAVC data. - uint8_t* extra_data; - uint32_t extra_data_size; - - // Encryption scheme. - EncryptionScheme encryption_scheme; -}; - - -enum StreamType { - kStreamTypeAudio = 0, - kStreamTypeVideo = 1 -}; - -// Structure provided to ContentDecryptionModule::OnPlatformChallengeResponse() -// after a platform challenge was initiated via Host::SendPlatformChallenge(). -// All values will be NULL / zero in the event of a challenge failure. -struct PlatformChallengeResponse { - // |challenge| provided during Host::SendPlatformChallenge() combined with - // nonce data and signed with the platform's private key. - const uint8_t* signed_data; - uint32_t signed_data_length; - - // RSASSA-PKCS1-v1_5-SHA256 signature of the |signed_data| block. - const uint8_t* signed_data_signature; - uint32_t signed_data_signature_length; - - // X.509 device specific certificate for the |service_id| requested. - const uint8_t* platform_key_certificate; - uint32_t platform_key_certificate_length; -}; - -// Used when passing arrays of binary data. Does not own the referenced data. -struct BinaryData { - BinaryData() : data(NULL), length(0) {} - const uint8_t* data; - uint32_t length; -}; - -// The current status of the associated key. The valid types are defined in the -// spec: https://w3c.github.io/encrypted-media/#idl-def-MediaKeyStatus -enum KeyStatus { - kUsable = 0, - kInternalError = 1, - kExpired = 2, - kOutputRestricted = 3, - kOutputDownscaled = 4, - kStatusPending = 5, - kReleased = 6 -}; - -// Used when passing arrays of key information. Does not own the referenced -// data. |system_code| is an additional error code for unusable keys and -// should be 0 when |status| == kUsable. -struct KeyInformation { - KeyInformation() - : key_id(NULL), key_id_size(0), status(kInternalError), system_code(0) {} - const uint8_t* key_id; - uint32_t key_id_size; - KeyStatus status; - uint32_t system_code; -}; - -// Supported output protection methods for use with EnableOutputProtection() and -// returned by OnQueryOutputProtectionStatus(). -enum OutputProtectionMethods { - kProtectionNone = 0, - kProtectionHDCP = 1 << 0 -}; - -// Connected output link types returned by OnQueryOutputProtectionStatus(). -enum OutputLinkTypes { - kLinkTypeNone = 0, - kLinkTypeUnknown = 1 << 0, - kLinkTypeInternal = 1 << 1, - kLinkTypeVGA = 1 << 2, - kLinkTypeHDMI = 1 << 3, - kLinkTypeDVI = 1 << 4, - kLinkTypeDisplayPort = 1 << 5, - kLinkTypeNetwork = 1 << 6 -}; - -// Result of the QueryOutputProtectionStatus() call. -enum QueryResult { - kQuerySucceeded = 0, - kQueryFailed -}; - -// The Initialization Data Type. The valid types are defined in the spec: -// http://w3c.github.io/encrypted-media/initdata-format-registry.html#registry -enum InitDataType { - kCenc = 0, - kKeyIds = 1, - kWebM = 2 -}; - -// The type of session to create. The valid types are defined in the spec: -// https://w3c.github.io/encrypted-media/#idl-def-SessionType -enum SessionType { - kTemporary = 0, - kPersistentLicense = 1, - kPersistentKeyRelease = 2 -}; - -// The type of the message event. The valid types are defined in the spec: -// https://w3c.github.io/encrypted-media/#idl-def-MediaKeyMessageType -enum MessageType { - kLicenseRequest = 0, - kLicenseRenewal = 1, - kLicenseRelease = 2 -}; - -enum HdcpVersion : uint32_t { - kHdcpVersionNone, - kHdcpVersion1_0, - kHdcpVersion1_1, - kHdcpVersion1_2, - kHdcpVersion1_3, - kHdcpVersion1_4, - kHdcpVersion2_0, - kHdcpVersion2_1, - kHdcpVersion2_2 -}; - -struct Policy { - HdcpVersion min_hdcp_version; -}; - -// FileIO interface provides a way for the CDM to store data in a file in -// persistent storage. This interface aims only at providing basic read/write -// capabilities and should not be used as a full fledged file IO API. -// Each CDM and origin (e.g. HTTPS, "foo.example.com", 443) combination has -// its own persistent storage. All instances of a given CDM associated with a -// given origin share the same persistent storage. -// Note to implementors of this interface: -// Per-origin storage and the ability for users to clear it are important. -// See http://www.w3.org/TR/encrypted-media/#privacy-storedinfo. -class FileIO { - public: - // Opens the file with |file_name| for read and write. - // FileIOClient::OnOpenComplete() will be called after the opening - // operation finishes. - // - When the file is opened by a CDM instance, it will be classified as "in - // use". In this case other CDM instances in the same domain may receive - // kInUse status when trying to open it. - // - |file_name| must not contain forward slash ('/') or backslash ('\'), and - // must not start with an underscore ('_'). - virtual void Open(const char* file_name, uint32_t file_name_size) = 0; - - // Reads the contents of the file. FileIOClient::OnReadComplete() will be - // called with the read status. Read() should not be called if a previous - // Read() or Write() call is still pending; otherwise OnReadComplete() will - // be called with kInUse. - virtual void Read() = 0; - - // Writes |data_size| bytes of |data| into the file. - // FileIOClient::OnWriteComplete() will be called with the write status. - // All existing contents in the file will be overwritten. Calling Write() with - // NULL |data| will clear all contents in the file. Write() should not be - // called if a previous Write() or Read() call is still pending; otherwise - // OnWriteComplete() will be called with kInUse. - virtual void Write(const uint8_t* data, uint32_t data_size) = 0; - - // Closes the file if opened, destroys this FileIO object and releases any - // resources allocated. The CDM must call this method when it finished using - // this object. A FileIO object must not be used after Close() is called. - virtual void Close() = 0; - - protected: - FileIO() {} - virtual ~FileIO() {} -}; - -// Responses to FileIO calls. All responses will be called asynchronously. -// When kError is returned, the FileIO object could be in an error state. All -// following calls (other than Close()) could return kError. The CDM should -// still call Close() to destroy the FileIO object. -class FileIOClient { - public: - enum Status { - kSuccess = 0, - kInUse, - kError + // Represents an input buffer to be decrypted (and possibly decoded). It does + // not own any pointers in this struct. If |encryption_scheme| = kUnencrypted, + // the data is unencrypted. + // Note that this struct is organized so that sizeof(InputBuffer_2) + // equals the sum of sizeof() all members in both 32-bit and 64-bit compiles. + // Padding has been added to keep the fields aligned. + struct InputBuffer_2 { + const uint8_t* data; // Pointer to the beginning of the input data. + uint32_t data_size; // Size (in bytes) of |data|. + + EncryptionScheme encryption_scheme; + + const uint8_t* key_id; // Key ID to identify the decryption key. + uint32_t key_id_size; // Size (in bytes) of |key_id|. + uint32_t : 32; // Padding. + + const uint8_t* iv; // Initialization vector. + uint32_t iv_size; // Size (in bytes) of |iv|. + uint32_t : 32; // Padding. + + const struct SubsampleEntry* subsamples; + uint32_t num_subsamples; // Number of subsamples in |subsamples|. + uint32_t : 32; // Padding. + + // |pattern| is required if |encryption_scheme| specifies pattern encryption. + Pattern pattern; + + int64_t timestamp; // Presentation timestamp in microseconds. }; + CHECK_TYPE(InputBuffer_2, 64, 80); + + enum AudioCodec : uint32_t { kUnknownAudioCodec = 0, kCodecVorbis, kCodecAac }; + CHECK_TYPE(AudioCodec, 4, 4); + + // Deprecated: New CDM implementations should use AudioDecoderConfig_2. + struct AudioDecoderConfig_1 { + AudioCodec codec; + int32_t channel_count; + int32_t bits_per_channel; + int32_t samples_per_second; + + // Optional byte data required to initialize audio decoders, such as the + // vorbis setup header. + uint8_t* extra_data; + uint32_t extra_data_size; + }; + CHECK_TYPE(AudioDecoderConfig_1, 24, 32); - // Response to a FileIO::Open() call with the open |status|. - virtual void OnOpenComplete(Status status) = 0; - - // Response to a FileIO::Read() call to provide |data_size| bytes of |data| - // read from the file. - // - kSuccess indicates that all contents of the file has been successfully - // read. In this case, 0 |data_size| means that the file is empty. - // - 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, uint32_t data_size) = 0; - - // Response to a FileIO::Write() call. - // - kSuccess indicates that all the data has been written into the file - // successfully. - // - kInUse indicates that there are other read/write operations pending. - // - kError indicates write failure, e.g. the storage is not open or cannot be - // fully written. Upon write failure, the contents of the file should be - // regarded as corrupt and should not used. - virtual void OnWriteComplete(Status status) = 0; - - protected: - FileIOClient() {} - virtual ~FileIOClient() {} -}; - -// 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_8 { - public: - static const int kVersion = 8; - typedef Host_8 Host; - - // Initializes the CDM instance, providing information about permitted - // functionalities. - // 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. - virtual void Initialize(bool allow_distinctive_identifier, - bool allow_persistent_state) = 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(). - 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. 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& 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 kSessionError 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& audio_decoder_config) = 0; - - // Initializes the CDM video decoder with |video_decoder_config|. This - // function must be called before DecryptAndDecodeFrame() is called. + struct AudioDecoderConfig_2 { + AudioCodec codec; + int32_t channel_count; + int32_t bits_per_channel; + int32_t samples_per_second; + + // Optional byte data required to initialize audio decoders, such as the + // vorbis setup header. + uint8_t* extra_data; + uint32_t extra_data_size; + + // Encryption scheme. + EncryptionScheme encryption_scheme; + }; + CHECK_TYPE(AudioDecoderConfig_2, 28, 32); + + // Supported sample formats for AudioFrames. + enum AudioFormat : uint32_t { + kUnknownAudioFormat = 0, // Unknown format value. Used for error reporting. + kAudioFormatU8, // Interleaved unsigned 8-bit w/ bias of 128. + kAudioFormatS16, // Interleaved signed 16-bit. + kAudioFormatS32, // Interleaved signed 32-bit. + kAudioFormatF32, // Interleaved float 32-bit. + kAudioFormatPlanarS16, // Signed 16-bit planar. + kAudioFormatPlanarF32, // Float 32-bit planar. + }; + CHECK_TYPE(AudioFormat, 4, 4); + + // Surface formats based on FOURCC labels, see: http://www.fourcc.org/yuv.php + // Values are chosen to be consistent with Chromium's VideoPixelFormat values. + enum VideoFormat : uint32_t { + kUnknownVideoFormat = 0, // Unknown format value. Used for error reporting. + kYv12 = 1, // 12bpp YVU planar 1x1 Y, 2x2 VU samples. + kI420 = 2, // 12bpp YUV planar 1x1 Y, 2x2 UV samples. + + // In the following formats, each sample uses 16-bit in storage, while the + // sample value is stored in the least significant N bits where N is + // specified by the number after "P". For example, for YUV420P9, each Y, U, + // and V sample is stored in the least significant 9 bits in a 2-byte block. + kYUV420P9 = 16, + kYUV420P10 = 17, + kYUV422P9 = 18, + kYUV422P10 = 19, + kYUV444P9 = 20, + kYUV444P10 = 21, + kYUV420P12 = 22, + kYUV422P12 = 23, + kYUV444P12 = 24, + }; + CHECK_TYPE(VideoFormat, 4, 4); + + struct Size { + int32_t width; + int32_t height; + }; + CHECK_TYPE(Size, 8, 8); + + enum VideoCodec : uint32_t { + kUnknownVideoCodec = 0, + kCodecVp8, + kCodecH264, + kCodecVp9, + kCodecAv1 + }; + CHECK_TYPE(VideoCodec, 4, 4); + + enum VideoCodecProfile : uint32_t { + kUnknownVideoCodecProfile = 0, + kProfileNotNeeded, + kH264ProfileBaseline, + kH264ProfileMain, + kH264ProfileExtended, + kH264ProfileHigh, + kH264ProfileHigh10, + kH264ProfileHigh422, + kH264ProfileHigh444Predictive, + // VP9 Profiles are only passed in starting from CDM_9. + kVP9Profile0, + kVP9Profile1, + kVP9Profile2, + kVP9Profile3, + kAv1ProfileMain, + kAv1ProfileHigh, + kAv1ProfilePro + }; + CHECK_TYPE(VideoCodecProfile, 4, 4); + + // Deprecated: New CDM implementations should use VideoDecoderConfig_3. + struct VideoDecoderConfig_1 { + VideoCodec codec; + VideoCodecProfile profile; + VideoFormat format; + + // Width and height of video frame immediately post-decode. Not all pixels + // in this region are valid. + Size coded_size; + + // Optional byte data required to initialize video decoders, such as H.264 + // AAVC data. + uint8_t* extra_data; + uint32_t extra_data_size; + }; + CHECK_TYPE(VideoDecoderConfig_1, 28, 40); + + // Deprecated: New CDM implementations should use VideoDecoderConfig_3. + // Note that this struct is organized so that sizeof(VideoDecoderConfig_2) + // equals the sum of sizeof() all members in both 32-bit and 64-bit compiles. + // Padding has been added to keep the fields aligned. + struct VideoDecoderConfig_2 { + VideoCodec codec; + VideoCodecProfile profile; + VideoFormat format; + uint32_t : 32; // Padding. + + // Width and height of video frame immediately post-decode. Not all pixels + // in this region are valid. + Size coded_size; + + // Optional byte data required to initialize video decoders, such as H.264 + // AAVC data. + uint8_t* extra_data; + uint32_t extra_data_size; + + // Encryption scheme. + EncryptionScheme encryption_scheme; + }; + CHECK_TYPE(VideoDecoderConfig_2, 36, 40); + + struct VideoDecoderConfig_3 { + VideoCodec codec; + VideoCodecProfile profile; + VideoFormat format; + ColorSpace color_space; + + // Width and height of video frame immediately post-decode. Not all pixels + // in this region are valid. + Size coded_size; + + // Optional byte data required to initialize video decoders, such as H.264 + // AAVC data. + uint8_t* extra_data; + uint32_t extra_data_size; + + EncryptionScheme encryption_scheme; + }; + CHECK_TYPE(VideoDecoderConfig_3, 36, 40); + + enum StreamType : uint32_t { kStreamTypeAudio = 0, kStreamTypeVideo = 1 }; + CHECK_TYPE(StreamType, 4, 4); + + // Structure provided to ContentDecryptionModule::OnPlatformChallengeResponse() + // after a platform challenge was initiated via Host::SendPlatformChallenge(). + // All values will be NULL / zero in the event of a challenge failure. + struct PlatformChallengeResponse { + // |challenge| provided during Host::SendPlatformChallenge() combined with + // nonce data and signed with the platform's private key. + const uint8_t* signed_data; + uint32_t signed_data_length; + + // RSASSA-PKCS1-v1_5-SHA256 signature of the |signed_data| block. + const uint8_t* signed_data_signature; + uint32_t signed_data_signature_length; + + // X.509 device specific certificate for the |service_id| requested. + const uint8_t* platform_key_certificate; + uint32_t platform_key_certificate_length; + }; + CHECK_TYPE(PlatformChallengeResponse, 24, 48); + + // The current status of the associated key. The valid types are defined in the + // spec: https://w3c.github.io/encrypted-media/#idl-def-MediaKeyStatus + enum KeyStatus : uint32_t { + kUsable = 0, + kInternalError = 1, + kExpired = 2, + kOutputRestricted = 3, + kOutputDownscaled = 4, + kStatusPending = 5, + kReleased = 6 + }; + CHECK_TYPE(KeyStatus, 4, 4); + + // Used when passing arrays of key information. Does not own the referenced + // data. |system_code| is an additional error code for unusable keys and + // should be 0 when |status| == kUsable. + struct KeyInformation { + const uint8_t* key_id; + uint32_t key_id_size; + KeyStatus status; + uint32_t system_code; + }; + CHECK_TYPE(KeyInformation, 16, 24); + + // Supported output protection methods for use with EnableOutputProtection() and + // returned by OnQueryOutputProtectionStatus(). + enum OutputProtectionMethods : uint32_t { + kProtectionNone = 0, + kProtectionHDCP = 1 << 0 + }; + CHECK_TYPE(OutputProtectionMethods, 4, 4); + + // Connected output link types returned by OnQueryOutputProtectionStatus(). + enum OutputLinkTypes : uint32_t { + kLinkTypeNone = 0, + kLinkTypeUnknown = 1 << 0, + kLinkTypeInternal = 1 << 1, + kLinkTypeVGA = 1 << 2, + kLinkTypeHDMI = 1 << 3, + kLinkTypeDVI = 1 << 4, + kLinkTypeDisplayPort = 1 << 5, + kLinkTypeNetwork = 1 << 6 + }; + CHECK_TYPE(OutputLinkTypes, 4, 4); + + // Result of the QueryOutputProtectionStatus() call. + enum QueryResult : uint32_t { kQuerySucceeded = 0, kQueryFailed }; + CHECK_TYPE(QueryResult, 4, 4); + + // The Initialization Data Type. The valid types are defined in the spec: + // https://w3c.github.io/encrypted-media/format-registry/initdata/index.html#registry + enum InitDataType : uint32_t { kCenc = 0, kKeyIds = 1, kWebM = 2 }; + CHECK_TYPE(InitDataType, 4, 4); + + // The type of session to create. The valid types are defined in the spec: + // https://w3c.github.io/encrypted-media/#idl-def-SessionType + enum SessionType : uint32_t { + kTemporary = 0, + kPersistentLicense = 1, + kPersistentUsageRecord = 2 + }; + CHECK_TYPE(SessionType, 4, 4); + + // The type of the message event. The valid types are defined in the spec: + // https://w3c.github.io/encrypted-media/#idl-def-MediaKeyMessageType + enum MessageType : uint32_t { + kLicenseRequest = 0, + kLicenseRenewal = 1, + kLicenseRelease = 2, + // Only supported by Host_10 and later. On Host_9 and earlier, it's undefined + // behavior. For example, the host can drop the message or send it using + // other message type. + kIndividualizationRequest = 3 + }; + CHECK_TYPE(MessageType, 4, 4); + + enum HdcpVersion : uint32_t { + kHdcpVersionNone, + kHdcpVersion1_0, + kHdcpVersion1_1, + kHdcpVersion1_2, + kHdcpVersion1_3, + kHdcpVersion1_4, + kHdcpVersion2_0, + kHdcpVersion2_1, + kHdcpVersion2_2, + kHdcpVersion2_3 + }; + CHECK_TYPE(HdcpVersion, 4, 4); + + struct Policy { + HdcpVersion min_hdcp_version; + }; + CHECK_TYPE(Policy, 4, 4); + + // Represents a buffer created by Allocator implementations. + class CDM_CLASS_API Buffer { + public: + // Destroys the buffer in the same context as it was created. + virtual void Destroy() = 0; + + virtual uint32_t Capacity() const = 0; + virtual uint8_t* Data() = 0; + virtual void SetSize(uint32_t size) = 0; + virtual uint32_t Size() const = 0; + + protected: + Buffer() {} + virtual ~Buffer() {} + + private: + Buffer(const Buffer&); + void operator=(const Buffer&); + }; + + // Represents a decrypted block that has not been decoded. + class CDM_CLASS_API DecryptedBlock { + public: + virtual void SetDecryptedBuffer(Buffer* buffer) = 0; + virtual Buffer* DecryptedBuffer() = 0; + + // TODO(tomfinegan): Figure out if timestamp is really needed. If it is not, + // we can just pass Buffer pointers around. + virtual void SetTimestamp(int64_t timestamp) = 0; + virtual int64_t Timestamp() const = 0; + + protected: + DecryptedBlock() {} + virtual ~DecryptedBlock() {} + }; + + enum VideoPlane : uint32_t { + kYPlane = 0, + kUPlane = 1, + kVPlane = 2, + kMaxPlanes = 3, + }; + CHECK_TYPE(VideoPlane, 4, 4); + + class CDM_CLASS_API VideoFrame { + public: + virtual void SetFormat(VideoFormat format) = 0; + virtual VideoFormat Format() const = 0; + + virtual void SetSize(cdm::Size size) = 0; + virtual cdm::Size Size() const = 0; + + virtual void SetFrameBuffer(Buffer* frame_buffer) = 0; + virtual Buffer* FrameBuffer() = 0; + + virtual void SetPlaneOffset(VideoPlane plane, uint32_t offset) = 0; + virtual uint32_t PlaneOffset(VideoPlane plane) = 0; + + virtual void SetStride(VideoPlane plane, uint32_t stride) = 0; + virtual uint32_t Stride(VideoPlane plane) = 0; + + // Sets and gets the presentation timestamp which is in microseconds. + virtual void SetTimestamp(int64_t timestamp) = 0; + virtual int64_t Timestamp() const = 0; + + protected: + VideoFrame() {} + virtual ~VideoFrame() {} + }; + + // Represents a decoded video frame. The CDM should call the interface methods + // to set the frame attributes. See DecryptAndDecodeFrame(). + class CDM_CLASS_API VideoFrame_2 { + public: + virtual void SetFormat(VideoFormat format) = 0; + virtual void SetSize(cdm::Size size) = 0; + virtual void SetFrameBuffer(Buffer* frame_buffer) = 0; + virtual void SetPlaneOffset(VideoPlane plane, uint32_t offset) = 0; + virtual void SetStride(VideoPlane plane, uint32_t stride) = 0; + // Sets the presentation timestamp which is in microseconds. + virtual void SetTimestamp(int64_t timestamp) = 0; + virtual void SetColorSpace(ColorSpace color_space) = 0; + + protected: + VideoFrame_2() {} + virtual ~VideoFrame_2() {} + }; + + // Represents decrypted and decoded audio frames. AudioFrames can contain + // multiple audio output buffers, which are serialized into this format: // - // Returns kSuccess if the |video_decoder_config| is supported and the CDM - // video decoder is successfully initialized. - // Returns kSessionError 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& 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 only empty - // |video_frame| (|format| == kEmptyVideoFrame) is produced. + // |<------------------- serialized audio buffer ------------------->| + // | int64_t timestamp | int64_t length | length bytes of audio data | // - // 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& 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. + // For example, with three audio output buffers, the AudioFrames will look + // like this: // - // 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& encrypted_buffer, - AudioFrames* audio_frames) = 0; - - // Called by the host after a platform challenge was initiated via - // Host::SendPlatformChallenge(). - virtual void OnPlatformChallengeResponse( + // |<----------------- AudioFrames ------------------>| + // | audio buffer 0 | audio buffer 1 | audio buffer 2 | + class CDM_CLASS_API AudioFrames { + public: + virtual void SetFrameBuffer(Buffer* buffer) = 0; + virtual Buffer* FrameBuffer() = 0; + + // The CDM must call this method, providing a valid format, when providing + // frame buffers. Planar data should be stored end to end; e.g., + // |ch1 sample1||ch1 sample2|....|ch1 sample_last||ch2 sample1|... + virtual void SetFormat(AudioFormat format) = 0; + virtual AudioFormat Format() const = 0; + + protected: + AudioFrames() {} + virtual ~AudioFrames() {} + }; + + // FileIO interface provides a way for the CDM to store data in a file in + // persistent storage. This interface aims only at providing basic read/write + // capabilities and should not be used as a full fledged file IO API. + // Each CDM and origin (e.g. HTTPS, "foo.example.com", 443) combination has + // its own persistent storage. All instances of a given CDM associated with a + // given origin share the same persistent storage. + // Note to implementors of this interface: + // Per-origin storage and the ability for users to clear it are important. + // See http://www.w3.org/TR/encrypted-media/#privacy-storedinfo. + class CDM_CLASS_API FileIO { + public: + // Opens the file with |file_name| for read and write. + // FileIOClient::OnOpenComplete() will be called after the opening + // operation finishes. + // - When the file is opened by a CDM instance, it will be classified as "in + // use". In this case other CDM instances in the same domain may receive + // kInUse status when trying to open it. + // - |file_name| must only contain letters (A-Za-z), digits(0-9), or "._-". + // It must not start with an underscore ('_'), and must be at least 1 + // character and no more than 256 characters long. + virtual void Open(const char* file_name, uint32_t file_name_size) = 0; + + // Reads the contents of the file. FileIOClient::OnReadComplete() will be + // called with the read status. Read() should not be called if a previous + // Read() or Write() call is still pending; otherwise OnReadComplete() will + // be called with kInUse. + virtual void Read() = 0; + + // Writes |data_size| bytes of |data| into the file. + // FileIOClient::OnWriteComplete() will be called with the write status. + // All existing contents in the file will be overwritten. Calling Write() with + // NULL |data| will clear all contents in the file. Write() should not be + // called if a previous Write() or Read() call is still pending; otherwise + // OnWriteComplete() will be called with kInUse. + virtual void Write(const uint8_t* data, uint32_t data_size) = 0; + + // Closes the file if opened, destroys this FileIO object and releases any + // resources allocated. The CDM must call this method when it finished using + // this object. A FileIO object must not be used after Close() is called. + virtual void Close() = 0; + + protected: + FileIO() {} + virtual ~FileIO() {} + }; + + // Responses to FileIO calls. All responses will be called asynchronously. + // When kError is returned, the FileIO object could be in an error state. All + // following calls (other than Close()) could return kError. The CDM should + // still call Close() to destroy the FileIO object. + class CDM_CLASS_API FileIOClient { + public: + enum class Status : uint32_t { kSuccess = 0, kInUse, kError }; + + // Response to a FileIO::Open() call with the open |status|. + virtual void OnOpenComplete(Status status) = 0; + + // Response to a FileIO::Read() call to provide |data_size| bytes of |data| + // read from the file. + // - kSuccess indicates that all contents of the file has been successfully + // read. In this case, 0 |data_size| means that the file is empty. + // - 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, + uint32_t data_size) = 0; + + // Response to a FileIO::Write() call. + // - kSuccess indicates that all the data has been written into the file + // successfully. + // - kInUse indicates that there are other read/write operations pending. + // - kError indicates write failure, e.g. the storage is not open or cannot be + // fully written. Upon write failure, the contents of the file should be + // regarded as corrupt and should not used. + virtual void OnWriteComplete(Status status) = 0; + + protected: + FileIOClient() {} + virtual ~FileIOClient() {} + }; + + class CDM_CLASS_API Host_9; + class CDM_CLASS_API Host_10; + class CDM_CLASS_API Host_11; + + // 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_9 { + public: + static const int kVersion = 9; + typedef Host_9 Host; + + // Initializes the CDM instance, providing information about permitted + // functionalities. + // 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. + virtual void Initialize(bool allow_distinctive_identifier, + bool allow_persistent_state) = 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(). + 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. 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_1& 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_1& 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_1& 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_1& 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_1& 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( + // 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; - // Destroys the object in the same context as it was created. - virtual void Destroy() = 0; - - protected: - ContentDecryptionModule_8() {} - virtual ~ContentDecryptionModule_8() {} -}; - -// 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_9 { - public: - static const int kVersion = 9; - typedef Host_9 Host; - - // Initializes the CDM instance, providing information about permitted - // functionalities. - // 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. - virtual void Initialize(bool allow_distinctive_identifier, - bool allow_persistent_state) = 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(). - 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. 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& 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& 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& 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 only empty - // |video_frame| (|format| == kEmptyVideoFrame) is produced. - // - // 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& 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& encrypted_buffer, - AudioFrames* audio_frames) = 0; - - // Called by the host after a platform challenge was initiated via - // Host::SendPlatformChallenge(). - virtual void OnPlatformChallengeResponse( + // 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_9() {} + virtual ~ContentDecryptionModule_9() {} + }; + + // 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_10 { + public: + static const int kVersion = 10; + static const bool kIsStable = true; + typedef Host_10 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. 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( + // 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_9() {} - virtual ~ContentDecryptionModule_9() {} -}; - -// 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_10 { -public: - static const int kVersion = 10; - static const bool kIsStable = true; - typedef Host_10 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. 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 only empty - // |video_frame| (|format| == kEmptyVideoFrame) is produced. - // - // 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_10() {} - virtual ~ContentDecryptionModule_10() {} -}; - - - - - -// Represents a buffer created by Allocator implementations. -class CDM_CLASS_API Buffer { - public: - // Destroys the buffer in the same context as it was created. - virtual void Destroy() = 0; - - virtual uint32_t Capacity() const = 0; - virtual uint8_t* Data() = 0; - virtual void SetSize(uint32_t size) = 0; - virtual uint32_t Size() const = 0; - - protected: - Buffer() {} - virtual ~Buffer() {} - - private: - Buffer(const Buffer&); - void operator=(const Buffer&); -}; - -class CDM_CLASS_API Host_8 { - public: - static const int kVersion = 8; - - // 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 in seconds. - virtual Time GetCurrentWallTime() = 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|. - // |error| 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, - Error error, - 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. - // |legacy_destination_url| is only for supporting the prefixed EME API and - // is ignored by unprefixed EME. It should only be non-null if |message_type| - // is kLicenseRenewal. - virtual void OnSessionMessage(const char* session_id, - uint32_t session_id_size, - MessageType message_type, - const char* message, - uint32_t message_size, - const char* legacy_destination_url, - uint32_t legacy_destination_url_length) = 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. - // |key_ids| is the list of key ids for this session along with their - // current status. |key_ids_count| is the number of entries in |key_ids|. - // 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| - // can be 0 to represent "undefined". 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; - - // Called by the CDM when an error occurs in session |session_id| - // unrelated to one of the ContentDecryptionModule calls that accept a - // |promise_id|. |error| must be specified, |error_message| and - // |system_code| are optional. Length parameters should not include null - // termination. - // Note: - // - This method is only for supporting prefixed EME API. - // - This method will be ignored by unprefixed EME. All errors reported - // in this method should probably also be reported by one of other methods. - virtual void OnLegacySessionError( - const char* session_id, uint32_t session_id_length, - Error error, + // 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_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 + // 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_11 { + public: + static const int kVersion = 11; + static const bool kIsStable = false; + typedef Host_11 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 + // license(s) and key(s) associated with the session, whether they are in + // memory, persistent store, or both. For persistent session types, other + // session data (e.g. record of license destruction) will be cleared as + // defined for each session type once a release message acknowledgment is + // 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, + 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_3& 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_2* 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() {} + }; + + class CDM_CLASS_API Host_9 { + public: + static const int kVersion = 9; + + // 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 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_length) = 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; - - protected: - Host_8() {} - virtual ~Host_8() {} -}; - -class CDM_CLASS_API Host_9 { -public: - static const int kVersion = 9; - - // 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 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 - // 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; - -protected: - Host_9() {} - virtual ~Host_9() {} -}; - -class CDM_CLASS_API Host_10 { -public: - static const int kVersion = 10; - - // 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 - // 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; - -protected: - Host_10() {} - virtual ~Host_10() {} -}; - -// Represents a decrypted block that has not been decoded. -class CDM_CLASS_API DecryptedBlock { - public: - virtual void SetDecryptedBuffer(Buffer* buffer) = 0; - virtual Buffer* DecryptedBuffer() = 0; - - // TODO(tomfinegan): Figure out if timestamp is really needed. If it is not, - // we can just pass Buffer pointers around. - virtual void SetTimestamp(int64_t timestamp) = 0; - virtual int64_t Timestamp() const = 0; - - protected: - DecryptedBlock() {} - virtual ~DecryptedBlock() {} -}; - -class CDM_CLASS_API VideoFrame { - public: - enum VideoPlane { - kYPlane = 0, - kUPlane = 1, - kVPlane = 2, - kMaxPlanes = 3, + 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 + // 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; + + protected: + Host_9() {} + virtual ~Host_9() {} }; - virtual void SetFormat(VideoFormat format) = 0; - virtual VideoFormat Format() const = 0; - - virtual void SetSize(cdm::Size size) = 0; - virtual cdm::Size Size() const = 0; - - virtual void SetFrameBuffer(Buffer* frame_buffer) = 0; - virtual Buffer* FrameBuffer() = 0; - - virtual void SetPlaneOffset(VideoPlane plane, uint32_t offset) = 0; - virtual uint32_t PlaneOffset(VideoPlane plane) = 0; - - virtual void SetStride(VideoPlane plane, uint32_t stride) = 0; - virtual uint32_t Stride(VideoPlane plane) = 0; - - virtual void SetTimestamp(int64_t timestamp) = 0; - virtual int64_t Timestamp() const = 0; - - protected: - VideoFrame() {} - virtual ~VideoFrame() {} -}; - -// Represents decrypted and decoded audio frames. AudioFrames can contain -// multiple audio output buffers, which are serialized into this format: -// -// |<------------------- serialized audio buffer ------------------->| -// | int64_t timestamp | int64_t length | length bytes of audio data | -// -// For example, with three audio output buffers, the AudioFrames will look -// like this: -// -// |<----------------- AudioFrames ------------------>| -// | audio buffer 0 | audio buffer 1 | audio buffer 2 | -class CDM_CLASS_API AudioFrames { - public: - virtual void SetFrameBuffer(Buffer* buffer) = 0; - virtual Buffer* FrameBuffer() = 0; - - // The CDM must call this method, providing a valid format, when providing - // frame buffers. Planar data should be stored end to end; e.g., - // |ch1 sample1||ch1 sample2|....|ch1 sample_last||ch2 sample1|... - virtual void SetFormat(AudioFormat format) = 0; - virtual AudioFormat Format() const = 0; - - protected: - AudioFrames() {} - virtual ~AudioFrames() {} -}; + class CDM_CLASS_API Host_10 { + public: + static const int kVersion = 10; + + // 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 + // 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; + + protected: + Host_10() {} + virtual ~Host_10() {} + }; + + class CDM_CLASS_API Host_11 { + public: + static const int kVersion = 11; + + // 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 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; + + protected: + Host_11() {} + virtual ~Host_11() {} + }; } // namespace cdm -#endif // CDM_CONTENT_DECRYPTION_MODULE_H_ +#endif // CDM_CONTENT_DECRYPTION_MODULE_H_ \ No newline at end of file diff --git a/wvdecrypter/cdm/media/cdm/api/content_decryption_module_proxy.h b/wvdecrypter/cdm/media/cdm/api/content_decryption_module_proxy.h new file mode 100644 index 000000000..a29975a4c --- /dev/null +++ b/wvdecrypter/cdm/media/cdm/api/content_decryption_module_proxy.h @@ -0,0 +1,96 @@ +// 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. + }; + // 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, + 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. + kIntelConvergedSecurityAndManageabilityEngine, // 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; + // 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_ \ No newline at end of file diff --git a/wvdecrypter/cdm/media/cdm/cdm_adapter.cc b/wvdecrypter/cdm/media/cdm/cdm_adapter.cc index 3342fc3c1..1f923835c 100755 --- a/wvdecrypter/cdm/media/cdm/cdm_adapter.cc +++ b/wvdecrypter/cdm/media/cdm/cdm_adapter.cc @@ -50,12 +50,12 @@ void* GetCdmHost(int host_interface_version, void* user_data) switch (host_interface_version) { - case cdm::Host_8::kVersion: - return static_cast(adapter); case cdm::Host_9::kVersion: return static_cast(adapter); case cdm::Host_10::kVersion: return static_cast(adapter); + case cdm::Host_11::kVersion: + return static_cast(adapter); default: return nullptr; } @@ -69,6 +69,41 @@ void timerfunc(std::shared_ptr adp, uint64_t delay, void* context) adp->TimerExpired(context); } +cdm::AudioDecoderConfig_1 ToAudioDecoderConfig_1( + const cdm::AudioDecoderConfig_2& config) { + return{ config.codec, + config.channel_count, + config.bits_per_channel, + config.samples_per_second, + config.extra_data, + config.extra_data_size }; +} + +cdm::VideoDecoderConfig_1 ToVideoDecoderConfig_1( + const cdm::VideoDecoderConfig_3& config) { + return{ config.codec, config.profile, config.format, + config.coded_size, config.extra_data, config.extra_data_size }; +} + +cdm::VideoDecoderConfig_2 ToVideoDecoderConfig_2( + const cdm::VideoDecoderConfig_3& config) { + return{ config.codec, + config.profile, + config.format, + config.coded_size, + config.extra_data, + config.extra_data_size, + config.encryption_scheme }; +} + +cdm::InputBuffer_1 ToInputBuffer_1(const cdm::InputBuffer_2& buffer) { + return{ buffer.data, buffer.data_size, + buffer.key_id, buffer.key_id_size, + buffer.iv, buffer.iv_size, + buffer.subsamples, buffer.num_subsamples, + buffer.timestamp }; +} + /******************************* CdmAdapter ****************************************/ @@ -85,7 +120,7 @@ CdmAdapter::CdmAdapter( , key_system_(key_system) , cdm_config_(cdm_config) , active_buffer_(0) -, cdm8_(0), cdm9_(0), cdm10_(0) +, cdm9_(0), cdm10_(0), cdm11_(0) { //DCHECK(!key_system_.empty()); Initialize(); @@ -93,86 +128,85 @@ CdmAdapter::CdmAdapter( CdmAdapter::~CdmAdapter() { - if (cdm8_) - cdm8_->Destroy(), cdm8_ = nullptr; - else if (cdm9_) + if (cdm9_) cdm9_->Destroy(), cdm9_ = nullptr; else if (cdm10_) cdm10_->Destroy(), cdm10_ = nullptr; + else if (cdm11_) + cdm11_->Destroy(), cdm11_ = nullptr; else return; - DeinitializeCdmModuleFunc deinit_cdm_func = reinterpret_cast(base::GetFunctionPointerFromNativeLibrary(library_, "DeinitializeCdmModule")); - if (deinit_cdm_func) - deinit_cdm_func(); + deinit_cdm_func(); base::UnloadNativeLibrary(library_); } void CdmAdapter::Initialize() { - if (cdm8_ || cdm9_ || cdm10_) + if (cdm9_ || cdm10_ || cdm11_) { - if (cdm8_) - cdm8_->Destroy(), cdm8_ = nullptr; - else if (cdm9_) + if (cdm9_) cdm9_->Destroy(), cdm9_ = nullptr; else if (cdm10_) cdm10_->Destroy(), cdm10_ = nullptr; + else if (cdm11_) + cdm11_->Destroy(), cdm11_ = nullptr; base::UnloadNativeLibrary(library_); library_ = 0; } base::NativeLibraryLoadError error; -#if defined(OS_WIN) - library_ = base::LoadNativeLibraryDynamically(cdm_path_); -#else - library_ = base::LoadNativeLibrary(cdm_path_, 0); -#endif + library_ = base::LoadNativeLibrary(cdm_path_, &error); + if (!library_) return; - InitializeCdmModuleFunc init_cdm_func = reinterpret_cast(base::GetFunctionPointerFromNativeLibrary(library_, MAKE_STRING(INITIALIZE_CDM_MODULE))); - if (init_cdm_func) - init_cdm_func(); + init_cdm_func = reinterpret_cast(base::GetFunctionPointerFromNativeLibrary(library_, MAKE_STRING(INITIALIZE_CDM_MODULE))); + deinit_cdm_func = reinterpret_cast(base::GetFunctionPointerFromNativeLibrary(library_, "DeinitializeCdmModule")); + create_cdm_func = reinterpret_cast(base::GetFunctionPointerFromNativeLibrary(library_, "CreateCdmInstance")); + get_cdm_verion_func = reinterpret_cast(base::GetFunctionPointerFromNativeLibrary(library_, "GetCdmVersion")); - CreateCdmFunc create_cdm_func = reinterpret_cast(base::GetFunctionPointerFromNativeLibrary(library_, "CreateCdmInstance")); - if (!create_cdm_func) + if (!init_cdm_func || !create_cdm_func || !get_cdm_verion_func || !deinit_cdm_func) { base::UnloadNativeLibrary(library_); library_ = 0; return; } - GetCdmVersionFunc get_cdm_verion_func = reinterpret_cast(base::GetFunctionPointerFromNativeLibrary(library_, "GetCdmVersion")); - if (get_cdm_verion_func) - { - std::string version = get_cdm_verion_func(); - version = "CDM version: " + version; - client_->CDMLog(version.c_str()); - } + std::string version = get_cdm_verion_func(); + version = "CDM version: " + version; + client_->CDMLog(version.c_str()); + +#if defined(OS_WIN) + // Load DXVA before sandbox lockdown to give CDM access to Output Protection + // Manager (OPM). + base::LoadNativeLibrary("dxva2.dll", &error); +#endif // defined(OS_WIN) - cdm10_ = static_cast(create_cdm_func(10, key_system_.data(), key_system_.size(), GetCdmHost, this)); + init_cdm_func(); - if (!cdm10_) + cdm11_ = static_cast(create_cdm_func(11, key_system_.data(), key_system_.size(), GetCdmHost, this)); + + if (!cdm11_) { - cdm9_ = static_cast(create_cdm_func(9, key_system_.data(), key_system_.size(), GetCdmHost, this)); + cdm10_ = static_cast(create_cdm_func(10, key_system_.data(), key_system_.size(), GetCdmHost, this)); - if (!cdm9_) - cdm8_ = reinterpret_cast(create_cdm_func(8, key_system_.data(), key_system_.size(), GetCdmHost, this)); + if (!cdm10_) + cdm9_ = reinterpret_cast(create_cdm_func(9, key_system_.data(), key_system_.size(), GetCdmHost, this)); } - if (cdm8_ || cdm9_ || cdm10_) + if (cdm9_ || cdm10_ || cdm11_) { - if (cdm8_) - cdm8_->Initialize(cdm_config_.allow_distinctive_identifier, - cdm_config_.allow_persistent_state); - else if(cdm9_) + if (cdm9_) cdm9_->Initialize(cdm_config_.allow_distinctive_identifier, cdm_config_.allow_persistent_state); - else if (cdm10_) + else if(cdm10_) cdm10_->Initialize(cdm_config_.allow_distinctive_identifier, cdm_config_.allow_persistent_state, false); + else if (cdm11_) + cdm11_->Initialize(cdm_config_.allow_distinctive_identifier, + cdm_config_.allow_persistent_state, false); } else { @@ -202,15 +236,15 @@ void CdmAdapter::SetServerCertificate(uint32_t promise_id, server_certificate_data_size > limits::kMaxCertificateLength) { return; } - if (cdm8_) - cdm8_->SetServerCertificate(promise_id, server_certificate_data, - server_certificate_data_size); - else if (cdm9_) + if (cdm9_) cdm9_->SetServerCertificate(promise_id, server_certificate_data, server_certificate_data_size); else if (cdm10_) cdm10_->SetServerCertificate(promise_id, server_certificate_data, server_certificate_data_size); + else if (cdm11_) + cdm11_->SetServerCertificate(promise_id, server_certificate_data, + server_certificate_data_size); } void CdmAdapter::CreateSessionAndGenerateRequest(uint32_t promise_id, @@ -219,12 +253,7 @@ void CdmAdapter::CreateSessionAndGenerateRequest(uint32_t promise_id, const uint8_t* init_data, uint32_t init_data_size) { - if (cdm8_) - cdm8_->CreateSessionAndGenerateRequest( - promise_id, session_type, - init_data_type, init_data, - init_data_size); - else if (cdm9_) + if (cdm9_) cdm9_->CreateSessionAndGenerateRequest( promise_id, session_type, init_data_type, init_data, @@ -234,6 +263,11 @@ void CdmAdapter::CreateSessionAndGenerateRequest(uint32_t promise_id, promise_id, session_type, init_data_type, init_data, init_data_size); + else if (cdm11_) + cdm11_->CreateSessionAndGenerateRequest( + promise_id, session_type, + init_data_type, init_data, + init_data_size); } void CdmAdapter::LoadSession(uint32_t promise_id, @@ -241,15 +275,15 @@ void CdmAdapter::LoadSession(uint32_t promise_id, const char* session_id, uint32_t session_id_size) { - if (cdm8_) - cdm8_->LoadSession(promise_id, session_type, - session_id, session_id_size); - else if (cdm9_) + if (cdm9_) cdm9_->LoadSession(promise_id, session_type, session_id, session_id_size); else if (cdm10_) cdm10_->LoadSession(promise_id, session_type, session_id, session_id_size); + else if (cdm11_) + cdm11_->LoadSession(promise_id, session_type, + session_id, session_id_size); } void CdmAdapter::UpdateSession(uint32_t promise_id, @@ -258,14 +292,14 @@ void CdmAdapter::UpdateSession(uint32_t promise_id, const uint8_t* response, uint32_t response_size) { - if (cdm8_) - cdm8_->UpdateSession(promise_id, session_id, session_id_size, - response, response_size); - else if(cdm9_) + if (cdm9_) cdm9_->UpdateSession(promise_id, session_id, session_id_size, response, response_size); - else if (cdm10_) + else if(cdm10_) cdm10_->UpdateSession(promise_id, session_id, session_id_size, + response, response_size); + else if (cdm11_) + cdm11_->UpdateSession(promise_id, session_id, session_id_size, response, response_size); } @@ -273,37 +307,37 @@ void CdmAdapter::CloseSession(uint32_t promise_id, const char* session_id, uint32_t session_id_size) { - if (cdm8_) - cdm8_->CloseSession(promise_id, session_id, session_id_size); - else if (cdm9_) + if (cdm9_) cdm9_->CloseSession(promise_id, session_id, session_id_size); else if (cdm10_) cdm10_->CloseSession(promise_id, session_id, session_id_size); + else if (cdm11_) + cdm11_->CloseSession(promise_id, session_id, session_id_size); } void CdmAdapter::RemoveSession(uint32_t promise_id, const char* session_id, uint32_t session_id_size) { - if (cdm8_) - cdm8_->RemoveSession(promise_id, session_id, session_id_size); - else if (cdm9_) + if (cdm9_) cdm9_->RemoveSession(promise_id, session_id, session_id_size); else if (cdm10_) cdm10_->RemoveSession(promise_id, session_id, session_id_size); + else if (cdm11_) + cdm11_->RemoveSession(promise_id, session_id, session_id_size); } void CdmAdapter::TimerExpired(void* context) { - if (cdm8_) - cdm8_->TimerExpired(context); - else if (cdm9_) + if (cdm9_) cdm9_->TimerExpired(context); else if (cdm10_) cdm10_->TimerExpired(context); + else if (cdm11_) + cdm11_->TimerExpired(context); } -cdm::Status CdmAdapter::Decrypt(const cdm::InputBuffer& encrypted_buffer, +cdm::Status CdmAdapter::Decrypt(const cdm::InputBuffer_2& encrypted_buffer, cdm::DecryptedBlock* decrypted_buffer) { //We need this wait here for fast systems, during buffering @@ -315,14 +349,14 @@ cdm::Status CdmAdapter::Decrypt(const cdm::InputBuffer& encrypted_buffer, active_buffer_ = decrypted_buffer->DecryptedBuffer(); cdm::Status ret; - if (cdm8_) - ret = cdm8_->Decrypt(encrypted_buffer, decrypted_buffer); - else if (cdm9_) - ret = cdm9_->Decrypt(encrypted_buffer, decrypted_buffer); + if (cdm9_) + ret = cdm9_->Decrypt(ToInputBuffer_1(encrypted_buffer), decrypted_buffer); else if (cdm10_) + ret = cdm10_->Decrypt(encrypted_buffer, decrypted_buffer); + else if (cdm11_) { cdm::InputBuffer_2 tmp(encrypted_buffer); - ret = cdm10_->Decrypt(tmp, decrypted_buffer); + ret = cdm11_->Decrypt(tmp, decrypted_buffer); } active_buffer_ = 0; @@ -330,103 +364,103 @@ cdm::Status CdmAdapter::Decrypt(const cdm::InputBuffer& encrypted_buffer, } cdm::Status CdmAdapter::InitializeAudioDecoder( - const cdm::AudioDecoderConfig& audio_decoder_config) + const cdm::AudioDecoderConfig_2& audio_decoder_config) { - if (cdm8_) - return cdm8_->InitializeAudioDecoder(audio_decoder_config); - else if (cdm9_) - return cdm9_->InitializeAudioDecoder(audio_decoder_config); + if (cdm9_) + return cdm9_->InitializeAudioDecoder(ToAudioDecoderConfig_1(audio_decoder_config)); else if (cdm10_) return cdm10_->InitializeAudioDecoder(audio_decoder_config); + else if (cdm11_) + return cdm11_->InitializeAudioDecoder(audio_decoder_config); return cdm::kDeferredInitialization; } cdm::Status CdmAdapter::InitializeVideoDecoder( - const cdm::VideoDecoderConfig& video_decoder_config) + const cdm::VideoDecoderConfig_3& video_decoder_config) { - if (cdm8_) - return cdm8_->InitializeVideoDecoder(video_decoder_config); - else if (cdm9_) - return cdm9_->InitializeVideoDecoder(video_decoder_config); + if (cdm9_) + return cdm9_->InitializeVideoDecoder(ToVideoDecoderConfig_1(video_decoder_config)); else if (cdm10_) - return cdm10_->InitializeVideoDecoder(video_decoder_config); + return cdm10_->InitializeVideoDecoder(ToVideoDecoderConfig_2(video_decoder_config)); + else if (cdm11_) + return cdm11_->InitializeVideoDecoder(video_decoder_config); return cdm::kDeferredInitialization; } void CdmAdapter::DeinitializeDecoder(cdm::StreamType decoder_type) { - if (cdm8_) - cdm8_->DeinitializeDecoder(decoder_type); - else if (cdm9_) + if (cdm9_) cdm9_->DeinitializeDecoder(decoder_type); else if (cdm10_) cdm10_->DeinitializeDecoder(decoder_type); + else if (cdm11_) + cdm11_->DeinitializeDecoder(decoder_type); } void CdmAdapter::ResetDecoder(cdm::StreamType decoder_type) { - if (cdm8_) - cdm8_->ResetDecoder(decoder_type); - else if (cdm9_) + if (cdm9_) cdm9_->ResetDecoder(decoder_type); else if (cdm10_) cdm10_->ResetDecoder(decoder_type); + else if (cdm11_) + cdm11_->ResetDecoder(decoder_type); } -cdm::Status CdmAdapter::DecryptAndDecodeFrame(const cdm::InputBuffer& encrypted_buffer, - cdm::VideoFrame* video_frame) +cdm::Status CdmAdapter::DecryptAndDecodeFrame(const cdm::InputBuffer_2& encrypted_buffer, + CdmVideoFrame* video_frame) { std::lock_guard lock(decrypt_mutex_); cdm::Status ret(cdm::kDeferredInitialization); - if (cdm8_) - ret = cdm8_->DecryptAndDecodeFrame(encrypted_buffer, video_frame); - else if (cdm9_) - ret = cdm9_->DecryptAndDecodeFrame(encrypted_buffer, video_frame); + if (cdm9_) + ret = cdm9_->DecryptAndDecodeFrame(ToInputBuffer_1(encrypted_buffer), video_frame); else if (cdm10_) ret = cdm10_->DecryptAndDecodeFrame(encrypted_buffer, video_frame); + else if (cdm11_) + ret = cdm11_->DecryptAndDecodeFrame(encrypted_buffer, video_frame); active_buffer_ = 0; return ret; } -cdm::Status CdmAdapter::DecryptAndDecodeSamples(const cdm::InputBuffer& encrypted_buffer, +cdm::Status CdmAdapter::DecryptAndDecodeSamples(const cdm::InputBuffer_2& encrypted_buffer, cdm::AudioFrames* audio_frames) { std::lock_guard lock(decrypt_mutex_); - if (cdm8_) - return cdm8_->DecryptAndDecodeSamples(encrypted_buffer, audio_frames); - else if (cdm9_) - return cdm9_->DecryptAndDecodeSamples(encrypted_buffer, audio_frames); + if (cdm9_) + return cdm9_->DecryptAndDecodeSamples(ToInputBuffer_1(encrypted_buffer), audio_frames); else if (cdm10_) return cdm10_->DecryptAndDecodeSamples(encrypted_buffer, audio_frames); + else if (cdm11_) + return cdm11_->DecryptAndDecodeSamples(encrypted_buffer, audio_frames); return cdm::kDeferredInitialization; } void CdmAdapter::OnPlatformChallengeResponse( const cdm::PlatformChallengeResponse& response) { - if (cdm8_) - cdm8_->OnPlatformChallengeResponse(response); - else if (cdm9_) + if (cdm9_) cdm9_->OnPlatformChallengeResponse(response); else if (cdm10_) cdm10_->OnPlatformChallengeResponse(response); + else if (cdm11_) + cdm11_->OnPlatformChallengeResponse(response); } void CdmAdapter::OnQueryOutputProtectionStatus(cdm::QueryResult result, uint32_t link_mask, uint32_t output_protection_mask) { - if (cdm8_) - cdm8_->OnQueryOutputProtectionStatus(result, link_mask, - output_protection_mask); - else if (cdm9_) + if (cdm9_) cdm9_->OnQueryOutputProtectionStatus(result, link_mask, output_protection_mask); else if (cdm10_) cdm10_->OnQueryOutputProtectionStatus(result, link_mask, output_protection_mask); + else if (cdm11_) + cdm11_->OnQueryOutputProtectionStatus(result, link_mask, + output_protection_mask); } /******************************** HOST *****************************************/ @@ -460,25 +494,6 @@ void CdmAdapter::OnResolveNewSessionPromise(uint32_t promise_id, { } -void CdmAdapter::OnRejectPromise(uint32_t promise_id, - cdm::Error error, - uint32_t system_code, - const char* error_message, - uint32_t error_message_size) -{ -} - -void CdmAdapter::OnSessionMessage(const char* session_id, - uint32_t session_id_size, - cdm::MessageType message_type, - const char* message, - uint32_t message_size, - const char* legacy_destination_url, - uint32_t legacy_destination_url_size) -{ - SendClientMessage(session_id, session_id_size, CdmAdapterClient::kSessionMessage, reinterpret_cast(message), message_size, 0); -} - void CdmAdapter::OnSessionKeysChange(const char* session_id, uint32_t session_id_size, bool has_additional_usable_key, @@ -512,16 +527,6 @@ void CdmAdapter::OnSessionClosed(const char* session_id, SendClientMessage(session_id, session_id_size, CdmAdapterClient::kSessionClosed, nullptr, 0, 0); } -void CdmAdapter::OnLegacySessionError(const char* session_id, - uint32_t session_id_size, - cdm::Error error, - uint32_t system_code, - const char* error_message, - uint32_t error_message_size) -{ - SendClientMessage(session_id, session_id_size, CdmAdapterClient::kLegacySessionError, nullptr, 0, 0); -} - void CdmAdapter::SendPlatformChallenge(const char* service_id, uint32_t service_id_size, const char* challenge, @@ -559,21 +564,20 @@ void CdmAdapter::OnResolveKeyStatusPromise(uint32_t promise_id, cdm::KeyStatus k void CdmAdapter::OnRejectPromise(uint32_t promise_id, cdm::Exception exception, uint32_t system_code, const char* error_message, uint32_t error_message_size) { - OnRejectPromise(promise_id, static_cast(exception), system_code, error_message, error_message_size); } void CdmAdapter::OnSessionMessage(const char* session_id, uint32_t session_id_size, cdm::MessageType message_type, const char* message, uint32_t message_size) { - OnSessionMessage(session_id, session_id_size, message_type, message, message_size, 0, 0); + SendClientMessage(session_id, session_id_size, CdmAdapterClient::kSessionMessage, reinterpret_cast(message), message_size, 0); } void CdmAdapter::RequestStorageId(uint32_t version) { - if (cdm9_) - cdm9_->OnStorageId(1, nullptr, 0); - else if (cdm10_) + if (cdm10_) cdm10_->OnStorageId(1, nullptr, 0); + else if (cdm11_) + cdm11_->OnStorageId(1, nullptr, 0); } void CdmAdapter::OnInitialized(bool success) @@ -601,15 +605,15 @@ void CdmFileIoImpl::Open(const char* file_name, uint32_t file_name_size) { opened_ = true; base_path_ += std::string(file_name, file_name_size); - client_->OnOpenComplete(cdm::FileIOClient::kSuccess); + client_->OnOpenComplete(cdm::FileIOClient::Status::kSuccess); } else - client_->OnOpenComplete(cdm::FileIOClient::kInUse); + client_->OnOpenComplete(cdm::FileIOClient::Status::kInUse); } void CdmFileIoImpl::Read() { - cdm::FileIOClient::Status status(cdm::FileIOClient::kError); + cdm::FileIOClient::Status status(cdm::FileIOClient::Status::kError); size_t sz(0); free(reinterpret_cast(data_buffer_)); @@ -619,29 +623,29 @@ void CdmFileIoImpl::Read() if (file_descriptor_) { - status = cdm::FileIOClient::kSuccess; + status = cdm::FileIOClient::Status::kSuccess; fseek(file_descriptor_, 0, SEEK_END); sz = ftell(file_descriptor_); if (sz) { fseek(file_descriptor_, 0, SEEK_SET); if ((data_buffer_ = reinterpret_cast(malloc(sz))) == nullptr || fread(data_buffer_, 1, sz, file_descriptor_) != sz) - status = cdm::FileIOClient::kError; + status = cdm::FileIOClient::Status::kError; } } else - status = cdm::FileIOClient::kSuccess; + status = cdm::FileIOClient::Status::kSuccess; client_->OnReadComplete(status, data_buffer_, sz); } void CdmFileIoImpl::Write(const uint8_t* data, uint32_t data_size) { - cdm::FileIOClient::Status status(cdm::FileIOClient::kError); + cdm::FileIOClient::Status status(cdm::FileIOClient::Status::kError); file_descriptor_ = fopen(base_path_.c_str(), "wb"); if (file_descriptor_) { if (fwrite(data, 1, data_size, file_descriptor_) == data_size) - status = cdm::FileIOClient::kSuccess; + status = cdm::FileIOClient::Status::kSuccess; } client_->OnWriteComplete(status); } diff --git a/wvdecrypter/cdm/media/cdm/cdm_adapter.h b/wvdecrypter/cdm/media/cdm/cdm_adapter.h index 45f0d3961..d722f6cf0 100755 --- a/wvdecrypter/cdm/media/cdm/cdm_adapter.h +++ b/wvdecrypter/cdm/media/cdm/cdm_adapter.h @@ -34,10 +34,41 @@ class CdmAdapterClient virtual cdm::Buffer *AllocateBuffer(size_t sz) = 0; }; +class CdmVideoFrame : public cdm::VideoFrame, public cdm::VideoFrame_2 { +public: + CdmVideoFrame() = default; + + void SetFormat(cdm::VideoFormat format) override { m_format = format; } + cdm::VideoFormat Format() const override { return m_format; } + void SetSize(cdm::Size size) override { m_size = size; } + cdm::Size Size() const override { return m_size; } + void SetFrameBuffer(cdm::Buffer* frame_buffer) override { m_buffer = frame_buffer; } + cdm::Buffer* FrameBuffer() override { return m_buffer; } + void SetPlaneOffset(cdm::VideoPlane plane, uint32_t offset) override { m_planeOffsets[plane] = offset; } + void SetColorSpace(cdm::ColorSpace color_space) { m_colorSpace = color_space; }; + + virtual uint32_t PlaneOffset(cdm::VideoPlane plane) override { return m_planeOffsets[plane]; } + virtual void SetStride(cdm::VideoPlane plane, uint32_t stride) override { m_stride[plane] = stride; } + virtual uint32_t Stride(cdm::VideoPlane plane) override { return m_stride[plane]; } + virtual void SetTimestamp(int64_t timestamp) override { m_pts = timestamp; } + + virtual int64_t Timestamp() const override { return m_pts; } +private: + cdm::VideoFormat m_format; + cdm::Buffer *m_buffer = nullptr; + cdm::Size m_size; + cdm::ColorSpace m_colorSpace; + + uint32_t m_planeOffsets[cdm::VideoPlane::kMaxPlanes]; + uint32_t m_stride[cdm::VideoPlane::kMaxPlanes]; + + uint64_t m_pts; +}; + class CdmAdapter : public std::enable_shared_from_this - , public cdm::Host_8 , public cdm::Host_9 , public cdm::Host_10 + , public cdm::Host_11 { public: CdmAdapter(const std::string& key_system, @@ -73,29 +104,29 @@ class CdmAdapter : public std::enable_shared_from_this const char* session_id, uint32_t session_id_size); - void RemoveSession(uint32_t promise_id, + void RemoveSession(uint32_t promise_id, const char* session_id, uint32_t session_id_size); void TimerExpired(void* context); - cdm::Status Decrypt(const cdm::InputBuffer& encrypted_buffer, + cdm::Status Decrypt(const cdm::InputBuffer_2& encrypted_buffer, cdm::DecryptedBlock* decrypted_buffer); cdm::Status InitializeAudioDecoder( - const cdm::AudioDecoderConfig& audio_decoder_config); + const cdm::AudioDecoderConfig_2& audio_decoder_config); cdm::Status InitializeVideoDecoder( - const cdm::VideoDecoderConfig& video_decoder_config); + const cdm::VideoDecoderConfig_3& video_decoder_config); void DeinitializeDecoder(cdm::StreamType decoder_type); void ResetDecoder(cdm::StreamType decoder_type); - cdm::Status DecryptAndDecodeFrame(const cdm::InputBuffer& encrypted_buffer, - cdm::VideoFrame* video_frame); + cdm::Status DecryptAndDecodeFrame(const cdm::InputBuffer_2& encrypted_buffer, + CdmVideoFrame* video_frame); - cdm::Status DecryptAndDecodeSamples(const cdm::InputBuffer& encrypted_buffer, + cdm::Status DecryptAndDecodeSamples(const cdm::InputBuffer_2& encrypted_buffer, cdm::AudioFrames* audio_frames); void OnPlatformChallengeResponse( @@ -128,26 +159,12 @@ class CdmAdapter : public std::enable_shared_from_this const char* error_message, uint32_t error_message_size) override; - void OnRejectPromise(uint32_t promise_id, - cdm::Error error, - uint32_t system_code, - const char* error_message, - uint32_t error_message_size)override; - void OnSessionMessage(const char* session_id, uint32_t session_id_size, cdm::MessageType message_type, const char* message, uint32_t message_size) override; - void OnSessionMessage(const char* session_id, - uint32_t session_id_size, - cdm::MessageType message_type, - const char* message, - uint32_t message_size, - const char* legacy_destination_url, - uint32_t legacy_destination_url_size)override; - void OnSessionKeysChange(const char* session_id, uint32_t session_id_size, bool has_additional_usable_key, @@ -161,13 +178,6 @@ class CdmAdapter : public std::enable_shared_from_this void OnSessionClosed(const char* session_id, uint32_t session_id_size) override; - void OnLegacySessionError(const char* session_id, - uint32_t session_id_size, - cdm::Error error, - uint32_t system_code, - const char* error_message, - uint32_t error_message_size)override; - void SendPlatformChallenge(const char* service_id, uint32_t service_id_size, const char* challenge, @@ -184,11 +194,13 @@ class CdmAdapter : public std::enable_shared_from_this void RequestStorageId(uint32_t version) override; + cdm::CdmProxy* RequestCdmProxy(cdm::CdmProxyClient* client) override { return nullptr; }; + void OnInitialized(bool success) override; public: //Misc - virtual ~CdmAdapter(); + ~CdmAdapter(); bool valid(){ return library_ != 0; }; private: using InitializeCdmModuleFunc = void(*)(); @@ -200,8 +212,12 @@ class CdmAdapter : public std::enable_shared_from_this GetCdmHostFunc get_cdm_host_func, void* user_data); + InitializeCdmModuleFunc init_cdm_func; + CreateCdmFunc create_cdm_func; + GetCdmVersionFunc get_cdm_verion_func; + DeinitializeCdmModuleFunc deinit_cdm_func; - virtual void Initialize(); + void Initialize(); void SendClientMessage(const char* session, uint32_t session_size, CdmAdapterClient::CDMADPMSG msg, const uint8_t *data, size_t data_size, uint32_t status); // Keep a reference to the CDM. @@ -218,9 +234,9 @@ class CdmAdapter : public std::enable_shared_from_this cdm::MessageType message_type_; cdm::Buffer *active_buffer_; - cdm::ContentDecryptionModule_8 *cdm8_; cdm::ContentDecryptionModule_9 *cdm9_; cdm::ContentDecryptionModule_10 *cdm10_; + cdm::ContentDecryptionModule_11 *cdm11_; DISALLOW_COPY_AND_ASSIGN(CdmAdapter); }; diff --git a/wvdecrypter/wvdecrypter.cpp b/wvdecrypter/wvdecrypter.cpp index 26750003b..98338c486 100755 --- a/wvdecrypter/wvdecrypter.cpp +++ b/wvdecrypter/wvdecrypter.cpp @@ -158,79 +158,7 @@ class CdmFixedBuffer : public cdm::Buffer { void *instance_; }; -class CdmVideoFrame : public cdm::VideoFrame { -public: - CdmVideoFrame() :m_buffer(0) {}; - - virtual void SetFormat(cdm::VideoFormat format) override - { - m_format = format; - } - - virtual cdm::VideoFormat Format() const override - { - return m_format; - } - - virtual void SetSize(cdm::Size size) override - { - m_size = size; - } - - virtual cdm::Size Size() const override - { - return m_size; - } - - virtual void SetFrameBuffer(cdm::Buffer* frame_buffer) override - { - m_buffer = frame_buffer; - } - - virtual cdm::Buffer* FrameBuffer() override - { - return m_buffer; - } - - virtual void SetPlaneOffset(VideoPlane plane, uint32_t offset) override - { - m_planeOffsets[plane] = offset; - } - - virtual uint32_t PlaneOffset(VideoPlane plane) override - { - return m_planeOffsets[plane]; - } - - virtual void SetStride(VideoPlane plane, uint32_t stride) override - { - m_stride[plane] = stride; - } - - virtual uint32_t Stride(VideoPlane plane) override - { - return m_stride[plane]; - } - - virtual void SetTimestamp(int64_t timestamp) override - { - m_pts = timestamp; - } - - virtual int64_t Timestamp() const override - { - return m_pts; - } -private: - cdm::VideoFormat m_format; - cdm::Buffer *m_buffer; - cdm::Size m_size; - uint32_t m_planeOffsets[cdm::VideoFrame::kMaxPlanes]; - uint32_t m_stride[cdm::VideoFrame::kMaxPlanes]; - - uint64_t m_pts; -}; /*---------------------------------------------------------------------- | WV_CencSingleSampleDecrypter @@ -319,7 +247,7 @@ class WV_CencSingleSampleDecrypter : public AP4_CencSingleSampleDecrypter uint32_t promise_id_; bool drained_; - std::list videoFrames_; + std::list videoFrames_; std::mutex renewal_lock_; }; @@ -361,7 +289,7 @@ class WV_DRM : public media::CdmAdapterClient media::CdmAdapter *GetCdmAdapter() { return wv_adapter.get(); }; const std::string &GetLicenseURL() { return license_url_; }; - cdm::Status DecryptAndDecodeFrame(void* hostInstance, cdm::InputBuffer &cdm_in, cdm::VideoFrame *frame) + cdm::Status DecryptAndDecodeFrame(void* hostInstance, cdm::InputBuffer_2 &cdm_in, media::CdmVideoFrame *frame) { host_instance_ = hostInstance; cdm::Status ret = wv_adapter->DecryptAndDecodeFrame(cdm_in, frame); @@ -1204,7 +1132,7 @@ AP4_Result WV_CencSingleSampleDecrypter::DecryptSampleData(AP4_UI32 pool_id, } // transform ap4 format into cmd format - cdm::InputBuffer cdm_in; + cdm::InputBuffer_2 cdm_in; if (subsample_count > max_subsample_count_decrypt_) { subsample_buffer_decrypt_ = (cdm::SubsampleEntry*)realloc(subsample_buffer_decrypt_, subsample_count*sizeof(cdm::SubsampleEntry)); @@ -1264,6 +1192,9 @@ AP4_Result WV_CencSingleSampleDecrypter::DecryptSampleData(AP4_UI32 pool_id, cdm_in.key_id = fragInfo.key_; cdm_in.key_id_size = 16; cdm_in.subsamples = subsample_buffer_decrypt_; + cdm_in.encryption_scheme = cdm::EncryptionScheme::kCenc; + cdm_in.timestamp = 0; + cdm_in.pattern = { 0,0 }; CdmBuffer buf((useSingleDecrypt) ? &decrypt_out_ : &data_out); CdmDecryptedBlock cdm_out; @@ -1296,7 +1227,7 @@ AP4_Result WV_CencSingleSampleDecrypter::DecryptSampleData(AP4_UI32 pool_id, bool WV_CencSingleSampleDecrypter::OpenVideoDecoder(const SSD_VIDEOINITDATA *initData) { - cdm::VideoDecoderConfig vconfig; + cdm::VideoDecoderConfig_3 vconfig; vconfig.codec = static_cast(initData->codec); vconfig.coded_size.width = initData->width; vconfig.coded_size.height = initData->height; @@ -1304,6 +1235,8 @@ bool WV_CencSingleSampleDecrypter::OpenVideoDecoder(const SSD_VIDEOINITDATA *ini vconfig.extra_data_size = initData->extraDataSize; vconfig.format = static_cast (initData->videoFormats[0]); vconfig.profile = static_cast(initData->codecProfile); + vconfig.color_space = { 2, 2, 2, cdm::ColorRange::kInvalid }; + vconfig.encryption_scheme = cdm::EncryptionScheme::kCenc; cdm::Status ret = drm_.GetCdmAdapter()->InitializeVideoDecoder(vconfig); videoFrames_.clear(); @@ -1322,7 +1255,7 @@ SSD_DECODE_RETVAL WV_CencSingleSampleDecrypter::DecodeVideo(void* hostInstance, if (videoFrames_.size() == 4) return VC_ERROR; - cdm::InputBuffer cdm_in; + cdm::InputBuffer_2 cdm_in; if (sample->numSubSamples) { if (sample->clearBytes == NULL || sample->cipherBytes == NULL) { @@ -1352,6 +1285,8 @@ SSD_DECODE_RETVAL WV_CencSingleSampleDecrypter::DecodeVideo(void* hostInstance, cdm_in.iv = sample->iv; cdm_in.iv_size = sample->iv ? 16 : 0; cdm_in.timestamp = sample->pts; + cdm_in.encryption_scheme = cdm::EncryptionScheme::kCenc; + cdm_in.pattern = { 0,0 }; uint8_t unencryptedKID = 0x31; cdm_in.key_id = sample->kid ? sample->kid : &unencryptedKID; @@ -1362,12 +1297,12 @@ SSD_DECODE_RETVAL WV_CencSingleSampleDecrypter::DecodeVideo(void* hostInstance, //DecryptAndDecode calls Alloc wich cals kodi VideoCodec. Set instance handle. //LICENSERENEWAL: CheckLicenseRenewal(); - CdmVideoFrame frame; + media::CdmVideoFrame frame; cdm::Status ret = drm_.DecryptAndDecodeFrame(hostInstance, cdm_in, &frame); if (ret == cdm::Status::kSuccess) { - std::list::iterator f(videoFrames_.begin()); + std::list::iterator f(videoFrames_.begin()); while (f != videoFrames_.end() && f->Timestamp() < frame.Timestamp())++f; videoFrames_.insert(f, frame); } @@ -1390,7 +1325,7 @@ SSD_DECODE_RETVAL WV_CencSingleSampleDecrypter::DecodeVideo(void* hostInstance, { if (videoFrames_.size() == 4 || (videoFrames_.size() && (picture->flags & SSD_PICTURE::FLAG_DRAIN))) { - CdmVideoFrame &videoFrame_(videoFrames_.front()); + media::CdmVideoFrame &videoFrame_(videoFrames_.front()); picture->width = videoFrame_.Size().width; picture->height = videoFrame_.Size().height; @@ -1399,10 +1334,10 @@ SSD_DECODE_RETVAL WV_CencSingleSampleDecrypter::DecodeVideo(void* hostInstance, picture->decodedDataSize = videoFrame_.FrameBuffer()->Size(); picture->buffer = static_cast(videoFrame_.FrameBuffer())->Buffer(); - for (unsigned int i(0); i < cdm::VideoFrame::kMaxPlanes; ++i) + for (unsigned int i(0); i < cdm::VideoPlane::kMaxPlanes; ++i) { - picture->planeOffsets[i] = videoFrame_.PlaneOffset(static_cast(i)); - picture->stride[i] = videoFrame_.Stride(static_cast(i)); + picture->planeOffsets[i] = videoFrame_.PlaneOffset(static_cast(i)); + picture->stride[i] = videoFrame_.Stride(static_cast(i)); } picture->videoFormat = static_cast(videoFrame_.Format()); videoFrame_.SetFrameBuffer(nullptr); //marker for "No Picture"