Chromium为视频标签创建播放器的过程分析_第1页
Chromium为视频标签创建播放器的过程分析_第2页
Chromium为视频标签创建播放器的过程分析_第3页
Chromium为视频标签创建播放器的过程分析_第4页
Chromium为视频标签创建播放器的过程分析_第5页
已阅读5页,还剩34页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Chromium为视频标签创建播放器的过

程分析

Chromium为视频标签〈video〉创建播放器的过程分析Chromium是通过WebKit解析网页

内容的。当WebKit遇到〈video〉标签时,就会创建一个播放器实例。WebKit是平台无关的,

而播放器实现是平台相关的。因此,WebKit并没有自己实现播放器,而仅仅是创建一个播

放器接口。通过这个播放器接口,可以使用平台提供的播放器来播放视频的内容。这就简化

\Chromium对视频标签的支持。本文接下来就分析Chromium为视频标签创建播放器的过

程。

以Android平台为例,它的SDK提供了一个MediaPlayer接口,用来播放视频。

Chromium的目标就是为网页中的每一个<video>标签创建一个MediaPlayer实例,如图I所

示:

图1Chromum为,deci>标签创建MediaPlayg的过程

首先,WebKit会为网页中的每一个vvideo>标签创建一个类型为HTMLMediaElement的DOM

节点。HTMLMediaElement类内部有一个WcbMcdiaPlaycrClientlmpl接口。这个

WebMediaPlayerClienllnipl接口指向的是一个运行在Render进程的Content模块中的一个

WebMediaPlayerAndroid对象。这些WebMediaPlayerAndroid对象归一个称为

RendererMediaPayerManager的对象管理。

Render进程中的每一个WebMediaPlayerAndroid对象,在Browser进程中都有一个

对应的WebMediaPlayerBricige对象。这些WebMediaPlayerBridge对象归一个称为

BrowscrMcdiaPaycrManagcr的对象管理。每一个WebMediaPlayerBridge对象在Java层中又

都对应有一个MediaPlayer•对象。这些MediaPlayer对象描述的就是Android平台提供的播放

器。

接下来,我们就从WebKit解析〈video〉标签的属性开始,分析Chromium为它们创

建MediaPlayer的过程,如下所示:

[cppjviewplaincopy在CODE上查看代码片派生到我的代码片

voidHTMLMediaElement::parseAttribute(constQualifiedName&name,constAtomicString&

value)

(

if(name==srcAtti){

//Triggerareload,aslongasthe'src'attributeispresent.

if(lvalue.isNullO){

scheduleDelayedAction(LoadMediaResource);

这个函数定义在文件

external/chromium_org/thinl_party/WebKil/Sourcc/core/htnil/HTMLMcdiaElcmcnt.cpp中。

WebKit为网页的每一个标签创建了相应的DOM节点之后,就会调用这个DOM节

点的成员函数parseAlrribule对它的属性进行解析。从文章中一文可以容易知道,WebKit为

<video>标签创建的DOM节点的实际类型为HTMLVideoElementoHTMLVideoElement类是

从HTMLMediaElement类继承下来的,WebKit是调用后者的成同员函数parseAttribute来解

析〈video〉的属性。

我们假设Wide。〉标签通过src属性设置了要播放的视频文件的URL。这时候

HTMLMediaElement类的成员函数parseAttribute就会调用另外一个成员函数

scheduleDelayedAction为<video>标签创建播放器,如下所示:

[epp]viewplaincopy在CODE上杳看代码片派生到我的代码片

voidHTMLMediaElement::scheduleDelayedAction(DelayedActionTypeactionType)

if((actionType&LoadMediaResource)&&!(m_pendingAc(ionFlags&

LoadMediaResource)){

prepareForLoad();

m_pendingActionFlags|=LoadMediaResource;

if(!m_loadTimer.isActive())

m_loadTiiTier.siarOneShoc(0,FROM_HERE);

1

这个函数定义在文件

exteinal/chromium_org/third_party/WebKit/Source/core/html/HTMLMediaElement.cpp中。

从前面的调用过程可以知道,参数actionType的值等于LoadMediaResourceo这时候

如果HTMLMediaElement类的成员变量m_pendingAclionFlags的LoadMediaResource位等于

0,那么就说明WebKit还没有为当前正在解析的vvideo>标签创建过播放器接口。于是接下

来就会做两件事情:

I.调用另夕I'一个成员函数prepareForLoad开始为当前正在解析的〈video〉标签创建

图1所示的WebMediaPlayerClientlmpl接口:

2.将成员变量m_pendingActionFlags的LoadMediaResource位设置为1,表示WebKit

正在为当前正在:解析的<video>标签创建过播放器接口,避免接下来出现重复创建的情况。

HTMLMediaElement类的另外一个成员变量m」oadTimer描述的是一个定时器。如

果这个定时器还没有被启动,那么HTMLMediaElement类的成员函数scheduleDelayedAction

就会调用它的成员函数slarlOneShot马上进行启动。指定的启动时间单位为0,这意味着这

个定时器会马上超时。超时后它将会调用HTMLMediaElement类的成员函数loadTimcrFircd。

HTMLMediaElement类的成员函数loadTimerrired将会继续创建图1所示的

WebMediaPlayerAndroidWebMediaPlayerBridgeMediaPlayer接口。

接下来我们就先分析HTMLMediaElement类的成员函数prepareForLoad的实现,如

下所示:

[epp]viewplaincopy在CODE上查看代码片派生到我的代码片

voidHTMLMediaElement::prepareForLoad()

createMediaPlayer();

这个函数定义在文件

ex(ernal/chromium_org/(hird_party/WebKit/Source/core/htnil/HTMLMediaElemenl.cpp中。

HTMLMediaElement类的成员函数prepareForLoad主要是调用另外•个成员函数

createMediaPlayer为当前正在解析的<video>标签创建一个WebMediaPlayerClientlmpl接口,

如下所示:

[epp]viewplaincopy在CODE上查看代码片派生到我的代码片

voidHTMLMcdiaElcmcnt::crcatcMcdiaPlaycr()

ni_player=MediaPlayer::create(this);

层的播放器接口。

这一步执行完成之后,WebKit就为当前正在解析的<video>标签创建了一个类型为

WebMediaPlayerClienllnipl的播放器接口。回到前面分析的HTMLMediaElement类的成员函

数scheduleDelayedAction中,接下来它启动的定时器就会马上执行,也就

HTMLMediaElement类的成员函数loadTimerFired会马上被调用。

HTMLMediaElement类的成员函数loadTimerFired的实现如下所示:

[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片

voidHTMLMediaElemen(::loadTimerFired(Timer<HTMLMediaElement>*)

if(m_pendingActionFlags&LoadMediaResource){

if(m_loadState==LoadingFromSourceElement)

loadNcxtSoiirccChild();

else

loadlntcrnal();

)

m_pendingAc(ionFlag$=0;

}

这个函数定义在文件

exteinal/chromiuni_org/third_party/WebKit/Source/core/html/HTMLMediaElenient.cpp中。

前面分析的HTMLMediaElement类的成员函数scheduleDelayedAction已经将成员变

量m_pendingActionFlags的LoadMediaResource位设置为1。这时候HTMLMediaElement类

的成员函数loadTimerFired就会检查HTMLMediaElement类的另外一个成员变量

m_loadState的值是否等于LoadingFromSourceElement。如果等广,那么就说明当前正在解

析的〈video〉标签通过子元素〈source〉指定要播放的视频的URL。否则的话,就通过属性sre

指定要播放的视频的URL。

前面我们假定了当前正在解析的<vidco>标签通过属性sre指定要播放的视频的

URL,因此HTMLMediaElement类的成员函数loadTimerFired接下来就会调用成员函数

loadinternal继续为其创建其它的播放器接口,如下所示:

[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片

voidHTMLMediaElement:loadlntcrnalO

selectMediaResource();

这个函数定义在文件

ex(ernal/chromium_org/third_party/WzebKit/Source/core/htnil/HTMLMediaElernent.cpp中。

HTMLMediaElement类的成员函数loadlnternal调用另外一个成员函数

selectMediaResource为当前正在解析的<video>标签选择当前要播放的视频的URL“确定了

当前要播放的视频的URL之后,就会加载视频元数据。有了这些元数据之后,就可以为其

创建真正的播放器。

HTMLMediaElement类的成员函数selectMediaResource的实现如下所示:

[cpplviewplaincopy在CODE上查看代码片派生到我的代码片

voidHTMLMediaElement::selcctMcdiaResourcc()

enuniMode{attribute,children};

Modemode=attribute;

if(!fastiIasAttribu(e(srcAttr)){

//Otherwise,ifthemediaelementdoesnothaveasreattributebuthasasource

//elementchild,thenletmodebechildrenandletcandidatebe(hefirstsuch

//sourceelementchildintreeorder.

if(HTMLSourceElement*element

Traversal<HTMLSourceElement>::firstChild(*this)){

mode=children;

if(mode==attribute){

//Ifthesreattribute'svalueistheemptystring...jumpdowntothefailedstepbelow

KURLmediaURL=getNonEmptyURLAttribute(srcAttr);

loadResource(mediaURL,contentType,StringO);

return;

这个函数定义在文件

external/chroniiuin_org/third_party/WebKit/Source/core/htnil/HTMLMcdiaElcment.cpp中。

HTMLMediaElement类的成员函数selectMediaResource所做的事情就要确定是从当

前正在解析的<video>标签的src属性获得要加载的视频的URL,还是从它的了•元素(source〉

获得要加载的视频的URL。

如果当前正在解析的<video>标签设置了src属性,那么就会优先从这个属性获得要

加载的视频的URL。有了这个URL之后,HTMLMediaElement类的成员函数

selectMediaResource就会调用另外一个成员函数loadRcsourcc加载它所描述的视频的元数

据。

在我们这个情景中,当前正在解析的〈video〉标签设置了src属性。因此,接下来我

们就继续分析HTMLMediaElement类的成员函数loadResource的实现,如下所示:

[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片

voidHTMLMcdiaElcmcnt::loadRcsourcc(constK.URL&url,ContcntTypc&contcntTypc,const

String&keySystcm)

m_currentSrc=url;

boolattcmptLoad=true;

if(tocolIs(nicdiaSourccBlobProtocoi)){

if(isMediaStreamURL(url.stringO)){

m_usei-GestureRequiredForPlay=false;

}else{

m_mediaSource=HTMLMediaSource::lookup(url.string());

if(m_mediaSource){

if(!m_mcdiaSource->attachToElcmcnt(tliis)){

//ForgetourreferencetotheMediaSource,soweleaveitalone

//whileprocessingremainderofloadfailure.

m_mediaSource=nullptr;

attcmptLoad=false;

if(attempiLoad&&canLoadURL(ur),contentType,keySys(em)){

if(!m_havePreparedToPlay&&!autoplay()&&m_preload==MediaPlayer::None){

deferLoad();

}else{

starlPlayerLoadO;

这个函数定义在文件

external/chromium_org/third_party/WebKit/Source/core/html/HTMLMediaElemenl.cpp中。

HTMLMediaElement类的成员函数loadResource首先将当前要播放的视频的URL保

存在成员变量m_currentSrc中,接下来判断该URL的协议部分是否为“blob"。协议“blob”

是“BinaryLargeOBject”的缩写,表示一组二进制数据。例如,我们手头上有一组表示一

个Image的二进制数据,这时候可以调用URL.crcatcObjcctURL函数为这组二进制数据创建

一个blob协议地址,然后再将该地址设置为一个<img>标签的sre,这样就可以将图像显示

出来。

通过blob协议,还可以描述媒体数据。在WebKit中,媒体数据可以通过MediaSource

或者MediaStreamAPI描述。MediaSourceAPI的设计初衷是让JavaScript能动态产生媒体

流,然后交给〈video〉标签播放。MediaStreamAPI是为WebRTC设计的,不仅可以使用

<vidco>标签播放从本地摄像头采集的图像,还可以播放从网络发送过来的实时媒体流。关

于MediaSource和MediaSteamAPI的更详细信息,可以参考文章中和文章中这两篇文档。

如果当前要播放的视频的URL的协议部分为“blob",HTMLMediaElement类的成

员函数loadResource首先会检查它描述的是否是一个MediaStreamo如果是的话,那么就会

将HTMLMediaElement类的成员变量m_userGestureRequiredForPlay设置为false,表示后台

Tab网页的视频可以自动播放。Render进程有一个

udisable-gesture-requirement-for-media-playbackM选项。当这个选项的值设置为false时,

HTMLMediaElement类的成员变量m_userGestureRequiredForPlay就会被设置为true,表示

后台Tab网页的视频不可以自动播放。不过,如果要播放的视频是一个MediaStream,那么

不会受到此限制。关于Render进程的“disable-gesiure-requiremeni-「or-media-playback”启动

选项的更多信息,可以参考文章中一文。

如果当前要播放的视频的URL的协议部分为“blob”,但是它描述的不是一个Media

StreamAPI,那么HTMLMediaElement类的成员函数loadResource再检查它是否是一个Media

Sourceo如果是的话,就会将该MediaSource作为当前正在解析的〈video〉标签的播放源。

在这种情况卜,WebKit不需要从网络上下载媒体数据回来,只需要从指定的MediaSource

读取【可来就可以了。这时候木地变量auempiLoad的值会被设置为false。在其余情况下,木

地变量attemptLoad的值俣持为初始值true。

在本地变量attemptLoad的值为true的情况下,HTMLMediaElement类的成员函数

loadResource会调用另夕I、一'个成员函数canLoadURL继续检查当前要播放的视频的URL描

述的内容是否为多媒体数据,以及该多媒体使用的编码方式是否被支持。如果检查通过,

HTMLMediaElcmcnt类的成员函数loadResource再判断当前解析的<video>标签的是否需要

preload和autoplayo如果不需要,那么就会调用成员函数deferLoad延迟加载要播放的视频

的内容。否则的话,就会调用成员函数stailPlayerLoad马上加载要播放的视频的内容回来。

我们假设当前解析的<video>标签设置了autoplay,因此接下来我们就继续分析

HTMLMediaElenient类的成员函数startPlayerLoad的实现,如下所示:

[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片

voidHTMLMediaElemen(::startPlayerLoad()

KURLrequestURL=m_currentSrc;

m_playcr->load(loadType(),requcstURL,corsMode());

I

这个函数定义在文件

exteinal/chroniiuni_org/third_party/WebKit/Source/core/htnil/HTMLMediaElenient.cpp中。

从前面的分析可以知道,HTMLMediaElement类的成员变量m_player指向的是一个

WebMediaPlayerClienllmpl对象。HTMLMediaElement类的成员函数startPlayerLoad主要是

调用这个WcbMcdiaPlaycrClicntlmpl对象的成员函数load加载当前要播放的视频的内容。

WcbMcdiaPlaycrClientlmpl类的成员函数load的实现如卜所示:

[cpp]viewplaincopy在CODE1:查看代码片派生到我的代码片

voidWebMediaPlayerClientImpl::load(WebMediaPIayer::LoadTypeloadType,const

WTF::String&url,WebMediaPlayer::CORSModecorsMode)

KURLkurl(ParsedURLString,url);

ni_webMediaPlayer=createWebMediaPlayer(this,kurl,frame);

m_wcbMcdiaPlaycr->load(loadTypc,kurl,corsMode);

}

这个函数定义在文件

external/chromium_org/(hird_par(y/WebKit/Source/web/WebMediaPlayerClienlImpl.cpp中。

WebMediaPlayerClientlmpl类的成员函数load首先调用函数createWebMediaPiayer

请求运行在当前进程(Render进程)中的Comem模块创建一个播放器接口。这个Conleni

模块的播放器接口会保存在WebMediaPlayerClientlmpl类的成员变量m_webMediaPlayer中。

有了Content模块的播放器接口之后,WebMediaPlayerClientlmpI类的成员函数load再调用

它的成员函数load请求加载当前要播放的视频的内容。

接下来我们先分析Content模块的播放器接口的创建过程,也就是函数

createWebMediaPlayer的实现,如下所示:

[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片

staticPassOwnPtr<WebMediaPlayer>createWebMediaPlayer(WebMediaPlayerClient*client,

constWebURL&url,LocalFrame*frame)

(

WebLocalFramelmpl*webFrame=WebLocalFramelmpl::fromFrame(frame);

returnadoptPtr(webFraine->client()->createMediaPlayer(webFrame,url,client));

}

这个函数定义在文件

ex(ernal/chromium_org/third_party/WebKit/Source/web/WebMediaPlayei'ClientImpl.cpp中。

函数createWebMediaPlayer首先获得一个类型为blink::WcbFramcClient的接口。这

个接口是由WebKit的使用者设置给WebKit的,以便WcbKil可以通过它执行一些平台相关

的功能。在我们这个情景中,WebKit的使用者即为Render进程中的Content模块。Content

模块中的RenderFramelmpl类实现了该接口,并且会设置给WebKito因此,函数

createWebMediaPlayer接下来就会调用它的成员函数createMediaPlayer创建一个播放器接

□o

RenderFramelmpl类的成员函数crcatcMcdiaPlaycr的实现如下所示:

[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片

blink::WebMediaPlayer*RenderFramelmpl::createMediaPlayer(

blink::WebLocalFrame*frame,

constblink::WebURL&url,

blink::WebMediaPlayei'Client*client){

blink::WcbMcdiaStrcamwcb_strcam(

blink::WebMediaStreamRegistry::lookupMediaStreamDescriptor(url));

if(!wcb_strcain.isNull())

returnCreateWebMediaPlayerForMediaStream(url,client);

#ifdefined(OS_ANDR()ID)

returnCreateAndroidWebMediaPlayer(url,client);

#clse

#cndif//dcfincd(OS_ANDROID)

)

这个函数定义在文件external/chromium_org/content/renderer/render_franie_in)pl.cc

中。

RenderFramelmpl类的成员函数createMediaPlayer首先判断当前要播放的视频的

URL描述的是否是一个MediaStream。如果是的话,那么就会调用成员函数

CreateWebMediaPlayerForMediaStream创建一个类型为WebMediaPlayerMS的播放器。这个

类型为WebMediaPlayerMS的播放器是在WebRTC中实现的。我们不考虑这种情况。

如果当前要播放的视频的URL描述的不是一个MediaStream,那么RenderFramelmpl

类的成员函数createMediaPlayer就会调用另夕I、一个成员函数CreateAndroidWebMediaPlayer

创建另外一种类型的播放器,如下所示:

fcpp]viewplaincopy在CODE上查看代码片派生到我的代码片

WcbMcdiaPlaycr*RcndcrFraniclmpi::CrcatcAndroidWcbMediaPlaycr(

constblink::WebURL&url,

WebMediaPlayerClient*client){

GpuChannelHost*gpu_channel_hosl=

RenderThreadImpl::current()->EstablishGpuChannelSync(

CAUSE_FOR_GPU_LAUNCH_VIDEODECODEACCELERATOR_INITIALIZE);

scoped_refptr<S(rcamTextureractory>strcam_tcxturc_factory;

if(SynchronousComposiiorFactory*factory=

SynchronousCompositorFactory::GelInstance()){

stream_texture_factory=factory->CreateStreaniTextureFactory(routing_id_);

}else(

scoped_refptr<webkit::gpu::ContextProviderWebConteKt>context_provider=

RcndcrThrcadIinpl::currcnt()->SharcdMainThrcadContcxtProvidcr();

stream_texlure_faciory=SlreamTextureFactoryImp)::Create(

context_provider,gpu_channel_host,routing_id_);

)

returnnewWcbMcdiaPlaycrAndroid(

frame_,

client,

weak_factory_.GelWeakP(r(),

GetMediaPIayerManager(),

GetCdrnManager(),

stream_texture_factory,

RcndcrThrcadIinpl::currcnt()->GctMcdiaThrcadMessageLoopProxy(),

newRenderMediaLogO);

I

这个函数定义在文件extemal/chromiuin_org/content/renderer/render_frame_inipl.cc

中。

RenderFramelmpl类的成员函数CreateAndroidWebMediaPlayer首先是调用

RenderThreadlmpl类的成员函数EstablishGpuChannelSync为接下来要创建的播放器创建一

个到GPU进程的GPU通道。之所以要创建这个GPU通道,是因为Render要在GPU进程

中创建一个纹理,然后将这个纹理封装为一个SurfaceTexture,作为Android平台的

MediaPlayer的解码输出。也就是说,Render进程会通过这个SurfaceTexture接收Android平

台的MediaPlayer的解码输出,然后再以纹理的形式渲染在网贝上。GPU通道的创建过程,

也就是RenderThreadlinpl类的成员函数EstablishGpuChannelSync的实现,可以参考前面文

章中一文。

RenderFramelrnpl类的成员函数CreateAndroidWsbMediaPlayer最终创建的是一个类

型为WebMediaPlayerAndroid的播放器。创建这个类型为WebMediaPlayerAndroid的播放器

需要用到两个重要的对象。一个是StrcamTexturcFactory对象,另一个是

RendererMediaPlayerManage「对象。前者用来创建前面所述的纹理。后者用来管理在Render

进程中创建的播放器实例,

在WebView的情况下,调用SynchronousCompositorFactory类的静态成员函数

Getlnstance会获得一个SynchronousCompositorFactory对象。在这种情况下,上述

StreaniTextureFactory对象通过调用这个SynchronousCompositorFactory对象的成员函数

CrcatcStrcamTcxtureFactory获得。我们不考虑这一种情况。

在独立App的情况下,上述StreaniTextureFactory对象实际上是一个

SlreamTexlureFactorylmpl对象,它是通过调用StreamTexlureFactorylnipl类的静态成员函数

Create创建的,如下所示:

[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片

scopcd_rcfptr<StrcamTcxturcFactoryImpl>StrcamTcxturcFactoryhnpl::Crcatc(

constscoped_refptr<cc::ContextProvider>&context_provider,

GpuChannclHost*channel,

iniframe_id){

returnnewStreamTextureFactoryImpl(context_provider,channel,frame_id);

)

这个函数定义在文件

cxtcrnal/chromium_org/contcnt/rcndcrcr/mcdia/android/strcam_tcxturc_factory_iinpl.cc

从这里可以看到,StreamTextureFactoryImpI类论静态成员函数Create返回的是一个

StrcamTcxtureFactorylmpl对象。

回到前面分析的RenderFramelrnpl类的成员函数CreateAndroidWebMediaPlayer中,

它创建了一个StreamTextureFactoryImpI对象之后,接下来又会调用另外一个成员函数

GetMediaPlayerManager获得一个RendererMediaPlayerManager对象,如下所示:

[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片

RendererMediaPlayerManager*RcndcrFraincImpl::GctMcdiaPlaycrManagcr(){

if(!media_player_manager_){

media_player_inanager_=newRendererMediaPlayerManager(this);

returninedia_player_manager_;

这个函数定义在文件external/chromium_org/content/renderer/render_frame_impLcc

中。

从这里可以看到,RenderFramelmpI类的成员函数GetMediaPlayerManager返回的是

成员变量media_player_manager_指向的是一个RendererMediaPIayerManager对象。如果这个

RendererMediaPlayerManager对象还没有创建,那么就会先进行创建。

再回到前面分析的RenderFramelmpI类的成员函数CreateAndroidWebMediaPlayer

中,有了一个StreamTcxtureFactorjdinpl对象和一个RendererMediaPlayerManager对象之后,

它就会创建一个类型为WebMediaPlayerAndroid的播放器。

类型为WebMediaPlayerAndroid的播放器的创建过程,也就是

WebMediaPlayerAndroid类的构造函数的实现,如下所示:

[epp]viewplaincopy在CODE上查看代码片派生到我的代码片

WcbMcdiaPlaycr/Xndroid::\VcbMcdiaPlaycrAndroid(

blink:WcbFramc*frame,

blink::WcbMcdiaPlayci'Client*client,

base::WeakP(r<WebMediaPlayerDelegate>delegate,

RendererMediaPlayerManager*player_manager,

RendererCdmManager*cdm_manager,

scoped_refptr<StreamTextureFactory>factory,

constscopcd_rcfptr<basc::McssagcLoopProxy>&mcdia_loop,

media::MediaLog*media_log)

player_manager_(player_manager),

stream_texture_factory_(factory),

player_id_=player_manager_->RegislerMediaPlayer(lhis);

T^CreateStreamTextureProxylfNeededO;

)

这个函数定义在文件

cxtcrnal/chroinium_org/contcnt/rcndcrcr/mcdia/android/wcbmcdiaplaycr_android.cc「我。

WebMediaPlayerAndroid类的构造函数首先是将参数player_manager和factory描述

的StreamTextureFactorylmpl对象和RendererMediaPlayerManager对象分别保存在成员变量

player_manager_和siream」exture_faclory_中。

WebMediaPlayerAndroid类的构造函数接下来又会做两件事情:

I.调用上述RendererMcdiaPlayerManager对象的成员函数RcgisterMediaPlayer将当

前正在创建的WebMediaPlayerAndroid对象保存在其内部,并且为其分配一个ID。以后通

过这个ID就可以在该RendererMcdiaPlayerManager对象中找到当前正在创建的

WebMediaPlayerAndroid对象。

2.调用另外一个成员函数TryCreateStreainTextureProxylfNeeded创建一个

SurfaceTexture,以便后面可以用来接收Android平台的MediaPlayer的解码输出。

关于WebMediaPlayerAndroid类的成员函数TryCrealeStreamTextureProxyHNeeded创

建SurfaceTexture的过程,我们在接下来一篇文章中分析〈video,标签的视频渲染过程时再分

析。

这一步执行完成之后,运行在Render进程中的Conient模块就创建了一个类型为

WebMediaPlayerAndroid的播放器接口。这个播放器接口会返回给WebKit层的

WcbMcdiaPlaycrClicntlmpI类的成员函数load。WebMediaPlayerClientlmpl类的成员函数load

获得了这个播放器接口之后,就会调用它的成员函数load加载当前要播放的视频的内容,

如下所示:

[cpp]viewplaincopy在CODE1:查看代码片派生到我的代码片

voidWebMediaPlayerAndroid::load(LoadTypeload_type,

constblink::WebURL&url,

CORSModccors_modc){

switch(load_type){

caseLoadTypeURL:

player_type_=MEDIA_PLAYER_TYPE_URL;

break;

caseLoadTypeMediaSource:

player_type_=MEDIA_PLAYER_TYPE_MEDIA_SOURCE;

break;

caseLoadTypeMediaStream:

CHECK(false)«"WebMediaPlayerAndroiddoesn'tsupportMediaStreamon

"thisplatform";

return;

1

url_=url:

inidemuxer_clien(_id=0;

if(player_type_!=MEDIA_PLAYER_TYPE_URL){

RendererDemuxerAndroid*demuxer=

RenderThreadImpl::current()->ienderer_demuxer();

deniuxer_client_id=demuxer->GetNextDcmuxerClientID();

niedia_souice_delegate_.reset(newMediaSourceDelegate(

demuxer,demuxer_client_id,media_loop_,media_log_));

if(player_type_==MEDIA_PLAYER_TYPE_MEDIA_SOURCE){

media::SetDec^ptorReadyCBset_decryptor_ready_cb=

media::BindToCurrentLoop(

base::Bind(&WebMediaPlayerAndroid::SeiDecryp(orReadyCB,

weak_factory_.GetWeakPtr()));

media_source_delegate_->InitializeMediaSource(

base::Bind(&WebMediaPlayerAndroid::OnMediaSourceOpened,

ueak_factory_.GetWeakPtr()),

basc::Bind(&WcbMcdiaPlaycrAndroid::OnNccdKcy,

vveak_factory_.GclWcakPtr()),

set_decrjzptor_ready_cb,

base::Bind(&WebMediaPlayerAndroid::UpdateNetworkState,

vveak_factory_.GetWeakPtr()),

base::Bind(&WebMediaPlayerAndroid::OnDurationChanged,

ueak_factory_.GetWeakPtr()));

InitializcPlaycr(url_,framc_->documcnt().firstPartyForCookics(),

true,demuxer_client_id);

}else(

info」oader_.reset(

newMediaInfbLoader(

url,

cors_modc,

base::Bind(&WebMediaPlayerAndroid::DidLoadMediaInfo,

wcak_factory_.GctWcakPtr())));

info」oader_->Slarl(frame_);

这个函数定义在文件

cxtcrnal/chromium_org/contcnt/rcndcrcr/mcdia/android/wcbincdiaplaycr_android.cc「我。

类型为WebMediaPlayerAndroid的播放器只能史理普通URL描述的媒体流,以及

BLOB协议描述的类型为MediaSource的媒体流,不能处理类型为MediaStream的媒体流

(需要由WebRTC处理)。

类型为MediaSource的媒体流数据直接从指定的MediaSource获得。

WebMediaPlayerAndroid类的成员函数load将该MediaSource封装在一个

MediaSourceDelegate对象中,然后通过这个McdiaSourceDclegate对象来获得要播放的视频

的元数据。有了要播放的视频的元数据之后,就可以调用WebMediaPlayerAndroid类的成员

函数InitializePlayer初始化当前正在处理的播放器。

我们假设当前要播放的视频的URL是一个普通的URL,它描述的媒体流的元数据

要通过一个MedialnfoLoader对象从网络上下载回来。下载完成后,WebMediaPlayerAndroid

类的成员函数DidLoadMedialnfo会被调用,它的实现如下所示:

[cpplviewplaincopy在CODE上查看代码片派生到我的代码片

voidWebMediaPlayerAndroid::DidLoadMediaInfo(

MediainfbLoader::Slatusstatus,

constGURL&redirected_url,

constGURL&first_party_for_cookies,

boolallow_stored_credentials){

InitializePlayer(

redirected_url,first_party_for_cookies,allow_stored_credentials,0);

这个函数定义在文件

exteinal/chromium_org/content/renderer/media/android/webmecliaplayer_android.cc中。

WebMediaPlayerAndroid类的成员函数DidLoadMedialnfo会用卜载回来的视频元数

据初始化当前正在处理的播放器。这同样是通过调用WebMediaPlayerAndroid类的成员函数

InitializePlayer进行的,如下所示:

fepp]viewplaincopy在CODE上查看代码片派生到我的代码片

voidWcbMcdiaPlaycrAndroid::InitializcPlaycr(

constGURL&url,

constGURL&first_paiiy_for_cookies,

boolallow_stored_credenlials,

intdemuxer_client_id){

player_manager_->Initialize(

player_type_,player_id_,url,first_party_for_cookies,dcmuxcr_clicnt_id,

frame_->document(>.url(),allow_stored_credentials);

这个函数定义在文件

ex(ernal/chromium_org/content/renderer/media/android/webmediaplayer_android.cc中。

从前面的分析可以知道,WebMediaPlayerAndroid类的成员变量player_manager_指

向的是一个RendererMediaPlayerManager对象。WebMediaPlayerAndroid类的成员函数

InitializePlayer调用这个RendererMediaPlayerManager对象的成员函数Initialize对当前正在

处理的播放器进行初始化,如下所示:

[cpp]viewplaincopy在CODE1:查看代码片派生到我的代码片

voidRendererMediaPlayerManager::Initialize(

MediaPlayerHostMsg_Initialize_Typetype.

intplayer_id,

constGURL&url,

constGURL&first_party_for_cookies,

inidemuxer_client_id,

constGURL&frame_url,

boolallow_credentials){

MediaPlayerHostMsg_Initialize_Paramsmedia_player_params;

media_player_params.type=type;

media_player_params.player_id=player_id;

mcdia_playcr_params.dcmuxcr_clicnt_id=dcmuxcr_clicnt_id;

mcdia_player_params.url=url;

media_player_params.first_party_for_cookies=first_party_for_cookies;

media_player_params.frame_url=frame_url;

media_player_params.albw_credentials=allow_credentials;

Send(newMediaPlayerHDstMsg_Initialize(routing_id().niedia_player_params));

)

这个函数定义在文件

cxtcrnal/chroniium_org/contcnt/rcndcrcr/mcdia/android/rcndcrcr_incdia_playcr_managcr.cc

RendererMediaPlayerManager^Initialize向Browser进程发送一个类型

为MediaPlayerHostMsg_Initialize的IPC消息,用来请求Browser进程为当前正在处理的类

型为WebMediaPlayerAndroid的播放器创建一个由Android平台实现的播放器。

Browser进程是通过McdiaWcbContcntsObscrvcr类的成员函数

OnMediaPlayerMessageReceived接收类型为MediaPlayerHostMsg_Initialize的IPC消息的,

如下所示:

[cpp]viewplaincopy在CODE1:查看代码片派生到我的代码片

boolMediaWebContentsObserver::OnMediaPlayerMessageReceived(

constIPC::Message&msg,

RcndcrFrameHost*rcndcr_framc_host){

boolhandled=true;

IPC_BEGIN_MESSAGE_MAP(McdiaWcbContcntsObscrvcr,msg)

IPC_MESSAGE_FORWARD(MediaPlayerHostMsg_Initialize,

GelMediaPlayerManager(rendsr_frame_hosl),

IPC_MESSAGE_UNHANDLED(handled=false)

IPC_END_MESSAGE_MAP()

returnhandled;

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论