http://blog.csdn.net/alangdangjia/article/details/9495193
應該說真正了解TS,還是看了朋友推薦的《數字電視業務信息及其編碼》一書之后,MPEG2 TS和數字電視是緊密不可分割的,值得總結一下其中的一些關系。
ISO/IEC-13818-1:
系統部分;ISO/IEC-13818-2:視頻;ISO/IEC-13818-3:音頻;ISO/IEC-13818-4:一致性測試;ISO
/IEC-13818-5:軟件部分;ISO/IEC-13818-6:數字存儲媒體命令與控制;ISO/IEC-13818-7:高級音頻編碼;ISO
/IEC-13818-8:系統解碼實時接口;
MPEG2系統任務包括:1. 規定以包傳輸數據的協議;2. 規定收發兩端數據流同步的協議;3. 提供多個數據流的復用和解復用協議;3. 提供數據流加密的協議。以包形式存儲和傳送數據流是MPEG2系統之要點。
ES是直接從編碼器出來的數據流,可以是編碼過的視頻數據流,音頻數據流,或其他編碼數據流的統稱。ES流經過PES打包器之后,被轉換成PES包。PES包由包頭和payload組成,具體格式摘錄如下:
可以看到PTS/DTS是打在PES包里面的,這兩個parameters是解決視音頻同步顯示,防止解碼器輸入緩存上溢或下溢的關鍵。PTS表示顯示單元
出現在系統目標解碼器(STD: system target
decoder)的時間,DTS表示將存取單元全部字節從STD的ES解碼緩存器移走的時刻。每個I、P、B幀的包頭都有一個PTS和DTS,但PTS與DTS對B幀都是一樣的,無須標出B幀的DTS。對I幀和P幀,顯示前一定要存儲於視頻解碼器的重新排序緩存器中,經過延遲(重新排序)后再顯示,一定要分別標明PTS和DTS。
上節介紹過,ES首先需打包成PES流包,然后PES根據需要打包成PS或TS包進行存儲或傳輸。其每路ES只包含一路信源的編碼數據流,所以每路PES也只包含相對應信源的數據流。
對PS流而言,每個PES包頭含有PTS和DTS,流識別碼,用於區別不同性質ES。然后通過PS復用器將PES包復用成PS包。實際上是將PES包分解為
更細小的PS包。在解碼的時候,解復用器將PS分解成一個個PES包,拆包器然后將PES包拆成視頻和音頻的ES,最后輸入至各自解碼器進行解碼。一個問
題是:各個ES在解碼時,如何保證視音頻的同步呢?除了PTS和DTS的配合工作外,還有一個重要的參數是SCR(system clock
reference)。在編碼的時候,PTS,DTS和SCR都是由STC(system time
clock)生成的,在解碼時,STC會再生,並通過鎖相環路(PLL-phase lock
loop),用本地SCR相位與輸入的瞬時SCR相位鎖相比較,以確定解碼過程是否同步,若不同步,則用這個瞬時SCR調整27MHz的本地時鍾頻率。最
后,PTS,DTS和SCR一起配合,解決視音頻同步播放的問題。PS格式摘錄如下:
PS包的長度比較長且可變,主要用於無誤碼環境里,因為越長的話,同步越困難,且在丟包的情況下,重組也越困難。所以,PS適合於節目信息的編輯和本地內容應用的application。
TS流也是由一個或多個PES組合而來的,他們可以具有相同的時間基准,也可以不同。其基本的復用思想是,對具有相同時間基准的多個PES現進行節目復用,然后再對相互有獨立時間基准的各個PS進行傳輸復用,最終產生出TS。
其中,可用同步字節位串的自動相關特性,檢測數據流中的包限制,建立包同步;傳輸誤碼指示符,是指有不能消除誤碼時,采用誤碼校正解碼器可表示1bit 的誤碼,但無法校正;有效載荷單元起始指示符,表示該數據包是否存在確定的起始信息;傳輸優先,是給TS包分配優先權;PID值是由用戶確定的,解碼器根 據PID將TS上從不同ES來的TS包區別出來,以重建原來的ES;傳輸加擾控制,可指示數據包內容是否加擾,但包頭和自適應區永遠不加擾;自適應區控 制,用2 bit表示有否自適應區,即(01)表示有有用信息無自適應區,(10)表示無有用信息有自適應區,(11)表示有有用信息有自適應區,(00)無定義; 連續計數器可對PID包傳送順序計數,據計數器讀數,接收端可判斷是否有包丟失及包傳送順序錯誤。顯然,包頭對TS包具有同步、識別、檢錯及加密功能。
TS包自適應區由自適應區長、各種標志指示符、與插入標志有關的信息和填充數據4部分組成。其中標志部分由間斷指示符、隨機存取指示符、ES優化指示符、 PCR標志、接點標志、傳輸專用數據標志、原始PCR標志、自適應區擴展標志8個部分組成。重要的是標志部分的PCR字段,可給編解碼器的27MHz時鍾 提供同步資料,進行同步。其過程是,通過PLL,用解碼時本地用PCR相位與輸入的瞬時PCR相位鎖相比較,確定解碼過程是否同步,若不同步,則用這個瞬 時PCR調整時鍾頻率。因為,數字圖像采用了復雜而不同的壓縮編碼算法,造成每幅圖像的數據各不相同,使直接從壓縮編碼圖像數據的開始部分獲取時鍾信息成 為不可能。為此,選擇了某些(而非全部)TS包的自適應區來傳送定時信息。於是,被選中的TS包的自適應區,可用於測定包信息的控制bit和重要的控制信 息。自適應區無須伴隨每個包都發送,發送多少主要由選中的TS包的傳輸專用時標參數決定。標志中的隨機存取指示符和接點標志,在節目變動時,為隨機進入I 幀壓縮的數據流提供隨機進入點,也為插入當地節目提供方便。自適應區中的填充數據是由於PES包長不可能正好轉為TS包的整數倍,最后的TS包保留一小部 分有用容量,通過填充字節加以填補,這樣可以防止緩存器下溢,保持總碼率恆定不變。
前面3節總結了MPEG2
TS的基本格式,其中包括PES,PS和TS,以及相關字段的介紹。那么作為一種傳輸流,TS將內容進行打包/復用,讓其媒體內容變成TS傳輸,並最終在
解碼端解碼。簡單來看,TS是一個傳輸層的協議棧,它可以承載各種內容的傳輸,比如MPEG,WMV,H264,甚至是IP,那么其中的傳輸規范是如何定
義的呢?這個即是PSI(節目特定信息)要做的事情。
PSI
由四張表構成:PAT,PMT,CAT和NIT,這四張表分別描述了一個TS所包括的所有ES流的傳輸結構。首先的一個概念是,TS是以包形式傳播,在編
解碼端都需要以一定的包ID來標識TS流里承載的內容,比如,PAT表會存在於一個或多個TS包里,所以要用一個特別的包ID來表示,另外,不同的ES流
也需要不同的包ID來標識。我們有了PAT和PMT這兩種表,解碼器就可以根據PID,將TS上從不同ES來的TS包區分出來進行解碼。
TS的解碼分兩步進行,其一,是從PID為0
的TS包里,解析出PAT表,然后從PAT表里找到各個節目源的PID,一般此類節目源都由若干個ES流組成,並描述在PMT表里面,然后通過節目源的
PID,就可以在PMT表里檢索到各個ES的PID。其二,解碼器根據PMT表里的ES流的PID,將TS流上的包進行區分,並按不同的ES流進行解碼。
所以,TS是經過節目復用和傳輸復用兩層完成的,即在節目復用時,加入了PMT,在傳輸復用時,加入了PAT。同樣在節目解復用時,可以得到PMT,在傳
輸解復用時,可以得到PAT。下圖很好地概述了其思想。
TS是支持多路復用的,所以它可用來傳輸經復用后的多層節目。在復用過程中,要注意的是,解碼過程中所需要面對的時間參考和同步問題,因為解復用是需要各種信息同步進行的,所以在復用過程中,就需要插入相關的時間信息:PTS,DTS,PCR。
在TS形成過程中,PTS和DTS是在ES打包成PES時,根據STC的參考,將其時鍾信息注入PES包中的,而之后在PES切成TS時,再將PID和
PCR信息注入到TS包中,當多路TS再進行復用的時候,各路TS的PCR將會被提取出來,再進行分析,然后再根據統一的STC參考,將新的PCR生成並
注入到TS中去,最后,因為原來PAT表信息不在適用,所以新的PAT表需要再生成,並附加到新的TS流中去。經過這多層的復用之后,新的TS流即可以進
入調制,傳輸階段。過程可參見下圖:
解碼過程要面對的問題是:解復用,視音頻的同步,解碼緩存器無上下溢。解復用即是將TS在同一信道里不同時序進行傳輸的節目分離出來;視音頻同步由DTS,
PTS和PCR三者協調完成,並且PCR是重建系統時間基准的絕對時標,而DTS和PTS是解碼和重現時刻的相對時標;對解碼緩存器無上下溢的問題,必須
借助於系統目標解碼器(STD)模型來對其進行實現,基本思想如下:
- TS流進入解碼器后,首先由換向器,按照一定的時序關系,將各種ES流分解出來(其中也包括PSI信息流)。
- 分解過后的ES流會進入各自的傳輸緩存器,通過之后,其PES流進入各自的主存儲器,注意的是:PSI信息流會進入系統緩存器,最后也到達主存儲器。
- 最后,解碼器根據DTS信息,從各個主存儲器分別提取媒體或系統信息,進行解碼,並根據PTS信息,將媒體內容進行顯示處理。
其過程可參見下圖:
MPEG-2 學習筆記
一、概念
規范中講述的概念很多,容易讓人糊塗,所以先把一些概念理清,弄清楚它們之間的關系,再看后面的就可提高很多的效率。
(1)ES- Elementary Streams (原始流),對視頻、音頻信號及其他數據進行編碼壓縮后
的數據流稱為原始流。原始流包括訪問單元,比如視頻原始流的訪問單元就是一副圖像的編
碼數據。
(2) PES- Packetized Elementary Streams (分組的原始流),原始流形成的分組稱為PES分組,是用來傳遞原始流的一種數據結構
(3)節目是節目元素的集合。節目元素可能是原始流,這些原始流有共同的時間基點,用來做同步顯示。
(4)傳輸流和節目流
TS-Transport Stream 翻譯為“傳輸流”
PS-Program Stream 翻譯為“節目流”
PS用來傳輸和保存一道節目的編碼數據或其他數據。PS的組成單位是PES分組。
TS用來傳輸和保存多道節目的編碼數據或其他數據,TS的組成單位是節目。
PS適用於不容易發生錯誤的環境,以及涉及到軟件處理的應用,典型應用如DVD光盤的文件存儲
TS適用於容易發生錯誤的環境,典型應用就是數字電視信號的傳輸。
TS和PS是可以互相轉換的,比如從TS中抽取一道節目的內容並產生有效的PS是可能。
(5)傳輸流分組和PES分組
原始流分成很多PES分組,保持串行順序,一個PES分組只包含一個原始流的編碼數據。PES分組長度很大,最大可為64K字節。
PES分組分為“分組首部(header)”和“有效負載(payload)”。“有效負載”指跟隨在首部字節之后的字節。首部的前4個字節構成分組的起始碼,標識了該分組所屬原始流的類型和ID號。
TS分組也就是傳輸流數據形成的數據包。每個TS分組長度為188字節,包括“分組首部”和“有效負載,前4個字節是分組首部,包含了這個分組的一些信息。有些情況下需要更多的信息時,需在后面添加“調整字段(adaption field)”。

兩者之間的關系:

(5)PSI
全稱Program Specific Information,意為節目專用信息。傳輸流中是多路節目復用的,那么,怎么知道這些節目在傳輸流中的位置,區分屬於不同節目呢?所以就還需要一些附加信息,這就是PSI。PSI也是插入到TS分組中的,它們的PID是特定值。
MPEG-2中規定了4個PSI,包括PAT(節目關聯表),CAT(條件訪問表),PMT(節目映射表),
NIT(網絡信息表),這些PSI包含了進行多路解調和顯示節目的必要的和足夠的信
息。
具體的應用中可能包括更多的信息,比如DVB-T中定義了SDT(服務描述表),EIT(環境信息表),BAT(節目組相關表),TDT(時間日期表)等,統稱為DVB-SI(服務信息)。
PMT (Program Map Table )節目映射表
PMT所在分組的PID由PAT指定,所以要先解出PAT,再解PMT
PMT中包含了屬於同一節目的視頻、音頻和數據原始流的PID。
找到了PMT,解多路復用器就可找到一道節目對應的每個原始流的PID,再根據原始流
PID,去獲取原始流。如下圖:PID1和PID2分別對應某道節目的視頻原始流和音頻原始流
的PID。


二、數據結構
(1)TS分組
transport_packet()
{
sync_byte // 8 transport_error_indicator //1 payload_unit_start_indicator //1 transport_priority // 1
PID //13
transport_scrambling_control // 2 adaptation_field_control //2 continuity_counter //4 if(adaptation_field_control=='10' || adaptation_field_control=='11'){ adaptation_field() } if(adaptation_field_control=='01' || adaptation_field_control=='11') { for (i=0;i<N;i++){ data_byte //8 } } } |
sync_byte 同步字節,固定為0x47 ,表示后面的是一個TS分組,當然,后面包中的數據是不會出現0x47的
transport_error_indicator 傳輸錯誤標志位,一般傳輸錯誤的話就不會處理這個包了
payload_unit_start_indicator 這個位功能有點復雜,字面意思是有效負載的開始標志,根據后面有效負載的內容不同功能也不同,后面用到的時候再說。
transport_priority 傳輸優先級位,1表示高優先級,傳輸機制可能用到,解碼好像用不着。
PID 這個比較重要,指出了這個包的有效負載數據的類型,告訴我們這個包傳輸的是什么內容。前面已經敘述過。
transport_scrambling_control加密標志位,表示TS分組有效負載的加密模式。TS分組首部(也就是前面這32bit)是不應被加密的,00表示未加密。
adaption_field_control 翻譯為“調整字段控制”,表示TS分組首部后面是否跟隨有調整字段和有效負載。01僅含有效負載,10僅含調整字段,11含有調整字段和有效負載。為00的話解碼器不進行處理。空分組沒有調整字段。
(2)PAT
program_association_section() { table_id // 8 section_syntax_indicator //1 '0' //1 reserved // 2 section_length //12 transport_stream_id // 16 reserved // 2 version_number // 5 current_next_indicator //1 section_number //8 last_section_number // 8 for (i=0; i<N;i++) { program_number // 16 reserved // 3 if(program_number == '0') { network_PID // 13 } else { program_map_PID // 13 } } CRC_32 // 32 } |
table_id 固定為0x00 ,標志是該表是PAT
section_syntax_indicator 段語法標志位,固定為1
section_length 表示這個字節后面有用的字節數,包括CRC32。假如后面的字節加上前面的字節數少於188,后面會用0XFF填充。假如這個數值比較大,則PAT會分成幾部分來傳輸。
transport_stream_id 該傳輸流的ID,區別於一個網絡中其它多路復用的流。
version_number 范圍0-31,表示PAT的版本號,標注當前節目的版本.這是個非常有用的參數,當檢測到這個字段改變時,說明TS流中的節目已經變化了,程序必須重新搜索節目.
current_next_indicator 表示發送的PAT是當前有效還是下一個PAT有效。
section_number 分段的號碼。PAT可能分為多段傳輸,第一段為00,以后每個分段加1,最多可能有256個分段
last_section_number 最后一個分段的號碼
program_number 節目號
network_PID 網絡信息表(NIT)的PID,網絡信息表提供了該物理網絡的一些信息,和電視台相關的。節目號為0時對應的PID為network_PID
program_map_PID 節目映射表的PID,節目號大於0時對應的PID,每個節目對應一個
CRC_32 CRC32校驗碼
上面program_number,network_PID,program_map_PID 是循環出現的。program_number等於0時對應network_PID,program_number等於其它值時對應program_map_PID。
舉個例子,下述流為帶PAT的TS分組:
47 40 00 1c 00 00 b0 15 13 f6 e7 00 00 00 00 e0 10 00 01 e0 20 00 02 e0 21 1a 34 b4 77 ff…………..ff
其中紅色的四個字節是TS分組頭部,用數據結構解出首部,得到PID=0x00,表示為該分組的有效負載是PAT。藍色的00稱為“指針域”----Pointer field,表示了一個偏移量,即從后面第幾個字節開始是PAT部分。為00表示后面緊接着的就是PAT:00 b0 15 13 f6 e7 00 00 00 00 e0 10 00 01 e0 20 00 02 e0 21 1a 34 b4 77
再利用PAT的數據結構解出PAT,得到如下信息:
---------------PAT Information-------------
table_id: 00
section_syntax_indicator: 01
section_length: 0015
transport_stream_id: 13f6
version_number: 13
current_next_indicator: 01
section_number: 00
last_section_number: 00
program_number: 0000
program_number: 0001
program_map_PID: 0020
program_number: 0002
program_map_PID: 0021
CRC_32: 1a34b477
可以看出,此PAT只有一段,包含了三個節目,節目號0000對應於network_PID=0010 ,節目號0001對應於program_map_PID =0020,節目號0002對應於program_map_PID =0021,從實際的角度,我們應該把這三個節目號理解為三個頻道,第一個頻道中的內容是網絡信息,第二、三個頻道包含了節目信息。在數字電視中,一個頻道即對應於一個頻點,如498MHZ,一個頻道上可以有多個節目,后面的PMT即是告訴了我們某個頻道中所有節目對應的PID。
於是現在就搜尋PID=0x0020的TS分組,即是頻道2對應的PMT信息。
(其實樓主的理解不是完全正確,transport_stream_id標識了一個唯一的傳輸流(每一個傳輸流對應一個頻點,如498MHz),一個PAT表表示一個流里面的信息。
上面的三個節目號理解為三個頻道是正確的,但在數字電視中,一個頻道對應的也是一個節目,而不是一個頻點(當然節目號為0時對應的是NIT的PID)。)
(3)PMT
TS_program_map_section() { table_id // 8 section_syntax_indicator //1 '0' // 1 reserved // 2 section_length // 12 program_number //16 reserved // 2 version_number //5 current_next_indicator //1 section_number // 8 last_section_number //8 reserved //3 PCR_PID //13 reserved 4 program_info_length //12 for (i=0; i<N; i++) { descriptor() } for (i=0;i<N1;i++) { stream_type //8 reserved //3 elementary_PID //13 reserved //4 ES_info_length //12 for (i=0; i<N2; i++) { descriptor() } } CRC_32 //32 } |
table_id 固定為0x02 ,標志是該表是PMT
section_syntax_indicator
section_length
version_number
current_next_indicator 以上四個字段意思和PAT相同,可參考上面解釋
section_number
last_section_number 以上兩個字段意思和PAT相同,不過值都固定為0x00,我覺得這樣的原因可能是因為PMT不需要有先后順序,因為先定義哪個節目都是無所謂。
program_number 節目號,表示該PMT對應的節目
PCR_PID PCR(節目時鍾參考)所在TS分組的PID,根據PID可以去搜索相應的TS分組,解出PCR信息。
program_info_length 該節目的信息長度,在此字段之后可能會有一些字節描述該節目的信息
stream_type 指示了PID為elementary_PID的PES分組中原始流的類型,比如視頻流,音頻流等,見后面的表
elementary_PID 該節目中包括的視頻流,音頻流等對應的TS分組的PID
ES_info_length 該節目相關原始流的描述符的信息長度。

還是舉個例子,下述是一個包含PMT的TS分組,
47 40 20 1c 00 02 b0 1f 00 01 e7 00 00 e1 00 f0 00 02 e1 00 f0 05 02 03 b2 44 5f 04 e1 10 f0 03 03 01 67 c9 ab c8 d2
紅色的四個字節是TS分組頭部,藍色的00是“指針域”,意義同PAT中的指針域。所以下面的數據就是PMT的內容:02 b0 1f 00 01 e7 00 00 e1 00 f0 00 02 e1 00 f0 05 02 03 b2 44 5f 04 e1 10 f0 03 03 01 67 c9 ab c8 d2
再解出PMT,得到下列信息:
table_id: 02
section_syntax_indicator: 01
section_length: 01f
program_number: 0001
version_number: 13
current_next_indicator: 01
section_number: 00
last_section_number: 00
PCR_PID: 0100
program_info_length: 000
descriptor:
steam_type: 00
elementary_PID: 0001
ES_info_length: 000
descriptor:
steam_type: 02
elementary_PID: 0001
ES_info_length: 005
descriptor: 02 03 b2 44 5f
steam_type: 04
elementary_PID: 0011
ES_info_length: 003
descriptor: 03 01 67
CRC_32: c9abc8d2
可以看出,該節目號0001包含了三個流的信息,流類型分別為00,02,04,00的流為保留值,可以不考慮,02表示原始流為視頻流,其elementary_PID為0001,04表示原始流為音頻流,其elementary_PID為0011,兩個流分別還帶有descriptor(描述符),說明了該原始流的一些信息。
得到了這個elementary_PID,再從后面的傳輸流中找到PID為這個值的TS分組,其有效負載即為這個原始流的數據,獲取數據送到解碼器,即可還原這個視頻或音頻了。
三、總結
上面的都是一些零散的知識,跟我們實際應用有什么關系呢?下面就是一個簡易的應用過程---搜台。搜台過程大致如下:
先調整高頻頭到一個固定的頻率(如498MHZ),如果此頻率有數字信號,則相關芯片會自動把TS流數據傳送給MPEG- 2 decoder. MPEG-2 decoder先進行數據的同步,也就是等待完整的Packet的到來.然后循環查找是否出現PID== 0x0000的Packet,如果出現了,則馬上進入分析PAT的處理,獲取了所有的PMT的PID.接着循環查找是否出現PMT,如果發現了,則自動進入PMT分析,獲取該頻段所有的頻道數據並保存.如果沒有發現PAT或者沒有發現PMT,說明該頻段沒有信號,進入下一個頻率掃描。
上述過程主要涉及到PAT和PMT的一些解碼和解復用知識,這也是目前我學習到的,當然,數字電視涉及到的知識遠遠不止這些,解碼方面就還包括調整字段的處理,SI(業務信息)應用,時鍾的處理,CA加密解MI系統等,還需要繼續的學習和實踐。
TS流格式
http://wenku.baidu.com/link?url=w6wnbauBx0N4Ux9iXA-j-6sI65YboViaXhC95C3-QjxAErmszxg6PTOI4WoaaK14GnuoZGJkF2BSSUZP5CbxNYOcWvTaaYAFhLbU54z1aVu