Chromium浏览器media子系统mojo说明
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::Renderer
,MojoRenderer
实现media::Renderer
并将调用转发到media::mojom::RendererPtr
。MojoRendererService
实现media::mojom::Renderer
,并且可以托管任何media::Renderer
实现。
Remote Media组件可以轻松开启并无缝集成到当前媒体管道中。只需设置gn参数mojo_media_services
以指定要启用的远程媒体组件。例如,使用以下gn参数,媒体管道将启用MojoRenderer
和MojoCdm
:
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::Renderer
和media::mojom::ContentDecryptionModule
请求由运行在浏览器进程中的[MediaRendererService
]处理。media::mojom::VideoDecoder
请求由运行在GPU进程的MediaService
处理。
注意:media::mojom::InterfaceFactory
接口在MediaInterfaceProxy
和MediaService
之间的通信中被重用。
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使用kMediaServiceName
在ServiceManagerContext
中注册。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创建和管理它创建的媒体组件。
因此,在MediaInterfaceProxy
和MediaService
之间的通信中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接口将MediaPlayerRenderer
和 FlingingRenderer
代理到浏览器进程
这个想法可以概括为处理任何特殊情况Foo场景的专门的OOP FooRenderer。
创建专用OOP FooRenderer所需的类成对出现,在其各自的过程中用于类似的目的。按照惯例FooRenderer
位于目标进程中,而FooRendererClient
位于渲染器进程。MojoRenderer
和MojoRenderService
代理media::Renderer
和media::RendererClient
,在FooRenderer
和FooRendererClient
之间调用。
无法表示为media::Renderer[Client]
的命令和事件通过renderer extensions(请参见“render_extension.mojom”)进行跨进程操作。
FooRenderer[Client]Extension
mojo接口由相应的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::Renderer
和media::mojom::CDM
。它被托管在与默认MediaService
不同的进程中。它使用kMediaRendererServiceName
在ServiceManagerContext
中注册。这允许运行media::mojom::VideoDecoder
和media::mojom::Renderer
在两个不同的进程中。目前Chromecast使用它来支持浏览器进程中的CastRenderer
CDM
和GPU进程中的GPU加速视频解码器。主要目标是:
- 允许两个页面同时保存自己的视频管道,因为
CastRenderer
一次只支持一个视频管道。 - 支持GPU加速视频解码器用于RTC路径。
Mojo CDM and Mojo Decryptor
Mojo CDM在所有媒体播放器Mojo接口中很特殊,因为所有本地/远程媒体组件处理加密缓冲区都需要它。
- 本地媒体组件,如
DecryptingDemuxerStream
,DecryptingAudioDecoder
和Decrypting VideoDecoder
。 - 托管在
MediaService
中的远程媒体组件,例如MojoRendererService
、MojoAudioDecoderService
和
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
从内容层获取服务。在MediaService
和 CdmService
中,远程媒体组件通过secure auxiliary services获取服务。
某些服务确实需要RenderFrame
或用户配置文件标识,例如文件系统。由于媒体组件都属于给定的RenderFrame
,我们出于安全原因,在访问这些服务时必须维护框架标识。这些服务称为安全辅助服务。FrameServiceBase
是所有安全辅助服务的基类,以帮助管理这些服务(例如处理导航)。
创建MediaInterfaceProxy
时,除了提供media::mojom::InterfaceFactory
,RenderFrame
配备了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 inGpuServiceFactory
with
GpuMojoMediaClient
)MojoCdm
+MediaDrmBridge
(CDM)MediaDrmBridge
uses mojoProvisionFetcher
service for CDM provisioningMojoAudioDecoder
+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
withCastMojoMediaClient
)MojoRenderer
+CastRenderer
MojoCdm
+CastCdm
Desktop (ChromeOS/Linux/Mac/Windows)
- CdmService
CdmService
in the utility process (registered inUtilityServiceFactory
withContentCdmServiceClient
)MojoCdm
+CdmAdapter
+ Library CDM implementationCdmAdapter
uses various secure auxiliary services
- MediaService (in progress)
MediaService
in the GPU process (registered inGpuServiceFactory
withGpuMojoMediaClient
)MojoVideoDecoder
+ hardware video decoders such as D3D11VideoDecoder
Other Services
TODO:添加其他mojo服务的文档,例如远程处理等。
Chromium浏览器media子系统mojo说明相关推荐
- Chromium浏览器(CEF)的命令行列表说明
找到的Chromium浏览器的命令行说明列表,转放在这里以方便查看. List of Chromium Command Line Switches There are lots of command ...
- chrome/chromium浏览器的Enter passwod to unlock your login keyring
简直就跟牛皮癣一样,打开浏览器总是出现这个,困扰我很多年了 sudo apt-fast install seahorse 启动命令 seahorse & 把下面图中左上角Login,右键会出来 ...
- 同为Chromium浏览器,Edge却被“特别关照”
谷歌会在 Microsoft Edge 用户访问 Chrome Web Store(Chrome 网上应用商店) 时发去一条通知提醒,建议用户切换到 Google Chrome 以安全地使用扩展程序, ...
- Ubuntu 15 安装Chromium浏览器并添加Flash插件Pepper Flash Player
Chromium谷歌的开源浏览器将不再支持Netscape浏览器插件API,Adobe公司的Flash将无法正常工作了.然而用户可以使用Pepper Flash Player,这是谷歌浏览器上一款替代 ...
- 火狐浏览器中打开java_Ubuntu下通过Firefox Opera Chromium浏览器直接执行java应用程序(打开java jnlp文件)实现在服务器远程虚拟控制台完成远程管理的方法...
远程虚拟控制台依赖于java运行环境(jre),在通过浏览器打开链接前,系统必须安装jre环境,远程管理控制台其实就是一个java程序,打开相应的网站会下载一个jnlp(java网络加载协议)的文件, ...
- 有关chromium浏览器 ios 读证书 验证证书 (注没有找到方法),在这里做一下笔记
最近看了一下chromium浏览器代码,想找到 ios平台有关读证书和验证证书的接口,最终没有找到,但有发现一些证书相关的接口,不知道以后会不会用到,在这里做一下笔记. 如果你看到这篇文章,知道在io ...
- 运行Chromium浏览器缺少google api密钥无法登录谷歌账号的解决办法
每次打开 Chromium,地址栏下方就会提示 "缺少 Google API 密钥,因此 Chromium 的部分功能将无法使用".提示不仅很烦人,并且还无法在 Chromium ...
- Linux 下的chromium浏览器出现no internet connection错误
本人的操作系统是LinuxMint 18.3 最近的chromium浏览器一直连接不上网.而Firefox一直好好的.出现的错误大约如下: "There is no Internet con ...
- Chromium浏览器下载
在下载Chromium浏览器时,Chromium列表页面实现很容易让其他浏览器像Firfox卡死, 先登录到首页:http://commondatastorage.googleapis.com/chr ...
最新文章
- 美多商城之用户中心(用户基本信息)
- 【每日训练】2020/11/8(规律 + 二进制、单调栈 + 前缀和,后缀和、bitset + 枚举)
- 科技部向全社会征集颠覆性技术研发方向
- python中的format什么意思中文-Python中.format()常见的用法
- centos安装mysql 简书_在centos上安装mysql
- 洛谷 P1800 software_NOI导刊2010提高(06)(二分答案+DP检验)
- 抢疯了!字节、美团《人人都要学的架构思维》完整版PDF开放下载!
- 小小c语言贪吃蛇思路,【图片】C语言小游戏~贪吃蛇【c语言吧】_百度贴吧
- VS2010 MFC 使用GDI+给图片添加汉字
- linux 进程间广播,Linux系统编程之进程间通信之浅谈信号
- C# 解密微信步数 报错“填充无效,无法被移除。”
- lbj学习日记 03 循环和选择结构的刷题心得
- Ncurses学习经历(九)屏幕操作
- gnome 3 初见
- 2016年我国网络安全态势
- swp安装(Scientific Work Place)
- 小米路由器刷Xiaomi Mi WiFi Mini openwrt
- 奇瑞新能源掌门人鲍思语:未来将迈进大车市场
- 429. N 叉树的层序遍历 c++ 队列
- 基于帝企鹅算法优化BP神经网络实现数据预测matlab代码
热门文章
- JavaWeb-LayUI框架的介绍与使用方式(前端框架篇)
- emui5.0 Android0主题,华为P9升级EMUI 5.0后:脱胎换骨畅快淋漓
- 进程的三种基本状态及转换原因
- “以旅客为中心”的智慧机场建设,这些常见的智能设备应用其中
- 【北大先修课】计算概论(A)题库全代码
- 新媒体运营晋升空间大吗
- vue项目H5页面在苹果手机点击输入框输入内容时 页面自动放大
- java receive_Java PipedInputStream receive()方法与示例
- 【面试题】Java常见面试题集锦
- JAVA毕业设计web考试资料交易系统设计与实现计算机源码+lw文档+系统+调试部署+数据库