播放器技術(shù)分享(2):緩沖區(qū)管理

搞音視頻開(kāi)發(fā)好些年,分享過(guò)許多博客文章,比如:前幾年發(fā)布的《FFmpeg Tips》系列,《Android 音頻開(kāi)發(fā)》系列,《直播疑難雜癥排查》系列等等。最近想把多年來(lái)開(kāi)發(fā)和優(yōu)化播放器的經(jīng)驗(yàn)也分享出來(lái),同時(shí)也考慮把自己業(yè)余時(shí)間開(kāi)發(fā)的基于 ffmpeg 的播放器內(nèi)核開(kāi)源出來(lái),希望能幫助到音視頻領(lǐng)域的初學(xué)者。第一期文章要推出的內(nèi)容主要涉及到播放器比較核心的幾個(gè)技術(shù)點(diǎn),大概的目錄如下:

創(chuàng)新互聯(lián)建站客戶idc服務(wù)中心,提供雅安服務(wù)器托管、成都服務(wù)器、成都主機(jī)托管、成都雙線服務(wù)器等業(yè)務(wù)的一站式服務(wù)。通過(guò)各地的服務(wù)中心,我們向成都用戶提供優(yōu)質(zhì)廉價(jià)的產(chǎn)品以及開(kāi)放、透明、穩(wěn)定、高性價(jià)比的服務(wù),資深網(wǎng)絡(luò)工程師在機(jī)房提供7*24小時(shí)標(biāo)準(zhǔn)級(jí)技術(shù)保障。

1. 播放器技術(shù)分享(1):架構(gòu)設(shè)計(jì)

2. 播放器技術(shù)分享(2):緩沖區(qū)管理

3. 播放器技術(shù)分享(3):音畫(huà)同步

4. 播放器技術(shù)分享(4):首開(kāi)時(shí)間

5. 播放器技術(shù)分享(5):延時(shí)優(yōu)化

本篇是系列文章的第二篇,主要聊一聊播放器的緩沖區(qū)管理。

1 概述

在上一篇文章中,我們有提到利用緩沖區(qū)把單線程模型的數(shù)據(jù)流改造為多線程模型,從而可以有效抵抗網(wǎng)絡(luò)和解碼的抖動(dòng),防止頻繁卡頓,同時(shí)也能充分利用多核 CPU 的計(jì)算能力,如下圖所示:播放器技術(shù)分享(2):緩沖區(qū)管理

播放器的讀線程,將 IO 和 Parser 模塊輸出的”未解碼“的音視頻數(shù)據(jù)包放到”幀緩沖區(qū)“隊(duì)列中,將解碼后的數(shù)據(jù),存放到”顯示緩沖區(qū)“隊(duì)列中。

2 緩沖區(qū)的作用

我們深挖一下,這個(gè) “幀緩沖區(qū)” 和 “顯示緩沖區(qū)” 究竟起到了一個(gè)什么作用 ?

2.1 幀緩沖區(qū)

幀緩沖區(qū),作為“讀線程”和“解碼線程”之間的緩沖池,它主要起到了三個(gè)作用:

  1. 抵抗網(wǎng)絡(luò)抖動(dòng)

  2. 抵抗解碼抖動(dòng)

  3. 避免被動(dòng)丟幀導(dǎo)致花屏

假設(shè)沒(méi)有“幀緩沖區(qū)”,即:IO -> Parser -> Decoder 整個(gè)流程是串行的,那么會(huì)有如下潛在問(wèn)題:

  1. IO 網(wǎng)絡(luò)抖動(dòng)的時(shí)候(比如:短暫擁塞,無(wú)法讀到數(shù)據(jù)),那么整個(gè)數(shù)據(jù)鏈條都會(huì)被卡住,Decoder 只能干等著 IO 恢復(fù)

  2. Decoder 同樣會(huì)出現(xiàn)“抖動(dòng)”,因?yàn)榻獯a某些復(fù)雜的視頻幀,會(huì)耗時(shí)比較久,如果 Decoder 卡住,同樣 IO 模塊也只能干等著

  3. 因?yàn)檎麄€(gè)流程是串行的,每一幀都必須 IO -> Parser -> Decoder 走完才會(huì)讀取和處理下一幀,那么,當(dāng)網(wǎng)絡(luò)抖動(dòng)的時(shí)候,會(huì)出現(xiàn)服務(wù)端的 TCP 協(xié)議棧緩存了較多的數(shù)據(jù),在網(wǎng)絡(luò)恢復(fù)的時(shí)候,下發(fā)到客戶端的時(shí)候,因?yàn)榻邮詹患皶r(shí),導(dǎo)致 TCP 發(fā)送隊(duì)列爆滿而產(chǎn)生被動(dòng)丟幀,從而使得后續(xù)因?yàn)閿?shù)據(jù)不完整導(dǎo)致解碼花屏

2.2 顯示緩沖區(qū)

顯示緩沖區(qū),作為“解碼線程”和“顯示線程”之間的緩沖池,它主要起到了三個(gè)作用:

  1. 實(shí)現(xiàn) “音畫(huà)同步” 的必要條件

  2. 抵抗渲染抖動(dòng)

假設(shè)沒(méi)有“顯示緩沖區(qū)”,即:Decoder -> Renderer 整個(gè)流程是串行的,那么會(huì)有如下潛在問(wèn)題:

  1. 無(wú)論是視頻幀還是音頻數(shù)據(jù),都是解碼完了就立馬送入了渲染模塊,無(wú)法添加音畫(huà)同步的邏輯處理

  2. 如果渲染模塊出現(xiàn)“抖動(dòng)”,會(huì)直接阻塞×××,無(wú)法異步去解碼幀緩沖區(qū)中的數(shù)據(jù),降低了效率

3 “主動(dòng)緩沖” 與 “被動(dòng)緩沖”

了解了緩沖區(qū)的作用,我們?cè)倏纯淳彌_區(qū)的數(shù)據(jù)是怎么被填充的 ?

緩沖區(qū)的數(shù)據(jù)填充,主要分為 2 種情況,第一種叫 “主動(dòng)緩沖”,另一種叫做 “被動(dòng)緩沖”

主動(dòng)緩沖:是指播放器主動(dòng)暫停緩沖區(qū)的數(shù)據(jù)消費(fèi),等待數(shù)據(jù)生產(chǎn)者逐漸填充數(shù)據(jù),直到達(dá)到某種條件再恢復(fù)

被動(dòng)緩沖:是指數(shù)據(jù)的消費(fèi)速度趕不上生產(chǎn)速度,從而被動(dòng)滯留了數(shù)據(jù)在緩沖區(qū)中

主動(dòng)緩沖,多用于點(diǎn)播場(chǎng)景,為了降低頻繁卡頓,在開(kāi)始播放視頻之前,會(huì)主動(dòng) buffering 一段時(shí)間(比如:10s)的數(shù)據(jù),再開(kāi)始播放。當(dāng)緩沖區(qū)內(nèi)的數(shù)據(jù)因?yàn)榫W(wǎng)絡(luò)抖動(dòng)等原因消耗完了,會(huì)再次啟動(dòng) buffering,如此循環(huán)。

播放器技術(shù)分享(2):緩沖區(qū)管理

如圖所示,假設(shè)播放器緩沖區(qū)內(nèi)的數(shù)據(jù)低于 Low 這個(gè)水位點(diǎn)后,會(huì)主動(dòng)暫停播放,啟動(dòng) buffering 過(guò)程直到緩沖區(qū)中的數(shù)據(jù)達(dá)到 M 水位值。

被動(dòng)緩沖,多出現(xiàn)在直播場(chǎng)景,可能有 2 種原因:

  1. 手機(jī)等設(shè)備的解碼性能不足,比如軟解 1080P 的高清視頻,導(dǎo)致視頻的解碼和渲染的速度趕不上視頻的讀取速度,導(dǎo)致數(shù)據(jù)堆積在“幀緩沖區(qū)”

  2. 網(wǎng)絡(luò)的頻繁抖動(dòng),導(dǎo)致客戶端無(wú)法及時(shí)拿到數(shù)據(jù)進(jìn)行解碼渲染,當(dāng)網(wǎng)絡(luò)恢復(fù)后,數(shù)據(jù)會(huì)迅速下發(fā)下來(lái),但播放器已沒(méi)有辦法再快速消費(fèi)掉(因?yàn)椴シ诺乃俾适枪潭ǖ?,除非添加追幀的邏輯,后續(xù)文章會(huì)詳細(xì)介紹)

4 緩沖區(qū)的大小怎么定 ?

理解了緩沖區(qū)的作用,那這兩個(gè)緩沖區(qū)的大小如何制定呢 ?首先,我們需要知道這兩個(gè)緩沖區(qū)大小究竟影響或者決定了什么 ?

  1. 緩沖區(qū)越大 -> 抗抖動(dòng)能力越強(qiáng)

  2. 緩沖區(qū)越大 -> 內(nèi)存占用越高

  3. 緩沖區(qū)越大 -> 播放延時(shí)越大

由此可見(jiàn),緩沖區(qū)也不是越大越好,需要根據(jù)實(shí)際的使用場(chǎng)景來(lái)決定。

“顯示緩沖區(qū)” 其實(shí)是 解碼線程 和 渲染線程 之間的橋梁,由于解碼和渲染的抖動(dòng)并不頻繁,所以并不需要特別大的緩沖區(qū),最低 3 幀左右即可,一幀在生產(chǎn),一幀在消費(fèi),還有一幀在緩沖區(qū)中待命。

而 “幀緩沖區(qū)” 是用來(lái)抵抗網(wǎng)絡(luò)抖動(dòng)的,網(wǎng)絡(luò)抖動(dòng)往往是比較頻繁的,抖動(dòng)的時(shí)間也有時(shí)會(huì)比較久一些,所以 “幀緩沖區(qū)” 相對(duì)要設(shè)置得大一點(diǎn),但以不過(guò)于影響內(nèi)存和播放延時(shí)為前提。

對(duì)于直播場(chǎng)景,為了防止 “被動(dòng)丟幀”,往往 “幀緩沖區(qū)” 默認(rèn)是設(shè)置為 “無(wú)限大” 的,當(dāng)檢測(cè)到緩沖區(qū)達(dá)到一定閾值后,啟動(dòng)一些諸如主動(dòng)丟幀或者倍數(shù)播放的方式,來(lái)快速消耗掉緩沖的內(nèi)容,從而降低內(nèi)存和延時(shí)。

5 緩沖區(qū)何時(shí)會(huì)主動(dòng)清空 ?

有如下幾種場(chǎng)景,播放器會(huì)主動(dòng)清空緩沖區(qū)內(nèi)的數(shù)據(jù):

  1. 播放器重置

  2. 播放進(jìn)度條被拖動(dòng)

  3. 消除累積延時(shí)

  4. 系統(tǒng)內(nèi)存告警

6 IJKPlayer 的緩沖區(qū)管理

播放器技術(shù)分享(2):緩沖區(qū)管理

ijkplayer 使用非常廣泛,這里以它為例看看播放器緩沖區(qū)的真實(shí)案例是怎么樣的 ?

  1. 播放器打開(kāi)后,緩沖 100ms,再開(kāi)始播放

  2. 如果遇到了卡頓(緩沖區(qū)為空),則暫停播放,緩沖到 1000ms,再開(kāi)始播放

  3. 如果再次遇到卡頓,則緩沖到 2000ms 再播,依次類(lèi)推,直到 5000ms

可以看出,它的緩沖區(qū)的最大閾值是逐步遞增上去的,這是一個(gè)非常棒的用戶體驗(yàn)優(yōu)化,因?yàn)槿绻脩艟W(wǎng)絡(luò)不是那么差的話,不用第一次緩沖就等 5s 了

7 總結(jié)

播放器的緩沖區(qū)管理,就分享到這里了,如有疑問(wèn)的小伙伴歡迎來(lái)信 lujun.hust@gmail.com 交流。另外,也歡迎大家關(guān)注我的新浪微博 @盧_俊 或者 微信公眾號(hào) @Jhuster 獲取最新的文章和資訊。 

播放器技術(shù)分享(2):緩沖區(qū)管理

分享標(biāo)題:播放器技術(shù)分享(2):緩沖區(qū)管理
鏈接分享:http://www.muchs.cn/article6/jpcdig.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供用戶體驗(yàn)、外貿(mào)建站、域名注冊(cè)電子商務(wù)、網(wǎng)站設(shè)計(jì)、網(wǎng)站維護(hù)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

營(yíng)銷(xiāo)型網(wǎng)站建設(shè)