Commit 44322fd2 authored by Yuchen Liu's avatar Yuchen Liu Committed by Commit Bot

[Chromecast] Support multiple media services

Cast may run two media services, one in browser process with CMA media
pipeline, the other in gpu process with GPU VDA:

1. Introduce a new media service "media_renderer", which is used and
implemented on Cast. It's the same media service as before, we only use
it to create media::Renderer and media::ContentDecryptionModule.

2. Change Cast's default media service host to "gpu", so that
DefaultRenderer could use MojoVideoDecoder for v4l2 decoder.

3. Cast runs "media_renderer" service in browser process, to replace the
old "media" service.

Merge-With: eureka-internal/316201
Bug: internal b/138261332
Test: YT, GPM
Change-Id: I08ea092b8b94115b3a7e642f8d188d67ef3884e3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1815719
Commit-Queue: Yuchen Liu <yucliu@chromium.org>
Reviewed-by: default avatarPeter Beverloo <peter@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarDirk Pranke <dpranke@chromium.org>
Reviewed-by: default avatarSean Topping <seantopping@chromium.org>
Reviewed-by: default avatarKen Rockot <rockot@google.com>
Reviewed-by: default avatarXiaohan Wang <xhwang@chromium.org>
Cr-Commit-Position: refs/heads/master@{#706624}
parent c42512af
...@@ -41,9 +41,10 @@ declare_args() { ...@@ -41,9 +41,10 @@ declare_args() {
} }
declare_args() { declare_args() {
# True to enable the cast renderer. It is enabled by default for non-android # True to enable the cast renderer. It is enabled by default for linux and
# builds. # android audio only builds.
enable_cast_renderer = is_chromecast && !is_android enable_cast_renderer =
is_chromecast && (is_linux || (is_cast_audio_only && is_android))
} }
# Configures media options for cast. See media/media_options.gni # Configures media options for cast. See media/media_options.gni
...@@ -51,22 +52,30 @@ cast_mojo_media_services = [] ...@@ -51,22 +52,30 @@ cast_mojo_media_services = []
cast_mojo_media_host = "none" cast_mojo_media_host = "none"
if (enable_cast_renderer) { if (enable_cast_renderer) {
# In this path, mojo media services are hosted in two processes:
# 1. "renderer" and "cdm" run in browser process. This is hard coded in the
# code.
# 2. "video_decoder" runs in the process specified by "cast_mojo_media_host".
cast_mojo_media_services = [ cast_mojo_media_services = [
"cdm", "cdm",
"renderer", "renderer",
] ]
cast_mojo_media_host = "browser"
} else if (is_android) { if (!is_cast_audio_only) {
cast_mojo_media_services += [ "video_decoder" ]
}
cast_mojo_media_host = "gpu"
} else if (is_android && !is_cast_audio_only) {
# On Android, all the enabled mojo media services run in the process specified
# by "cast_mojo_media_host".
cast_mojo_media_services = [ cast_mojo_media_services = [
"cdm", "cdm",
"audio_decoder", "audio_decoder",
"video_decoder",
] ]
if (is_cast_audio_only) {
cast_mojo_media_host = "browser" cast_mojo_media_host = "gpu"
} else {
cast_mojo_media_services += [ "video_decoder" ]
cast_mojo_media_host = "gpu"
}
} }
# Assert that Chromecast is being built for a supported platform. # Assert that Chromecast is being built for a supported platform.
......
...@@ -85,11 +85,11 @@ ...@@ -85,11 +85,11 @@
#include "ui/display/screen.h" #include "ui/display/screen.h"
#include "ui/gl/gl_switches.h" #include "ui/gl/gl_switches.h"
#if BUILDFLAG(ENABLE_MOJO_MEDIA_IN_BROWSER_PROCESS) #if BUILDFLAG(ENABLE_CAST_RENDERER)
#include "chromecast/media/service/cast_mojo_media_client.h" #include "chromecast/media/service/cast_mojo_media_client.h"
#include "media/mojo/mojom/constants.mojom.h" // nogncheck #include "media/mojo/mojom/constants.mojom.h" // nogncheck
#include "media/mojo/services/media_service.h" // nogncheck #include "media/mojo/services/media_service.h" // nogncheck
#endif // ENABLE_MOJO_MEDIA_IN_BROWSER_PROCESS #endif // BUILDFLAG(ENABLE_CAST_RENDERER)
#if defined(OS_LINUX) || defined(OS_ANDROID) #if defined(OS_LINUX) || defined(OS_ANDROID)
#include "components/crash/content/browser/crash_handler_host_linux.h" #include "components/crash/content/browser/crash_handler_host_linux.h"
...@@ -102,7 +102,6 @@ ...@@ -102,7 +102,6 @@
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
#include "components/cdm/browser/cdm_message_filter_android.h" #include "components/cdm/browser/cdm_message_filter_android.h"
#include "components/crash/content/app/crashpad.h" #include "components/crash/content/app/crashpad.h"
#include "media/mojo/services/android_mojo_media_client.h"
#if !BUILDFLAG(USE_CHROMECAST_CDMS) #if !BUILDFLAG(USE_CHROMECAST_CDMS)
#include "components/cdm/browser/media_drm_storage_impl.h" #include "components/cdm/browser/media_drm_storage_impl.h"
#include "url/origin.h" #include "url/origin.h"
...@@ -146,11 +145,10 @@ namespace chromecast { ...@@ -146,11 +145,10 @@ namespace chromecast {
namespace shell { namespace shell {
namespace { namespace {
#if BUILDFLAG(ENABLE_MOJO_MEDIA_IN_BROWSER_PROCESS) #if BUILDFLAG(ENABLE_CAST_RENDERER)
static void CreateMediaService(CastContentBrowserClient* browser_client, static void CreateMediaService(CastContentBrowserClient* browser_client,
service_manager::mojom::ServiceRequest request) { service_manager::mojom::ServiceRequest request) {
std::unique_ptr<::media::MediaService> service; std::unique_ptr<::media::MediaService> service;
#if BUILDFLAG(ENABLE_CAST_RENDERER)
auto mojo_media_client = std::make_unique<media::CastMojoMediaClient>( auto mojo_media_client = std::make_unique<media::CastMojoMediaClient>(
browser_client->GetCmaBackendFactory(), browser_client->GetCmaBackendFactory(),
base::Bind(&CastContentBrowserClient::CreateCdmFactory, base::Bind(&CastContentBrowserClient::CreateCdmFactory,
...@@ -160,15 +158,9 @@ static void CreateMediaService(CastContentBrowserClient* browser_client, ...@@ -160,15 +158,9 @@ static void CreateMediaService(CastContentBrowserClient* browser_client,
browser_client->media_resource_tracker()); browser_client->media_resource_tracker());
service = std::make_unique<::media::MediaService>( service = std::make_unique<::media::MediaService>(
std::move(mojo_media_client), std::move(request)); std::move(mojo_media_client), std::move(request));
#elif defined(OS_ANDROID)
service = std::make_unique<::media::MediaService>(
std::make_unique<::media::AndroidMojoMediaClient>(), std::move(request));
#else
#error "Unsupported configuration."
#endif // defined(ENABLE_CAST_RENDERER)
service_manager::Service::RunAsyncUntilTermination(std::move(service)); service_manager::Service::RunAsyncUntilTermination(std::move(service));
} }
#endif // BUILDFLAG(ENABLE_MOJO_MEDIA_IN_BROWSER_PROCESS) #endif // BUILDFLAG(ENABLE_CAST_RENDERER)
#if defined(OS_ANDROID) && !BUILDFLAG(USE_CHROMECAST_CDMS) #if defined(OS_ANDROID) && !BUILDFLAG(USE_CHROMECAST_CDMS)
void CreateOriginId(cdm::MediaDrmStorageImpl::OriginIdObtainedCB callback) { void CreateOriginId(cdm::MediaDrmStorageImpl::OriginIdObtainedCB callback) {
...@@ -348,11 +340,8 @@ bool CastContentBrowserClient::OverridesAudioManager() { ...@@ -348,11 +340,8 @@ bool CastContentBrowserClient::OverridesAudioManager() {
#if BUILDFLAG(USE_CHROMECAST_CDMS) #if BUILDFLAG(USE_CHROMECAST_CDMS)
std::unique_ptr<::media::CdmFactory> CastContentBrowserClient::CreateCdmFactory( std::unique_ptr<::media::CdmFactory> CastContentBrowserClient::CreateCdmFactory(
service_manager::mojom::InterfaceProvider* host_interfaces) { service_manager::mojom::InterfaceProvider* host_interfaces) {
#if BUILDFLAG(ENABLE_MOJO_MEDIA_IN_BROWSER_PROCESS)
return std::make_unique<media::CastCdmFactory>(GetMediaTaskRunner(), return std::make_unique<media::CastCdmFactory>(GetMediaTaskRunner(),
media_resource_tracker()); media_resource_tracker());
#endif // BUILDFLAG(ENABLE_MOJO_MEDIA_IN_BROWSER_PROCESS)
return nullptr;
} }
#endif // BUILDFLAG(USE_CHROMECAST_CDMS) #endif // BUILDFLAG(USE_CHROMECAST_CDMS)
...@@ -792,15 +781,15 @@ void CastContentBrowserClient::GetApplicationMediaInfo( ...@@ -792,15 +781,15 @@ void CastContentBrowserClient::GetApplicationMediaInfo(
void CastContentBrowserClient::RunServiceInstance( void CastContentBrowserClient::RunServiceInstance(
const service_manager::Identity& identity, const service_manager::Identity& identity,
mojo::PendingReceiver<service_manager::mojom::Service>* receiver) { mojo::PendingReceiver<service_manager::mojom::Service>* receiver) {
#if BUILDFLAG(ENABLE_MOJO_MEDIA_IN_BROWSER_PROCESS) #if BUILDFLAG(ENABLE_CAST_RENDERER)
if (identity.name() == ::media::mojom::kMediaServiceName) { if (identity.name() == ::media::mojom::kMediaRendererServiceName) {
service_manager::mojom::ServiceRequest request(std::move(*receiver)); service_manager::mojom::ServiceRequest request(std::move(*receiver));
GetMediaTaskRunner()->PostTask( GetMediaTaskRunner()->PostTask(
FROM_HERE, FROM_HERE,
base::BindOnce(&CreateMediaService, this, std::move(request))); base::BindOnce(&CreateMediaService, this, std::move(request)));
return; return;
} }
#endif // BUILDFLAG(ENABLE_MOJO_MEDIA_IN_BROWSER_PROCESS) #endif // BUILDFLAG(ENABLE_CAST_RENDERER)
#if BUILDFLAG(ENABLE_EXTERNAL_MOJO_SERVICES) #if BUILDFLAG(ENABLE_EXTERNAL_MOJO_SERVICES)
if (identity.name() == external_mojo::BrokerService::kServiceName) { if (identity.name() == external_mojo::BrokerService::kServiceName) {
......
...@@ -1178,6 +1178,8 @@ jumbo_source_set("browser") { ...@@ -1178,6 +1178,8 @@ jumbo_source_set("browser") {
"media/media_devices_util.h", "media/media_devices_util.h",
"media/media_experiment_manager.cc", "media/media_experiment_manager.cc",
"media/media_experiment_manager.h", "media/media_experiment_manager.h",
"media/media_interface_factory_holder.cc",
"media/media_interface_factory_holder.h",
"media/media_interface_proxy.cc", "media/media_interface_proxy.cc",
"media/media_interface_proxy.h", "media/media_interface_proxy.h",
"media/media_internals.cc", "media/media_internals.cc",
......
...@@ -62,6 +62,7 @@ const std::vector<service_manager::Manifest>& GetBuiltinServiceManifests() { ...@@ -62,6 +62,7 @@ const std::vector<service_manager::Manifest>& GetBuiltinServiceManifests() {
media::GetCdmManifest(), media::GetCdmManifest(),
#endif #endif
media::GetMediaManifest(), media::GetMediaManifest(),
media::GetMediaRendererManifest(),
data_decoder::GetManifest(), data_decoder::GetManifest(),
device::GetManifest(), device::GetManifest(),
media_session::GetManifest(), media_session::GetManifest(),
......
// Copyright 2019 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/media_interface_factory_holder.h"
#include "base/bind.h"
#include "content/public/common/service_manager_connection.h"
#include "media/mojo/mojom/media_service.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
namespace content {
MediaInterfaceFactoryHolder::MediaInterfaceFactoryHolder(
const std::string& service_name,
CreateInterfaceProviderCB create_interface_provider_cb)
: service_name_(service_name),
create_interface_provider_cb_(std::move(create_interface_provider_cb)) {}
MediaInterfaceFactoryHolder::~MediaInterfaceFactoryHolder() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
}
media::mojom::InterfaceFactory* MediaInterfaceFactoryHolder::Get() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (!interface_factory_ptr_)
ConnectToMediaService();
return interface_factory_ptr_.get();
}
void MediaInterfaceFactoryHolder::ConnectToMediaService() {
media::mojom::MediaServicePtr media_service;
// TODO(slan): Use the BrowserContext Connector instead. See crbug.com/638950.
service_manager::Connector* connector =
ServiceManagerConnection::GetForProcess()->GetConnector();
connector->BindInterface(service_name_, &media_service);
media_service->CreateInterfaceFactory(MakeRequest(&interface_factory_ptr_),
create_interface_provider_cb_.Run());
interface_factory_ptr_.set_connection_error_handler(base::BindOnce(
&MediaInterfaceFactoryHolder::OnMediaServiceConnectionError,
base::Unretained(this)));
}
void MediaInterfaceFactoryHolder::OnMediaServiceConnectionError() {
DVLOG(1) << __func__;
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
interface_factory_ptr_.reset();
}
} // namespace content
// Copyright 2019 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_MEDIA_INTERFACE_FACTORY_HOLDER_H_
#define CONTENT_BROWSER_MEDIA_MEDIA_INTERFACE_FACTORY_HOLDER_H_
#include <string>
#include "base/callback.h"
#include "base/macros.h"
#include "base/threading/thread_checker.h"
#include "media/mojo/mojom/interface_factory.mojom.h"
#include "services/service_manager/public/mojom/interface_provider.mojom.h"
namespace content {
// Helper class to get media::mojom::InterfaceFactoryPtr.
// Get() lazily connects to the media service specified by |service_name_|.
class MediaInterfaceFactoryHolder {
public:
using CreateInterfaceProviderCB =
base::RepeatingCallback<service_manager::mojom::InterfaceProviderPtr()>;
MediaInterfaceFactoryHolder(
const std::string& service_name,
CreateInterfaceProviderCB create_interface_provider_cb);
~MediaInterfaceFactoryHolder();
// Gets the MediaService |interface_factory_ptr_|. The returned pointer is
// still owned by this class.
media::mojom::InterfaceFactory* Get();
private:
void ConnectToMediaService();
// Callback for connection error from |interface_factory_ptr_|.
void OnMediaServiceConnectionError();
const std::string service_name_;
CreateInterfaceProviderCB create_interface_provider_cb_;
media::mojom::InterfaceFactoryPtr interface_factory_ptr_;
THREAD_CHECKER(thread_checker_);
DISALLOW_COPY_AND_ASSIGN(MediaInterfaceFactoryHolder);
};
} // namespace content
#endif // CONTENT_BROWSER_MEDIA_MEDIA_INTERFACE_FACTORY_HOLDER_H_
...@@ -125,10 +125,22 @@ MediaInterfaceProxy::MediaInterfaceProxy( ...@@ -125,10 +125,22 @@ MediaInterfaceProxy::MediaInterfaceProxy(
DCHECK(render_frame_host_); DCHECK(render_frame_host_);
DCHECK(!error_handler.is_null()); DCHECK(!error_handler.is_null());
auto create_interface_provider_cb =
base::BindRepeating(&MediaInterfaceProxy::GetFrameServices,
base::Unretained(this), base::Token(), std::string());
media_interface_factory_ptr_ = std::make_unique<MediaInterfaceFactoryHolder>(
media::mojom::kMediaServiceName, create_interface_provider_cb);
#if BUILDFLAG(ENABLE_CAST_RENDERER)
media_renderer_interface_factory_ptr_ =
std::make_unique<MediaInterfaceFactoryHolder>(
media::mojom::kMediaRendererServiceName,
std::move(create_interface_provider_cb));
#endif // BUILDFLAG(ENABLE_CAST_RENDERER)
binding_.set_connection_error_handler(std::move(error_handler)); binding_.set_connection_error_handler(std::move(error_handler));
// |interface_factory_ptr_| and |cdm_factory_map_| will be lazily // |cdm_factory_map_| will be lazily connected in GetCdmFactory().
// connected in GetMediaInterfaceFactory() and GetCdmFactory().
} }
MediaInterfaceProxy::~MediaInterfaceProxy() { MediaInterfaceProxy::~MediaInterfaceProxy() {
...@@ -139,7 +151,7 @@ MediaInterfaceProxy::~MediaInterfaceProxy() { ...@@ -139,7 +151,7 @@ MediaInterfaceProxy::~MediaInterfaceProxy() {
void MediaInterfaceProxy::CreateAudioDecoder( void MediaInterfaceProxy::CreateAudioDecoder(
media::mojom::AudioDecoderRequest request) { media::mojom::AudioDecoderRequest request) {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
InterfaceFactory* factory = GetMediaInterfaceFactory(); InterfaceFactory* factory = media_interface_factory_ptr_->Get();
if (factory) if (factory)
factory->CreateAudioDecoder(std::move(request)); factory->CreateAudioDecoder(std::move(request));
} }
...@@ -147,7 +159,7 @@ void MediaInterfaceProxy::CreateAudioDecoder( ...@@ -147,7 +159,7 @@ void MediaInterfaceProxy::CreateAudioDecoder(
void MediaInterfaceProxy::CreateVideoDecoder( void MediaInterfaceProxy::CreateVideoDecoder(
media::mojom::VideoDecoderRequest request) { media::mojom::VideoDecoderRequest request) {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
InterfaceFactory* factory = GetMediaInterfaceFactory(); InterfaceFactory* factory = media_interface_factory_ptr_->Get();
if (factory) if (factory)
factory->CreateVideoDecoder(std::move(request)); factory->CreateVideoDecoder(std::move(request));
} }
...@@ -157,7 +169,7 @@ void MediaInterfaceProxy::CreateDefaultRenderer( ...@@ -157,7 +169,7 @@ void MediaInterfaceProxy::CreateDefaultRenderer(
media::mojom::RendererRequest request) { media::mojom::RendererRequest request) {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
InterfaceFactory* factory = GetMediaInterfaceFactory(); InterfaceFactory* factory = media_interface_factory_ptr_->Get();
if (factory) if (factory)
factory->CreateDefaultRenderer(audio_device_id, std::move(request)); factory->CreateDefaultRenderer(audio_device_id, std::move(request));
} }
...@@ -168,7 +180,8 @@ void MediaInterfaceProxy::CreateCastRenderer( ...@@ -168,7 +180,8 @@ void MediaInterfaceProxy::CreateCastRenderer(
media::mojom::RendererRequest request) { media::mojom::RendererRequest request) {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
InterfaceFactory* factory = GetMediaInterfaceFactory(); // CastRenderer is always hosted in "media_renderer" service.
InterfaceFactory* factory = media_renderer_interface_factory_ptr_->Get();
if (factory) if (factory)
factory->CreateCastRenderer(overlay_plane_id, std::move(request)); factory->CreateCastRenderer(overlay_plane_id, std::move(request));
} }
...@@ -217,21 +230,25 @@ void MediaInterfaceProxy::CreateCdm( ...@@ -217,21 +230,25 @@ void MediaInterfaceProxy::CreateCdm(
const std::string& key_system, const std::string& key_system,
media::mojom::ContentDecryptionModuleRequest request) { media::mojom::ContentDecryptionModuleRequest request) {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
#if !BUILDFLAG(ENABLE_LIBRARY_CDMS) #if BUILDFLAG(ENABLE_LIBRARY_CDMS)
auto* factory = GetMediaInterfaceFactory();
if (factory)
factory->CreateCdm(key_system, std::move(request));
#else
auto* factory = GetCdmFactory(key_system); auto* factory = GetCdmFactory(key_system);
#elif BUILDFLAG(ENABLE_CAST_RENDERER)
// CDM service lives together with renderer service if cast renderer is
// enabled, because cast renderer creates its own audio/video decoder.
auto* factory = media_renderer_interface_factory_ptr_->Get();
#else
// CDM service lives together with audio/video decoder service.
auto* factory = media_interface_factory_ptr_->Get();
#endif
if (factory) if (factory)
factory->CreateCdm(key_system, std::move(request)); factory->CreateCdm(key_system, std::move(request));
#endif
} }
void MediaInterfaceProxy::CreateDecryptor( void MediaInterfaceProxy::CreateDecryptor(
int cdm_id, int cdm_id,
mojo::PendingReceiver<media::mojom::Decryptor> receiver) { mojo::PendingReceiver<media::mojom::Decryptor> receiver) {
InterfaceFactory* factory = GetMediaInterfaceFactory(); InterfaceFactory* factory = media_interface_factory_ptr_->Get();
if (factory) if (factory)
factory->CreateDecryptor(cdm_id, std::move(receiver)); factory->CreateDecryptor(cdm_id, std::move(receiver));
} }
...@@ -284,42 +301,6 @@ MediaInterfaceProxy::GetFrameServices(const base::Token& cdm_guid, ...@@ -284,42 +301,6 @@ MediaInterfaceProxy::GetFrameServices(const base::Token& cdm_guid,
return interfaces; return interfaces;
} }
media::mojom::InterfaceFactory*
MediaInterfaceProxy::GetMediaInterfaceFactory() {
DCHECK(thread_checker_.CalledOnValidThread());
if (!interface_factory_ptr_)
ConnectToMediaService();
return interface_factory_ptr_.get();
}
void MediaInterfaceProxy::ConnectToMediaService() {
DVLOG(1) << __func__;
DCHECK(!interface_factory_ptr_);
media::mojom::MediaServicePtr media_service;
// TODO(slan): Use the BrowserContext Connector instead. See crbug.com/638950.
GetSystemConnector()->BindInterface(media::mojom::kMediaServiceName,
&media_service);
media_service->CreateInterfaceFactory(
MakeRequest(&interface_factory_ptr_),
GetFrameServices(base::Token{}, std::string()));
interface_factory_ptr_.set_connection_error_handler(
base::BindOnce(&MediaInterfaceProxy::OnMediaServiceConnectionError,
base::Unretained(this)));
}
void MediaInterfaceProxy::OnMediaServiceConnectionError() {
DVLOG(1) << __func__;
DCHECK(thread_checker_.CalledOnValidThread());
interface_factory_ptr_.reset();
}
#if BUILDFLAG(ENABLE_LIBRARY_CDMS) #if BUILDFLAG(ENABLE_LIBRARY_CDMS)
media::mojom::CdmFactory* MediaInterfaceProxy::GetCdmFactory( media::mojom::CdmFactory* MediaInterfaceProxy::GetCdmFactory(
...@@ -409,7 +390,7 @@ void MediaInterfaceProxy::CreateCdmProxyInternal( ...@@ -409,7 +390,7 @@ void MediaInterfaceProxy::CreateCdmProxyInternal(
DVLOG(1) << __func__; DVLOG(1) << __func__;
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
InterfaceFactory* factory = GetMediaInterfaceFactory(); InterfaceFactory* factory = media_interface_factory_ptr_->Get();
if (factory) if (factory)
factory->CreateCdmProxy(cdm_guid, std::move(receiver)); factory->CreateCdmProxy(cdm_guid, std::move(receiver));
} }
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "base/token.h" #include "base/token.h"
#include "base/unguessable_token.h" #include "base/unguessable_token.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "content/browser/media/media_interface_factory_holder.h"
#include "media/media_buildflags.h" #include "media/media_buildflags.h"
#include "media/mojo/buildflags.h" #include "media/mojo/buildflags.h"
#include "media/mojo/mojom/content_decryption_module.mojom.h" #include "media/mojo/mojom/content_decryption_module.mojom.h"
...@@ -84,15 +85,6 @@ class MediaInterfaceProxy : public media::mojom::InterfaceFactory { ...@@ -84,15 +85,6 @@ class MediaInterfaceProxy : public media::mojom::InterfaceFactory {
const base::Token& cdm_guid, const base::Token& cdm_guid,
const std::string& cdm_file_system_id); const std::string& cdm_file_system_id);
// Gets the MediaService |interface_factory_ptr_|. Returns null if unexpected
// error happened.
InterfaceFactory* GetMediaInterfaceFactory();
void ConnectToMediaService();
// Callback for connection error from |interface_factory_ptr_|.
void OnMediaServiceConnectionError();
#if BUILDFLAG(ENABLE_LIBRARY_CDMS) #if BUILDFLAG(ENABLE_LIBRARY_CDMS)
// Gets a CdmFactory pointer for |key_system|. Returns null if unexpected // Gets a CdmFactory pointer for |key_system|. Returns null if unexpected
// error happened. // error happened.
...@@ -134,7 +126,16 @@ class MediaInterfaceProxy : public media::mojom::InterfaceFactory { ...@@ -134,7 +126,16 @@ class MediaInterfaceProxy : public media::mojom::InterfaceFactory {
// in the service named kMediaServiceName hosted in the process specified by // in the service named kMediaServiceName hosted in the process specified by
// the "mojo_media_host" gn argument. Available options are browser, GPU and // the "mojo_media_host" gn argument. Available options are browser, GPU and
// utility processes. // utility processes.
media::mojom::InterfaceFactoryPtr interface_factory_ptr_; std::unique_ptr<MediaInterfaceFactoryHolder> media_interface_factory_ptr_;
#if BUILDFLAG(ENABLE_CAST_RENDERER)
// InterfacePtr to the remote InterfaceFactory implementation
// in the service named kMediaRendererServiceName hosted. It provides the
// remote implementation of media::Renderer and
// media::ContentDecryptionModule.
std::unique_ptr<MediaInterfaceFactoryHolder>
media_renderer_interface_factory_ptr_;
#endif // BUILDFLAG(ENABLE_CAST_RENDERER)
#if BUILDFLAG(ENABLE_LIBRARY_CDMS) #if BUILDFLAG(ENABLE_LIBRARY_CDMS)
// CDM GUID to CDM InterfaceFactoryPtr mapping, where the InterfaceFactory // CDM GUID to CDM InterfaceFactoryPtr mapping, where the InterfaceFactory
......
...@@ -123,6 +123,7 @@ const service_manager::Manifest& GetContentBrowserManifest() { ...@@ -123,6 +123,7 @@ const service_manager::Manifest& GetContentBrowserManifest() {
.RequireCapability("network", "test") .RequireCapability("network", "test")
.RequireCapability(mojom::kRendererServiceName, "browser") .RequireCapability(mojom::kRendererServiceName, "browser")
.RequireCapability("media", "media:media") .RequireCapability("media", "media:media")
.RequireCapability("media_renderer", "media:media")
.RequireCapability("*", "app") .RequireCapability("*", "app")
.RequireCapability("content", "navigation") .RequireCapability("content", "navigation")
.RequireCapability("resource_coordinator", "service_callbacks") .RequireCapability("resource_coordinator", "service_callbacks")
......
...@@ -83,7 +83,8 @@ ...@@ -83,7 +83,8 @@
#include "services/service_manager/sandbox/win/sandbox_win.h" #include "services/service_manager/sandbox/win/sandbox_win.h"
#endif #endif
#if BUILDFLAG(ENABLE_MOJO_MEDIA_IN_BROWSER_PROCESS) #if BUILDFLAG(ENABLE_MOJO_MEDIA_IN_BROWSER_PROCESS) || \
BUILDFLAG(ENABLE_CAST_RENDERER)
#include "media/mojo/mojom/constants.mojom.h" // nogncheck #include "media/mojo/mojom/constants.mojom.h" // nogncheck
#include "media/mojo/services/media_service_factory.h" // nogncheck #include "media/mojo/services/media_service_factory.h" // nogncheck
#endif #endif
...@@ -289,12 +290,24 @@ void ShellContentBrowserClient::BindInterfaceRequestFromFrame( ...@@ -289,12 +290,24 @@ void ShellContentBrowserClient::BindInterfaceRequestFromFrame(
void ShellContentBrowserClient::RunServiceInstance( void ShellContentBrowserClient::RunServiceInstance(
const service_manager::Identity& identity, const service_manager::Identity& identity,
mojo::PendingReceiver<service_manager::mojom::Service>* receiver) { mojo::PendingReceiver<service_manager::mojom::Service>* receiver) {
#if BUILDFLAG(ENABLE_MOJO_MEDIA_IN_BROWSER_PROCESS) || \
BUILDFLAG(ENABLE_CAST_RENDERER)
bool is_media_service = false;
#if BUILDFLAG(ENABLE_MOJO_MEDIA_IN_BROWSER_PROCESS) #if BUILDFLAG(ENABLE_MOJO_MEDIA_IN_BROWSER_PROCESS)
if (identity.name() == media::mojom::kMediaServiceName) { if (identity.name() == media::mojom::kMediaServiceName)
is_media_service = true;
#endif // BUILDFLAG(ENABLE_MOJO_MEDIA_IN_BROWSER_PROCESS)
#if BUILDFLAG(ENABLE_CAST_RENDERER)
if (identity.name() == media::mojom::kMediaRendererServiceName)
is_media_service = true;
#endif // BUILDFLAG(ENABLE_CAST_RENDERER)
if (is_media_service) {
service_manager::Service::RunAsyncUntilTermination( service_manager::Service::RunAsyncUntilTermination(
media::CreateMediaServiceForTesting(std::move(*receiver))); media::CreateMediaServiceForTesting(std::move(*receiver)));
} }
#endif #endif // BUILDFLAG(ENABLE_MOJO_MEDIA_IN_BROWSER_PROCESS) ||
// BUILDFLAG(ENABLE_CAST_RENDERER)
} }
bool ShellContentBrowserClient::ShouldTerminateOnServiceQuit( bool ShellContentBrowserClient::ShouldTerminateOnServiceQuit(
......
...@@ -81,13 +81,19 @@ each `RenderFrameHostImpl` owns a `MediaInterfaceProxy`, which implements ...@@ -81,13 +81,19 @@ each `RenderFrameHostImpl` owns a `MediaInterfaceProxy`, which implements
`MediaInterfaceProxy` is a central hub for handling media player mojo interface `MediaInterfaceProxy` is a central hub for handling media player mojo interface
requests. By default it will forward all the requests to the requests. By default it will forward all the requests to the
[`MediaService`](#MediaService). But it also has the flexibility to handle some [`MediaService`](#MediaService). But it also has the flexibility to handle some
special or more complicated use cases. For example, on desktop platforms, when special or more complicated use cases. For example:
library CDM is enabled, the `media::mojom::ContentDecryptionModule` request will * On desktop platforms, when library CDM is enabled, the
be forwarded to the [`CdmService`](#CdmService) running in its own CDM (utility) `media::mojom::ContentDecryptionModule` request will be forwarded to the
process. For another example, on Android, the `media::mojom::Renderer` request [`CdmService`](#CdmService) running in its own CDM (utility) process.
is handled in the `RenderFrameHostImpl` context directly by creating * On Android, the `media::mojom::Renderer` request is handled in the
`MediaPlayerRenderer` in the browser process, even though the `MediaService` is `RenderFrameHostImpl` context directly by creating `MediaPlayerRenderer` in
configured to run in the GPU process. the browser process, even though the `MediaService` is configured to run in
the GPU process.
* On Chromecast, the `media::mojom::Renderer` and
`media::mojom::ContentDecryptionModule` requests are handled by
[`MediaRendererService`](#MediaRendererService) which runs in the browser
process. The `media::mojom::VideoDecoder` request is handled by the default
`MediaService` which runs in the GPU process.
Note that `media::mojom::InterfaceFactory` interface is reused in the Note that `media::mojom::InterfaceFactory` interface is reused in the
communication between `MediaInterfaceProxy` and `MediaService` (see communication between `MediaInterfaceProxy` and `MediaService` (see
...@@ -244,6 +250,19 @@ also has additional support on library CDM, e.g. loading the library CDM etc. ...@@ -244,6 +250,19 @@ also has additional support on library CDM, e.g. loading the library CDM etc.
Note that `CdmService` only supports `media::mojom::CDM` and does NOT support Note that `CdmService` only supports `media::mojom::CDM` and does NOT support
other media player mojo interfaces. other media player mojo interfaces.
### MediaRendererService
`MediaRendererService` supports `media::mojom::Renderer` and
`media::mojom::CDM`. It's hosted in a different process than the default
`MediaService`. It's registered in `ServiceManagerContext` using
'kMediaRendererServiceName`. This allows to run `media::mojom::VideoDecoder` and
`media::mojom::Renderer` in two different processes. Currently Chromecast use
this to support `CastRenderer` `CDM` in browser process and GPU accelerated
video decoder in GPU process. The main goals are:
1. Allow two pages to hold their own video pipeline simultaneously, because
`CastRenderer` only support one video pipeline at a time.
2. Support GPU accelerated video decoder for RTC path.
### Mojo CDM and Mojo Decryptor ### Mojo CDM and Mojo Decryptor
Mojo CDM is special among all media player mojo interfaces because it is needed Mojo CDM is special among all media player mojo interfaces because it is needed
......
...@@ -9,6 +9,13 @@ module media.mojom; ...@@ -9,6 +9,13 @@ module media.mojom;
// media/mojo/services/media_manifest.json // media/mojo/services/media_manifest.json
const string kMediaServiceName = "media"; const string kMediaServiceName = "media";
// The default service name for MediaService hosting Renderer and CDM service.
// It's used when the default MediaService is hosted in a different process.
// This must match the name in media/mojo/service/media_manifest.json
// Currently this is used on Chromecast and the service is hosted in browser
// process.
const string kMediaRendererServiceName = "media_renderer";
// The default service name for MediaService hosting only the CDM service. // The default service name for MediaService hosting only the CDM service.
// This must match the name in media/mojo/services/cdm_manifest.json // This must match the name in media/mojo/services/cdm_manifest.json
const string kCdmServiceName = "cdm"; const string kCdmServiceName = "cdm";
...@@ -25,11 +25,11 @@ ...@@ -25,11 +25,11 @@
#include "media/mojo/services/mojo_video_decoder_service.h" #include "media/mojo/services/mojo_video_decoder_service.h"
#endif // BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER) #endif // BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER)
#if BUILDFLAG(ENABLE_MOJO_RENDERER) #if BUILDFLAG(ENABLE_MOJO_RENDERER) || BUILDFLAG(ENABLE_CAST_RENDERER)
#include "base/bind_helpers.h" #include "base/bind_helpers.h"
#include "media/base/renderer.h" #include "media/base/renderer.h"
#include "media/mojo/services/mojo_renderer_service.h" #include "media/mojo/services/mojo_renderer_service.h"
#endif // BUILDFLAG(ENABLE_MOJO_RENDERER) #endif // BUILDFLAG(ENABLE_MOJO_RENDERER) || BUILDFLAG(ENABLE_CAST_RENDERER)
#if BUILDFLAG(ENABLE_MOJO_CDM) #if BUILDFLAG(ENABLE_MOJO_CDM)
#include "media/base/cdm_factory.h" #include "media/base/cdm_factory.h"
...@@ -129,7 +129,6 @@ void InterfaceFactoryImpl::CreateCastRenderer( ...@@ -129,7 +129,6 @@ void InterfaceFactoryImpl::CreateCastRenderer(
const base::UnguessableToken& overlay_plane_id, const base::UnguessableToken& overlay_plane_id,
media::mojom::RendererRequest request) { media::mojom::RendererRequest request) {
DVLOG(2) << __func__; DVLOG(2) << __func__;
#if BUILDFLAG(ENABLE_MOJO_RENDERER)
auto renderer = mojo_media_client_->CreateCastRenderer( auto renderer = mojo_media_client_->CreateCastRenderer(
host_interfaces_.get(), base::ThreadTaskRunnerHandle::Get(), &media_log_, host_interfaces_.get(), base::ThreadTaskRunnerHandle::Get(), &media_log_,
overlay_plane_id); overlay_plane_id);
...@@ -153,7 +152,6 @@ void InterfaceFactoryImpl::CreateCastRenderer( ...@@ -153,7 +152,6 @@ void InterfaceFactoryImpl::CreateCastRenderer(
base::IgnoreResult( base::IgnoreResult(
&mojo::StrongBindingSet<mojom::Renderer>::RemoveBinding), &mojo::StrongBindingSet<mojom::Renderer>::RemoveBinding),
base::Unretained(&renderer_bindings_), binding_id)); base::Unretained(&renderer_bindings_), binding_id));
#endif // BUILDFLAG(ENABLE_MOJO_RENDERER)
} }
#endif #endif
......
...@@ -94,11 +94,11 @@ class InterfaceFactoryImpl : public DeferredDestroy<mojom::InterfaceFactory> { ...@@ -94,11 +94,11 @@ class InterfaceFactoryImpl : public DeferredDestroy<mojom::InterfaceFactory> {
mojo::StrongBindingSet<mojom::VideoDecoder> video_decoder_bindings_; mojo::StrongBindingSet<mojom::VideoDecoder> video_decoder_bindings_;
#endif // BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER) #endif // BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER)
#if BUILDFLAG(ENABLE_MOJO_RENDERER) #if BUILDFLAG(ENABLE_MOJO_RENDERER) || BUILDFLAG(ENABLE_CAST_RENDERER)
// TODO(xhwang): Use MojoMediaLog for Renderer. // TODO(xhwang): Use MojoMediaLog for Renderer.
NullMediaLog media_log_; NullMediaLog media_log_;
mojo::StrongBindingSet<mojom::Renderer> renderer_bindings_; mojo::StrongBindingSet<mojom::Renderer> renderer_bindings_;
#endif // BUILDFLAG(ENABLE_MOJO_RENDERER) #endif // BUILDFLAG(ENABLE_MOJO_RENDERER) || BUILDFLAG(ENABLE_CAST_RENDERER)
#if BUILDFLAG(ENABLE_MOJO_CDM) #if BUILDFLAG(ENABLE_MOJO_CDM)
std::unique_ptr<CdmFactory> cdm_factory_; std::unique_ptr<CdmFactory> cdm_factory_;
......
...@@ -45,4 +45,26 @@ const service_manager::Manifest& GetMediaManifest() { ...@@ -45,4 +45,26 @@ const service_manager::Manifest& GetMediaManifest() {
return *manifest; return *manifest;
} }
const service_manager::Manifest& GetMediaRendererManifest() {
static base::NoDestructor<service_manager::Manifest> manifest {
service_manager::ManifestBuilder()
.WithServiceName(mojom::kMediaRendererServiceName)
.WithDisplayName("Media Renderer Service")
.WithOptions(
service_manager::ManifestOptionsBuilder()
.WithExecutionMode(
service_manager::Manifest::ExecutionMode::kInProcessBuiltin)
.Build())
.ExposeCapability(
"media:media",
service_manager::Manifest::InterfaceList<mojom::MediaService>())
#if defined(IS_CHROMECAST)
.RequireCapability(chromecast::mojom::kChromecastServiceName,
"multizone")
#endif
.Build()
};
return *manifest;
}
} // namespace media } // namespace media
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
namespace media { namespace media {
const service_manager::Manifest& GetMediaManifest(); const service_manager::Manifest& GetMediaManifest();
const service_manager::Manifest& GetMediaRendererManifest();
} // namespace media } // namespace media
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment