Chromium為視頻標簽創(chuàng)建播放器的過程分析_第1頁
Chromium為視頻標簽創(chuàng)建播放器的過程分析_第2頁
Chromium為視頻標簽創(chuàng)建播放器的過程分析_第3頁
Chromium為視頻標簽創(chuàng)建播放器的過程分析_第4頁
Chromium為視頻標簽創(chuàng)建播放器的過程分析_第5頁
已閱讀5頁,還剩34頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

Chromium為視頻標簽創(chuàng)建播放器的過

程分析

Chromium為視頻標簽〈video〉創(chuàng)建播放器的過程分析Chromium是通過WebKit解析網(wǎng)頁

內(nèi)容的。當WebKit遇到〈video〉標簽時,就會創(chuàng)建一個播放器實例。WebKit是平臺無關(guān)的,

而播放器實現(xiàn)是平臺相關(guān)的。因此,WebKit并沒有自己實現(xiàn)播放器,而僅僅是創(chuàng)建一個播

放器接口。通過這個播放器接口,可以使用平臺提供的播放器來播放視頻的內(nèi)容。這就簡化

\Chromium對視頻標簽的支持。本文接下來就分析Chromium為視頻標簽創(chuàng)建播放器的過

程。

以Android平臺為例,它的SDK提供了一個MediaPlayer接口,用來播放視頻。

Chromium的目標就是為網(wǎng)頁中的每一個<video>標簽創(chuàng)建一個MediaPlayer實例,如圖I所

示:

圖1Chromum為,deci>標簽創(chuàng)建MediaPlayg的過程

首先,WebKit會為網(wǎng)頁中的每一個vvideo>標簽創(chuàng)建一個類型為HTMLMediaElement的DOM

節(jié)點。HTMLMediaElement類內(nèi)部有一個WcbMcdiaPlaycrClientlmpl接口。這個

WebMediaPlayerClienllnipl接口指向的是一個運行在Render進程的Content模塊中的一個

WebMediaPlayerAndroid對象。這些WebMediaPlayerAndroid對象歸一個稱為

RendererMediaPayerManager的對象管理。

Render進程中的每一個WebMediaPlayerAndroid對象,在Browser進程中都有一個

對應(yīng)的WebMediaPlayerBricige對象。這些WebMediaPlayerBridge對象歸一個稱為

BrowscrMcdiaPaycrManagcr的對象管理。每一個WebMediaPlayerBridge對象在Java層中又

都對應(yīng)有一個MediaPlayer?對象。這些MediaPlayer對象描述的就是Android平臺提供的播放

器。

接下來,我們就從WebKit解析〈video〉標簽的屬性開始,分析Chromium為它們創(chuàng)

建MediaPlayer的過程,如下所示:

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

voidHTMLMediaElement::parseAttribute(constQualifiedName&name,constAtomicString&

value)

(

if(name==srcAtti){

//Triggerareload,aslongasthe'src'attributeispresent.

if(lvalue.isNullO){

scheduleDelayedAction(LoadMediaResource);

這個函數(shù)定義在文件

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

WebKit為網(wǎng)頁的每一個標簽創(chuàng)建了相應(yīng)的DOM節(jié)點之后,就會調(diào)用這個DOM節(jié)

點的成員函數(shù)parseAlrribule對它的屬性進行解析。從文章中一文可以容易知道,WebKit為

<video>標簽創(chuàng)建的DOM節(jié)點的實際類型為HTMLVideoElementoHTMLVideoElement類是

從HTMLMediaElement類繼承下來的,WebKit是調(diào)用后者的成同員函數(shù)parseAttribute來解

析〈video〉的屬性。

我們假設(shè)Wide?!禈撕炌ㄟ^src屬性設(shè)置了要播放的視頻文件的URL。這時候

HTMLMediaElement類的成員函數(shù)parseAttribute就會調(diào)用另外一個成員函數(shù)

scheduleDelayedAction為<video>標簽創(chuàng)建播放器,如下所示:

[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

這個函數(shù)定義在文件

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

從前面的調(diào)用過程可以知道,參數(shù)actionType的值等于LoadMediaResourceo這時候

如果HTMLMediaElement類的成員變量m_pendingAclionFlags的LoadMediaResource位等于

0,那么就說明WebKit還沒有為當前正在解析的vvideo>標簽創(chuàng)建過播放器接口。于是接下

來就會做兩件事情:

I.調(diào)用另夕I'一個成員函數(shù)prepareForLoad開始為當前正在解析的〈video〉標簽創(chuàng)建

圖1所示的WebMediaPlayerClientlmpl接口:

2.將成員變量m_pendingActionFlags的LoadMediaResource位設(shè)置為1,表示W(wǎng)ebKit

正在為當前正在:解析的<video>標簽創(chuàng)建過播放器接口,避免接下來出現(xiàn)重復(fù)創(chuàng)建的情況。

HTMLMediaElement類的另外一個成員變量m」oadTimer描述的是一個定時器。如

果這個定時器還沒有被啟動,那么HTMLMediaElement類的成員函數(shù)scheduleDelayedAction

就會調(diào)用它的成員函數(shù)slarlOneShot馬上進行啟動。指定的啟動時間單位為0,這意味著這

個定時器會馬上超時。超時后它將會調(diào)用HTMLMediaElement類的成員函數(shù)loadTimcrFircd。

HTMLMediaElement類的成員函數(shù)loadTimerrired將會繼續(xù)創(chuàng)建圖1所示的

WebMediaPlayerAndroidWebMediaPlayerBridgeMediaPlayer接口。

接下來我們就先分析HTMLMediaElement類的成員函數(shù)prepareForLoad的實現(xiàn),如

下所示:

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

voidHTMLMediaElement::prepareForLoad()

createMediaPlayer();

這個函數(shù)定義在文件

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

HTMLMediaElement類的成員函數(shù)prepareForLoad主要是調(diào)用另外?個成員函數(shù)

createMediaPlayer為當前正在解析的<video>標簽創(chuàng)建一個WebMediaPlayerClientlmpl接口,

如下所示:

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

voidHTMLMcdiaElcmcnt::crcatcMcdiaPlaycr()

ni_player=MediaPlayer::create(this);

層的播放器接口。

這一步執(zhí)行完成之后,WebKit就為當前正在解析的<video>標簽創(chuàng)建了一個類型為

WebMediaPlayerClienllnipl的播放器接口?;氐角懊娣治龅腍TMLMediaElement類的成員函

數(shù)scheduleDelayedAction中,接下來它啟動的定時器就會馬上執(zhí)行,也就

HTMLMediaElement類的成員函數(shù)loadTimerFired會馬上被調(diào)用。

HTMLMediaElement類的成員函數(shù)loadTimerFired的實現(xiàn)如下所示:

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

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

if(m_pendingActionFlags&LoadMediaResource){

if(m_loadState==LoadingFromSourceElement)

loadNcxtSoiirccChild();

else

loadlntcrnal();

)

m_pendingAc(ionFlag$=0;

}

這個函數(shù)定義在文件

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

前面分析的HTMLMediaElement類的成員函數(shù)scheduleDelayedAction已經(jīng)將成員變

量m_pendingActionFlags的LoadMediaResource位設(shè)置為1。這時候HTMLMediaElement類

的成員函數(shù)loadTimerFired就會檢查HTMLMediaElement類的另外一個成員變量

m_loadState的值是否等于LoadingFromSourceElement。如果等廣,那么就說明當前正在解

析的〈video〉標簽通過子元素〈source〉指定要播放的視頻的URL。否則的話,就通過屬性sre

指定要播放的視頻的URL。

前面我們假定了當前正在解析的<vidco>標簽通過屬性sre指定要播放的視頻的

URL,因此HTMLMediaElement類的成員函數(shù)loadTimerFired接下來就會調(diào)用成員函數(shù)

loadinternal繼續(xù)為其創(chuàng)建其它的播放器接口,如下所示:

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

voidHTMLMediaElement:loadlntcrnalO

selectMediaResource();

這個函數(shù)定義在文件

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

HTMLMediaElement類的成員函數(shù)loadlnternal調(diào)用另外一個成員函數(shù)

selectMediaResource為當前正在解析的<video>標簽選擇當前要播放的視頻的URL“確定了

當前要播放的視頻的URL之后,就會加載視頻元數(shù)據(jù)。有了這些元數(shù)據(jù)之后,就可以為其

創(chuàng)建真正的播放器。

HTMLMediaElement類的成員函數(shù)selectMediaResource的實現(xiàn)如下所示:

[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;

這個函數(shù)定義在文件

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

HTMLMediaElement類的成員函數(shù)selectMediaResource所做的事情就要確定是從當

前正在解析的<video>標簽的src屬性獲得要加載的視頻的URL,還是從它的了?元素(source〉

獲得要加載的視頻的URL。

如果當前正在解析的<video>標簽設(shè)置了src屬性,那么就會優(yōu)先從這個屬性獲得要

加載的視頻的URL。有了這個URL之后,HTMLMediaElement類的成員函數(shù)

selectMediaResource就會調(diào)用另外一個成員函數(shù)loadRcsourcc加載它所描述的視頻的元數(shù)

據(jù)。

在我們這個情景中,當前正在解析的〈video〉標簽設(shè)置了src屬性。因此,接下來我

們就繼續(xù)分析HTMLMediaElement類的成員函數(shù)loadResource的實現(xiàn),如下所示:

[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;

這個函數(shù)定義在文件

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

HTMLMediaElement類的成員函數(shù)loadResource首先將當前要播放的視頻的URL保

存在成員變量m_currentSrc中,接下來判斷該URL的協(xié)議部分是否為“blob"。協(xié)議“blob”

是“BinaryLargeOBject”的縮寫,表示一組二進制數(shù)據(jù)。例如,我們手頭上有一組表示一

個Image的二進制數(shù)據(jù),這時候可以調(diào)用URL.crcatcObjcctURL函數(shù)為這組二進制數(shù)據(jù)創(chuàng)建

一個blob協(xié)議地址,然后再將該地址設(shè)置為一個<img>標簽的sre,這樣就可以將圖像顯示

出來。

通過blob協(xié)議,還可以描述媒體數(shù)據(jù)。在WebKit中,媒體數(shù)據(jù)可以通過MediaSource

或者MediaStreamAPI描述。MediaSourceAPI的設(shè)計初衷是讓JavaScript能動態(tài)產(chǎn)生媒體

流,然后交給〈video〉標簽播放。MediaStreamAPI是為WebRTC設(shè)計的,不僅可以使用

<vidco>標簽播放從本地攝像頭采集的圖像,還可以播放從網(wǎng)絡(luò)發(fā)送過來的實時媒體流。關(guān)

于MediaSource和MediaSteamAPI的更詳細信息,可以參考文章中和文章中這兩篇文檔。

如果當前要播放的視頻的URL的協(xié)議部分為“blob",HTMLMediaElement類的成

員函數(shù)loadResource首先會檢查它描述的是否是一個MediaStreamo如果是的話,那么就會

將HTMLMediaElement類的成員變量m_userGestureRequiredForPlay設(shè)置為false,表示后臺

Tab網(wǎng)頁的視頻可以自動播放。Render進程有一個

udisable-gesture-requirement-for-media-playbackM選項。當這個選項的值設(shè)置為false時,

HTMLMediaElement類的成員變量m_userGestureRequiredForPlay就會被設(shè)置為true,表示

后臺Tab網(wǎng)頁的視頻不可以自動播放。不過,如果要播放的視頻是一個MediaStream,那么

不會受到此限制。關(guān)于Render進程的“disable-gesiure-requiremeni-「or-media-playback”啟動

選項的更多信息,可以參考文章中一文。

如果當前要播放的視頻的URL的協(xié)議部分為“blob”,但是它描述的不是一個Media

StreamAPI,那么HTMLMediaElement類的成員函數(shù)loadResource再檢查它是否是一個Media

Sourceo如果是的話,就會將該MediaSource作為當前正在解析的〈video〉標簽的播放源。

在這種情況卜,WebKit不需要從網(wǎng)絡(luò)上下載媒體數(shù)據(jù)回來,只需要從指定的MediaSource

讀取【可來就可以了。這時候木地變量auempiLoad的值會被設(shè)置為false。在其余情況下,木

地變量attemptLoad的值俁持為初始值true。

在本地變量attemptLoad的值為true的情況下,HTMLMediaElement類的成員函數(shù)

loadResource會調(diào)用另夕I、一'個成員函數(shù)canLoadURL繼續(xù)檢查當前要播放的視頻的URL描

述的內(nèi)容是否為多媒體數(shù)據(jù),以及該多媒體使用的編碼方式是否被支持。如果檢查通過,

HTMLMediaElcmcnt類的成員函數(shù)loadResource再判斷當前解析的<video>標簽的是否需要

preload和autoplayo如果不需要,那么就會調(diào)用成員函數(shù)deferLoad延遲加載要播放的視頻

的內(nèi)容。否則的話,就會調(diào)用成員函數(shù)stailPlayerLoad馬上加載要播放的視頻的內(nèi)容回來。

我們假設(shè)當前解析的<video>標簽設(shè)置了autoplay,因此接下來我們就繼續(xù)分析

HTMLMediaElenient類的成員函數(shù)startPlayerLoad的實現(xiàn),如下所示:

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

voidHTMLMediaElemen(::startPlayerLoad()

KURLrequestURL=m_currentSrc;

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

I

這個函數(shù)定義在文件

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

從前面的分析可以知道,HTMLMediaElement類的成員變量m_player指向的是一個

WebMediaPlayerClienllmpl對象。HTMLMediaElement類的成員函數(shù)startPlayerLoad主要是

調(diào)用這個WcbMcdiaPlaycrClicntlmpl對象的成員函數(shù)load加載當前要播放的視頻的內(nèi)容。

WcbMcdiaPlaycrClientlmpl類的成員函數(shù)load的實現(xiàn)如卜所示:

[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);

}

這個函數(shù)定義在文件

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

WebMediaPlayerClientlmpl類的成員函數(shù)load首先調(diào)用函數(shù)createWebMediaPiayer

請求運行在當前進程(Render進程)中的Comem模塊創(chuàng)建一個播放器接口。這個Conleni

模塊的播放器接口會保存在WebMediaPlayerClientlmpl類的成員變量m_webMediaPlayer中。

有了Content模塊的播放器接口之后,WebMediaPlayerClientlmpI類的成員函數(shù)load再調(diào)用

它的成員函數(shù)load請求加載當前要播放的視頻的內(nèi)容。

接下來我們先分析Content模塊的播放器接口的創(chuàng)建過程,也就是函數(shù)

createWebMediaPlayer的實現(xiàn),如下所示:

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

staticPassOwnPtr<WebMediaPlayer>createWebMediaPlayer(WebMediaPlayerClient*client,

constWebURL&url,LocalFrame*frame)

(

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

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

}

這個函數(shù)定義在文件

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

函數(shù)createWebMediaPlayer首先獲得一個類型為blink::WcbFramcClient的接口。這

個接口是由WebKit的使用者設(shè)置給WebKit的,以便WcbKil可以通過它執(zhí)行一些平臺相關(guān)

的功能。在我們這個情景中,WebKit的使用者即為Render進程中的Content模塊。Content

模塊中的RenderFramelmpl類實現(xiàn)了該接口,并且會設(shè)置給WebKito因此,函數(shù)

createWebMediaPlayer接下來就會調(diào)用它的成員函數(shù)createMediaPlayer創(chuàng)建一個播放器接

□o

RenderFramelmpl類的成員函數(shù)crcatcMcdiaPlaycr的實現(xiàn)如下所示:

[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)

)

這個函數(shù)定義在文件external/chromium_org/content/renderer/render_franie_in)pl.cc

中。

RenderFramelmpl類的成員函數(shù)createMediaPlayer首先判斷當前要播放的視頻的

URL描述的是否是一個MediaStream。如果是的話,那么就會調(diào)用成員函數(shù)

CreateWebMediaPlayerForMediaStream創(chuàng)建一個類型為WebMediaPlayerMS的播放器。這個

類型為WebMediaPlayerMS的播放器是在WebRTC中實現(xiàn)的。我們不考慮這種情況。

如果當前要播放的視頻的URL描述的不是一個MediaStream,那么RenderFramelmpl

類的成員函數(shù)createMediaPlayer就會調(diào)用另夕I、一個成員函數(shù)CreateAndroidWebMediaPlayer

創(chuàng)建另外一種類型的播放器,如下所示:

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

這個函數(shù)定義在文件extemal/chromiuin_org/content/renderer/render_frame_inipl.cc

中。

RenderFramelmpl類的成員函數(shù)CreateAndroidWebMediaPlayer首先是調(diào)用

RenderThreadlmpl類的成員函數(shù)EstablishGpuChannelSync為接下來要創(chuàng)建的播放器創(chuàng)建一

個到GPU進程的GPU通道。之所以要創(chuàng)建這個GPU通道,是因為Render要在GPU進程

中創(chuàng)建一個紋理,然后將這個紋理封裝為一個SurfaceTexture,作為Android平臺的

MediaPlayer的解碼輸出。也就是說,Render進程會通過這個SurfaceTexture接收Android平

臺的MediaPlayer的解碼輸出,然后再以紋理的形式渲染在網(wǎng)貝上。GPU通道的創(chuàng)建過程,

也就是RenderThreadlinpl類的成員函數(shù)EstablishGpuChannelSync的實現(xiàn),可以參考前面文

章中一文。

RenderFramelrnpl類的成員函數(shù)CreateAndroidWsbMediaPlayer最終創(chuàng)建的是一個類

型為WebMediaPlayerAndroid的播放器。創(chuàng)建這個類型為WebMediaPlayerAndroid的播放器

需要用到兩個重要的對象。一個是StrcamTexturcFactory對象,另一個是

RendererMediaPlayerManage「對象。前者用來創(chuàng)建前面所述的紋理。后者用來管理在Render

進程中創(chuàng)建的播放器實例,

在WebView的情況下,調(diào)用SynchronousCompositorFactory類的靜態(tài)成員函數(shù)

Getlnstance會獲得一個SynchronousCompositorFactory對象。在這種情況下,上述

StreaniTextureFactory對象通過調(diào)用這個SynchronousCompositorFactory對象的成員函數(shù)

CrcatcStrcamTcxtureFactory獲得。我們不考慮這一種情況。

在獨立App的情況下,上述StreaniTextureFactory對象實際上是一個

SlreamTexlureFactorylmpl對象,它是通過調(diào)用StreamTexlureFactorylnipl類的靜態(tài)成員函數(shù)

Create創(chuàng)建的,如下所示:

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

scopcd_rcfptr<StrcamTcxturcFactoryImpl>StrcamTcxturcFactoryhnpl::Crcatc(

constscoped_refptr<cc::ContextProvider>&context_provider,

GpuChannclHost*channel,

iniframe_id){

returnnewStreamTextureFactoryImpl(context_provider,channel,frame_id);

)

這個函數(shù)定義在文件

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

從這里可以看到,StreamTextureFactoryImpI類論靜態(tài)成員函數(shù)Create返回的是一個

StrcamTcxtureFactorylmpl對象。

回到前面分析的RenderFramelrnpl類的成員函數(shù)CreateAndroidWebMediaPlayer中,

它創(chuàng)建了一個StreamTextureFactoryImpI對象之后,接下來又會調(diào)用另外一個成員函數(shù)

GetMediaPlayerManager獲得一個RendererMediaPlayerManager對象,如下所示:

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

RendererMediaPlayerManager*RcndcrFraincImpl::GctMcdiaPlaycrManagcr(){

if(!media_player_manager_){

media_player_inanager_=newRendererMediaPlayerManager(this);

returninedia_player_manager_;

這個函數(shù)定義在文件external/chromium_org/content/renderer/render_frame_impLcc

中。

從這里可以看到,RenderFramelmpI類的成員函數(shù)GetMediaPlayerManager返回的是

成員變量media_player_manager_指向的是一個RendererMediaPIayerManager對象。如果這個

RendererMediaPlayerManager對象還沒有創(chuàng)建,那么就會先進行創(chuàng)建。

再回到前面分析的RenderFramelmpI類的成員函數(shù)CreateAndroidWebMediaPlayer

中,有了一個StreamTcxtureFactorjdinpl對象和一個RendererMediaPlayerManager對象之后,

它就會創(chuàng)建一個類型為WebMediaPlayerAndroid的播放器。

類型為WebMediaPlayerAndroid的播放器的創(chuàng)建過程,也就是

WebMediaPlayerAndroid類的構(gòu)造函數(shù)的實現(xiàn),如下所示:

[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;

)

這個函數(shù)定義在文件

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

WebMediaPlayerAndroid類的構(gòu)造函數(shù)首先是將參數(shù)player_manager和factory描述

的StreamTextureFactorylmpl對象和RendererMediaPlayerManager對象分別保存在成員變量

player_manager_和siream」exture_faclory_中。

WebMediaPlayerAndroid類的構(gòu)造函數(shù)接下來又會做兩件事情:

I.調(diào)用上述RendererMcdiaPlayerManager對象的成員函數(shù)RcgisterMediaPlayer將當

前正在創(chuàng)建的WebMediaPlayerAndroid對象保存在其內(nèi)部,并且為其分配一個ID。以后通

過這個ID就可以在該RendererMcdiaPlayerManager對象中找到當前正在創(chuàng)建的

WebMediaPlayerAndroid對象。

2.調(diào)用另外一個成員函數(shù)TryCreateStreainTextureProxylfNeeded創(chuàng)建一個

SurfaceTexture,以便后面可以用來接收Android平臺的MediaPlayer的解碼輸出。

關(guān)于WebMediaPlayerAndroid類的成員函數(shù)TryCrealeStreamTextureProxyHNeeded創(chuàng)

建SurfaceTexture的過程,我們在接下來一篇文章中分析〈video,標簽的視頻渲染過程時再分

析。

這一步執(zhí)行完成之后,運行在Render進程中的Conient模塊就創(chuàng)建了一個類型為

WebMediaPlayerAndroid的播放器接口。這個播放器接口會返回給WebKit層的

WcbMcdiaPlaycrClicntlmpI類的成員函數(shù)load。WebMediaPlayerClientlmpl類的成員函數(shù)load

獲得了這個播放器接口之后,就會調(diào)用它的成員函數(shù)load加載當前要播放的視頻的內(nèi)容,

如下所示:

[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_);

這個函數(shù)定義在文件

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

類型為WebMediaPlayerAndroid的播放器只能史理普通URL描述的媒體流,以及

BLOB協(xié)議描述的類型為MediaSource的媒體流,不能處理類型為MediaStream的媒體流

(需要由WebRTC處理)。

類型為MediaSource的媒體流數(shù)據(jù)直接從指定的MediaSource獲得。

WebMediaPlayerAndroid類的成員函數(shù)load將該MediaSource封裝在一個

MediaSourceDelegate對象中,然后通過這個McdiaSourceDclegate對象來獲得要播放的視頻

的元數(shù)據(jù)。有了要播放的視頻的元數(shù)據(jù)之后,就可以調(diào)用WebMediaPlayerAndroid類的成員

函數(shù)InitializePlayer初始化當前正在處理的播放器。

我們假設(shè)當前要播放的視頻的URL是一個普通的URL,它描述的媒體流的元數(shù)據(jù)

要通過一個MedialnfoLoader對象從網(wǎng)絡(luò)上下載回來。下載完成后,WebMediaPlayerAndroid

類的成員函數(shù)DidLoadMedialnfo會被調(diào)用,它的實現(xiàn)如下所示:

[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);

這個函數(shù)定義在文件

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

WebMediaPlayerAndroid類的成員函數(shù)DidLoadMedialnfo會用卜載回來的視頻元數(shù)

據(jù)初始化當前正在處理的播放器。這同樣是通過調(diào)用WebMediaPlayerAndroid類的成員函數(shù)

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);

這個函數(shù)定義在文件

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

從前面的分析可以知道,WebMediaPlayerAndroid類的成員變量player_manager_指

向的是一個RendererMediaPlayerManager對象。WebMediaPlayerAndroid類的成員函數(shù)

InitializePlayer調(diào)用這個RendererMediaPlayerManager對象的成員函數(shù)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));

)

這個函數(shù)定義在文件

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

RendererMediaPlayerManager^Initialize向Browser進程發(fā)送一個類型

為MediaPlayerHostMsg_Initialize的IPC消息,用來請求Browser進程為當前正在處理的類

型為WebMediaPlayerAndroid的播放器創(chuàng)建一個由Android平臺實現(xiàn)的播放器。

Browser進程是通過McdiaWcbContcntsObscrvcr類的成員函數(shù)

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. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論