123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131 |
- // Copyright 2021 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.
- #include "media/cdm/win/media_foundation_cdm_module.h"
- #include "base/files/file_util.h"
- #include "base/logging.h"
- #include "base/strings/utf_string_conversions.h"
- #include "base/win/scoped_hstring.h"
- #include "media/base/win/mf_helpers.h"
- namespace media {
- namespace {
- using Microsoft::WRL::ComPtr;
- static MediaFoundationCdmModule* g_cdm_module = nullptr;
- } // namespace
- // static
- MediaFoundationCdmModule* MediaFoundationCdmModule::GetInstance() {
- if (!g_cdm_module)
- g_cdm_module = new MediaFoundationCdmModule();
- return g_cdm_module;
- }
- MediaFoundationCdmModule::MediaFoundationCdmModule() = default;
- MediaFoundationCdmModule::~MediaFoundationCdmModule() = default;
- void MediaFoundationCdmModule::Initialize(const base::FilePath& cdm_path) {
- DVLOG(1) << __func__ << ": cdm_path=" << cdm_path.value();
- CHECK(!initialized_)
- << "MediaFoundationCdmModule can only be initialized once!";
- initialized_ = true;
- cdm_path_ = cdm_path;
- // If `cdm_path_` is not empty, load the CDM before the sandbox is sealed.
- if (!cdm_path_.empty()) {
- library_ = base::ScopedNativeLibrary(cdm_path_);
- LOG_IF(ERROR, !library_.is_valid())
- << __func__ << ": Failed to load CDM at " << cdm_path_.value()
- << " (Error: " << library_.GetError()->ToString() << ")";
- }
- }
- HRESULT MediaFoundationCdmModule::GetCdmFactory(
- const std::string& key_system,
- Microsoft::WRL::ComPtr<IMFContentDecryptionModuleFactory>& cdm_factory) {
- if (!initialized_) {
- DLOG(ERROR) << __func__ << " failed: Not initialized";
- return E_NOT_VALID_STATE;
- }
- if (key_system.empty()) {
- DLOG(ERROR) << __func__ << " failed: Empty key system";
- return ERROR_INVALID_PARAMETER;
- }
- if (key_system_.empty())
- key_system_ = key_system;
- if (key_system != key_system_) {
- DLOG(ERROR) << __func__ << " failed: key system mismatch";
- return E_NOT_VALID_STATE;
- }
- if (!cdm_factory_)
- RETURN_IF_FAILED(ActivateCdmFactory());
- cdm_factory = cdm_factory_;
- return S_OK;
- }
- HRESULT MediaFoundationCdmModule::ActivateCdmFactory() {
- DCHECK(initialized_);
- // For OS or store CDM, the `cdm_path_` is empty. Just use default creation.
- if (cdm_path_.empty()) {
- DCHECK(!library_.is_valid());
- ComPtr<IMFMediaEngineClassFactory4> class_factory;
- RETURN_IF_FAILED(CoCreateInstance(CLSID_MFMediaEngineClassFactory, nullptr,
- CLSCTX_INPROC_SERVER,
- IID_PPV_ARGS(&class_factory)));
- auto key_system_str = base::UTF8ToWide(key_system_);
- RETURN_IF_FAILED(class_factory->CreateContentDecryptionModuleFactory(
- key_system_str.c_str(), IID_PPV_ARGS(&cdm_factory_)));
- return S_OK;
- }
- if (!library_.is_valid()) {
- LOG(ERROR) << "CDM failed to load previously";
- return E_FAIL;
- }
- // Initialization required to call base::win::ScopedHString::Create();
- if (!base::win::ScopedHString::ResolveCoreWinRTStringDelayload())
- return E_FAIL;
- // Get function pointer to the activation factory.
- using GetActivationFactoryFunc =
- HRESULT(WINAPI*)(_In_ HSTRING activatible_class_id,
- _COM_Outptr_ IActivationFactory * *factory);
- const char kDllGetActivationFactory[] = "DllGetActivationFactory";
- auto get_activation_factory_func = reinterpret_cast<GetActivationFactoryFunc>(
- library_.GetFunctionPointer(kDllGetActivationFactory));
- if (!get_activation_factory_func) {
- LOG(ERROR) << "Cannot get function " << kDllGetActivationFactory;
- return E_FAIL;
- }
- // Activate CdmFactory. Assuming the class ID is always in the format
- // "<key_system>.ContentDecryptionModuleFactory".
- auto class_name = base::win::ScopedHString::Create(
- base::StringPiece(key_system_ + ".ContentDecryptionModuleFactory"));
- ComPtr<IActivationFactory> activation_factory;
- RETURN_IF_FAILED(
- get_activation_factory_func(class_name.get(), &activation_factory));
- ComPtr<IInspectable> inspectable_factory;
- RETURN_IF_FAILED(activation_factory->ActivateInstance(&inspectable_factory));
- RETURN_IF_FAILED(inspectable_factory.As(&cdm_factory_));
- return S_OK;
- }
- } // namespace media
|