Skip to content

Commit

Permalink
media: Add DCOMPSurfaceRegistry mojom interface
Browse files Browse the repository at this point in the history
This interface allows a non-privileged client (in the render process)
to register a DCOMP surface handle to be accessed in the GPU process.
To do this, we have to route to the browser process. The client is
MediaFoundationRendererClient in the render process, and the
implementation is the DCOMPSurfaceRegistryBroker in the browser process,
which then uses GpuService to call into the GPU process.

This CL is based on the prototype CL uploaded by frankli@microsoft.com:
https://chromium-review.googlesource.com/c/chromium/src/+/1779403

See design doc at:
https://docs.google.com/document/d/1gQz0r3WmQUbXshL_Z9zYEeVjUgvEFhelOpCt3WWmo0o

Bug: 999747
Change-Id: If891bc853348df2be1559421ad592d1999320266
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3028644
Commit-Queue: Xiaohan Wang <xhwang@chromium.org>
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
Reviewed-by: John Rummell <jrummell@chromium.org>
Reviewed-by: Sunny Sachanandani <sunnyps@chromium.org>
Reviewed-by: Alex Moshchuk <alexmos@chromium.org>
Cr-Commit-Position: refs/heads/master@{#907335}
  • Loading branch information
xhwang-chromium authored and Chromium LUCI CQ committed Jul 31, 2021
1 parent 9996b4e commit 4f50dbd
Show file tree
Hide file tree
Showing 21 changed files with 245 additions and 20 deletions.
Expand Up @@ -145,6 +145,12 @@ class TestGpuService : public mojom::GpuService {
jea_receiver) override {}
#endif // BUILDFLAG(IS_CHROMEOS_ASH)

#if defined(OS_WIN)
void RegisterDCOMPSurfaceHandle(
mojo::PlatformHandle surface_handle,
RegisterDCOMPSurfaceHandleCallback callback) override {}
#endif

void CreateVideoEncodeAcceleratorProvider(
mojo::PendingReceiver<media::mojom::VideoEncodeAcceleratorProvider>
receiver) override {}
Expand Down
13 changes: 13 additions & 0 deletions components/viz/service/gl/gpu_service_impl.cc
Expand Up @@ -88,6 +88,8 @@
#endif // BUILDFLAG(IS_CHROMEOS_ASH)

#if defined(OS_WIN)
#include "mojo/public/cpp/system/platform_handle.h"
#include "ui/gl/dcomp_surface_registry.h"
#include "ui/gl/direct_composition_surface_win.h"
#endif

Expand Down Expand Up @@ -755,6 +757,17 @@ void GpuServiceImpl::CreateJpegEncodeAccelerator(
}
#endif // BUILDFLAG(IS_CHROMEOS_ASH)

#if defined(OS_WIN)
void GpuServiceImpl::RegisterDCOMPSurfaceHandle(
mojo::PlatformHandle surface_handle,
RegisterDCOMPSurfaceHandleCallback callback) {
auto token =
gl::DCOMPSurfaceRegistry::GetInstance()->RegisterDCOMPSurfaceHandle(
surface_handle.TakeHandle());
std::move(callback).Run(token);
}
#endif // defined(OS_WIN)

void GpuServiceImpl::CreateVideoEncodeAcceleratorProvider(
mojo::PendingReceiver<media::mojom::VideoEncodeAcceleratorProvider>
vea_provider_receiver) {
Expand Down
6 changes: 6 additions & 0 deletions components/viz/service/gl/gpu_service_impl.h
Expand Up @@ -152,6 +152,12 @@ class VIZ_SERVICE_EXPORT GpuServiceImpl : public gpu::GpuChannelManagerDelegate,
jea_receiver) override;
#endif // BUILDFLAG(IS_CHROMEOS_ASH)

#if defined(OS_WIN)
void RegisterDCOMPSurfaceHandle(
mojo::PlatformHandle surface_handle,
RegisterDCOMPSurfaceHandleCallback callback) override;
#endif // defined(OS_WIN)

void CreateVideoEncodeAcceleratorProvider(
mojo::PendingReceiver<media::mojom::VideoEncodeAcceleratorProvider>
vea_provider_receiver) override;
Expand Down
7 changes: 7 additions & 0 deletions content/browser/BUILD.gn
Expand Up @@ -2599,6 +2599,13 @@ source_set("browser") {
]
}

if (is_win) {
sources += [
"media/dcomp_surface_registry_broker.cc",
"media/dcomp_surface_registry_broker.h",
]
}

if (use_atk) {
sources += [
"accessibility/accessibility_event_recorder_auralinux.cc",
Expand Down
9 changes: 9 additions & 0 deletions content/browser/browser_interface_binders.cc
Expand Up @@ -853,6 +853,15 @@ void PopulateFrameBinders(RenderFrameHostImpl* host, mojo::BinderMap* map) {
&RenderFrameHostImpl::BindMediaMetricsProviderReceiver,
base::Unretained(host)));

#if defined(OS_WIN)
// This class is lightweighted and must run on the IO task runner because
// GpuProcessHost only runs on the IO task runner.
map->Add<media::mojom::DCOMPSurfaceRegistry>(
base::BindRepeating(&RenderFrameHostImpl::BindDCOMPSurfaceRegistry,
base::Unretained(host)),
GetIOThreadTaskRunner({}));
#endif

#if BUILDFLAG(ENABLE_MEDIA_REMOTING)
map->Add<media::mojom::RemoterFactory>(
base::BindRepeating(&RenderFrameHostImpl::BindMediaRemoterFactoryReceiver,
Expand Down
Expand Up @@ -85,6 +85,11 @@ class TestGpuService : public viz::mojom::GpuService {
mojo::PendingReceiver<chromeos_camera::mojom::JpegEncodeAccelerator>
jea_receiver) override {}
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
#if defined(OS_WIN)
void RegisterDCOMPSurfaceHandle(
mojo::PlatformHandle surface_handle,
RegisterDCOMPSurfaceHandleCallback callback) override {}
#endif
void CreateVideoEncodeAcceleratorProvider(
mojo::PendingReceiver<media::mojom::VideoEncodeAcceleratorProvider>
receiver) override {}
Expand Down
37 changes: 37 additions & 0 deletions content/browser/media/dcomp_surface_registry_broker.cc
@@ -0,0 +1,37 @@
// 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 "content/browser/media/dcomp_surface_registry_broker.h"

#include "base/logging.h"
#include "content/browser/gpu/gpu_process_host.h"
#include "mojo/public/cpp/bindings/callback_helpers.h"

namespace content {

DCOMPSurfaceRegistryBroker::DCOMPSurfaceRegistryBroker() = default;

DCOMPSurfaceRegistryBroker::~DCOMPSurfaceRegistryBroker() = default;

void DCOMPSurfaceRegistryBroker::RegisterDCOMPSurfaceHandle(
mojo::PlatformHandle surface_handle,
RegisterDCOMPSurfaceHandleCallback callback) {
DVLOG(1) << __func__;

auto* gpu_process_host =
GpuProcessHost::Get(GpuProcessKind::GPU_PROCESS_KIND_SANDBOXED, false);
if (!gpu_process_host) {
DLOG(ERROR) << __func__ << ": Failed to get GpuProcessHost!";
std::move(callback).Run(base::UnguessableToken());
return;
}

auto* gpu_service = gpu_process_host->gpu_host()->gpu_service();
gpu_service->RegisterDCOMPSurfaceHandle(
std::move(surface_handle),
mojo::WrapCallbackWithDefaultInvokeIfNotRun(std::move(callback),
base::UnguessableToken()));
}

} // namespace content
33 changes: 33 additions & 0 deletions content/browser/media/dcomp_surface_registry_broker.h
@@ -0,0 +1,33 @@
// 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.

#ifndef CONTENT_BROWSER_MEDIA_DCOMP_SURFACE_REGISTRY_BROKER_H_
#define CONTENT_BROWSER_MEDIA_DCOMP_SURFACE_REGISTRY_BROKER_H_

#include "media/mojo/mojom/dcomp_surface_registry.mojom.h"

namespace content {

// This class is hosted in the browser process and it allows unprivileged
// renderer process clients to register and unregister DCOMP surface handles for
// GPU process access.
// This class is bound and lives on the browser IO thread since GpuProcessHost
// must be called on the IO thread.
class DCOMPSurfaceRegistryBroker : public media::mojom::DCOMPSurfaceRegistry {
public:
DCOMPSurfaceRegistryBroker();
DCOMPSurfaceRegistryBroker(const DCOMPSurfaceRegistryBroker&) = delete;
DCOMPSurfaceRegistryBroker& operator=(const DCOMPSurfaceRegistryBroker&) =
delete;
~DCOMPSurfaceRegistryBroker() override;

// media::mojom::DCOMPSurfaceRegistry:
void RegisterDCOMPSurfaceHandle(
mojo::PlatformHandle surface_handle,
RegisterDCOMPSurfaceHandleCallback callback) override;
};

} // namespace content

#endif // CONTENT_BROWSER_MEDIA_DCOMP_SURFACE_REGISTRY_BROKER_H_
16 changes: 16 additions & 0 deletions content/browser/renderer_host/render_frame_host_impl.cc
Expand Up @@ -238,6 +238,11 @@
#include "content/browser/renderer_host/popup_menu_helper_mac.h"
#endif

#if defined(OS_WIN)
#include "content/browser/media/dcomp_surface_registry_broker.h"
#include "media/cdm/win/media_foundation_cdm.h"
#endif // defined(OS_WIN)

#if BUILDFLAG(ENABLE_PLUGINS)
#include "content/browser/plugin_service_impl.h"
#include "content/browser/renderer_host/pepper/pepper_renderer_connection.h"
Expand Down Expand Up @@ -8945,6 +8950,17 @@ void RenderFrameHostImpl::BindMediaMetricsProviderReceiver(
std::move(receiver));
}

#if defined(OS_WIN)
void RenderFrameHostImpl::BindDCOMPSurfaceRegistry(
mojo::PendingReceiver<media::mojom::DCOMPSurfaceRegistry> receiver) {
if (base::FeatureList::IsEnabled(media::kHardwareSecureDecryption) &&
media::MediaFoundationCdm::IsAvailable()) {
mojo::MakeSelfOwnedReceiver(std::make_unique<DCOMPSurfaceRegistryBroker>(),
std::move(receiver));
}
}
#endif

#if BUILDFLAG(ENABLE_MEDIA_REMOTING)
void RenderFrameHostImpl::BindMediaRemoterFactoryReceiver(
mojo::PendingReceiver<media::mojom::RemoterFactory> receiver) {
Expand Down
9 changes: 9 additions & 0 deletions content/browser/renderer_host/render_frame_host_impl.h
Expand Up @@ -139,6 +139,10 @@
#include "third_party/blink/public/mojom/serial/serial.mojom-forward.h"
#endif

#if defined(OS_WIN)
#include "media/mojo/mojom/dcomp_surface_registry.mojom.h"
#endif

#if BUILDFLAG(ENABLE_MEDIA_REMOTING)
#include "media/mojo/mojom/remoting.mojom-forward.h"
#endif
Expand Down Expand Up @@ -1704,6 +1708,11 @@ class CONTENT_EXPORT RenderFrameHostImpl
void BindMediaMetricsProviderReceiver(
mojo::PendingReceiver<media::mojom::MediaMetricsProvider> receiver);

#if defined(OS_WIN)
void BindDCOMPSurfaceRegistry(
mojo::PendingReceiver<media::mojom::DCOMPSurfaceRegistry> receiver);
#endif

#if BUILDFLAG(ENABLE_MEDIA_REMOTING)
void BindMediaRemoterFactoryReceiver(
mojo::PendingReceiver<media::mojom::RemoterFactory> receiver);
Expand Down
17 changes: 15 additions & 2 deletions content/renderer/media/media_factory.cc
Expand Up @@ -16,7 +16,6 @@
#include "base/strings/string_number_conversions.h"
#include "base/task_runner_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "build/buildflag.h"
#include "cc/trees/layer_tree_settings.h"
#include "content/public/common/content_client.h"
Expand Down Expand Up @@ -723,11 +722,16 @@ MediaFactory::CreateRendererFactorySelector(
render_thread->GetDCOMPTextureFactory(),
render_thread->GetMediaThreadTaskRunner());

auto dcomp_surface_registry_creation_cb = base::BindRepeating(
&MediaFactory::CreateDCOMPSurfaceRegistry, base::Unretained(this));

factory_selector->AddFactory(
RendererType::kMediaFoundation,
std::make_unique<media::MediaFoundationRendererClientFactory>(
render_thread->compositor_task_runner(),
std::move(dcomp_texture_creation_cb), CreateMojoRendererFactory()));
std::move(dcomp_texture_creation_cb),
std::move(dcomp_surface_registry_creation_cb),
CreateMojoRendererFactory()));
}
#endif // defined(OS_WIN)

Expand Down Expand Up @@ -913,4 +917,13 @@ MediaFactory::CreateMojoRendererFactory() {
GetMediaInterfaceFactory());
}

#if defined(OS_WIN)
mojo::PendingRemote<media::mojom::DCOMPSurfaceRegistry>
MediaFactory::CreateDCOMPSurfaceRegistry() {
mojo::PendingRemote<media::mojom::DCOMPSurfaceRegistry> remote;
interface_broker_->GetInterface(remote.InitWithNewPipeAndPassReceiver());
return remote;
}
#endif

} // namespace content
12 changes: 11 additions & 1 deletion content/renderer/media/media_factory.h
Expand Up @@ -8,6 +8,7 @@
#include <memory>

#include "base/memory/weak_ptr.h"
#include "build/build_config.h"
#include "build/buildflag.h"
#include "build/chromecast_buildflags.h"
#include "components/viz/common/surfaces/surface_id.h"
Expand All @@ -23,6 +24,10 @@
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/web/web_media_inspector.h"

#if defined(OS_WIN)
#include "media/mojo/mojom/dcomp_surface_registry.mojom.h"
#endif // defined(OS_WIN)

#if BUILDFLAG(ENABLE_MEDIA_REMOTING)
// Needed by remoting sender.
#include "media/mojo/mojom/remoting.mojom.h"
Expand Down Expand Up @@ -53,7 +58,7 @@ class MediaLog;
class MediaObserver;
class RemotePlaybackClientWrapper;
class RendererWebMediaPlayerDelegate;
}
} // namespace media

namespace content {

Expand Down Expand Up @@ -154,6 +159,11 @@ class MediaFactory {

std::unique_ptr<media::MojoRendererFactory> CreateMojoRendererFactory();

#if defined(OS_WIN)
mojo::PendingRemote<media::mojom::DCOMPSurfaceRegistry>
CreateDCOMPSurfaceRegistry();
#endif

// The render frame we're helping. RenderFrameImpl owns this factory, so the
// pointer will always be valid.
RenderFrameImpl* render_frame_;
Expand Down
3 changes: 3 additions & 0 deletions gpu/ipc/service/dcomp_texture_win.cc
Expand Up @@ -136,12 +136,15 @@ void DCOMPTexture::SetTextureSize(const gfx::Size& size) {
}

void DCOMPTexture::SetSurfaceHandle(const base::UnguessableToken& token) {
DVLOG(1) << __func__;
bool succeeded = false;
base::win::ScopedHandle surface_handle =
gl::DCOMPSurfaceRegistry::GetInstance()->TakeDCOMPSurfaceHandle(token);
if (surface_handle.IsValid()) {
surface_handle_.Set(surface_handle.Take());
succeeded = true;
} else {
DLOG(ERROR) << __func__ << ": No surface registered for token " << token;
}

if (client_)
Expand Down
28 changes: 13 additions & 15 deletions media/mojo/clients/win/media_foundation_renderer_client.cc
Expand Up @@ -19,9 +19,13 @@ MediaFoundationRendererClient::MediaFoundationRendererClient(
scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner,
std::unique_ptr<media::MojoRenderer> mojo_renderer,
std::unique_ptr<DCOMPTextureWrapper> dcomp_texture_wrapper,
mojo::PendingRemote<mojom::DCOMPSurfaceRegistry>
pending_dcomp_surface_registry,
media::VideoRendererSink* sink)
: mojo_renderer_(std::move(mojo_renderer)),
dcomp_texture_wrapper_(std::move(dcomp_texture_wrapper)),
pending_dcomp_surface_registry_(
std::move(pending_dcomp_surface_registry)),
sink_(sink),
media_task_runner_(std::move(media_task_runner)),
compositor_task_runner_(std::move(compositor_task_runner)),
Expand Down Expand Up @@ -95,6 +99,9 @@ void MediaFoundationRendererClient::OnRemoteRendererInitialized(
}

if (has_video_) {
DCHECK(!dcomp_surface_registry_.is_bound());
dcomp_surface_registry_.Bind(std::move(pending_dcomp_surface_registry_));

using Self = MediaFoundationRendererClient;
auto weak_ptr = weak_factory_.GetWeakPtr();
dcomp_texture_wrapper_->Initialize(
Expand Down Expand Up @@ -143,31 +150,22 @@ void MediaFoundationRendererClient::OnReceivedRemoteDCOMPSurface(

void MediaFoundationRendererClient::RegisterDCOMPSurfaceHandleInGPUProcess(
base::win::ScopedHandle surface_handle) {
if (!media_task_runner_->BelongsToCurrentThread()) {
media_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&MediaFoundationRendererClient::
RegisterDCOMPSurfaceHandleInGPUProcess,
weak_factory_.GetWeakPtr(), std::move(surface_handle)));
return;
}

DVLOG_FUNC(1) << "surface_handle=" << surface_handle.Get();
DCHECK(has_video_);

mojo::ScopedHandle mojo_surface_handle =
mojo::WrapPlatformHandle(mojo::PlatformHandle(std::move(surface_handle)));

// TODO(frankli): Pass the |mojo_surface_handle| to Gpu process.
NOTIMPLEMENTED();
dcomp_surface_registry_->RegisterDCOMPSurfaceHandle(
mojo::PlatformHandle(std::move(surface_handle)),
base::BindOnce(
&MediaFoundationRendererClient::OnDCOMPSurfaceRegisteredInGPUProcess,
weak_factory_.GetWeakPtr()));
}

void MediaFoundationRendererClient::OnDCOMPSurfaceRegisteredInGPUProcess(
const base::UnguessableToken& token) {
DVLOG_FUNC(1);
DCHECK(has_video_);

NOTIMPLEMENTED();
dcomp_texture_wrapper_->SetDCOMPSurface(token);
}

void MediaFoundationRendererClient::OnDCOMPTextureInitialized(bool success) {
Expand Down

0 comments on commit 4f50dbd

Please sign in to comment.