題記:時間戳將每一秒分成90000份,即將每一毫秒分成90份
MPEG2系統用於視音頻同步以及系統時鐘恢復的時間標籤分別在ES,PES和TS這3個層次中。
在TS 層, TS頭信息包含了節目時鐘參考PCR(Program Clock Reference),
用於恢復出與編碼端一致的系統時序時鐘STC(System Time Clock)。
在PES層, 在PES頭信息裏包含有表示時間戳PTS(Presentation Time Stamp)和
解碼時間戳DTS(Decoding Time Stamp);
在ES 層, 與同步有關的主要是視頻緩衝驗證VBV(Video Buffer Verifier),
用以防止解碼器的緩衝器出現上溢或者下溢;
同步機制
編碼器
系統時鐘STC:
編碼器中有一個系統時鐘(其頻率是27MHz),
此時鐘用來產生指示音視頻的正確顯示和解碼的時間戳,
同時可用來指示在採樣過程中系統時鐘本身的瞬時值
PCR(Program Clock Reference):
指示系統時鐘本身的瞬時值的時間標籤稱爲節目參考時鐘標籤(PCR)。
PCR的插入必須在PCR字段的最後離開復用器的那一時刻,
同時把27MHz系統時鐘的採樣瞬時值作爲PCR字段插入到相應的PCR域。
它是放在TS包頭的自適應區中傳送.
27MHz的系統時鐘STC經波形整理後分成兩路:
PCR_ext (9bits ), 由27MHz脈衝直接觸發計數器生成擴展域.
PCR_base(33bits), 經300分頻器分頻成90kHz脈衝送入一個33位計數器生成90kHz基值,
用於和PTS/DTS比較,產生解碼和顯示所需要的同步信號.
這兩部分被置入PCR域,共同組成42位的PCR.
輸入到T-STD解碼器的第i個字節的PCR值:
PCR(i) = PCR_base(i)*300 + PCR_ext(i)
i: 包含program_clock_reference_base域的最後一個比特的字節號.
PCR_base(i) = ((system_clock_frequency * t(i)) / 300) % 2^33
PCR_ext(i) = ((system_clock_frequency * t(i)) / 1 ) % 300
t(i): 字節i的編碼時間.
例如:
時間"03:02:29.012"的PCR計算如下:
03:02:29.012 = ((3 * 60) + 2) * 60 + 29.012 = 10949.012s
PCR_base = ((27 000 000 * 10949.012) / 300) % 2^33 = 98 541 080
PCR_ext = ((27 000 000 * 10949.012) / 1 ) % 300 = 0
PCR = 98 541 080 * 300 + 0 = 295 623 324 000
逆推一個:
假設PCR= 1209740011800
PCRbase = 1209740011800/300 = 4032466706
PCR-ext = 1209740011800%300 = 0
t =PCRbase*300/27000000 = 44805.185622222222222222222222222
time: t/3600: ( t-(t/3600))/60: t-( t-(t/3600))/60 = 12:26:45.185622222222222222222222222
PCR-base的作用:
a. 與PTS和DTS作比較, 當二者相同時, 相應的單元被顯示或者解碼.
b. 在解碼器切換節目時,提供對解碼器PCR計數器的初始值,
以讓該PCR值與PTS、DTS最大可能地達到相同的時間起點.
PCR-ext的作用:
通過解碼器端的鎖相環路修正解碼器的系統時鐘, 使其達到和編碼器一致的27MHz.
PTS(Presentation Time Stamp):
指示音視頻顯示時間的時間戳稱爲顯示時間戳(PTS);
PTS域爲33bits, 是對系統時鐘的300分頻的時鐘的計數值.
它被編碼成爲3個獨立的字段:
PTS[32..30][29..15][14..0]
表示此分組中第一個訪問單元在系統目標解碼器中的預定顯示時間.
PTS值爲:
PTS(k) = ((system_clock_frequency * TPn(k)) / 300) % 2^33
TPn(k): 表示單元Pn(k)的表示時間.
以上一個PCR:12:26:45.185622222222222222222222222爲基準
當前IDR幀(poc=0)的PTS爲:4032475706
time = PTS*300/27000000 = 44805.285622222222222222222222222 = 12:26:45.285622222222222222222222222
當期poc=1 的PTS爲:4032479306
time1 = PTS*300/27000000 =44805.365622222222222222222222222 = 12:26:45.325622222222222222222222222222
time1-time2 = 0.04
即0.04s 播放一幀 一秒播放 25幀
我們可以看到兩個PTS之間相差3600 40ms播放一幀 則 3600 = 40*90(90hz) = 3600
DTS(Decoding Time Stamp):
指示音視頻的解碼時間戳稱爲解碼時間戳(DTS),
DTS域爲33bits,編碼成爲3個獨立的字段:
DTS[32..30][29..15][14..0]
表示此分組中第一個訪問單元在系統目標解碼器中的預定解碼時間.
DTS值爲:
DTS(j) = ((system_clock_frequency * TDn(j)) / 300) % 2^33
TDn(j): 第n個ES流的第j個存取單元An(j)的解碼時間.
DTS就視頻來說,因爲視頻編碼的時候用到了雙向預測,
一個圖像單元被解出,並非馬上就被顯示,可能在存儲器中留一段時間,作爲其餘圖像單元的解碼參考,
在被參考完畢後,才被顯示.
音頻PTS:
針對音頻和視頻的同步顯示,MPEG提出了一個音頻PTS.
由於聲音沒有用到雙向預測,它的解碼次序就是它的顯示次序,故它只有PTS.
VBV_delay:
視頻流延時值,
在解碼時利用視頻流緩衝區把視頻流緩存到相應的vbv_delay時間後,
再啓動解碼器解碼、顯示、實現音視頻的同步.
VBV_delay存在於視頻ES的頭部,長度爲16bit.
解碼器
首先, 解析PCR, 重建和編碼器同步的27MHz系統時鐘, 恢復27MHz系統時鐘後;
再, 通過VBV_delay(視頻流延時值)的數值來確定解碼的開始;
之後, 利用PES流中解碼時間戳(DTS)和顯示時間戳(PTS)來確定解碼和顯示的次序.
用PCR來對系統時鐘進行修正.
解碼器同步算法總結如下:
(1). 解碼器從輸入碼流的包頭中解出時間信息PCR送入到系統時間時鐘恢復電路;
系統時間時鐘恢復電路在接收到每一個新的PCR時,進行本地系統時間時鐘恢復和鎖相。
(2). 解複用器後,從PES包頭中解出顯示時間標籤PTS和解碼時間標籤DTS,並送入到基本流解碼器中。
(3). 基本流解碼器在接收到新的PTS/DTS後,存入對應的FIFO(先進先處存儲器)中進行管理;
對於沒有PTS/DTS的顯示單元,需要對其時間標籤進行插值,並送入到FIFO中管理。
(4). 每一顯示單元開始解碼前,用其對應的DTS與STC進行比較,當STC與DTS相等時開始解碼;
(5). 每一顯示單元開始顯示前,用其對應的PTS與STC進行比較,當STC與PTS相等時開始顯示。
三、失同步處理
27 MHz系統時鐘經過300分頻後,得到本地的33 bits PCR_Base, 該時鐘與寄存器中當前圖像的PTS/DTS進行比較,
系統軟件根據比較結果做出相應的處理:
(1). 若當前的PTS/DTS比PCR計數器的值小於半幀以上,即PTS_Base≤-ΔPTS/2,
此時說明系統解碼過慢,解碼器處於失步狀態,應根據該幀的結構做出相應的同步調整;
(2). 若當前的PTS/DTS比PCR計數器的值在半幀時間以內,
我們認爲此時系統解碼正常,立即顯示/解碼當前幀;
(3). 若當前的PTS/DTS大於PCR計數器的值,則此時解碼器稍快,
在這種情況下,只需等到PCR與PTS/DTS相等時,就可顯示/解碼。
附註:
上面講的都是解碼器的同步機制,
對於轉碼來說,如ffmpeg等並不是這麼做的。