media_foundation_cdm_module.cc 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. // Copyright 2021 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. #include "media/cdm/win/media_foundation_cdm_module.h"
  5. #include "base/files/file_util.h"
  6. #include "base/logging.h"
  7. #include "base/strings/utf_string_conversions.h"
  8. #include "base/win/scoped_hstring.h"
  9. #include "media/base/win/mf_helpers.h"
  10. namespace media {
  11. namespace {
  12. using Microsoft::WRL::ComPtr;
  13. static MediaFoundationCdmModule* g_cdm_module = nullptr;
  14. } // namespace
  15. // static
  16. MediaFoundationCdmModule* MediaFoundationCdmModule::GetInstance() {
  17. if (!g_cdm_module)
  18. g_cdm_module = new MediaFoundationCdmModule();
  19. return g_cdm_module;
  20. }
  21. MediaFoundationCdmModule::MediaFoundationCdmModule() = default;
  22. MediaFoundationCdmModule::~MediaFoundationCdmModule() = default;
  23. void MediaFoundationCdmModule::Initialize(const base::FilePath& cdm_path) {
  24. DVLOG(1) << __func__ << ": cdm_path=" << cdm_path.value();
  25. CHECK(!initialized_)
  26. << "MediaFoundationCdmModule can only be initialized once!";
  27. initialized_ = true;
  28. cdm_path_ = cdm_path;
  29. // If `cdm_path_` is not empty, load the CDM before the sandbox is sealed.
  30. if (!cdm_path_.empty()) {
  31. library_ = base::ScopedNativeLibrary(cdm_path_);
  32. LOG_IF(ERROR, !library_.is_valid())
  33. << __func__ << ": Failed to load CDM at " << cdm_path_.value()
  34. << " (Error: " << library_.GetError()->ToString() << ")";
  35. }
  36. }
  37. HRESULT MediaFoundationCdmModule::GetCdmFactory(
  38. const std::string& key_system,
  39. Microsoft::WRL::ComPtr<IMFContentDecryptionModuleFactory>& cdm_factory) {
  40. if (!initialized_) {
  41. DLOG(ERROR) << __func__ << " failed: Not initialized";
  42. return E_NOT_VALID_STATE;
  43. }
  44. if (key_system.empty()) {
  45. DLOG(ERROR) << __func__ << " failed: Empty key system";
  46. return ERROR_INVALID_PARAMETER;
  47. }
  48. if (key_system_.empty())
  49. key_system_ = key_system;
  50. if (key_system != key_system_) {
  51. DLOG(ERROR) << __func__ << " failed: key system mismatch";
  52. return E_NOT_VALID_STATE;
  53. }
  54. if (!cdm_factory_)
  55. RETURN_IF_FAILED(ActivateCdmFactory());
  56. cdm_factory = cdm_factory_;
  57. return S_OK;
  58. }
  59. HRESULT MediaFoundationCdmModule::ActivateCdmFactory() {
  60. DCHECK(initialized_);
  61. // For OS or store CDM, the `cdm_path_` is empty. Just use default creation.
  62. if (cdm_path_.empty()) {
  63. DCHECK(!library_.is_valid());
  64. ComPtr<IMFMediaEngineClassFactory4> class_factory;
  65. RETURN_IF_FAILED(CoCreateInstance(CLSID_MFMediaEngineClassFactory, nullptr,
  66. CLSCTX_INPROC_SERVER,
  67. IID_PPV_ARGS(&class_factory)));
  68. auto key_system_str = base::UTF8ToWide(key_system_);
  69. RETURN_IF_FAILED(class_factory->CreateContentDecryptionModuleFactory(
  70. key_system_str.c_str(), IID_PPV_ARGS(&cdm_factory_)));
  71. return S_OK;
  72. }
  73. if (!library_.is_valid()) {
  74. LOG(ERROR) << "CDM failed to load previously";
  75. return E_FAIL;
  76. }
  77. // Initialization required to call base::win::ScopedHString::Create();
  78. if (!base::win::ScopedHString::ResolveCoreWinRTStringDelayload())
  79. return E_FAIL;
  80. // Get function pointer to the activation factory.
  81. using GetActivationFactoryFunc =
  82. HRESULT(WINAPI*)(_In_ HSTRING activatible_class_id,
  83. _COM_Outptr_ IActivationFactory * *factory);
  84. const char kDllGetActivationFactory[] = "DllGetActivationFactory";
  85. auto get_activation_factory_func = reinterpret_cast<GetActivationFactoryFunc>(
  86. library_.GetFunctionPointer(kDllGetActivationFactory));
  87. if (!get_activation_factory_func) {
  88. LOG(ERROR) << "Cannot get function " << kDllGetActivationFactory;
  89. return E_FAIL;
  90. }
  91. // Activate CdmFactory. Assuming the class ID is always in the format
  92. // "<key_system>.ContentDecryptionModuleFactory".
  93. auto class_name = base::win::ScopedHString::Create(
  94. base::StringPiece(key_system_ + ".ContentDecryptionModuleFactory"));
  95. ComPtr<IActivationFactory> activation_factory;
  96. RETURN_IF_FAILED(
  97. get_activation_factory_func(class_name.get(), &activation_factory));
  98. ComPtr<IInspectable> inspectable_factory;
  99. RETURN_IF_FAILED(activation_factory->ActivateInstance(&inspectable_factory));
  100. RETURN_IF_FAILED(inspectable_factory.As(&cdm_factory_));
  101. return S_OK;
  102. }
  103. } // namespace media