Chromium在Android平台上对HTML5 Video视频播放的实现浅析

在HTML5规范出来之前,网页对音视频的支持基本上是通过flash插件来实现的,因为HTML规范本身没有定义音视频方面的功能。在HTML5规范出来之后,网页才正式支持音视频多媒体功能。HTML5支持音视频多媒体最大的特点是,音视频与图片一样可以用其他技术来进行操作,首先在html中可以直接放置一个video标签来显示一个视频,其次可以通过CSS技术来改变它的样式,还可以使用JavaScript接口来控制音视频多媒体的播放暂停等等。本文就主要介绍Chromium在Android平台上是如何实现HTML5 Video视频播放功能的。


在HTML5规范中,我们可以使用video标签来播放视频,而video标签对应到Webkit中的类型就是HTMLVideoElement,上图是Chromium实现video功能相关的类图。蓝色表示运行在Render进程,橙色表示运行在Browser进程,绿色是Browser进程的GPU线程。在Android平台上,Chromium使用了系统提供的音视频渲染框架,也就是最终会对接到系统提供是android.media.MediaPlayer类。

在Webkit的实现中,为多媒体资源抽象了一个基类,也就是HTMLMediaElement,HTMLVideoElement继承了HTMLMediaElement,实际上大部分逻辑也都是放在HTMLMediaElement类里面实现的。

WebMediaPlayer和WebMediaPlayerClient则是Blink中定义的抽象接口,WebMediaPlayer定义了一系列音视频控制的接口给HTMLMediaElement使用,例如播放、暂停等等,而WebMediaPlayerClient则负责将播放器中的状态信息通知到HTMLMediaElement,HTMLMediaElement需要继承WebMediaPlayerClient类来接收这些状态信息。另外HTMLMediaElement还要负责将一些事件派发到JavaScript中,例如音视频加载过程中的loadstart、canplay事件。

WebMediaPlayerAndroid是Chromium为Android平台专门实现的一个类,它继承了WebMediaPlayer接口,与HTMLMediaElement是一一对应的,由RenderMediaPlayerManager统一管理,但它其实不是真正的播放器,真正的Android播放器是在Browser进程中创建的,WebMediaPlayerAndroid的主要作用是通过IPC与Browser进程通信,创建Android播放器,下达一些HTMLMediaElement传下来的播放器指令或接收状态信息并反馈给HTMLMediaElement。

MediaPlayerAndroid是Chromium定义的用于对接Android MediaPlayer的播放器,它的子类MediaPlayerBridge是具体的实现类,能够通过JNI调用到java层的同名对象MediaPlayerBridge,java层的MediaPlayerBridge类则直接控制Android系统播放器MediaPlayer,而java层的MediaPlayerListener复制监听MediaPlayer的状态信息,例如onBufferingUpdate、onCompletion等等,然后再通过JNI调用回native层的MediaPlayerListener,再交给MediaPlayerAndroid处理,最后调用到MediaPlayerManager。

BrowserMediaPlayerManager继承自MediaPlayerManager类,用于管理browser进程的所有 MediaPlayerAndroid对象,一方面BrowserMediaPlayerManager接收IPC消息,创建MediaPlayerAndroid,下达一些播放器控制指令,例如初始化,播放,暂停等等,同时又能接收处理MediaPlayerAndroid的状态信息,然后通过IPC通信反馈给Render进程的WebMediaPlayerAndroid,例如OnBufferingUpdate、OnPlaybackComplete等等。

ContentVideoView是用于全屏播放的类,它在BrowserMediaPlayerManager中被创建出来,通过一系列的调用后设置给MediaPlayer,用于绘制视频画面,ContentVideoView可以通过JNI调用到java层的同名类ContentVideoView,java层的ContentVideoView会创建一个SurfaceView,最终的视频也就是绘制在这个SurfaceView上。

如果是走原生小窗口播放的话,则是在WebMediaPlayerAndroid中,通过StreamTextureFactory,创建StreamTextureProxy代理类,发起请求从Render进程到Browser进程,最终对接到Android系统提供的android.graphics.SurfaceTexture来作为播放器的输出目标。

StreamTextureProxy和StreamTextureFactory都是基础抽象类,真正实现的是StreamTextureProxyImpl和 StreamTextureFactoryImpl,StreamTextureProxyImpl还实现了StreamTextureHost的listener接口,用于接收OnFrameAvailable回调,StreamTextureHost则通过GpuChannelHost与Browser进程通信,在Browser进程中,负责处理的是GPU线程,由StreamTexture来接收处理StreamTextureHost发送的IPC消息,例如GpuStreamTextureMsg_StartListening,在StreamTexture的构造函数中,会创建一个gfx::SurfaceTexture对象,并设置一个callback_(StreamTexture::OnFrameAvailable),这个回调函数用于通知Chromium执行合成操作,gfx::SurfaceTexture则通过JNI 调用到java层的SurfaceTexturePlatformWrapper类,并设置一个SurfaceTextureListener,SurfaceTexturePlatformWrapper对象会创建一个android.graphics.SurfaceTexture,Chromium会设置该对象到MediaPlayer对象作为播放器的输出目标,同样SurfaceTextureListener对应的java类也会被设置到android.graphics.SurfaceTexture中。

当播放器把解码后的数据写到android.graphics.SurfaceTexture后,会调用SurfaceTextureListener的onFrameAvailable函数,然后通过JNI调用回native端的SurfaceTextureListener,执行前面设置的callback,也就是StreamTexture::OnFrameAvailable,在该函数中通过IPC发送到Render进程,响应该IPC消息的是StreamTextureHost::OnFrameAvailable,接着执行StreamTextureProxyImpl:: OnFrameAvailable,最终执行到cc::VideoFrameProvider::Client的DidReceiveFrame,开始执行合成操作。



  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值