Chromium浏览器media子系统mojo说明

该文件夹包含mojo接口、客户端和实现,它们扩展了核心media来支持大多数进程外使用,包括media Player、Metrics(WatchTime)等。

目前,media不依赖于mojo,因此其他应用程序可以使用media,而无需引入mojo依赖。

文章目录

  • Chromium浏览器media子系统mojo说明
    • Media Player
      • Media组件
      • Media Player Mojo接口
      • 开启Remote Media组件
      • Media Mojo Interface Factory
      • Frameless Media Interface Factory
      • MediaService
        • Flexible Process Model
        • Connects Different Media Components
        • Customization through MojoMediaClient
        • Site Isolation
        • Specialized Out-of-Process media::Renderers
        • Support Other Clients
      • CdmService
      • MediaRendererService
      • Mojo CDM and Mojo Decryptor
        • Using a Decryptor (via CdmContext)
        • Using CdmContext
      • Secure Auxiliary Services
      • Security
      • Adoption
        • Android
        • ChromeCast
        • Desktop (ChromeOS/Linux/Mac/Windows)
    • Other Services

Media Player

Media组件

Media Player(WebMediaPlayer)支持HTML5 <video>播放。在内部,它依赖于许多media组件来执行某些特定任务,例如media renderer(媒体渲染器)audio decoder(音频解码器)video decoder(视频解码器)和content decryption module(内容解密模块)(CDM)。媒体渲染器、音频解码器或视频解码器需要CDM来处理受保护的内容。

虽然大多数HTML5媒体播放器栈和加密媒体扩展(EME)栈都位于沙盒渲染进程中(例如出于安全原因),但在某些情况下,某些媒体组件必须位于不同的进程中。

例如:

  • 基于硬件的媒体渲染器,其中所有音频/视频解码和渲染都在硬件中进行,沙盒渲染进程无法访问。
  • 基于硬件的视频解码器,沙盒渲染进程不可访问。
  • 在Android系统中,依赖于Android Java API的媒体组件,沙盒渲染进程不可访问。
  • 包含第三方代码的CDM,应在其自己的沙盒进程中运行。

我们提供了一个通用框架来支持Chromium中的大多数进程外(OOP)媒体组件。

Media Player Mojo接口

我们使用mojom接口作为每个媒体组件的传输层,以支持远程托管。这些接口称为Media Player Mojo接口

  • media::Renderer -> media::mojom::Renderer
  • media::AudioDecoder -> media::mojom::AudioDecoder
  • media::VideoDecoder -> media::mojom::VideoDecoder
  • media::ContentDecryptionModule -> media::mojom::ContentDecryptionModule
  • media::Decryptor -> media::mojom::Decryptor

开启Remote Media组件

这些接口的标准客户端和实现都已经提供。例如,对于media::RendererMojoRenderer实现media::Renderer并将调用转发到media::mojom::RendererPtrMojoRendererService实现media::mojom::Renderer,并且可以托管任何media::Renderer实现。

Remote Media组件可以轻松开启并无缝集成到当前媒体管道中。只需设置gn参数mojo_media_services以指定要启用的远程媒体组件。例如,使用以下gn参数,媒体管道将启用MojoRendererMojoCdm

mojo_media_services = ["renderer", "cdm"]

Media Mojo Interface Factory

media::mojom::InterfaceFactory具有工厂方法,如CreateRenderer()CreateCdm()等。它用于请求媒体播放器mojo接口。

在渲染进程中,每个RenderFrameImpl都有一个mojo::PendingRemote<media::mojom::InterfaceFactory>,用于从浏览器进程请求该框架的所有媒体播放器mojo接口。在浏览器进程中,每个RenderFrameHostImpl都有一个MediaInterfaceProxy,它实现了media::mojom::InterfaceFactory

MediaInterfaceProxy是处理媒体播放器mojo接口请求的中心。默认情况下,它会将所有请求转发到[MediaService]。但它也可以灵活地处理一些特殊或更复杂的用例。

例如:

  • 在桌面平台上,当启用CDM时,media::mojom::ContentDecryptionModule请求将转发到[CdmService],[CdmService]在其自己的CDM进程中运行。
  • 在Android系统中,media::mojom::Renderer请求通过在浏览器进程创建MediaPlayerRenderer,在RenderFrameHostImpl上下文进行处理,即使MediaService配置为在GPU进程中运行。
  • 在Chromecast上,media::mojom::Renderermedia::mojom::ContentDecryptionModule请求由运行在浏览器进程中的[MediaRendererService]处理。media::mojom::VideoDecoder请求由运行在GPU进程的MediaService处理。

注意:media::mojom::InterfaceFactory接口在MediaInterfaceProxyMediaService之间的通信中被重用。

Frameless Media Interface Factory

除了处理普通媒体播放请求的MediaInterfaceProxy之外,FramelessMediaInterfaceProxy处理不需要或没有框架的媒体案例请求。

受保护的媒体播放需要框架,因为媒体解码和CDM在框架内相关联。

FramelessMediaInterfaceProxy由WebCodecs、WebRTC使用,用于早期查询支持的编解码器。

MediaService

MediaService是一个提供媒体播放器mojo接口实现的mojoservice_manager::service。它的好处如下:

Flexible Process Model

不同的平台或产品,对远程媒体组件应该在哪运行的需求不同。例如,硬件解码器通常应该在GPU进程中运行。

ServiceManagerContext能够在浏览器进程或GPU进程启动一个服务。因此,通过使用MediaService,很容易支持托管远程媒体组件在多数Chromium进程种类(Browser/GPU)。这可以使用gn参数mojo_media_host来设置。

例如:

mojo_media_host = "browser" or “gpu”

MediaService使用kMediaServiceNameServiceManagerContext中注册。mojo_media_host用于确定服务注册在哪个进程中运行。

Connects Different Media Components

一些远程媒体组件依赖于其他组件来工作。例如,渲染器、音频解码器或视频解码器需要CDM才能处理加密流。通常会调用SetCdm()来连接CDM渲染器或CDM解码器。例如,如果渲染器接口和CDM接口是单独托管的,那么很难实现SetCdm()调用。它需要一个对象或实体,同时知道这两者
以便能够连接它们。MediaService在内部处理此问题,实际上充当这样一个对象或实体,所以你不必重新发明
车轮。

Customization through MojoMediaClient

MediaService提供托管OOP媒体组件所需的一切,但它不提供媒体组件本身。MediaService的客户端负责提供具体的媒体组件实现。

MojoMediaClient接口为MediaService客户端提供了具体媒体组件实现的方式。创建MediaService时,必须传入一个MojoMediaClient,以便media Service知道如何创建媒体组件。

例如,ChromeCast使用MediaService在浏览器进程中托管媒体渲染器和CDM,并通过CastMojoMediaClient(一种MojoMediaClient实现)提供“CastRenderer”和“CastCdm”。注意,这种重写机制并不是在任何地方都实现的。添加支持很简单,我们只会在需要时添加它。

Site Isolation

在Blink中,媒体元素和EME MediaKeys都属于WebLocalFrame。在Chromium中,这转换为属于RenderFrame的媒体播放器和CDM。

在渲染过程中,这一点很清楚。但是,当托管所有远程媒体在一个MediaService(服务管理器仅支持一个进程单个服务)时,框架边界可能变得模糊。这对于彼此交互的媒体组件来说尤其危险。

例如,foo.com中的Renderer与bar.net中的CDM共用1MediaService。如果设置foo.com Renderer去处理加密,就会产生错误。

为了防止这种情况发生,我们引入了一个额外的层来模拟RenderFrame边界。MediaService托管多个InterfaceFactory(每个RenderFrame一个),每个InterfaceFactory创建和管理它创建的媒体组件。

因此,在MediaInterfaceProxyMediaService之间的通信中media::mojom::InterfaceFactory被重用。

Specialized Out-of-Process media::Renderers

media::Renderer接口是一个简单的API,它非常通用,用于执行上层媒体播放命令。我们可以通过专用渲染器来扩展WebMediaPlayer的功能。

具体来说,我们可以构建一个子组件,它封装了高级场景复杂性,编写一个小适配层,将组件公开为media::Renderer,并将其嵌入现有的media::Pipeline状态机。专用渲染器通过限制文件和类的细节,通过需要很少的控制流量样板等方式降低复杂度。

由专用渲染器启用的2个复杂场景如下:一个是通过授权给Android Media Player(请参见MediaPlayerRenderer)处理Android系统的HLS播放,另一个是将“src=”媒体从Android手机转换为cast设备(请参见FlingingRenderer)。这两个示例都有子组件需要在浏览器进程中运行。因此,我们使用在renderer.mojom和render_extensions.mojom中定义的Mojo接口将MediaPlayerRendererFlingingRenderer 代理到浏览器进程
这个想法可以概括为处理任何特殊情况Foo场景专门的OOP FooRenderer

创建专用OOP FooRenderer所需的类成对出现,在其各自的过程中用于类似的目的。按照惯例FooRenderer位于目标进程中,而FooRendererClient位于渲染器进程。MojoRendererMojoRenderService代理media::Renderermedia::RendererClient,在FooRendererFooRendererClient之间调用。

无法表示为media::Renderer[Client]的命令和事件通过renderer extensions(请参见“render_extension.mojom”)进行跨进程操作。
FooRenderer[Client]Extensionmojo接口由相应的FooRenderer[Client] 实现。

FooRenderer[Client]Factory设置特定场景的样板,和所有与其他进程对话所需的mojo接口指针/请求。当调用mojom::InterfaceFactory::CreateFooRenderer()时,接口指针和请求进行跨进程。

如下所示:


要允许在WebMediaPlayer中创建和使用FooRenderer,FooRendererClientFactory必须生成并传递给RendererFactorySelector。还必须为RendererFactorySelector提供查询当前是否需要使用FooRenderer。当我们进入一个Foo scenario时,通过suspend()/resume()循环media::Pipeline应该足够下次调用
RendererFactorySelector::GetCurrentFactory()返回
FooRendererClientFactory。当调用RendererFactory::CreateRenderer()时,
管道将接收FooRendererClient作为不透明的media::Renderer

默认管道状态机将控制OOP FooRenderer。当我们退出Foo scenario时,再次循环管道应该会进入正确的状态。

Support Other Clients

MediaService作为service_manager::Service,可以由除媒体播放器之外的客户端在渲染过程中使用。例如,我们可以有另一个(mojo)服务来处理音频数据,并希望在媒体渲染器中播放它。由于MediaService是一个mojo服务,因此任何其他mojo服务都可以通过service_manager::mojom::Connector连接到它,并使用它所托管的remote media Renderer。

CdmService

尽管MediaService支持media::mojom::CDM,但在某些情况下(例如,桌面应用的CDM库),通常出于安全原因远程CDM需要在其自己的进程中运行,CdmService被引入来处理此问题。

它也实现了service_manager::Service”,并使用kCdmServiceName
ServiceManagerContext 中注册。目前它总是注册为在实用程序进程中运行(使用CDM沙盒类型)。

CdmService还具有对CDM库的额外支持,例如加载CDM库等。

注意:CdmService仅支持media::mojom::CDM,不支持其他媒体播放器mojo接口。

MediaRendererService

MediaRendererService支持media::mojom::Renderermedia::mojom::CDM。它被托管在与默认MediaService不同的进程中。它使用kMediaRendererServiceNameServiceManagerContext中注册。这允许运行media::mojom::VideoDecodermedia::mojom::Renderer在两个不同的进程中。目前Chromecast使用它来支持浏览器进程中的CastRenderer CDM和GPU进程中的GPU加速视频解码器。主要目标是:

  1. 允许两个页面同时保存自己的视频管道,因为CastRenderer一次只支持一个视频管道。
  2. 支持GPU加速视频解码器用于RTC路径。

Mojo CDM and Mojo Decryptor

Mojo CDM在所有媒体播放器Mojo接口中很特殊,因为所有本地/远程媒体组件处理加密缓冲区都需要它。

  1. 本地媒体组件,如DecryptingDemuxerStreamDecryptingAudioDecoderDecrypting VideoDecoder
  2. 托管在MediaService中的远程媒体组件,例如MojoRendererServiceMojoAudioDecoderService
    MojoVideoDecoderService

在JavaScript层,媒体播放器和MediaKeys通过
[setMediaKeys()](https://w3c.github.io/encrypted-media/#dom-htmlmediaelement setmediakeys)连接。这由渲染进程的SetCdm()实现。

媒体组件可以通过两种方式使用CDM。

Using a Decryptor (via CdmContext)

某些CDM提供了Decryptor实现,支持解密方法,例如Decrypt(), DecryptAndDecode()等。AesDecryptor和CDM库都支持Decryptor接口。

对于远程CDM,例如由MediaService或者CdmService中的MojoCdmService托管的CDM,如果远程CDM支持Decryptor接口,
MojoCdm就也支持Decryptor接口,这通过MojoDecryptor实现,它设置了一个新的消息管道来转发所有Decryptor调用远程CDM中的Decryptor

Using CdmContext

在某些情况下,媒体组件被设置为与特定CDM一起工作。
例如,在Android系统中,基于MediaCodec的解码器(例如MediaCodecAudioDecoder)只能通过MediaCryptoContext使用基于MediaDrm的CDM 。媒体组件和CDM必须在同一个过程中,因为这两者的相互作用通常发生在OS级别的深处。理论上,他们都可以在
渲染进程。但在实践中,通常是CDM和媒体组件由MediaService在远程(例如GPU)进程中托管。

为了能够将远程CDM连接到远程媒体组件,每个MediaService中的InterfaceFactoryImpl实例(对应一个RenderFrame)维护一个MojoCdmServiceContext,用于跟踪所有为RenderFrame创建的远程CDM。每个远程CDM分配一个唯一的CDM ID,这个CDM ID在渲染进程中发送回MojoCdm。在渲染进程,当SetCdm()被调用,CDM ID将传递给本地媒体组件(例如MojoRenderer),转发给远程媒体组件
(例如MojoRendererService)。远程媒体组件将从
MojoCdmServiceContext获取与CDM ID关联的CdmContext,以及
完成连接。

Secure Auxiliary Services

媒体组件通常需要其他服务才能工作。在渲染进程中,本地媒体组件通过MediaClient从内容层获取服务。在MediaServiceCdmService中,远程媒体组件通过secure auxiliary services获取服务。

某些服务确实需要RenderFrame或用户配置文件标识,例如文件系统。由于媒体组件都属于给定的RenderFrame,我们出于安全原因,在访问这些服务时必须维护框架标识。这些服务称为安全辅助服务。FrameServiceBase 是所有安全辅助服务的基类,以帮助管理这些服务(例如处理导航)。

创建MediaInterfaceProxy时,除了提供media::mojom::InterfaceFactoryRenderFrame配备了media::mojom::FrameInterfaceFactory,基于每帧的服务开放这些安全辅助。FrameInterfaceFactory直接提供一种方法
通过BindEmbedderReceiver()方法注册其他辅助服务。

目前,只有远程CDM需要安全的辅助服务。这是一个当前支持服务的列表

  • OutputProtection:检查输出保护状态
  • PlatformVerification:检查平台是否安全
  • CdmFileIO:用于CDM存储持久数据
  • ProvisionFetcher:用于Android MediaDrm设备配置

Security

在大多数情况下,客户端运行的最不可信的渲染进程。此外,始终假设客户端代码可能受到破坏,例如以随机顺序调用或传入垃圾参数。

由于[Flexible Process Model],有时很难知道服务端在哪个进程中运行。根据经验,假设所有服务端代码可以在特权进程(例如浏览器进程)中运行,包括常见的支持代码,如MojoVideoDecoderService,以及
具体的[Media Component],例如Android的MediaCodecVideoDecoder。要准确了解 [Media Component]在哪个进程中运行,请参见下面的 [Adoption]。

另请注意,所有 [Secure Auxiliary Services]在一个比媒体所在的进程更有特权的进程中运行。例如,所有现有服务都运行在浏览器进程中。他们必须防御受损的媒体组件。

Adoption

Android

  • MediaService in the GPU process (registered in GpuServiceFactory with
    GpuMojoMediaClient)
  • MojoCdm + MediaDrmBridge (CDM)
  • MediaDrmBridge uses mojo ProvisionFetcher service for CDM provisioning
  • MojoAudioDecoder + MediaCodecAudioDecoder
  • MojoVideoDecoder + MediaCodecVideoDecoder (in progress)
  • HLS support:
    • MojoRenderer + MediaPlayerRenderer
    • NOT using MediaService. Instead, MojoRendererService is hosted by
      RenderFrameHostImpl/MediaInterfaceProxy in the browser process
      directly.
  • Flinging media to cast devices (RemotePlayback API):
    • MojoRenderer + FlingingRenderer
    • NOT using MediaService. Instead, MojoRendererService is hosted by
      RenderFrameHostImpl/MediaInterfaceProxy in the browser process
      directly.

ChromeCast

  • MediaService in the Browser process (registered in
    CastContentBrowserClient with CastMojoMediaClient)
  • MojoRenderer + CastRenderer
  • MojoCdm + CastCdm

Desktop (ChromeOS/Linux/Mac/Windows)

  • CdmService

    • CdmService in the utility process (registered in UtilityServiceFactory with ContentCdmServiceClient)
    • MojoCdm + CdmAdapter + Library CDM implementation
    • CdmAdapter uses various secure auxiliary services
  • MediaService (in progress)
    • MediaService in the GPU process (registered in GpuServiceFactory with GpuMojoMediaClient)
    • MojoVideoDecoder + hardware video decoders such as D3D11VideoDecoder

Other Services

TODO:添加其他mojo服务的文档,例如远程处理等。

Chromium浏览器media子系统mojo说明相关推荐

  1. Chromium浏览器(CEF)的命令行列表说明

    找到的Chromium浏览器的命令行说明列表,转放在这里以方便查看. List of Chromium Command Line Switches There are lots of command ...

  2. chrome/chromium浏览器的Enter passwod to unlock your login keyring

    简直就跟牛皮癣一样,打开浏览器总是出现这个,困扰我很多年了 sudo apt-fast install seahorse 启动命令 seahorse & 把下面图中左上角Login,右键会出来 ...

  3. 同为Chromium浏览器,Edge却被“特别关照”

    谷歌会在 Microsoft Edge 用户访问 Chrome Web Store(Chrome 网上应用商店) 时发去一条通知提醒,建议用户切换到 Google Chrome 以安全地使用扩展程序, ...

  4. Ubuntu 15 安装Chromium浏览器并添加Flash插件Pepper Flash Player

    Chromium谷歌的开源浏览器将不再支持Netscape浏览器插件API,Adobe公司的Flash将无法正常工作了.然而用户可以使用Pepper Flash Player,这是谷歌浏览器上一款替代 ...

  5. 火狐浏览器中打开java_Ubuntu下通过Firefox Opera Chromium浏览器直接执行java应用程序(打开java jnlp文件)实现在服务器远程虚拟控制台完成远程管理的方法...

    远程虚拟控制台依赖于java运行环境(jre),在通过浏览器打开链接前,系统必须安装jre环境,远程管理控制台其实就是一个java程序,打开相应的网站会下载一个jnlp(java网络加载协议)的文件, ...

  6. 有关chromium浏览器 ios 读证书 验证证书 (注没有找到方法),在这里做一下笔记

    最近看了一下chromium浏览器代码,想找到 ios平台有关读证书和验证证书的接口,最终没有找到,但有发现一些证书相关的接口,不知道以后会不会用到,在这里做一下笔记. 如果你看到这篇文章,知道在io ...

  7. 运行Chromium浏览器缺少google api密钥无法登录谷歌账号的解决办法

    每次打开 Chromium,地址栏下方就会提示 "缺少 Google API 密钥,因此 Chromium 的部分功能将无法使用".提示不仅很烦人,并且还无法在 Chromium ...

  8. Linux 下的chromium浏览器出现no internet connection错误

    本人的操作系统是LinuxMint 18.3 最近的chromium浏览器一直连接不上网.而Firefox一直好好的.出现的错误大约如下: "There is no Internet con ...

  9. Chromium浏览器下载

    在下载Chromium浏览器时,Chromium列表页面实现很容易让其他浏览器像Firfox卡死, 先登录到首页:http://commondatastorage.googleapis.com/chr ...

最新文章

  1. 美多商城之用户中心(用户基本信息)
  2. 【每日训练】2020/11/8(规律 + 二进制、单调栈 + 前缀和,后缀和、bitset + 枚举)
  3. 科技部向全社会征集颠覆性技术研发方向
  4. python中的format什么意思中文-Python中.format()常见的用法
  5. centos安装mysql 简书_在centos上安装mysql
  6. 洛谷 P1800 software_NOI导刊2010提高(06)(二分答案+DP检验)
  7. 抢疯了!字节、美团《人人都要学的架构思维》完整版PDF开放下载!
  8. 小小c语言贪吃蛇思路,【图片】C语言小游戏~贪吃蛇【c语言吧】_百度贴吧
  9. VS2010 MFC 使用GDI+给图片添加汉字
  10. linux 进程间广播,Linux系统编程之进程间通信之浅谈信号
  11. C# 解密微信步数 报错“填充无效,无法被移除。”
  12. lbj学习日记 03 循环和选择结构的刷题心得
  13. Ncurses学习经历(九)屏幕操作
  14. gnome 3 初见
  15. 2016年我国网络安全态势
  16. swp安装(Scientific Work Place)
  17. 小米路由器刷Xiaomi Mi WiFi Mini openwrt
  18. 奇瑞新能源掌门人鲍思语:未来将迈进大车市场
  19. 429. N 叉树的层序遍历 c++ 队列
  20. 基于帝企鹅算法优化BP神经网络实现数据预测matlab代码

热门文章

  1. JavaWeb-LayUI框架的介绍与使用方式(前端框架篇)
  2. emui5.0 Android0主题,华为P9升级EMUI 5.0后:脱胎换骨畅快淋漓
  3. 进程的三种基本状态及转换原因
  4. “以旅客为中心”的智慧机场建设,这些常见的智能设备应用其中
  5. 【北大先修课】计算概论(A)题库全代码
  6. 新媒体运营晋升空间大吗
  7. vue项目H5页面在苹果手机点击输入框输入内容时 页面自动放大
  8. java receive_Java PipedInputStream receive()方法与示例
  9. 【面试题】Java常见面试题集锦
  10. JAVA毕业设计web考试资料交易系统设计与实现计算机源码+lw文档+系统+调试部署+数据库