0

media: Introduce InterfaceFactory.CreateStableVideoDecoder()

This CL adds a new method to the InterfaceFactory Mojo interface,
CreateStableVideoDecoder(), to be used with the GTFO OOP-VD path
(go/oopvd-gtfo-dd).

The intended usage is for a renderer process to ask the browser process
to broker a media.stable.mojom.StableVideoDecoder connection on its
behalf. Ultimately, the receiving endpoint will end up living in a
utility video decoder process.

Bug: b:327268445
Test: None
Change-Id: I70b7ab768de192d1f7cfc03d257b705aabfcf333
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5330169
Reviewed-by: danakj <danakj@chromium.org>
Commit-Queue: Andres Calderon Jaramillo <andrescj@chromium.org>
Reviewed-by: Pilar Molina Lopez <pmolinalopez@chromium.org>
Reviewed-by: Dan Sanders <sandersd@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1277992}
This commit is contained in:
Andres Calderon Jaramillo
2024-03-25 22:22:08 +00:00
committed by Chromium LUCI CQ
parent 084e3e8276
commit f70b47c8d5
14 changed files with 159 additions and 0 deletions

@@ -19,6 +19,7 @@
#if BUILDFLAG(ALLOW_OOP_VIDEO_DECODER)
#include "content/public/browser/stable_video_decoder_factory.h"
#include "media/base/media_switches.h"
#include "mojo/public/cpp/bindings/message.h"
#endif // BUILDFLAG(ALLOW_OOP_VIDEO_DECODER)
namespace content {
@@ -98,6 +99,47 @@ void FramelessMediaInterfaceProxy::CreateVideoDecoder(
std::move(oop_video_decoder));
}
#if BUILDFLAG(ALLOW_OOP_VIDEO_DECODER)
void FramelessMediaInterfaceProxy::CreateStableVideoDecoder(
mojo::PendingReceiver<media::stable::mojom::StableVideoDecoder>
video_decoder) {
DVLOG(2) << __func__;
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
switch (media::GetOutOfProcessVideoDecodingMode()) {
case media::OOPVDMode::kEnabledWithGpuProcessAsProxy:
case media::OOPVDMode::kDisabled:
// Well-behaved clients shouldn't call CreateStableVideoDecoder() in this
// OOP-VD mode.
//
// Note: FramelessMediaInterfaceProxy::CreateStableVideoDecoder() might be
// called outside of a message dispatch, e.g., by
// GpuDataManagerImplPrivate::RequestMojoMediaVideoCapabilities().
// However, these calls should only occur inside of the browser process
// which we can trust not to reach this point, hence the CHECK().
CHECK(mojo::IsInMessageDispatch());
mojo::ReportBadMessage("CreateStableVideoDecoder() called unexpectedly");
return;
case media::OOPVDMode::kEnabledWithoutGpuProcessAsProxy:
if (!render_process_host_) {
if (!stable_vd_factory_remote_.is_bound()) {
LaunchStableVideoDecoderFactory(
stable_vd_factory_remote_.BindNewPipeAndPassReceiver());
stable_vd_factory_remote_.reset_on_disconnect();
}
CHECK(stable_vd_factory_remote_.is_bound());
stable_vd_factory_remote_->CreateStableVideoDecoder(
std::move(video_decoder), /*tracker=*/{});
} else {
render_process_host_->CreateStableVideoDecoder(
std::move(video_decoder));
}
break;
}
}
#endif // BUILDFLAG(ALLOW_OOP_VIDEO_DECODER)
void FramelessMediaInterfaceProxy::CreateAudioEncoder(
mojo::PendingReceiver<media::mojom::AudioEncoder> receiver) {
DVLOG(2) << __func__;

@@ -54,6 +54,11 @@ class FramelessMediaInterfaceProxy final
mojo::PendingReceiver<media::mojom::VideoDecoder> receiver,
mojo::PendingRemote<media::stable::mojom::StableVideoDecoder>
dst_video_decoder) final;
#if BUILDFLAG(ALLOW_OOP_VIDEO_DECODER)
void CreateStableVideoDecoder(
mojo::PendingReceiver<media::stable::mojom::StableVideoDecoder>
video_decoder) final;
#endif // BUILDFLAG(ALLOW_OOP_VIDEO_DECODER)
void CreateAudioEncoder(
mojo::PendingReceiver<media::mojom::AudioEncoder> receiver) final;
void CreateDefaultRenderer(

@@ -78,6 +78,7 @@
#if BUILDFLAG(ALLOW_OOP_VIDEO_DECODER)
#include "content/public/browser/stable_video_decoder_factory.h"
#include "media/base/media_switches.h"
#include "mojo/public/cpp/bindings/message.h"
#endif // BUILDFLAG(ALLOW_OOP_VIDEO_DECODER)
namespace content {
@@ -320,6 +321,28 @@ void MediaInterfaceProxy::CreateVideoDecoder(
std::move(oop_video_decoder));
}
#if BUILDFLAG(ALLOW_OOP_VIDEO_DECODER)
void MediaInterfaceProxy::CreateStableVideoDecoder(
mojo::PendingReceiver<media::stable::mojom::StableVideoDecoder>
video_decoder) {
DCHECK(thread_checker_.CalledOnValidThread());
switch (media::GetOutOfProcessVideoDecodingMode()) {
case media::OOPVDMode::kEnabledWithGpuProcessAsProxy:
case media::OOPVDMode::kDisabled:
// Well-behaved clients shouldn't call CreateStableVideoDecoder() in this
// OOP-VD mode and MediaInterfaceProxy::CreateStableVideoDecoder() should
// always be called during a message dispatch.
CHECK(mojo::IsInMessageDispatch());
mojo::ReportBadMessage("CreateStableVideoDecoder() called unexpectedly");
return;
case media::OOPVDMode::kEnabledWithoutGpuProcessAsProxy:
render_frame_host().GetProcess()->CreateStableVideoDecoder(
std::move(video_decoder));
break;
}
}
#endif // BUILDFLAG(ALLOW_OOP_VIDEO_DECODER)
void MediaInterfaceProxy::CreateAudioEncoder(
mojo::PendingReceiver<media::mojom::AudioEncoder> receiver) {
DCHECK(thread_checker_.CalledOnValidThread());

@@ -58,6 +58,11 @@ class MediaInterfaceProxy final : public DocumentUserData<MediaInterfaceProxy>,
mojo::PendingReceiver<media::mojom::VideoDecoder> receiver,
mojo::PendingRemote<media::stable::mojom::StableVideoDecoder>
dst_video_decoder) final;
#if BUILDFLAG(ALLOW_OOP_VIDEO_DECODER)
void CreateStableVideoDecoder(
mojo::PendingReceiver<media::stable::mojom::StableVideoDecoder>
video_decoder) final;
#endif // BUILDFLAG(ALLOW_OOP_VIDEO_DECODER)
void CreateAudioEncoder(
mojo::PendingReceiver<media::mojom::AudioEncoder> receiver) final;
void CreateDefaultRenderer(

@@ -278,6 +278,14 @@ class FakeInterfaceFactory : public media::mojom::InterfaceFactory {
std::move(receiver));
}
#if BUILDFLAG(ALLOW_OOP_VIDEO_DECODER)
void CreateStableVideoDecoder(
mojo::PendingReceiver<media::stable::mojom::StableVideoDecoder>
video_decoder) override {
// TODO(b/327268445): we'll need to complete this for GTFO OOP-VD testing.
}
#endif // BUILDFLAG(ALLOW_OOP_VIDEO_DECODER)
// Stub out other mojom::InterfaceFactory interfaces.
void CreateAudioDecoder(
mojo::PendingReceiver<media::mojom::AudioDecoder> receiver) override {}

@@ -72,6 +72,24 @@ void MediaInterfaceFactory::CreateVideoDecoder(
/*dst_video_decoder=*/{});
}
#if BUILDFLAG(ALLOW_OOP_VIDEO_DECODER)
void MediaInterfaceFactory::CreateStableVideoDecoder(
mojo::PendingReceiver<media::stable::mojom::StableVideoDecoder>
video_decoder) {
if (!task_runner_->BelongsToCurrentThread()) {
task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&MediaInterfaceFactory::CreateStableVideoDecoder,
weak_this_, std::move(video_decoder)));
return;
}
DVLOG(1) << __func__;
GetMediaInterfaceFactory()->CreateStableVideoDecoder(
std::move(video_decoder));
}
#endif // BUILDFLAG(ALLOW_OOP_VIDEO_DECODER)
void MediaInterfaceFactory::CreateAudioEncoder(
mojo::PendingReceiver<media::mojom::AudioEncoder> receiver) {
if (!task_runner_->BelongsToCurrentThread()) {

@@ -52,6 +52,11 @@ class MediaInterfaceFactory final : public media::mojom::InterfaceFactory {
mojo::PendingReceiver<media::mojom::VideoDecoder> receiver,
mojo::PendingRemote<media::stable::mojom::StableVideoDecoder>
dst_video_decoder) final;
#if BUILDFLAG(ALLOW_OOP_VIDEO_DECODER)
void CreateStableVideoDecoder(
mojo::PendingReceiver<media::stable::mojom::StableVideoDecoder>
video_decoder) final;
#endif // BUILDFLAG(ALLOW_OOP_VIDEO_DECODER)
void CreateAudioEncoder(
mojo::PendingReceiver<media::mojom::AudioEncoder> receiver) final;
void CreateDefaultRenderer(

@@ -110,6 +110,10 @@ mojom("mojom") {
enabled_features += [ "is_linux_or_chromeos" ]
}
if (allow_oop_video_decoder) {
enabled_features += [ "allow_oop_video_decoder" ]
}
# Help select ServiceSandbox for media_service.mojom.
if (mojo_media_host == "browser") {
enabled_features += [ "mojo_media_in_browser" ]

@@ -28,10 +28,25 @@ interface InterfaceFactory {
// the GPU process acts a proxy between a renderer and a video decoder process
// so that it can create a gpu::Mailbox for each decoded frame. As such, only
// the GPU process should be provided with a valid |dst_video_decoder|.
//
// TODO(b/327268445): we can remove the `dst_video_decoder` parameter once
// GTFO OOP-VD is used instead of regular OOP-VD.
CreateVideoDecoder(
pending_receiver<VideoDecoder> video_decoder,
pending_remote<media.stable.mojom.StableVideoDecoder>? dst_video_decoder);
// Creates a StableVideoDecoder (`video_decoder`). This method is intended to
// be used only for the "GTFO OOP-VD" mode, i.e., when the StableVideoDecoder
// client talks directly to the StableVideoDecoder service without using the
// GPU process as a proxy (in contrast to the "regular OOP-VD" mode).
//
// The StableVideoDecoder implementation lives in a utility process. Clients
// are expected to live in either the browser process (for supported profile
// querying) or the renderer process (to drive video decoding).
[EnableIf=allow_oop_video_decoder]
CreateStableVideoDecoder(
pending_receiver<media.stable.mojom.StableVideoDecoder> video_decoder);
// Creates an AudioEncoder bound to a given receiver.
CreateAudioEncoder(pending_receiver<AudioEncoder> audio_encoder);

@@ -193,6 +193,15 @@ void InterfaceFactoryImpl::CreateVideoDecoder(
#endif // BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER)
}
#if BUILDFLAG(ALLOW_OOP_VIDEO_DECODER)
void InterfaceFactoryImpl::CreateStableVideoDecoder(
mojo::PendingReceiver<media::stable::mojom::StableVideoDecoder>
video_decoder) {
// The browser process ensures that this is not called in the GPU process.
NOTREACHED_NORETURN();
}
#endif // BUILDFLAG(ALLOW_OOP_VIDEO_DECODER)
void InterfaceFactoryImpl::CreateAudioEncoder(
mojo::PendingReceiver<mojom::AudioEncoder> receiver) {
#if BUILDFLAG(ENABLE_MOJO_AUDIO_ENCODER)

@@ -56,6 +56,11 @@ class InterfaceFactoryImpl final
mojo::PendingReceiver<mojom::VideoDecoder> receiver,
mojo::PendingRemote<media::stable::mojom::StableVideoDecoder>
dst_video_decoder) final;
#if BUILDFLAG(ALLOW_OOP_VIDEO_DECODER)
void CreateStableVideoDecoder(
mojo::PendingReceiver<media::stable::mojom::StableVideoDecoder>
video_decoder) final;
#endif // BUILDFLAG(ALLOW_OOP_VIDEO_DECODER)
void CreateAudioEncoder(
mojo::PendingReceiver<mojom::AudioEncoder> receiver) final;

@@ -90,6 +90,13 @@ class TestInterfaceFactory final : public media::mojom::InterfaceFactory {
dst_video_decoder) override {
NOTREACHED();
}
#if BUILDFLAG(ALLOW_OOP_VIDEO_DECODER)
void CreateStableVideoDecoder(
mojo::PendingReceiver<media::stable::mojom::StableVideoDecoder>
video_decoder) override {
NOTREACHED();
}
#endif // BUILDFLAG(ALLOW_OOP_VIDEO_DECODER)
void CreateAudioDecoder(
mojo::PendingReceiver<media::mojom::AudioDecoder> receiver) override {
NOTREACHED();

@@ -136,6 +136,11 @@ class FakeInterfaceFactory : public media::mojom::InterfaceFactory {
mojo::PendingReceiver<media::mojom::VideoDecoder> receiver,
mojo::PendingRemote<media::stable::mojom::StableVideoDecoder>
dst_video_decoder) override {}
#if BUILDFLAG(ALLOW_OOP_VIDEO_DECODER)
void CreateStableVideoDecoder(
mojo::PendingReceiver<media::stable::mojom::StableVideoDecoder>
video_decoder) override {}
#endif // BUILDFLAG(ALLOW_OOP_VIDEO_DECODER)
void CreateDefaultRenderer(
const std::string& audio_device_id,
mojo::PendingReceiver<media::mojom::Renderer> receiver) override {}

@@ -127,6 +127,14 @@ class FakeInterfaceFactory : public media::mojom::InterfaceFactory {
std::move(receiver));
}
#if BUILDFLAG(ALLOW_OOP_VIDEO_DECODER)
void CreateStableVideoDecoder(
mojo::PendingReceiver<media::stable::mojom::StableVideoDecoder>
video_decoder) override {
// TODO(b/327268445): we'll need to complete this for GTFO OOP-VD testing.
}
#endif // BUILDFLAG(ALLOW_OOP_VIDEO_DECODER)
// Stub out other mojom::InterfaceFactory interfaces.
void CreateAudioDecoder(
mojo::PendingReceiver<media::mojom::AudioDecoder> receiver) override {}