cdm_wrapper.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. // Copyright 2013 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef MEDIA_CDM_CDM_WRAPPER_H_
  5. #define MEDIA_CDM_CDM_WRAPPER_H_
  6. #include <stdint.h>
  7. #include "base/check.h"
  8. #include "base/feature_list.h"
  9. #include "base/memory/raw_ptr.h"
  10. #include "media/base/media_switches.h"
  11. #include "media/cdm/api/content_decryption_module.h"
  12. #include "media/cdm/cdm_helpers.h"
  13. #include "media/cdm/supported_cdm_versions.h"
  14. namespace media {
  15. namespace {
  16. cdm::VideoDecoderConfig_2 ToVideoDecoderConfig_2(
  17. const cdm::VideoDecoderConfig_3& config) {
  18. return {config.codec,
  19. config.profile,
  20. config.format,
  21. config.coded_size,
  22. config.extra_data,
  23. config.extra_data_size,
  24. config.encryption_scheme};
  25. }
  26. } // namespace
  27. // Returns a pointer to the requested CDM upon success.
  28. // Returns NULL if an error occurs or the requested |cdm_interface_version| or
  29. // |key_system| is not supported or another error occurs.
  30. // The caller should cast the returned pointer to the type matching
  31. // |cdm_interface_version|.
  32. // Caller retains ownership of arguments and must call Destroy() on the returned
  33. // object.
  34. typedef void* (*CreateCdmFunc)(int cdm_interface_version,
  35. const char* key_system,
  36. uint32_t key_system_size,
  37. GetCdmHostFunc get_cdm_host_func,
  38. void* user_data);
  39. // CdmWrapper wraps different versions of ContentDecryptionModule interfaces and
  40. // exposes a common interface to the caller.
  41. //
  42. // The caller should call CdmWrapper::Create() to create a CDM instance.
  43. // CdmWrapper will first try to create a CDM instance that supports the latest
  44. // CDM interface (ContentDecryptionModule). If such an instance cannot be
  45. // created (e.g. an older CDM was loaded), CdmWrapper will try to create a CDM
  46. // that supports an older version of CDM interface (e.g.
  47. // ContentDecryptionModule_*). Internally CdmWrapper converts the CdmWrapper
  48. // calls to corresponding ContentDecryptionModule calls.
  49. //
  50. // Since this file is highly templated and default implementations are short
  51. // (just a shim layer in most cases), everything is done in this header file.
  52. //
  53. // TODO(crbug.com/799169): After pepper CDM support is removed, this file can
  54. // depend on media/ and we can clean this class up, e.g. pass in CdmConfig.
  55. class CdmWrapper {
  56. public:
  57. static CdmWrapper* Create(CreateCdmFunc create_cdm_func,
  58. const char* key_system,
  59. uint32_t key_system_size,
  60. GetCdmHostFunc get_cdm_host_func,
  61. void* user_data);
  62. CdmWrapper(const CdmWrapper&) = delete;
  63. CdmWrapper& operator=(const CdmWrapper&) = delete;
  64. virtual ~CdmWrapper() {}
  65. // Returns the version of the CDM interface that the created CDM uses.
  66. virtual int GetInterfaceVersion() = 0;
  67. // Initializes the CDM instance and returns whether OnInitialized() will be
  68. // called on the host. The caller should NOT wait for OnInitialized() if false
  69. // is returned.
  70. virtual bool Initialize(bool allow_distinctive_identifier,
  71. bool allow_persistent_state,
  72. bool use_hw_secure_codecs) = 0;
  73. virtual void SetServerCertificate(uint32_t promise_id,
  74. const uint8_t* server_certificate_data,
  75. uint32_t server_certificate_data_size) = 0;
  76. // Gets the key status for a policy that contains the |min_hdcp_version|.
  77. // Returns whether GetStatusForPolicy() is supported. If true, the CDM should
  78. // resolve or reject the promise. If false, the caller will reject the
  79. // promise.
  80. [[nodiscard]] virtual bool GetStatusForPolicy(
  81. uint32_t promise_id,
  82. cdm::HdcpVersion min_hdcp_version) = 0;
  83. virtual void CreateSessionAndGenerateRequest(uint32_t promise_id,
  84. cdm::SessionType session_type,
  85. cdm::InitDataType init_data_type,
  86. const uint8_t* init_data,
  87. uint32_t init_data_size) = 0;
  88. virtual void LoadSession(uint32_t promise_id,
  89. cdm::SessionType session_type,
  90. const char* session_id,
  91. uint32_t session_id_size) = 0;
  92. virtual void UpdateSession(uint32_t promise_id,
  93. const char* session_id,
  94. uint32_t session_id_size,
  95. const uint8_t* response,
  96. uint32_t response_size) = 0;
  97. virtual void CloseSession(uint32_t promise_id,
  98. const char* session_id,
  99. uint32_t session_id_size) = 0;
  100. virtual void RemoveSession(uint32_t promise_id,
  101. const char* session_id,
  102. uint32_t session_id_size) = 0;
  103. virtual void TimerExpired(void* context) = 0;
  104. virtual cdm::Status Decrypt(const cdm::InputBuffer_2& encrypted_buffer,
  105. cdm::DecryptedBlock* decrypted_buffer) = 0;
  106. virtual cdm::Status InitializeAudioDecoder(
  107. const cdm::AudioDecoderConfig_2& audio_decoder_config) = 0;
  108. virtual cdm::Status InitializeVideoDecoder(
  109. const cdm::VideoDecoderConfig_3& video_decoder_config) = 0;
  110. virtual void DeinitializeDecoder(cdm::StreamType decoder_type) = 0;
  111. virtual void ResetDecoder(cdm::StreamType decoder_type) = 0;
  112. virtual cdm::Status DecryptAndDecodeFrame(
  113. const cdm::InputBuffer_2& encrypted_buffer,
  114. media::VideoFrameImpl* video_frame) = 0;
  115. virtual cdm::Status DecryptAndDecodeSamples(
  116. const cdm::InputBuffer_2& encrypted_buffer,
  117. cdm::AudioFrames* audio_frames) = 0;
  118. virtual void OnPlatformChallengeResponse(
  119. const cdm::PlatformChallengeResponse& response) = 0;
  120. virtual void OnQueryOutputProtectionStatus(
  121. cdm::QueryResult result,
  122. uint32_t link_mask,
  123. uint32_t output_protection_mask) = 0;
  124. virtual void OnStorageId(uint32_t version,
  125. const uint8_t* storage_id,
  126. uint32_t storage_id_size) = 0;
  127. protected:
  128. CdmWrapper() {}
  129. };
  130. // Template class that does the CdmWrapper -> CdmInterface conversion. Default
  131. // implementations are provided. Any methods that need special treatment should
  132. // be specialized.
  133. template <int CdmInterfaceVersion>
  134. class CdmWrapperImpl : public CdmWrapper {
  135. public:
  136. using CdmInterface =
  137. typename CdmInterfaceTraits<CdmInterfaceVersion>::CdmInterface;
  138. static_assert(CdmInterfaceVersion == CdmInterface::kVersion,
  139. "CDM interface version mismatch.");
  140. static CdmWrapper* Create(CreateCdmFunc create_cdm_func,
  141. const char* key_system,
  142. uint32_t key_system_size,
  143. GetCdmHostFunc get_cdm_host_func,
  144. void* user_data) {
  145. void* cdm_instance =
  146. create_cdm_func(CdmInterfaceVersion, key_system, key_system_size,
  147. get_cdm_host_func, user_data);
  148. if (!cdm_instance)
  149. return nullptr;
  150. return new CdmWrapperImpl<CdmInterfaceVersion>(
  151. static_cast<CdmInterface*>(cdm_instance));
  152. }
  153. CdmWrapperImpl(const CdmWrapperImpl&) = delete;
  154. CdmWrapperImpl& operator=(const CdmWrapperImpl&) = delete;
  155. ~CdmWrapperImpl() override { cdm_->Destroy(); }
  156. int GetInterfaceVersion() override { return CdmInterfaceVersion; }
  157. bool Initialize(bool allow_distinctive_identifier,
  158. bool allow_persistent_state,
  159. bool use_hw_secure_codecs) override {
  160. cdm_->Initialize(allow_distinctive_identifier, allow_persistent_state,
  161. use_hw_secure_codecs);
  162. return true;
  163. }
  164. void SetServerCertificate(uint32_t promise_id,
  165. const uint8_t* server_certificate_data,
  166. uint32_t server_certificate_data_size) override {
  167. cdm_->SetServerCertificate(promise_id, server_certificate_data,
  168. server_certificate_data_size);
  169. }
  170. bool GetStatusForPolicy(uint32_t promise_id,
  171. cdm::HdcpVersion min_hdcp_version) override {
  172. cdm_->GetStatusForPolicy(promise_id, {min_hdcp_version});
  173. return true;
  174. }
  175. void CreateSessionAndGenerateRequest(uint32_t promise_id,
  176. cdm::SessionType session_type,
  177. cdm::InitDataType init_data_type,
  178. const uint8_t* init_data,
  179. uint32_t init_data_size) override {
  180. cdm_->CreateSessionAndGenerateRequest(
  181. promise_id, session_type, init_data_type, init_data, init_data_size);
  182. }
  183. void LoadSession(uint32_t promise_id,
  184. cdm::SessionType session_type,
  185. const char* session_id,
  186. uint32_t session_id_size) override {
  187. cdm_->LoadSession(promise_id, session_type, session_id, session_id_size);
  188. }
  189. void UpdateSession(uint32_t promise_id,
  190. const char* session_id,
  191. uint32_t session_id_size,
  192. const uint8_t* response,
  193. uint32_t response_size) override {
  194. cdm_->UpdateSession(promise_id, session_id, session_id_size, response,
  195. response_size);
  196. }
  197. void CloseSession(uint32_t promise_id,
  198. const char* session_id,
  199. uint32_t session_id_size) override {
  200. cdm_->CloseSession(promise_id, session_id, session_id_size);
  201. }
  202. void RemoveSession(uint32_t promise_id,
  203. const char* session_id,
  204. uint32_t session_id_size) override {
  205. cdm_->RemoveSession(promise_id, session_id, session_id_size);
  206. }
  207. void TimerExpired(void* context) override { cdm_->TimerExpired(context); }
  208. cdm::Status Decrypt(const cdm::InputBuffer_2& encrypted_buffer,
  209. cdm::DecryptedBlock* decrypted_buffer) override {
  210. return cdm_->Decrypt(encrypted_buffer, decrypted_buffer);
  211. }
  212. cdm::Status InitializeAudioDecoder(
  213. const cdm::AudioDecoderConfig_2& audio_decoder_config) override {
  214. return cdm_->InitializeAudioDecoder(audio_decoder_config);
  215. }
  216. cdm::Status InitializeVideoDecoder(
  217. const cdm::VideoDecoderConfig_3& video_decoder_config) override {
  218. return cdm_->InitializeVideoDecoder(video_decoder_config);
  219. }
  220. void DeinitializeDecoder(cdm::StreamType decoder_type) override {
  221. cdm_->DeinitializeDecoder(decoder_type);
  222. }
  223. void ResetDecoder(cdm::StreamType decoder_type) override {
  224. cdm_->ResetDecoder(decoder_type);
  225. }
  226. cdm::Status DecryptAndDecodeFrame(
  227. const cdm::InputBuffer_2& encrypted_buffer,
  228. media::VideoFrameImpl* video_frame) override {
  229. return cdm_->DecryptAndDecodeFrame(encrypted_buffer, video_frame);
  230. }
  231. cdm::Status DecryptAndDecodeSamples(
  232. const cdm::InputBuffer_2& encrypted_buffer,
  233. cdm::AudioFrames* audio_frames) override {
  234. return cdm_->DecryptAndDecodeSamples(encrypted_buffer, audio_frames);
  235. }
  236. void OnPlatformChallengeResponse(
  237. const cdm::PlatformChallengeResponse& response) override {
  238. cdm_->OnPlatformChallengeResponse(response);
  239. }
  240. void OnQueryOutputProtectionStatus(cdm::QueryResult result,
  241. uint32_t link_mask,
  242. uint32_t output_protection_mask) override {
  243. cdm_->OnQueryOutputProtectionStatus(result, link_mask,
  244. output_protection_mask);
  245. }
  246. void OnStorageId(uint32_t version,
  247. const uint8_t* storage_id,
  248. uint32_t storage_id_size) override {
  249. cdm_->OnStorageId(version, storage_id, storage_id_size);
  250. }
  251. private:
  252. CdmWrapperImpl(CdmInterface* cdm) : cdm_(cdm) { DCHECK(cdm_); }
  253. raw_ptr<CdmInterface> cdm_;
  254. };
  255. // Specialization for cdm::ContentDecryptionModule_10 methods.
  256. template <>
  257. cdm::Status CdmWrapperImpl<10>::InitializeVideoDecoder(
  258. const cdm::VideoDecoderConfig_3& video_decoder_config) {
  259. return cdm_->InitializeVideoDecoder(
  260. ToVideoDecoderConfig_2(video_decoder_config));
  261. }
  262. // static
  263. CdmWrapper* CdmWrapper::Create(CreateCdmFunc create_cdm_func,
  264. const char* key_system,
  265. uint32_t key_system_size,
  266. GetCdmHostFunc get_cdm_host_func,
  267. void* user_data) {
  268. static_assert(CheckSupportedCdmInterfaceVersions(10, 11),
  269. "Mismatch between CdmWrapper::Create() and "
  270. "IsSupportedCdmInterfaceVersion()");
  271. // Try to create the CDM using the latest CDM interface version.
  272. // This is only attempted if requested.
  273. CdmWrapper* cdm_wrapper = nullptr;
  274. // TODO(xhwang): Check whether we can use static loops to simplify this code.
  275. // Try to use the latest supported and enabled CDM interface first. If it's
  276. // not supported by the CDM, try to create the CDM using older supported
  277. // versions.
  278. if (IsSupportedAndEnabledCdmInterfaceVersion(11)) {
  279. cdm_wrapper =
  280. CdmWrapperImpl<11>::Create(create_cdm_func, key_system, key_system_size,
  281. get_cdm_host_func, user_data);
  282. }
  283. if (!cdm_wrapper && IsSupportedAndEnabledCdmInterfaceVersion(10)) {
  284. cdm_wrapper =
  285. CdmWrapperImpl<10>::Create(create_cdm_func, key_system, key_system_size,
  286. get_cdm_host_func, user_data);
  287. }
  288. return cdm_wrapper;
  289. }
  290. } // namespace media
  291. #endif // MEDIA_CDM_CDM_WRAPPER_H_