前言
TS流這個是MPEG國際組織規定的音視頻封裝的標準,機頂盒接收的都是這種格式的數據。DVB-T、DVB-S、DVB-C(地面機頂盒、衛星機頂盒、有線機頂盒)解析的都是TS流數據。
TS流背景介紹
在介紹具體字段,參數這些頭疼,煩人的東西之前,我覺得有必要先介紹下TS流的應用背景,有了這個概念,再去深入學習,將如虎添翼。TS流最經典的應用就是我們平時生活中的數字高清電視。我們看的電視碼流就是TS封裝格式的碼流,電視碼流發送過來后,就會由我們的機頂盒進行解封裝,解碼,然后傳給電視機進行播放。這里就有一個問題,我們看電視,有很多的頻道,節目,對應碼流是怎么區分的呢?(TIPS,頻道和節目的關系,比如我們有中央電視臺綜合頻道,下屬CCTV-1~CCTV14這些節目)TS流引入了PAT和PMT兩張表格的概念來解決這個問題。
PAT和PMT
TS流是以每188字節為一包,我們可以稱為ts packet。這個ts packet有可能是音視頻數據,也有可能是表格。舉例說明,TS流的包順序為:
PAT,PMT,DATA,DATA,,,,,,PAT,PMT,DATA,DATA,,,,,,
每隔一段時間,發送一張PAT表,緊接著發送一張PMT表,接著發送DATA(音視頻)數據。
那么你可能要問了,有了這2張表格怎么區分頻道,節目呢?PAT表格里面包含所有PMT表格的信息,一個PMT表格對應一個頻道,比如中央電視臺綜合頻道。而一個PMT里面包含所有節目的信息,比如CCTV1~CCTV14。在實際情況中我們是有很多頻道的,所以PMT表格可不止一張,有可能是PAT,PMT,PMT,PMT,,,DATA,DATA,,,,PAT,PMT,PMT,,,DATA,DATA這樣的形式。除了這個設定外,每個頻道或節目都有自己的標識符(PID),這樣當我們拿到一個DATA,解析出里面的PID,就知道是什么節目,并且也知道所屬頻道是什么了。我們看電視的時候,會收到所有節目的DATA,當我們正在看某個節目的時候,機頂盒會把這個節目的DATA單獨過濾出來,其它的舍棄。
TS packet格式講解
ts packet我們知道一包是188字節,它分為ts header和ts body。其中ts header里面會有個PID字段標識著當前ts body的類型。ts body有可能是表格,也有可能是DATA,表格沒什么好說的,我們說下DATA的結構。DATA包
其實就是PES包,而PES包是對ES的封裝,PES包分為PES頭加ES。這里的ES是原始流,是指經過壓縮后的H264,aac等格式的音視頻數據。那么幀數據,PES包,ts packet包的對應關系是什么樣的呢?一幀數據封裝成一個PES包(含PES頭和ES),這個PES包如果小于188字節,那么一個ts packet就可以放下了。最終ts packet一包的格式就是ts header+填充字節+PES包(PES頭+ES)。填充字節的意思是如果ts header加上PES包不滿188字節,這個時候肯定要填充下使其湊滿188字節發送。是不是很簡單?那么我們知道視頻幀是很大的,往往大于188字節,這個時候怎么存放呢?還是把一個視頻幀放入一個PES包。然后分別放在幾個ts packet包即可。結構如下:
第一個ts packet:ts header+PES頭+部分ES
第二個ts packet:ts header+部分ES
...
最后一個ts packet:ts header+填充字節+部分ES
PES頭加上這些部分ES,就是一個PES包。
具體字段解析
具體字段請參考ISOIEC 13818-1.pdf文檔,看起來應該沒什么困難,這里不再累述。
但是其中ts header里的payload_unit_start_indicator和pes header里的PES_packet_length這兩個字段,在解析ts流的時候至關重要,新手可能比較困惑,不懂其意,我得好好講講。
payload_unit_start_indicator有兩個值,0或1,具體的意思我們來舉個例子。假設有兩個視頻幀,每個視頻幀假設都需要3個ts packet包來存放一個PES包。那么一共有6個ts packet,它們的payload_unit_start_indicator的值為1,0,0,1,0,0,值為1代表一個幀的開始,下一個1就是新的一幀的開始了。
PES_packet_length顧名思義就是PES包的長度,但是注意,它是2個字節存儲的,這意味著,最大只能表示65535,一旦視頻幀很大,超過這個長度,怎么辦,就把PES_packet_length置為0,這是ISO標準規定的。所以在解析的時候,不能以PES_packet_length為準,要參考payload_unit_start_indicator。
pts dts pcr單位
pts:顯示時間戳,單位是毫秒*90
dts:解碼時間戳,單位是毫秒*90
pcr:節目時鐘參考,單位是毫秒90300