Skip to content

Commit

Permalink
media: Make IMFCdmProxy a C++ interface
Browse files Browse the repository at this point in the history
Currently IMFCdmProxy is a Windows COM interface. But it's really just
a normal class used internally in Chromium, and it doesn't need to be a
COM interface. Actually it's the only COM interface we define in
Chromium (other than in third_party or test).

This CL changes IMFCdmProxy to be a normal C++ interface. We also rename
it to MediaFoundationCdmProxy to match the interface type.

Bug: 1196826
Change-Id: I18609be6c5e8e6c623217a2d6c64d78c3176eff4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2889741
Commit-Queue: Xiaohan Wang <xhwang@chromium.org>
Reviewed-by: John Rummell <jrummell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#883079}
  • Loading branch information
xhwang-chromium authored and Chromium LUCI CQ committed May 14, 2021
1 parent 9353865 commit ce34ac4
Show file tree
Hide file tree
Showing 12 changed files with 125 additions and 108 deletions.
12 changes: 6 additions & 6 deletions media/base/cdm_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,14 @@

#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/optional.h"
#include "base/unguessable_token.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "media/base/media_export.h"
#include "media/media_buildflags.h"

#if defined(OS_WIN)
#include <wrl/client.h>
struct IMFCdmProxy;
#endif

#if BUILDFLAG(IS_CHROMEOS_ASH)
namespace chromeos {
class ChromeOsCdmContext;
Expand All @@ -35,6 +31,10 @@ class MediaCryptoContext;
class FuchsiaCdmContext;
#endif

#if defined(OS_WIN)
class MediaFoundationCdmProxy;
#endif

// An interface representing the context that a media player needs from a
// content decryption module (CDM) to decrypt (and decode) encrypted buffers.
// Typically this will be passed to the media player (e.g. using SetCdm()).
Expand Down Expand Up @@ -101,7 +101,7 @@ class MEDIA_EXPORT CdmContext {
virtual bool RequiresMediaFoundationRenderer();

using GetMediaFoundationCdmProxyCB =
base::OnceCallback<void(Microsoft::WRL::ComPtr<IMFCdmProxy>)>;
base::OnceCallback<void(scoped_refptr<MediaFoundationCdmProxy>)>;
// This allows a CdmContext to expose an IMFTrustedInput instance for use in
// a Media Foundation rendering pipeline. This method is asynchronous because
// the underlying MF-based CDM might not have a native session created yet.
Expand Down
2 changes: 1 addition & 1 deletion media/base/win/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ source_set("hresult_status_helper") {
}

source_set("mf_cdm_proxy") {
sources = [ "mf_cdm_proxy.h" ]
sources = [ "media_foundation_cdm_proxy.h" ]
deps = [ "//base" ]
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,58 +2,64 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef MEDIA_BASE_WIN_MF_CDM_PROXY_H_
#define MEDIA_BASE_WIN_MF_CDM_PROXY_H_
#ifndef MEDIA_BASE_WIN_MEDIA_FOUNDATION_CDM_PROXY_H_
#define MEDIA_BASE_WIN_MEDIA_FOUNDATION_CDM_PROXY_H_

#include <mfobjects.h>
#include <stdint.h>
#include <unknwn.h>
#include <windef.h>

// Interface for clients to get information from MediaFoundationCdm to
// implements COM interfaces.
// COM interface is used because we are working with Media Foundation which uses
// COM extensively for object lifetime management.
MIDL_INTERFACE("565ab5c2-9923-44e0-997a-f93ccba5dcbf")
IMFCdmProxy : public IUnknown {
#include "base/memory/ref_counted.h"

namespace media {

// Interface for the media pipeline to get information from MediaFoundationCdm.
// TODO(xhwang): Investigate whether this class needs to be ref-counted.
class MediaFoundationCdmProxy
: public base::RefCountedThreadSafe<MediaFoundationCdmProxy> {
public:
// Used by MediaFoundationProtectionManager to get
// ABI::Windows::Media::Protection::IMediaProtectionPMPServer to implement
// ABI::Windows::Media::Protection::IMediaProtectionManager::get_Properties as
// in
// ABI::Windows::Media::Protection::IMediaProtectionManager::get_Properties
// https://docs.microsoft.com/en-us/uwp/api/windows.media.protection.mediaprotectionmanager
virtual HRESULT STDMETHODCALLTYPE GetPMPServer(
/* [in] */ __RPC__in REFIID riid,
/* [iid_is][out] */ __RPC__deref_out_opt LPVOID * object_result) = 0;
virtual HRESULT GetPMPServer(REFIID riid, LPVOID* object_result) = 0;

// Used by MediaFoundationSourceWrapper to implement
// IMFTrustedInput::GetInputTrustAuthority as in
// https://docs.microsoft.com/en-us/windows/win32/api/mfidl/nn-mfidl-imftrustedinput
//
// |content_init_data| is optional initialization data as in
// https://www.w3.org/TR/encrypted-media/#initialization-data
virtual HRESULT STDMETHODCALLTYPE GetInputTrustAuthority(
_In_ uint32_t stream_id, _In_ uint32_t stream_count,
_In_reads_bytes_opt_(content_init_data_size)
const uint8_t* content_init_data,
_In_ uint32_t content_init_data_size, _In_ REFIID riid,
_COM_Outptr_ IUnknown** object_out) = 0;
virtual HRESULT GetInputTrustAuthority(uint32_t stream_id,
uint32_t stream_count,
const uint8_t* content_init_data,
uint32_t content_init_data_size,
REFIID riid,
IUnknown** object_out) = 0;

// When the media Renderer is suspended, `MediaFoundationSourceWrapper`
// provides its last set of key IDs using `SetLastKeyId()` when it is
// destructed. Then during resume, the new `MediaFoundationSourceWrapper`
// calls `RefreshTrustedInput()` to let the CDM use the key IDs information to
// perform some optimization.
virtual HRESULT STDMETHODCALLTYPE SetLastKeyId(_In_ uint32_t stream_id,
_In_ REFGUID key_id) = 0;
virtual HRESULT STDMETHODCALLTYPE RefreshTrustedInput() = 0;
virtual HRESULT SetLastKeyId(uint32_t stream_id, REFGUID key_id) = 0;
virtual HRESULT RefreshTrustedInput() = 0;

// Used by MediaFoundationProtectionManager to implement
// IMFContentProtectionManager::BeginEnableContent as in
// https://msdn.microsoft.com/en-us/windows/ms694217(v=vs.71)
//
// |result| is used to obtain the result of an asynchronous operation as in
// `result` is used to obtain the result of an asynchronous operation as in
// https://docs.microsoft.com/en-us/windows/win32/api/mfobjects/nn-mfobjects-imfasyncresult
virtual HRESULT STDMETHODCALLTYPE ProcessContentEnabler(
_In_ IUnknown * request, _In_ IMFAsyncResult * result) = 0;
virtual HRESULT ProcessContentEnabler(IUnknown* request,
IMFAsyncResult* result) = 0;

protected:
friend base::RefCountedThreadSafe<MediaFoundationCdmProxy>;
virtual ~MediaFoundationCdmProxy() = default;
};

#endif // MEDIA_BASE_WIN_MF_CDM_PROXY_H_
} // namespace media

#endif // MEDIA_BASE_WIN_MEDIA_FOUNDATION_CDM_PROXY_H_
32 changes: 16 additions & 16 deletions media/cdm/win/media_foundation_cdm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
#include "base/win/windows_version.h"
#include "media/base/bind_to_current_loop.h"
#include "media/base/cdm_promise.h"
#include "media/base/win/mf_cdm_proxy.h"
#include "media/base/win/media_foundation_cdm_proxy.h"
#include "media/base/win/mf_helpers.h"
#include "media/cdm/win/media_foundation_cdm_session.h"

Expand Down Expand Up @@ -96,16 +96,14 @@ HRESULT RefreshDecryptor(IMFTransform* decryptor,
return S_OK;
}

class CdmProxyImpl
: public RuntimeClass<RuntimeClassFlags<ClassicCom>, IMFCdmProxy> {
class CdmProxyImpl : public MediaFoundationCdmProxy {
public:
explicit CdmProxyImpl(ComPtr<IMFContentDecryptionModule> mf_cdm)
: mf_cdm_(mf_cdm) {}
~CdmProxyImpl() override = default;

// IMFCdmProxy implementation
// MediaFoundationCdmProxy implementation

STDMETHODIMP GetPMPServer(REFIID riid, LPVOID* object_result) override {
HRESULT GetPMPServer(REFIID riid, LPVOID* object_result) override {
DVLOG_FUNC(1);
ComPtr<IMFGetService> cdm_services;
RETURN_IF_FAILED(mf_cdm_.As(&cdm_services));
Expand All @@ -114,12 +112,12 @@ class CdmProxyImpl
return S_OK;
}

STDMETHODIMP GetInputTrustAuthority(uint32_t stream_id,
uint32_t /*stream_count*/,
const uint8_t* content_init_data,
uint32_t content_init_data_size,
REFIID riid,
IUnknown** object_out) override {
HRESULT GetInputTrustAuthority(uint32_t stream_id,
uint32_t /*stream_count*/,
const uint8_t* content_init_data,
uint32_t content_init_data_size,
REFIID riid,
IUnknown** object_out) override {
DVLOG_FUNC(1);

if (input_trust_authorities_.count(stream_id)) {
Expand Down Expand Up @@ -148,13 +146,13 @@ class CdmProxyImpl
return S_OK;
}

STDMETHODIMP SetLastKeyId(uint32_t stream_id, REFGUID key_id) override {
HRESULT SetLastKeyId(uint32_t stream_id, REFGUID key_id) override {
DVLOG_FUNC(1);
last_key_ids_[stream_id] = key_id;
return S_OK;
}

STDMETHODIMP RefreshTrustedInput() override {
HRESULT RefreshTrustedInput() override {
DVLOG_FUNC(1);

// Refresh all decryptors of the last key IDs.
Expand All @@ -180,7 +178,7 @@ class CdmProxyImpl
return S_OK;
}

STDMETHODIMP
HRESULT
ProcessContentEnabler(IUnknown* request, IMFAsyncResult* result) override {
DVLOG_FUNC(1);
ComPtr<IMFContentEnabler> content_enabler;
Expand All @@ -189,6 +187,8 @@ class CdmProxyImpl
}

private:
~CdmProxyImpl() override = default;

HRESULT GetProtectionSystemId(GUID* protection_system_id) {
// Typically the CDM should only return one protection system ID. So just
// use the first one if available.
Expand Down Expand Up @@ -403,7 +403,7 @@ bool MediaFoundationCdm::GetMediaFoundationCdmProxy(
DVLOG_FUNC(1);

if (!cdm_proxy_)
cdm_proxy_ = Make<CdmProxyImpl>(mf_cdm_);
cdm_proxy_ = base::MakeRefCounted<CdmProxyImpl>(mf_cdm_);

BindToCurrentLoop(std::move(get_mf_cdm_proxy_cb)).Run(cdm_proxy_);
return true;
Expand Down
3 changes: 2 additions & 1 deletion media/cdm/win/media_foundation_cdm.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <memory>
#include <string>

#include "base/memory/scoped_refptr.h"
#include "media/base/cdm_context.h"
#include "media/base/content_decryption_module.h"
#include "media/base/media_export.h"
Expand Down Expand Up @@ -93,7 +94,7 @@ class MEDIA_EXPORT MediaFoundationCdm : public ContentDecryptionModule,
// Session ID to session map.
std::map<std::string, std::unique_ptr<MediaFoundationCdmSession>> sessions_;

Microsoft::WRL::ComPtr<IMFCdmProxy> cdm_proxy_;
scoped_refptr<MediaFoundationCdmProxy> cdm_proxy_;
};

} // namespace media
Expand Down
14 changes: 10 additions & 4 deletions media/renderers/win/media_foundation_protection_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,13 @@ namespace media {

using Microsoft::WRL::ComPtr;

MediaFoundationProtectionManager::MediaFoundationProtectionManager() = default;
MediaFoundationProtectionManager::~MediaFoundationProtectionManager() = default;
MediaFoundationProtectionManager::MediaFoundationProtectionManager() {
DVLOG_FUNC(1);
}

MediaFoundationProtectionManager::~MediaFoundationProtectionManager() {
DVLOG_FUNC(1);
}

HRESULT MediaFoundationProtectionManager::RuntimeClassInitialize() {
DVLOG_FUNC(1);
Expand All @@ -36,11 +41,12 @@ HRESULT MediaFoundationProtectionManager::RuntimeClassInitialize() {
return S_OK;
}

HRESULT MediaFoundationProtectionManager::SetCdmProxy(IMFCdmProxy* cdm_proxy) {
HRESULT MediaFoundationProtectionManager::SetCdmProxy(
scoped_refptr<MediaFoundationCdmProxy> cdm_proxy) {
DVLOG_FUNC(1);

DCHECK(cdm_proxy);
cdm_proxy_ = cdm_proxy;
cdm_proxy_ = std::move(cdm_proxy);
ComPtr<ABI::Windows::Media::Protection::IMediaProtectionPMPServer> pmp_server;
RETURN_IF_FAILED(cdm_proxy_->GetPMPServer(IID_PPV_ARGS(&pmp_server)));
RETURN_IF_FAILED(SetPMPServer(pmp_server.Get()));
Expand Down
8 changes: 5 additions & 3 deletions media/renderers/win/media_foundation_protection_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
#include <windows.media.protection.h>
#include <wrl.h>

#include "media/base/win/mf_cdm_proxy.h"
#include "base/memory/scoped_refptr.h"
#include "media/base/win/media_foundation_cdm_proxy.h"

namespace media {

Expand All @@ -33,7 +34,7 @@ class MediaFoundationProtectionManager
~MediaFoundationProtectionManager() override;

HRESULT RuntimeClassInitialize();
HRESULT SetCdmProxy(IMFCdmProxy* cdm_proxy);
HRESULT SetCdmProxy(scoped_refptr<MediaFoundationCdmProxy> cdm_proxy);

// IMFContentProtectionManager.
IFACEMETHODIMP BeginEnableContent(IMFActivate* enabler_activate,
Expand Down Expand Up @@ -65,7 +66,8 @@ class MediaFoundationProtectionManager
protected:
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::Collections::IPropertySet>
property_set_;
Microsoft::WRL::ComPtr<IMFCdmProxy> cdm_proxy_;

scoped_refptr<MediaFoundationCdmProxy> cdm_proxy_;

HRESULT SetPMPServer(
ABI::Windows::Media::Protection::IMediaProtectionPMPServer* pmp_server);
Expand Down
6 changes: 3 additions & 3 deletions media/renderers/win/media_foundation_renderer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ void MediaFoundationRenderer::SetLatencyHint(
}

void MediaFoundationRenderer::OnCdmProxyReceived(
ComPtr<IMFCdmProxy> cdm_proxy) {
scoped_refptr<MediaFoundationCdmProxy> cdm_proxy) {
DVLOG_FUNC(1);

if (!waiting_for_mf_cdm_ || !content_protection_manager_) {
Expand All @@ -337,8 +337,8 @@ void MediaFoundationRenderer::OnCdmProxyReceived(

waiting_for_mf_cdm_ = false;

content_protection_manager_->SetCdmProxy(cdm_proxy.Get());
mf_source_->SetCdmProxy(cdm_proxy.Get());
content_protection_manager_->SetCdmProxy(cdm_proxy);
mf_source_->SetCdmProxy(cdm_proxy);
HRESULT hr = SetSourceOnMediaEngine();
if (FAILED(hr)) {
DLOG(ERROR) << "Failed to set source on media engine: " << PrintHr(hr);
Expand Down
2 changes: 1 addition & 1 deletion media/renderers/win/media_foundation_renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ class MEDIA_EXPORT MediaFoundationRenderer
void OnVideoNaturalSizeChange();
void OnTimeUpdate();

void OnCdmProxyReceived(Microsoft::WRL::ComPtr<IMFCdmProxy> cdm_proxy);
void OnCdmProxyReceived(scoped_refptr<MediaFoundationCdmProxy> cdm_proxy);

HRESULT SetDCompModeInternal(bool enabled);
HRESULT GetDCompSurfaceInternal(HANDLE* surface_handle);
Expand Down
Loading

0 comments on commit ce34ac4

Please sign in to comment.