// Copyright 2015 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 MEDIA_CDM_CDM_ADAPTER_H_ #define MEDIA_CDM_CDM_ADAPTER_H_ #include #include #include #include #include "base/callback.h" #include "base/compiler_specific.h" #include "base/files/file_path.h" #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/scoped_native_library.h" #include "base/threading/thread.h" #include "media/base/audio_buffer.h" #include "media/base/cdm_config.h" #include "media/base/cdm_context.h" #include "media/base/cdm_factory.h" #include "media/base/cdm_promise_adapter.h" #include "media/base/content_decryption_module.h" #include "media/base/decryptor.h" #include "media/base/media_export.h" #include "media/cdm/api/content_decryption_module.h" #include "ui/gfx/geometry/size.h" namespace media { class AudioFramesImpl; class CdmAuxiliaryHelper; class CdmWrapper; class MEDIA_EXPORT CdmAdapter : public ContentDecryptionModule, public CdmContext, public Decryptor, public cdm::Host_10, public cdm::Host_11 { public: using CreateCdmFunc = void* (*)(int cdm_interface_version, const char* key_system, uint32_t key_system_size, GetCdmHostFunc get_cdm_host_func, void* user_data); // Creates the CDM and initialize it using |key_system| and |cdm_config|. // |allocator| is to be used whenever the CDM needs memory and to create // VideoFrames. |file_io_provider| is to be used whenever the CDM needs access // to the file system. Callbacks will be used for events generated by the CDM. // |cdm_created_cb| will be called when the CDM is initialized. static void Create( const std::string& key_system, const CdmConfig& cdm_config, CreateCdmFunc create_cdm_func, std::unique_ptr helper, const SessionMessageCB& session_message_cb, const SessionClosedCB& session_closed_cb, const SessionKeysChangeCB& session_keys_change_cb, const SessionExpirationUpdateCB& session_expiration_update_cb, CdmCreatedCB cdm_created_cb); // Returns the version of the CDM interface that the created CDM uses. Must // only be called after the CDM is successfully initialized. int GetInterfaceVersion(); // ContentDecryptionModule implementation. void SetServerCertificate(const std::vector& certificate, std::unique_ptr promise) final; void GetStatusForPolicy(HdcpVersion min_hdcp_version, std::unique_ptr promise) final; void CreateSessionAndGenerateRequest( CdmSessionType session_type, EmeInitDataType init_data_type, const std::vector& init_data, std::unique_ptr promise) final; void LoadSession(CdmSessionType session_type, const std::string& session_id, std::unique_ptr promise) final; void UpdateSession(const std::string& session_id, const std::vector& response, std::unique_ptr promise) final; void CloseSession(const std::string& session_id, std::unique_ptr promise) final; void RemoveSession(const std::string& session_id, std::unique_ptr promise) final; CdmContext* GetCdmContext() final; // CdmContext implementation. std::unique_ptr RegisterEventCB(EventCB event_cb) final; Decryptor* GetDecryptor() final; int GetCdmId() const final; // Decryptor implementation. void RegisterNewKeyCB(StreamType stream_type, NewKeyCB key_added_cb) final; void Decrypt(StreamType stream_type, scoped_refptr encrypted, DecryptCB decrypt_cb) final; void CancelDecrypt(StreamType stream_type) final; void InitializeAudioDecoder(const AudioDecoderConfig& config, DecoderInitCB init_cb) final; void InitializeVideoDecoder(const VideoDecoderConfig& config, DecoderInitCB init_cb) final; void DecryptAndDecodeAudio(scoped_refptr encrypted, const AudioDecodeCB& audio_decode_cb) final; void DecryptAndDecodeVideo(scoped_refptr encrypted, const VideoDecodeCB& video_decode_cb) final; void ResetDecoder(StreamType stream_type) final; void DeinitializeDecoder(StreamType stream_type) final; // Common cdm::Host_10 and cdm::Host_11 implementation. cdm::Buffer* Allocate(uint32_t capacity) override; void SetTimer(int64_t delay_ms, void* context) override; cdm::Time GetCurrentWallTime() override; void OnInitialized(bool success) override; void OnResolveKeyStatusPromise(uint32_t promise_id, cdm::KeyStatus key_status) override; void OnResolveNewSessionPromise(uint32_t promise_id, const char* session_id, uint32_t session_id_size) override; void OnResolvePromise(uint32_t promise_id) override; void OnRejectPromise(uint32_t promise_id, cdm::Exception exception, 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 OnSessionKeysChange(const char* session_id, uint32_t session_id_size, bool has_additional_usable_key, const cdm::KeyInformation* keys_info, uint32_t keys_info_count) override; void OnExpirationChange(const char* session_id, uint32_t session_id_size, cdm::Time new_expiry_time) override; void OnSessionClosed(const char* session_id, uint32_t session_id_size) override; void SendPlatformChallenge(const char* service_id, uint32_t service_id_size, const char* challenge, uint32_t challenge_size) override; void EnableOutputProtection(uint32_t desired_protection_mask) override; void QueryOutputProtectionStatus() override; void OnDeferredInitializationDone(cdm::StreamType stream_type, cdm::Status decoder_status) override; cdm::FileIO* CreateFileIO(cdm::FileIOClient* client) override; void RequestStorageId(uint32_t version) override; private: CdmAdapter(const std::string& key_system, const CdmConfig& cdm_config, CreateCdmFunc create_cdm_func, std::unique_ptr helper, const SessionMessageCB& session_message_cb, const SessionClosedCB& session_closed_cb, const SessionKeysChangeCB& session_keys_change_cb, const SessionExpirationUpdateCB& session_expiration_update_cb); ~CdmAdapter() final; // Resolves the |promise| if the CDM is successfully initialized; rejects it // otherwise. void Initialize(std::unique_ptr promise); // Create an instance of the CDM for |key_system|. // Caller owns the returned pointer. Returns nullptr on error, e.g. does not // support |key_system|, does not support an supported interface, etc. CdmWrapper* CreateCdmInstance(const std::string& key_system); // Helper for SetTimer(). void TimerExpired(void* context); // Converts audio data stored in |audio_frames| into individual audio // buffers in |result_frames|. Returns true upon success. bool AudioFramesDataToAudioFrames( std::unique_ptr audio_frames, Decryptor::AudioFrames* result_frames); // Callbacks for Platform Verification. void OnChallengePlatformDone(bool success, const std::string& signed_data, const std::string& signed_data_signature, const std::string& platform_key_certificate); void OnStorageIdObtained(uint32_t version, const std::vector& storage_id); // Callbacks for OutputProtection. void OnEnableOutputProtectionDone(bool success); void OnQueryOutputProtectionStatusDone(bool success, uint32_t link_mask, uint32_t protection_mask); // Helper methods to report output protection UMAs. void ReportOutputProtectionQuery(); void ReportOutputProtectionQueryResult(uint32_t link_mask, uint32_t protection_mask); // Callback to report |file_size_bytes| of the file successfully read by // cdm::FileIO. void OnFileRead(int file_size_bytes); const std::string key_system_; const CdmConfig cdm_config_; CreateCdmFunc create_cdm_func_; // Helper that provides additional functionality for the CDM. std::unique_ptr helper_; // Callbacks for firing session events. SessionMessageCB session_message_cb_; SessionClosedCB session_closed_cb_; SessionKeysChangeCB session_keys_change_cb_; SessionExpirationUpdateCB session_expiration_update_cb_; // CDM origin used in crash reporting. const std::string cdm_origin_; scoped_refptr task_runner_; scoped_refptr pool_; // Callback for Initialize(). uint32_t init_promise_id_ = CdmPromiseAdapter::kInvalidPromiseId; // Callbacks for deferred initialization. DecoderInitCB audio_init_cb_; DecoderInitCB video_init_cb_; // Callbacks for new keys added. NewKeyCB new_audio_key_cb_; NewKeyCB new_video_key_cb_; // Keep track of audio parameters. int audio_samples_per_second_ = 0; ChannelLayout audio_channel_layout_ = CHANNEL_LAYOUT_NONE; // Keep track of aspect ratio from the latest configuration. double pixel_aspect_ratio_ = 0.0; // Whether the current video config is encrypted. bool is_video_encrypted_ = false; // Tracks whether an output protection query and a positive query result (no // unprotected external link) have been reported to UMA. bool uma_for_output_protection_query_reported_ = false; bool uma_for_output_protection_positive_result_reported_ = false; // Tracks CDM file IO related states. int last_read_file_size_kb_ = 0; bool file_size_uma_reported_ = false; // Used to keep track of promises while the CDM is processing the request. CdmPromiseAdapter cdm_promise_adapter_; // Declare |cdm_| after other member variables to avoid the CDM accessing // deleted objects (e.g. |helper_|) during destruction. std::unique_ptr cdm_; // NOTE: Weak pointers must be invalidated before all other member variables. base::WeakPtrFactory weak_factory_{this}; DISALLOW_COPY_AND_ASSIGN(CdmAdapter); }; } // namespace media #endif // MEDIA_CDM_CDM_ADAPTER_H_