Chromium源碼--視頻播放流程分析(WebMediaPlayerImpl解析)


轉載請注明出處:http://www.cnblogs.com/fangkm/p/3797278.html

承接上一篇文章。媒體播放,需要指定一個源文件,html5用URL格式來指定視頻源文件地址,可以是http鏈接,也可以使本地源文件(不能直接指定,需要借助blob二進制類型)。播放網絡文件比播放本地文件多了個下載流程, 所以下面直接分析網絡文件的播放流程,本地文件的播放流程也就清楚了。首先分析下網絡視頻資源的加載流程,相關結構圖如下:

WebMediaPlayerImpl類有一成員BufferedDataSource來負責管理URL網絡資源的加載邏輯。

BufferedDataSource資源加載邏輯主要由BufferedResourceLoader完成,

BufferedResourceLoader類維護一個WebURLLoader接口的派生類AssociatedURLLoader對象, AssociatedURLLoader類也並沒有真正的和webkit_glue層的WebURLLoaderImpl一樣實現WebURLLoader的接口,而是通過DocumentThreadableLoader類最終依賴WebURLLoaderImpl的實現給主進程發送URL請求WebURLLoaderImpl(WebURLLoaderImpl的流程請參見:http://www.cnblogs.com/fangkm/p/3784660.html)。

AssociatedURLLoader對象與frame對象關聯,當調用WebFrame的stopLoading方法時,該請求也會取消。

BufferedResourceLoader內部維護一個可增長的內存緩沖區來保存請求到的視頻數據。

分析到這里我始終沒發現暫停緩沖機制,也沒有找到緩沖到磁盤文件的地方,如果視頻文件過大的話,全部積放在內存,資源消耗過大肯定造成極不好的程序體驗。當然我這里的Chromium代碼也有點老了,可能新版的已經改進了。

視頻數據已經准備完畢,接下來的工作就是解析音視頻數據了。在分析這部分之前首先簡單普及下音視頻的相關概念。一般的視頻文件都有視頻流和音頻流兩部分組成,不同的視頻格式音視頻的封裝格式肯定不一樣。將音頻流和視頻流合成文件的過程稱為muxer,反之從媒體文件中分離音頻流和視頻流的過程稱為demuxer. 播放視頻文件就需要從文件流中分離出音頻流和視頻流,分別對其進行解碼,解碼后的視頻幀可以直接渲染,音頻幀可以送到音頻輸出設備的緩沖區進行播放,當然,視頻渲染和音頻播放的時間戳一定要控制同步。

WebMediaPlayerImpl中有關demuxer的邏輯結構如下:

WebMediaPlayerImpl根據資源的不同創建不同的demuxer對象。

如果視頻源是通過JavaScript傳送過來的二進制數據,則創建ChunkDemuxer對象來分離音頻流和視頻流;

如果視頻源是通過URL指定的網絡源,則創建FFmpegDemuxer對象,依賴BufferedDataSource對象來訪問通過網絡加載的媒體流數據。

ChunkDemuxer和FFmpegDemuxer的具體實現暫且不表,先只需要了解他們的作用是將媒體流分離出視頻流和音頻流。先分析整個播放流程。

WebMediaPlayerImpl類有一個Pipeline對象來負責視頻的播放流程, Pipeline本身就是流水線的意思,正適合視頻播放的一系列流程。Pipeline內部利用狀態機維護播放中的各種階段的邏輯。Pipeline調用AudioRendererImpl初始化時,會調用Demuxer的GetStream方法,指定獲取音頻流數據傳入AudioRendererImpl對象;同理調用VideoRendererBase初始化時,會取到視頻流數據來傳入。音視頻流的讀取操作由DemuxerStream接口來抽象。

下面分析一下VideoRendererBase的流程, VideoRendererBase這名字起的有點奇怪,帶個Render單詞,確做的是視頻流的解碼邏輯,真正的繪制操作還是拋到WebMediaPlayerImpl類,具體請參見WebMediaPlayerImpl的paint方法。先看結構:

VideoRendererBase維護了一個VideoDecoder列表,內部主要邏輯都交給VideoFrameStream處理, VideoFrameStream的主要功能包括解碼器的選取、從DemuxerStream讀取視頻流進行解碼,解碼后的結果為一視頻幀結構VideoFrame,這個結構封裝的是YUV數據,可以直接或轉換成RGB進行渲染操作。

簡單介紹下這里的視頻解碼器創建和選取邏輯:

在WebMediaPlayerImpl類中就已經創建好視頻解碼器列表,按順序依次為:

1. 如果gpu支持視頻解碼,則創建GpuVideoDecoder對象

2. 創建VpxVideoDecoder對象

3. 創建FFmpegVideoDecoder對象

創建好解碼器列表后傳入VideoRendererBase對象,最終由VideoFrameStream來管理選取邏輯:

1. 如果視頻配置信息里有加密選項,則創建DecryptingVideoDecoder做為解碼器

2. 如果無加密選項,則從傳入的解碼器列表中選擇第一個做為解碼器。

3. 如果調用選擇的解碼器的Initialize無效(解碼器不支持該格式的解碼),則按順序選擇列表中的下一個解碼器。

 

AudioRendererImpl的結構與VideoRendererBase類似,在音頻渲染方面比視頻渲染稍微復雜一點,需要將音頻數據輸出到聲卡設備進行播放。相關結構圖:

到此為止,網頁播放器整個流程差不多已經清晰了,當然還有很多細節沒扒,比如說Media Source流對應的分離器ChunkDemuxer的實現、FFmpegDemuxer內部怎么對ffmpeg的使用、各種解碼器的實現等,沒有開發經驗,要研究透這些細節真的很耗時,有興趣的童鞋可以自己研究。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM