淺談音視頻 pts dts基本概念及理解
視頻的播放過(guò)程可以簡(jiǎn)單理解為一幀一幀的畫(huà)面按照時(shí)間順序呈現(xiàn)出來(lái)的過(guò)程,就像在一個(gè)本子的每一頁(yè)畫(huà)上畫(huà),然后快速翻動(dòng)的感覺(jué)。
但是在實(shí)際應(yīng)用中,并不是每一幀都是完整的畫(huà)面,因?yàn)槿绻恳粠?huà)面都是完整的圖片,那么一個(gè)視頻的體積就會(huì)很大,這樣對(duì)于網(wǎng)絡(luò)傳輸或者視頻數(shù)據(jù)存儲(chǔ)來(lái)說(shuō)成本太高,所以通常會(huì)對(duì)視頻流中的一部分畫(huà)面進(jìn)行壓縮(編碼)處理。由于壓縮處理的方式不同,視頻中的畫(huà)面幀就分為了不同的類(lèi)別,其中包括:I 幀、P 幀、B 幀。
I、P、B 幀
I 幀、P 幀、B 幀的區(qū)別在于:
I 幀(Intra coded frames):I 幀圖像采用幀內(nèi)編碼方式,即只利用了單幀圖像內(nèi)的空間相關(guān)性,而沒(méi)有利用時(shí)間相關(guān)性。I 幀使用幀內(nèi)壓縮,不使用運(yùn)動(dòng)補(bǔ)償,由于 I 幀不依賴(lài)其它幀,所以是隨機(jī)存取的入點(diǎn),同時(shí)是解碼的基準(zhǔn)幀。I 幀主要用于接收機(jī)的初始化和信道的獲取,以及節(jié)目的切換和插入,I 幀圖像的壓縮倍數(shù)相對(duì)較低。I 幀圖像是周期性出現(xiàn)在圖像序列中的,出現(xiàn)頻率可由編碼器選擇。
P 幀(Predicted frames):P 幀和 B 幀圖像采用幀間編碼方式,即同時(shí)利用了空間和時(shí)間上的相關(guān)性。P 幀圖像只采用前向時(shí)間預(yù)測(cè),可以提高壓縮效率和圖像質(zhì)量。P 幀圖像中可以包含幀內(nèi)編碼的部分,即 P 幀中的每一個(gè)宏塊可以是前向預(yù)測(cè),也可以是幀內(nèi)編碼。
B 幀(Bi-directional predicted frames):B 幀圖像采用雙向時(shí)間預(yù)測(cè),可以大大提高壓縮倍數(shù)。值得注意的是,由于 B 幀圖像采用了未來(lái)幀作為參考,因此 MPEG-2 編碼碼流中圖像幀的傳輸順序和顯示順序是不同的。
也就是說(shuō),一個(gè) I 幀可以不依賴(lài)其他幀就解碼出一幅完整的圖像,而 P 幀、B 幀不行。P 幀需要依賴(lài)視頻流中排在它前面的幀才能解碼出圖像。B 幀則需要依賴(lài)視頻流中排在它前面或后面的幀才能解碼出圖像。
這就帶來(lái)一個(gè)問(wèn)題:在視頻流中,先到來(lái)的 B 幀無(wú)法立即解碼,需要等待它依賴(lài)的后面的 I、P 幀先解碼完成,這樣一來(lái)播放時(shí)間與解碼時(shí)間不一致了,順序打亂了,那這些幀該如何播放呢?這時(shí)就需要我們來(lái)了解另外兩個(gè)概念:DTS 和 PTS(詳見(jiàn)下邊說(shuō)明)。
兩個(gè)I frame之間形成一個(gè)GOP,在x264中同時(shí)可以通過(guò)參數(shù)來(lái)設(shè)定bf的大小,即:I 和p或者兩個(gè)P之間B的數(shù)量。
通過(guò)上述基本可以說(shuō)明如果有B frame 存在的情況下一個(gè)GOP的最后一個(gè)frame一定是P.
看x264代碼,感覺(jué)GOP 就是IDR幀到另一個(gè)IDR幀之間 就是一個(gè)GOP.在視頻編碼序列中,GOP即Group of picture(圖像組),指兩個(gè)I幀之間的距離,Reference(參考周期)指兩個(gè)P幀之間的距離(如下圖)。一個(gè)I幀所占用的字節(jié)數(shù)大于一個(gè)P幀,一個(gè)P幀所占用的字節(jié)數(shù)大于一個(gè)B幀(如下圖所示)。
所以在碼率不變的前提下,GOP值越大,P、B幀的數(shù)量會(huì)越多,平均每個(gè)I、P、B幀所占用的字節(jié)數(shù)就越多,也就更容易獲取較好的圖像質(zhì)量;Reference越大,B幀的數(shù)量越多,同理也更容易獲得較好的圖像質(zhì)量。
需要說(shuō)明的是,通過(guò)提高GOP值來(lái)提高圖像質(zhì)量是有限度的,在遇到場(chǎng)景切換的情況時(shí),H.264編碼器會(huì)自動(dòng)強(qiáng)制插入一個(gè)I幀,此時(shí)實(shí)際的GOP值被縮短了。另一方面,在一個(gè)GOP中,P、B幀是由I幀預(yù)測(cè)得到的,當(dāng)I幀的圖像質(zhì)量比較差時(shí),會(huì)影響到一個(gè)GOP中后續(xù)P、B幀的圖像質(zhì)量,直到下一個(gè)GOP開(kāi)始才有可能得以恢復(fù),所以GOP值也不宜設(shè)置過(guò)大。
同時(shí),由于P、B幀的復(fù)雜度大于I幀,所以過(guò)多的P、B幀會(huì)影響編碼效率,使編碼效率降低。另外,過(guò)長(zhǎng)的GOP還會(huì)影響Seek操作的響應(yīng)速度,由于P、B幀是由前面的I或P幀預(yù)測(cè)得到的,所以Seek操作需要直接定位,解碼某一個(gè)P或B幀時(shí),需要先解碼得到本GOP內(nèi)的I幀及之前的N個(gè)預(yù)測(cè)幀才可以,GOP值越長(zhǎng),需要解碼的預(yù)測(cè)幀就越多,seek響應(yīng)的時(shí)間也越長(zhǎng)。
DTS、PTS 的概念
DTS、PTS 的概念如下所述:
DTS(Decoding Time Stamp):即解碼時(shí)間戳,這個(gè)時(shí)間戳的意義在于告訴播放器該在什么時(shí)候解碼這一幀的數(shù)據(jù)。
PTS(Presentation Time Stamp):即顯示時(shí)間戳,這個(gè)時(shí)間戳用來(lái)告訴播放器該在什么時(shí)候顯示這一幀的數(shù)據(jù)。
需要注意的是:雖然 DTS、PTS 是用于指導(dǎo)播放端的行為,但它們是在編碼的時(shí)候由編碼器生成的。
當(dāng)視頻流中沒(méi)有 B 幀時(shí),通常 DTS 和 PTS 的順序是一致的。但如果有 B 幀時(shí),就回到了我們前面說(shuō)的問(wèn)題:解碼順序和播放順序不一致了。
比如一個(gè)視頻中,幀的顯示順序是:I B B P,現(xiàn)在我們需要在解碼 B 幀時(shí)知道 P 幀中信息,因此這幾幀在視頻流中的順序可能是:I P B B,這時(shí)候就體現(xiàn)出每幀都有 DTS 和 PTS 的作用了。DTS 告訴我們?cè)摪词裁错樞蚪獯a這幾幀圖像,PTS 告訴我們?cè)摪词裁错樞蝻@示這幾幀圖像。順序大概如下:
PTS: 480 640 560 520 600 800 720 680 760 960 ... DTS: 400 440 480 520 560 600 640 680 720 760 ... Stream: I P B B B P B B B P ... 播放序: 1 5 3 2 4 9 7 6 8 10 ... PTS >= DTS
音視頻的同步
上面說(shuō)了視頻幀、DTS、PTS 相關(guān)的概念。我們都知道在一個(gè)媒體流中,除了視頻以外,通常還包括音頻。音頻的播放,也有 DTS、PTS 的概念,但是音頻沒(méi)有類(lèi)似視頻中 B 幀,不需要雙向預(yù)測(cè),所以音頻幀的 DTS、PTS 順序是一致的。
音頻視頻混合在一起播放,就呈現(xiàn)了我們常??吹降膹V義的視頻。在音視頻一起播放的時(shí)候,我們通常需要面臨一個(gè)問(wèn)題:怎么去同步它們,以免出現(xiàn)畫(huà)不對(duì)聲的情況。
要實(shí)現(xiàn)音視頻同步,通常需要選擇一個(gè)參考時(shí)鐘,參考時(shí)鐘上的時(shí)間是線性遞增的,編碼音視頻流時(shí)依據(jù)參考時(shí)鐘上的時(shí)間給每幀數(shù)據(jù)打上時(shí)間戳。在播放時(shí),讀取數(shù)據(jù)幀上的時(shí)間戳,同時(shí)參考當(dāng)前參考時(shí)鐘上的時(shí)間來(lái)安排播放。這里的說(shuō)的時(shí)間戳就是我們前面說(shuō)的 PTS。實(shí)踐中,我們可以選擇:同步視頻到音頻、同步音頻到視頻、同步音頻和視頻到外部時(shí)鐘。
PTS和DTS的時(shí)間基
PST和DTS的單位是什么?
為了回答這個(gè)問(wèn)題,先引入FFmpeg中時(shí)間基的概念,也就是time_base。它也是用來(lái)度量時(shí)間的。
如果把1秒分為25等份,你可以理解就是一把尺,那么每一格表示的就是1/25秒。此時(shí)的time_base={1,25}
如果你是把1秒分成90000份,每一個(gè)刻度就是1/90000秒,此時(shí)的time_base={1,90000}。
所謂時(shí)間基表示的就是每個(gè)刻度是多少秒
pts的值就是占多少個(gè)時(shí)間刻度(占多少個(gè)格子)。它的單位不是秒,而是時(shí)間刻度。只有pts加上time_base兩者同時(shí)在一起,才能表達(dá)出時(shí)間是多少。
好比我只告訴你,某物體的長(zhǎng)度占某一把尺上的20個(gè)刻度。但是我不告訴你,這把尺總共是多少厘米的,你就沒(méi)辦法計(jì)算每個(gè)刻度是多少厘米,你也就無(wú)法知道物體的長(zhǎng)度。
pts=20個(gè)刻度
time_base={1,10} 每一個(gè)刻度是1/10厘米
所以物體的長(zhǎng)度=ptstime_base=201/10 厘米
在ffmpeg中。av_q2d(time_base)=每個(gè)刻度是多少秒
此時(shí)你應(yīng)該不難理解 pts*av_q2d(time_base)才是幀的顯示時(shí)間戳。
下面理解時(shí)間基的轉(zhuǎn)換,為什么要有時(shí)間基轉(zhuǎn)換。
首先,不同的封裝格式,timebase是不一樣的。另外,整個(gè)轉(zhuǎn)碼過(guò)程,不同的數(shù)據(jù)狀態(tài)對(duì)應(yīng)的時(shí)間基也不一致。拿mpegts封裝格式25fps來(lái)說(shuō)(只說(shuō)視頻,音頻大致一樣,但也略有不同)。非壓縮時(shí)候的數(shù)據(jù)(即YUV或者其它),在ffmpeg中對(duì)應(yīng)的結(jié)構(gòu)體為AVFrame,它的時(shí)間基為AVCodecContext 的time_base ,AVRational{1,25}。
壓縮后的數(shù)據(jù)(對(duì)應(yīng)的結(jié)構(gòu)體為AVPacket)對(duì)應(yīng)的時(shí)間基為AVStream的time_base,AVRational{1,90000}。
因?yàn)閿?shù)據(jù)狀態(tài)不同,時(shí)間基不一樣,所以我們必須轉(zhuǎn)換,在1/25時(shí)間刻度下占10格,在1/90000下是占多少格。這就是pts的轉(zhuǎn)換。
根據(jù)pts來(lái)計(jì)算一楨在整個(gè)視頻中的時(shí)間位置:
timestamp(秒) = pts * av_q2d(st->time_base)
duration和pts單位一樣,duration表示當(dāng)前幀的持續(xù)時(shí)間占多少格?;蛘呃斫馐莾蓭拈g隔時(shí)間是占多少格。一定要理解單位。
pts:格子數(shù)
av_q2d(st->time_base): 秒/格
計(jì)算視頻長(zhǎng)度:
time(秒) = st->duration * av_q2d(st->time_base)
ffmpeg內(nèi)部的時(shí)間與標(biāo)準(zhǔn)的時(shí)間轉(zhuǎn)換方法:
ffmpeg內(nèi)部的時(shí)間戳 = AV_TIME_BASE * time(秒)
AV_TIME_BASE_Q=1/AV_TIME_BASE
av_rescale_q(int64_t a, AVRational bq, AVRational cq)函數(shù)
這個(gè)函數(shù)的作用是計(jì)算a*bq / cq來(lái)把時(shí)間戳從一個(gè)時(shí)間基調(diào)整到另外一個(gè)時(shí)間基。在進(jìn)行時(shí)間基轉(zhuǎn)換的時(shí)候,應(yīng)該首先這個(gè)函數(shù),因?yàn)樗梢员苊庖绯龅那闆r發(fā)生。
函數(shù)表示在bq下的占a個(gè)格子,在cq下是多少。
關(guān)于音頻pts的計(jì)算:
音頻sample_rate:samples per second,即采樣率,表示每秒采集多少采樣點(diǎn)。
比如44100HZ,就是一秒采集44100個(gè)sample.
即每個(gè)sample的時(shí)間是1/44100秒
一個(gè)音頻幀的AVFrame有nb_samples個(gè)sample,所以一個(gè)AVFrame耗時(shí)是nb_samples*(1/44100)秒
即標(biāo)準(zhǔn)時(shí)間下duration_s=nb_samples*(1/44100)秒,
轉(zhuǎn)換成AVStream時(shí)間基下
duration=duration_s / av_q2d(st->time_base)
基于st->time_base的num值一般等于采樣率,所以duration=nb_samples.
pts=nduration=nnb_samples
到此這篇關(guān)于淺談音視頻 pts dts基本概念及理解的文章就介紹到這了,更多相關(guān)音視頻 pts dts內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
軟件測(cè)試之使用Fiddler實(shí)現(xiàn)弱網(wǎng)測(cè)試
我們?cè)谧鲞\(yùn)維測(cè)試中會(huì)使用到到很多軟件測(cè)試工具,本篇文章給大家分析一下軟件測(cè)試,教大家在軟件測(cè)試時(shí)來(lái)使用Fiddler實(shí)現(xiàn)弱網(wǎng)測(cè)試2021-08-08so easy!10行代碼寫(xiě)個(gè)"狗屁不通"文章生成器功能
這篇文章主要介紹了通過(guò)10行代碼寫(xiě)個(gè)"狗屁不通"文章生成器功能,真的超級(jí)簡(jiǎn)單,感興趣的朋友跟隨腳本之家小編一起看看吧2020-01-01Elasticsearch在應(yīng)用中常見(jiàn)錯(cuò)誤示例解析
這篇文章主要為大家介紹了Elasticsearch在應(yīng)用中常見(jiàn)錯(cuò)誤示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-04-04