TS流分析
一 從TS流開始
數(shù)字電視機(jī)頂盒接收到的是一段段的碼流,我們稱之為TS(Transport Stream,傳輸流),每個TS流都攜帶一些信息,如Video、Audio以及我們需要學(xué)習(xí)的PAT、PMT等信息。因此,我們首先需要了解TS流是什么,以及TS流是怎樣形成、有著怎樣的結(jié)構(gòu)。
(一) TS流、PS流、PES流和ES流都是什么?
ES流(Elementary Stream):基本碼流,不分段的音頻、視頻或其他信息的連續(xù)碼流。
PES流:把基本流ES分割成段,并加上相應(yīng)頭文件打包成形的打包基本碼流。
PS流(Program Stream):節(jié)目流,將具有共同時間基準(zhǔn)的一個或多個PES組合(復(fù)合)而成的單一數(shù)據(jù)流(用于播放或編輯系統(tǒng),如m2p)。
TS流(Transport Stream):傳輸流,將具有共同時間基準(zhǔn)或獨立時間基準(zhǔn)的一個或多個PES組合(復(fù)合)而成的單一數(shù)據(jù)流(用于數(shù)據(jù)傳輸)。
*NOTE:TS流和PS流的區(qū)別:TS流的包結(jié)構(gòu)是長度是固定的;PS流的包結(jié)構(gòu)是可變長度的。這導(dǎo)致了TS流的抵抗傳輸誤碼的能力強(qiáng)于PS流(TS碼流由于采用了固定長度的包結(jié)構(gòu),當(dāng)傳輸誤碼破壞了某一TS包的同步信息時,接收機(jī)可在固定的位置檢測它后面包中的同步信息,從而恢復(fù)同步,避免了信息丟失。而PS包由于長度是變化的,一旦某一PS包的同步信息丟失,接收機(jī)無法確定下一包的同步位置,就會造成失步,導(dǎo)致嚴(yán)重的信息丟失。因此,在信道環(huán)境較為惡劣,傳輸誤碼較高時,一般采用TS碼流;而在信道環(huán)境較好,傳輸誤碼較低時,一般采用PS碼流。)
由于TS碼流具有較強(qiáng)的抵抗傳輸誤碼的能力,因此目前在傳輸媒體中進(jìn)行傳輸?shù)腗PEG-2碼流基本上都采用了TS碼流的包格。
(二) TS流是如何產(chǎn)生的?
從上圖可以看出,視頻ES和音頻ES通過打包器和共同或獨立的系統(tǒng)時間基準(zhǔn)形成一個個PES,通過TS復(fù)用器復(fù)用形成的傳輸流。注意這里的TS流是位流格式(分析Packet的時候會解釋),也即是說TS流是可以按位讀取的。
(三) TS流的格式是怎樣的?
TS流是基于Packet的位流格式,每個包是188個字節(jié)(或204個字節(jié),在188個字節(jié)后加上了16字節(jié)的CRC校驗數(shù)據(jù),其他格式一樣)。整個TS流組成形式如下:
Packet Header(包頭)信息說明
1
sync_byte
8bits
同步字節(jié)
2
transport_error_indicator
1bit
錯誤指示信息(1:該包至少有1bits傳輸錯誤)
3
payload_unit_start_indicator
1bit
負(fù)載單元開始標(biāo)志(packet不滿188字節(jié)時需填充)
4
transport_priority
1bit
傳輸優(yōu)先級標(biāo)志(1:優(yōu)先級高)
5
PID
13bits
Packet ID號碼,唯一的號碼對應(yīng)不同的包
6
transport_scrambling_control
2bits
加密標(biāo)志(00:未加密;其他表示已加密)
7
adaptation_field_control
2bits
附加區(qū)域控制
8
continuity_counter
4bits
包遞增計數(shù)器
PID是TS流中唯一識別標(biāo)志,Packet Data是什么內(nèi)容就是由PID決定的。如果一個TS流中的一個Packet的Packet Header中的PID是0x0000,那么這個Packet的Packet Data就是DVB的PAT表而非其他類型數(shù)據(jù)(如Video、Audio或其他業(yè)務(wù)信息)。下表給出了一些表的PID值,這些值是固定的,不允許用于更改。
表
PID 值
PAT
0x0000
CAT
0x0001
TSDT
0x0002
EIT,ST
0x0012
RST,ST
0x0013
TDT,TOT,ST
0x0014
下面以一個TS流的其中一個Packet中的Packet Header為例進(jìn)行說明:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
…
Packet(十六進(jìn)制)
4
7
0
7
e
5
1
2
…
Packet(二進(jìn)制)
0
1
0
0
0
1
1
1
0
0
0
0
0
1
1
1
1
1
1
0
0
1
0
1
0
0
0
1
0
0
1
0
…
Packet Header 信息
1 sync_byte=0x47
2
3
4
5 PID=0x07e5
6
7
8
…
sync_byte=01000111, 就是0x47,這是DVB TS規(guī)定的同步字節(jié),固定是0x47.
transport_error_indicator=0, 表示當(dāng)前包沒有發(fā)生傳輸錯誤.
payload_unit_start_indicator=0, 含義參考ISO13818-1標(biāo)準(zhǔn)文檔
transport_priority=0,表示當(dāng)前包是低優(yōu)先級.
PID=00111 11100101即0x07e5, Video PID
transport_scrambling_control=00,表示節(jié)目沒有加密
adaptation_field_control=01即0x01,具體含義請參考ISO13818-1
continuity_counte=0010即0x02,表示當(dāng)前傳送的相同類型的包是第3個
TS流的基本內(nèi)容就是這些了。
回顧一下,TS流是一種位流(當(dāng)然就是數(shù)字的),它是由ES流分割成PES后復(fù)用而成的;它經(jīng)過網(wǎng)絡(luò)傳輸被機(jī)頂盒接收到;數(shù)字電視機(jī)頂盒接收到TS流后將解析TS流。
TS流是由一個個Packet(包)構(gòu)成的,每個包都是由Packet Header(包頭)和Packet Data(包數(shù)據(jù))組成的。其中Packet Header指示了該Packet是什么屬性的,并給出了該Packet Data的數(shù)據(jù)的唯一網(wǎng)絡(luò)標(biāo)識符PID。
到這里,我們對TS流已經(jīng)有了一定的了解,下面將從TS流轉(zhuǎn)向PAT表和PMT表的學(xué)習(xí)。
二 從TS流到PAT、PMT
說完了TS流的基本概念,就該開始對TS流進(jìn)行更深入的研究了。首先需要想一想:TS流的本質(zhì)是什么?它的確是一段碼流,并且是一段由數(shù)據(jù)包(Packet)組成的碼流。那么這些數(shù)據(jù)包究竟是怎樣的呢?它和我們收看的電視節(jié)目之間又有什么區(qū)別?這些都是這部分需要了解的內(nèi)容。
在上一節(jié)中,我們可以看到PID這個被標(biāo)紅的字段頻繁地出現(xiàn)。PID是當(dāng)前TS流的Packet區(qū)別于其他Packet類型的唯一識別符,通過讀取每個包的Packet Header,我們可以知道這個Packet的數(shù)據(jù)屬于何種類型。上一節(jié)列出了幾項固定的PID值,它們用于識別存儲了特殊信息的Packet。下面要談的PAT表的PID值就是固定的0x0000。
(一) PAT表(Program Association Table,節(jié)目關(guān)聯(lián)表)
由于下面的內(nèi)容比較繁雜,這里先給出一個大綱,方便查閱:
1. PAT表的描述(表格+分析)
2. PAT表的定義(代碼+分析)
3. PAT表的結(jié)構(gòu)(代碼+分析)
4. PAT表的解析(代碼+分析)
5. 通過一段TS流中一個Packet分析PAT表(表格+分析)
下面,開始正式的分析!
1.PAT表的描述(表格+分析)
PAT表定義了當(dāng)前TS流中所有的節(jié)目,其PID為0x0000,它是PSI的根節(jié)點,要查尋找節(jié)目必須從PAT表開始查找。
PAT表攜帶以下信息:
TS流ID
transport_stream_id
該ID標(biāo)志唯一的流ID
節(jié)目頻道號
program_number
該號碼標(biāo)志TS流中的一個頻道,該頻道可以包含很多的節(jié)目(即可以包含多個Video PID和Audio PID)
PMT的PID
program_map_PID
表示本頻道使用哪個PID做為PMT的PID,因為可以有很多的頻道,因此DVB規(guī)定PMT的PID可以由用戶自己定義
2. PAT表的定義(代碼+分析)
PAT表主要包含頻道號碼和每一個頻道對應(yīng)的PMT的PID號碼,這些信息我們在處理PAT表格的時候會保存起來,以后會使用到這些數(shù)據(jù)。下面將PAT表的定義給出:
[cpp]view plaincopy typedefstructTS_PAT_Program { unsignedprogram_number:16;//節(jié)目號 unsignedprogram_map_PID:13;//節(jié)目映射表的PID,節(jié)目號大于0時對應(yīng)的PID,每個節(jié)目對應(yīng)一個 }TS_PAT_Program
3. PAT表的結(jié)構(gòu)(代碼+分析)
再將PAT表的結(jié)構(gòu)體給出:
[cpp]view plaincopy typedefstructTS_PAT { unsignedtable_id:8;//固定為0x00,標(biāo)志是該表是PAT表 unsignedsection_syntax_indicator:1;//段語法標(biāo)志位,固定為1 unsignedzero:1;//0 unsignedreserved_1:2;//保留位 unsignedsection_length:12;//表示從下一個字段開始到CRC32(含)之間有用的字節(jié)數(shù) unsignedtransport_stream_id:16;//該傳輸流的ID,區(qū)別于一個網(wǎng)絡(luò)中其它多路復(fù)用的流 unsignedreserved_2:2;//保留位 unsignedversion_number:5;//范圍0-31,表示PAT的版本號 unsignedcurrent_next_indicator:1;//發(fā)送的PAT是當(dāng)前有效還是下一個PAT有效 unsignedsection_number:8;//分段的號碼。PAT可能分為多段傳輸,第一段為00,以后每個分段加1,最多可能有256個分段 unsignedlast_section_number:8;//最后一個分段的號碼 std::vector