ExoPlayer 源碼分析 一 HLS 拉流及播放流程
ExoPlayer 源碼分析 二 類圖 & 名詞解釋
ExoPlayer 源碼分析 三 變速播放
ExoPlayer 源碼分析 四 緩存策略
ExoPlayer 源碼分析 五 碼率自適應(yīng)
本文基于 ExoPlayer 2.13.2 。
線程相關(guān)

LoadTask
LoadTask 實(shí)現(xiàn)了 Runnable 接口,而且同時(shí)繼承了 Handler ,它有三個(gè)作用:
- 通過 Loadable 加載數(shù)據(jù)—— run 方法中調(diào)用 Loadable 的 load 方法。
- load 完成之后通過 handler 通知 callback。
- 加載過程中如有異常發(fā)生,通知 callback。
Loadable
真正執(zhí)行加載工作的類,它的兩個(gè)實(shí)現(xiàn)后續(xù)再分析。
Loader
Loader 中有個(gè)線程池,當(dāng)有工作要做的時(shí)候它會(huì)創(chuàng)建一個(gè) LoadTask 丟進(jìn)線程池中之行。
配置文件
HLS

HlsMediaPlaylist
HlsMediaPlaylist 可以簡(jiǎn)單理解為一路可播放的流,其中的 Segment 表示這一路流被切成小的分段,播放時(shí) Segment 按順序加載。
HlsMasterPlayList
Alternate Media 支持多種碼率或多種語言的流,這時(shí)候就需要多級(jí)目錄,HlsMasterPlayList 可以看作是一級(jí)目錄,其中的每個(gè) Variant 解析出來又是 HlsMediaPlaylist。
DASH

這個(gè)類圖各個(gè)組件很好的對(duì)應(yīng)了 MPD 文件:

MediaPresentationDescription(MPD)
MPD 是一種分層數(shù)據(jù)文件,用 xml 表示,一個(gè) MPD 描述了視頻的所有信息,一個(gè) MPD 包含一個(gè)或多個(gè) Period。
Period
每個(gè) Period 代表一個(gè)時(shí)間段,同一個(gè)時(shí)間段內(nèi),可用的媒體內(nèi)容以及碼率不會(huì)變更。如果是直播可能需要周期的去服務(wù)器更新 MPD 文件,服務(wù)器可能會(huì)移除舊的已經(jīng)過時(shí)的Period,或是添加新的Period。新的Period中可能會(huì)添加新的可用碼率或去掉上一個(gè)Period中存在的某些碼率。
AdaptationSet
一個(gè) Period 由一個(gè)或多個(gè) AdaptationSet 組成,AdaptationSet 由一組可供切換不同碼率的流組成。
Representation
每個(gè) Adaptationset 包含了一個(gè)或者多個(gè)Representations.
Segment
每個(gè)Representation由一個(gè)或者多個(gè)segment組成 ;
DataSource

DataSource
DataSource 負(fù)責(zé)提供媒體數(shù)據(jù),DefaultHttpDataSource 等就是它不同形式的實(shí)現(xiàn),這個(gè)比較好理解就不一一解釋了。
Chunk

Chunk
Chunk 實(shí)現(xiàn)了 Loadable 接口,它可以放入線程中執(zhí)行,用于加載數(shù)據(jù)。Hls 和 DASH 都是分段加載的,一個(gè) Chunk 的子類負(fù)責(zé)加載一個(gè) Segment 的數(shù)據(jù)(這里不確定 Chunk 和 Segment 的關(guān)系是否一對(duì)一,有時(shí)間再詳細(xì)分析)。
TsChunk
用于加載 Hls 中的 MPEG2TS 塊。
MediaPlaylistChunk
處理 Hls 配置文件的 chunk。
SingleSampleMediaChunk
VTT 等字幕文件是不需要分塊加載的,可以一次性加載完,SingleSampleMediaChunk 用于處理這種情況。
ContainerMediaChunk
DASH 和 SmoothStreaming 都是用它加載和解析分段的多媒體數(shù)據(jù)。
Extractor

Extractor
顧名思義就是內(nèi)容提取器,從原始數(shù)據(jù)流中提取出音頻、視頻、字幕等內(nèi)容。具體提取方式由子類實(shí)現(xiàn)。比如 TsExtractor 構(gòu)造了一系列 PayLoadReader,通過他們實(shí)現(xiàn),而 Mp4Extractor 則是自己實(shí)現(xiàn)。
ExtractorInput
提供數(shù)據(jù)供 Extractor 消費(fèi),它的默認(rèn)實(shí)現(xiàn)是 DefaultExtractorInput 數(shù)據(jù)源是 DataSource。
ExtractorOutput
接收 Extractor 提取的流級(jí)數(shù)據(jù)。
TrackOutput
接收由 Extractor 提取的數(shù)據(jù),它的默認(rèn)實(shí)現(xiàn)是 DefaultTrackOut,它內(nèi)部通過 RollingSampleBuffer 存儲(chǔ)數(shù)據(jù)。
RollingSampleBuffer
樣本數(shù)據(jù)和相應(yīng)樣本信息的滾動(dòng)緩沖區(qū),存儲(chǔ)數(shù)據(jù)的容器是阻塞的雙端隊(duì)列,RollingSampleBuffer 將它封裝成滾動(dòng)的形式。
ChunkSource

ChunkSource
用于構(gòu)建并提供 Chunk 對(duì)象,上面說過 Chunk 是一種 Loadable ,它負(fù)責(zé)從網(wǎng)絡(luò)、file 等加載數(shù)據(jù)。HlsChunkSource 并未實(shí)現(xiàn) ChunkSource 接口。
SampleSource

SampleHolder
Extractor 提取后的數(shù)據(jù)存儲(chǔ)在 RollingSampleBuffer 中,這里的數(shù)據(jù)比如一個(gè) nal unit 就稱為 Sample。SampleHolder 里有一個(gè) buffer 用于暫存 Sample 數(shù)據(jù)供解碼器使用。
SampleSource
為解碼器提供 Sample 數(shù)據(jù)。
SampleSourceReader
從 RollingSampleBuffer 讀取 Sample 數(shù)據(jù)。
Render

Renderer 的子類并不只負(fù)責(zé)渲染,而是負(fù)責(zé)讀取 Sample、解碼、渲染這三個(gè)行為,Renderer 通過繼承將公共的行為抽象出來。比如 SampleSourceTrackRenderer 負(fù)責(zé)從 RollingSampleBuffer 中讀取數(shù)據(jù),MediaCodecTrackRenderer 負(fù)責(zé)初始化 MediaCodec 并將數(shù)據(jù)寫入 MediaCodec 的 inputBuffer 中。而
MediaCodecAudioTrackRenderer 中則創(chuàng)建了 AudioTrack 負(fù)責(zé)音頻輸出。
Hls 相關(guān)類圖
