版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
基于流媒體的數(shù)字電視的軟件實現(xiàn)——關于TS流的解析
制作人:張進目錄1.MPEG系統(tǒng)2.TS的基本概念3.TS的解析4..TS流的數(shù)據(jù)結構5.TS流的解析實例講解1.MPEG系統(tǒng)隨著通信數(shù)字技術的快速發(fā)展,一種全新的采用數(shù)字電視技術的電視系統(tǒng)被廣泛采用,相比模擬電視系統(tǒng)其具有很多優(yōu)點。數(shù)字電視的核心技術是MPEG(MovingPictureExpertGroup)的編碼與解碼技術,基于它的標準產生兩種碼流:節(jié)目碼流和傳輸碼流(TS流)。MPEG系統(tǒng)任務簡介一.MPEG–2是一個系統(tǒng),它的作用是:對音頻、視頻、數(shù)據(jù)、控制等基本比特流實現(xiàn)復用提供各種定時及初始化經解碼器提供PSI(節(jié)目特定信息)支持有條件接收(CA),隨機接入,數(shù)字存儲和糾錯二.MPEG-2系統(tǒng)輸出兩個數(shù)碼流:節(jié)目比特流PS,用于相對無誤差的環(huán)境傳輸比特流TS,用于有噪聲媒質MPEG系統(tǒng)結構圖系統(tǒng)層信息流通方式
首先,從視頻、音頻編碼器而來的數(shù)據(jù)稱為基本碼流(ES),然后,ES被分別打包,形成兩個打包的基本碼流(PES),再后,PES被復接成一個節(jié)目碼流(PS)和一個傳輸碼流(TS)。其圖示如下基本碼流ES→打包基本碼流PES→節(jié)目碼流PS傳輸碼流TS
ES-ElementaryStreams(原始流),對視頻、音頻信號及其他數(shù)據(jù)進行編碼壓縮后的數(shù)據(jù)流稱為原始流。原始流包括訪問單元,比如視頻原始流的訪問單元就是一副圖像的編碼數(shù)據(jù)。
PES-PacketizedElementaryStreams(分組的原始流),原始流形成的分組稱為PES分組,是用來傳遞原始流的一種數(shù)據(jù)結構
節(jié)目是節(jié)目元素的集合。節(jié)目元素可能是原始流,這些原始流有共同的時間基點,用來做同步顯示。
PS的組成單位是PES分組。TS用來傳輸和保存多道節(jié)目的編碼數(shù)據(jù)或其他數(shù)據(jù),TS的組成單位是節(jié)目。PS適用于不容易發(fā)生錯誤的環(huán)境,以及涉及到軟件處理的應用,典型應用如DVD光盤的文件存儲TS適用于容易發(fā)生錯誤的環(huán)境,典型應用就是數(shù)字電視信號的傳輸。TS和PS是可以互相轉換的,比如從TS中抽取一道節(jié)目的內容并產生有效的PS是可能。
MPEG-2的同步
MPEG算法提供一定的定時方法,保證視音頻的同步。
MPEG-1為解碼器制定了兩個時鐘:系統(tǒng)時鐘基準(SCR)顯示時間標記(PTS)
MPEG-2為解碼器制定了三個時鐘:系統(tǒng)時鐘基準(SCR)顯示時間標記(PTS)節(jié)目時鐘基準(PCR)2.TS的基本概念TransportStream傳輸流將具有共同時間基準或具有獨立時間基準的一個或多個節(jié)目組合而成的單一的數(shù)據(jù)流傳輸流由一系列的包分組構成,分個分組是188個字節(jié),其主體結構分為Header和Payload兩部分。在Header部分是一些包的控制信息,其中PID字段是該包的身份,對包的操作的標識。在Payload字段中含有有效地負載或是傳輸字段。特點:包長固定,188字節(jié);面向數(shù)字化分配媒介(有線、衛(wèi)星、地面網)的傳輸層接口傳輸流由一道或多道節(jié)目組成,每道節(jié)目由一個或多個原始流和其他一些流復合在一起,包括視頻流、音頻流、節(jié)目特殊信息流(PSI)和其他數(shù)據(jù)包。其中,PSI有四種類型:程序關聯(lián)表PAT、程序映射表PMT、網絡信息表NIT、條件訪問表CAT;TS包結構
PSI全稱ProgramSpecificInformation,意為節(jié)目專用信息。傳輸流中是多路節(jié)目復用的,那么,怎么知道這些節(jié)目在傳輸流中的位置,區(qū)分屬于不同節(jié)目呢?所以就還需要一些附加信息,這就是PSI。PSI也是插入到TS分組中的,它們的PID是特定值。MPEG-2中規(guī)定了4個PSI,包括PAT(節(jié)目關聯(lián)表),CAT(條件訪問表),PMT(節(jié)目映射表),NIT(網絡信息表),這些PSI包含了進行多路解調和顯示節(jié)目的必要的和足夠的信息。應用中可能包括更多的信息,比如DVB-T中定義了SDT(服務描述表),EIT(環(huán)境信息表),BAT(節(jié)目組相關表),TDT(時間日期表)等,統(tǒng)稱為DVB-SI(服務信息)。PSI的PID是特定的,含PSI的數(shù)據(jù)包必須周期性的出現(xiàn)在傳輸流中。
PMT(ProgramMapTable)節(jié)目映射表PMT所在分組的PID由PAT指定,所以要先解出PAT,再解PMT。PMT中包含了屬于同一節(jié)目的視頻、音頻和數(shù)據(jù)原始流的PID。找到了PMT,解多路復用器就可找到一道節(jié)目對應的每個原始流的PID,再根據(jù)原始流PID,去獲取原始流。
PAT(ProgramAssociationTable)節(jié)目關聯(lián)表PAT所在分組的PID=0PAT中列出了傳輸流中存在的節(jié)目流PAT指定了傳輸流中每個節(jié)目對應PMT所在分組的PIDPAT的第一條數(shù)據(jù)指定了NIT所在分組的PID,其他數(shù)據(jù)指定了PMT所在分組的PID。
CAT(ConditionalAccessTable)條件訪問表CAT所在分組的PID=1CAT中列出了條件控制信息(ECM)和條件管理信息(EMM)所在分組的PID。CAT用于節(jié)目的加密和解密NIT(NetworkInformationTable)網絡信息表NIT所在分組的PID由PAT指定NIT提供一組傳輸流的相關信息,以及于網絡自身特性相關的信息,比如網絡名稱,傳輸參數(shù)(如頻率,調制方式等)。NIT一般是解碼器內部使用的數(shù)據(jù),當然也可以做為EPG的一個顯示數(shù)據(jù)提供給用戶做為參考。幾種PSI之間的關系,如下圖所示:首先PAT中指定了傳輸流中所存在的節(jié)目,及每個節(jié)目對應的PMT的PID號。比如Program1對應的PMT的PID=22,然后找到PID=22的TS分組,解出PMT,得到這個節(jié)目中包含的原始流的PID,再根據(jù)原始流的PID去找相應的TS分組,獲取原始流的數(shù)據(jù),然后就可以送入解碼器解碼了。3.TS流的解析PSI由四張表構成:PAT,PMT,CAT和NIT,這四張表分別描述了一個TS所包括的所有ES流的傳輸結構。首先的一個概念是,TS是以包形式傳播,在編解碼端都需要以一定的包ID來標識TS流里承載的內容,比如,PAT表會存在于一個或多個TS包里,所以要用一個特別的包ID來表示,另外,不同的ES流也需要不同的包ID來標識。我們有了PAT和PMT這兩種表,解碼器就可以根據(jù)PID,將TS上從不同ES來的TS包區(qū)分出來進行解碼。TS的解碼分兩步進行,其一,是從PID為0的TS包里,解析出PAT表,然后從PAT表里找到各個節(jié)目源的PID,一般此類節(jié)目源都由若干個ES流組成,并描述在PMT表里面,然后通過節(jié)目源的PID,就可以在PMT表里檢索到各個ES的PID。其二,解碼器根據(jù)PMT表里的ES流的PID,將TS流上的包進行區(qū)分,并按不同的ES流進行解碼。所以,TS是經過節(jié)目復用和傳輸復用兩層完成的,即在節(jié)目復用時,加入了PMT,在傳輸復用時,加入了PAT。同樣在節(jié)目解復用時,可以得到PMT,在傳輸解復用時,可以得到PAT。下圖很好地概述了其思想。TS是支持多路復用的,所以它可用來傳輸經復用后的多層節(jié)目。在復用過程中,要注意的是,解碼過程中所需要面對的時間參考和同步問題,因為解復用是需要各種信息同步進行的,所以在復用過程中,就需要插入相關的時間信息:PTS,DTS,PCR。在TS形成過程中,PTS和DTS是在ES打包成PES時,根據(jù)STC的參考,將其時鐘信息注入PES包中的,而之后在PES切成TS時,再將PID和PCR信息注入到TS包中,當多路TS再進行復用的時候,各路TS的PCR將會被提取出來,再進行分析,然后再根據(jù)統(tǒng)一的STC參考,將新的PCR生成并注入到TS中去,最后,因為原來PAT表信息不在適用,所以新的PAT表需要再生成,并附加到新的TS流中去。經過這多層的復用之后,新的TS流即可以進入調制,傳輸階段。過程可參見下圖:解碼過程要面對的問題是:解復用,視音頻的同步,解碼緩存器無上下溢。解復用即是將TS在同一信道里不同時序進行傳輸?shù)墓?jié)目分離出來;視音頻同步由DTS,PTS和PCR三者協(xié)調完成,并且PCR是重建系統(tǒng)時間基準的絕對時標,而DTS和PTS是解碼和重現(xiàn)時刻的相對時標;對解碼緩存器無上下溢的問題,必須借助于系統(tǒng)目標解碼器(STD)模型來對其進行實現(xiàn),基本思想如下:TS流進入解碼器后,首先由換向器,按照一定的時序關系,將各種ES流分解出來(其中也包括PSI信息流)。分解過后的ES流會進入各自的傳輸緩存器,通過之后,其PES流進入各自的主存儲器,注意的是:PSI信息流會進入系統(tǒng)緩存器,最后也到達主存儲器。最后,解碼器根據(jù)DTS信息,從各個主存儲器分別提取媒體或系統(tǒng)信息,進行解碼,并根據(jù)PTS信息,將媒體內容進行顯示處理。其過程可參見下圖由圖可知:1.PSI依然是"根",只有定位到PSI表后,才能索引出PAT,和各個節(jié)目的PMT表。2.PAT表記錄了什么呢?表頭信息和節(jié)目信息。
表頭信息包含若干字段,但最關鍵的是version_number,why?因為TS流里任何節(jié)目信息的變化,這個字段都會往上遞加,從而使得TS解碼器可以據(jù)此讓Decoder對不同節(jié)目做解碼復位。
節(jié)目信息包括TS流里每路節(jié)目的program_number,PMT_PID。由此再結合表頭信息,TS解碼器即可以定位到具體的有變化的節(jié)目流(新增或減少)
3.接下來和PAT表平行的就是PMT表了,因為PAT表已經給出明確的節(jié)目信息,所以,解碼器可以定位到自己需要的節(jié)目。在PMT表里,我們可以看到表頭信息,和音視頻的stream_type,PID信息等。這樣解碼器即可以定位到具體的音視頻包上,進行節(jié)目解碼。4.TS的數(shù)據(jù)結構因為在TS流里可以填入很多種東西,所以有必要有一種機制來確定怎么來標識這些數(shù)據(jù)。制定TS流標準的機構就規(guī)定了一些數(shù)據(jù)結構來定義。比如:PSI(ProgramSpecificInformation)表,所以解析起來就像這樣:先接收一個負載里為PAT的數(shù)據(jù)包,在整個數(shù)據(jù)包里找到一個PMT包的ID。然后再接收一個含有PMT的數(shù)據(jù)包,在這個數(shù)據(jù)包里找到有關填入數(shù)據(jù)類型的ID。之后就在接收到的TS包里找含有這個ID的負載內容,這個內容就是填入的信息。根據(jù)填入的數(shù)據(jù)類型的ID的不同,在TS流復合多種信息是可行的。關鍵就是找到標識的ID號。數(shù)據(jù)結構(1)TS分組前面提到,TS分組由188個字節(jié)構成,其結構如下:
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
}
}
}前面32bit的數(shù)據(jù)即TS分組首部,它指出了這個分組的屬性。sync_byte
同步字節(jié),固定為0x47
,表示后面的是一個TS分組,當然,后面包中的數(shù)據(jù)是不會出現(xiàn)0x47的transport_error_indicator
傳輸錯誤標志位,一般傳輸錯誤的話就不會處理這個包了payload_unit_start_indicator
這個位功能有點復雜,字面意思是有效負載的開始標志,根據(jù)后面有效負載的內容不同功能也不同,后面用到的時候再說。transport_priority
傳輸優(yōu)先級位,1表示高優(yōu)先級,傳輸機制可能用到,解碼好像用不著。PID
這個比較重要,指出了這個包的有效負載數(shù)據(jù)的類型,告訴我們這個包傳輸?shù)氖鞘裁磧热?。前面已經敘述過。transport_scrambling_control
加密標志位,表示TS分組有效負載的加密模式。TS分組首部(也就是前面這32bit)是不應被加密的,00表示未加密。
adaption_field_control
翻譯為“調整字段控制”,表示TS分組首部后面是否跟隨有調整字段和有效負載。01僅含有效負載,10僅含調整字段,11含有調整字段和有效負載。為00的話解碼器不進行處理??辗纸M沒有調整字段
continuity_counter
一個4bit的計數(shù)器,范圍0-15,具有相同的PID的TS分組傳輸時每次加1,到15后清0。不過,有些情況下是不計數(shù)的。如下:(1)TS分組無有效負載(2)復制的TS分組和原分組這個值一樣(3)后面講到的一個標志discontinuity_indicator為1時adaptation_field()
調整字段的處理data_byte
有效負載的剩余部分,可能為PES分組,PSI,或一些自定義的數(shù)據(jù)。(2)
PAT數(shù)據(jù)結構如下:
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
,標志是該表是PATsection_syntax_indicator
段語法標志位,固定為1section_length
表示這個字節(jié)后面有用的字節(jié)數(shù),包括CRC32。假如后面的字節(jié)加上前面的字節(jié)數(shù)少于188,后面會用0XFF填充。假如這個數(shù)值比較大,則PAT會分成幾部分來傳輸。transport_stream_id
該傳輸流的ID,區(qū)別于一個網絡中其它多路復用的流。version_number范圍0-31,表示PAT的版本號,標注當前節(jié)目的版本.這是個非常有用的參數(shù),當檢測到這個字段改變時,說明TS流中的節(jié)目已經變化了,程序必須重新搜索節(jié)目.current_next_indicator
表示發(fā)送的PAT是當前有效還是下一個PAT有效。section_number分段的號碼。PAT可能分為多段傳輸,第一段為00,以后每個分段加1,最多可能有256個分段last_section_number
最后一個分段的號碼
program_number
節(jié)目號network_PID
網絡信息表(NIT)的PID,網絡信息表提供了該物理網絡的一些信息,和電視臺相關的。節(jié)目號為0時對應的PID為network_PIDprogram_map_PID
節(jié)目映射表的PID,節(jié)目號大于0時對應的PID,每個節(jié)目對應一個CRC_32
CRC32校驗碼上面program_number,network_PID,program_map_PID
是循環(huán)出現(xiàn)的。program_number等于0時對應network_PID,program_number等于其它值時對應program_map_PID。(3)PMT
PMT數(shù)據(jù)結構如下:
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不需要有先后順序,因為先定義哪個節(jié)目都是無所謂。program_number
節(jié)目號,表示該PMT對應的節(jié)目PCR_PID
PCR(節(jié)目時鐘參考)所在TS分組的PID,根據(jù)PID可以去搜索相應的TS分組,解出PCR信息。program_info_length
該節(jié)目的信息長度,在此字段之后可能會有一些字節(jié)描述該節(jié)目的信息stream_type
指示了PID為elementary_PID的PES分組中原始流的類型,比如視頻流,音頻流等,見后面的表elementary_PID
該節(jié)目中包括的視頻流,音頻流等對應的TS分組的PIDES_info_length
該節(jié)目相關原始流的描述符的信息長度。5.TS流的解析實例講解TS流中的每個Packet為188個字節(jié),一個section可能由一個或多個Packet組成,而一個Table(如PAT、PMT、NIT等)則由多個Section組成,同一個表中的Section通過Tableid來加以細分。在讀取TS流文件時我們每次讀取188個字節(jié),進而形成Packet隊列和Section隊列。Packet隊列可以根據(jù)包的PID的值的不同添加到相應的隊列中。幾種PSI之間的關系:首先PAT中指定了傳輸流中所存在的節(jié)目,及每個節(jié)目對應的PMT的PID號。
比如Program1對應的PMT
的PID=22,然后找到PID=22的TS分組,解出PMT,得到這個節(jié)目中包含的原始流的PID,再根據(jù)原始流的PID去找相應的TS分組,獲取原始流的數(shù)據(jù),然后就可以送入解碼器解碼了。
根據(jù)前一篇中各數(shù)據(jù)的定義及數(shù)據(jù)結構,對數(shù)據(jù)進行分別解析如下:現(xiàn)在以一個例子來說明具體的操作:
在開始之前先給出一片實際TS流例子:
0000f32ch:474000170000B00D0001C10000
0001E0;G@....?..?...?
0000f33ch:20A2C32941FFFF
FF
FF
FF
FF
FF
FF
FF
FF
FF;
⒚)A
0000f34ch:FFFF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF;
0000f35ch:FFFF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF;
0000f36ch:FFFF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF;
0000f37ch:FFFF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF;
0000f38ch:FFFF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF;
0000f39ch:FFFF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF;
0000f3ach:FFFF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF;
0000f3bch:FFFF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF;
0000f3cch:FFFF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF;
0000f3dch:FFFF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF47402017;G@.
0000f3ech:0002B01B0001C10000E021F0001BE021;..?..?.??.?
0000f3fch:F0042A027E1F03E022F0005D16BD48
;具體的分析就以這個例子來分析。//AdjustTSpacketheader
voidadjust_TS_packet_header(TS_packet_header*pheader)
{
unsignedcharbuf[4];
memcpy(buf,pheader,4);
pheader->transport_error_indicator
=buf[1]>>7;
pheader->payload_unit_start_indicator
=buf[1]>>6&0x01;
pheader->transport_priority=buf[1]>>5&0x01;
pheader->PID
=(buf[1]&0x1F)<<8|buf[2];
pheader->transport_scrambling_control
=buf[3]>>6;
pheader->adaption_field_control
=buf[3]>>4&0x03;
pheader->continuity_counter
=buf[3]&0x03;
}
這是一個調整TS流數(shù)據(jù)包頭的函數(shù),這里牽扯到位段調整的問題。現(xiàn)在看一下TS流數(shù)據(jù)包頭的結構的定義://Transportpacketheader
typedef
struct
TS_packet_header
{
unsignedsync_byte
:8;
unsignedtransport_error_indicator
:1;
unsignedpayload_unit_start_indicator
:1;
unsignedtransport_priority
:1;
unsignedPID
:13;
unsignedtransport_scrambling_control
:2;
unsignedadaption_field_control
:2;
unsignedcontinuity_counter
:4;
}TS_packet_header;
下面我們來分析,在ISO/IEC13818-1里有說明,PAT(ProgramAssociationTable)的PID值為0x00,TS包的標識(即sync_byte)為0x47,并且為了確保這個TS包里的數(shù)據(jù)有效,所以我們一開始查找474000這三組16進制數(shù),為什么這樣?具體的奧秘在TS包的結構上,前面已經說了sync_byte固定為0x47?,F(xiàn)在往下看transport_error_indicator、payload_unit_start_indicator、transport_priority和PID這四個元素,PID為0x00,這是PAT的標識。transport_error_indicator為0,transport_priority為0。把他們看成是兩組8位16進制數(shù)就是:4000?,F(xiàn)在看看我們的TS流片斷例子,看來正好是474000開頭的,一個TS流的頭部占據(jù)了4個字節(jié)。剩下的負載部分的內容由PID來決定,例子看來就是一個PAT表。在這里有個地方需要注意一下,payload_unit_start_indicator為1時,在前4個字節(jié)之后會有一個調整字節(jié),它的數(shù)值決定了負載內容的具體開始位置。現(xiàn)在看例子中的數(shù)據(jù)4740001700第五個字節(jié)是00,說明緊跟著00之后就是具體的負載內容。下面給出PAT表的結構體://PATtable//ProgrammAssociationTable
typedef
structTS_PAT
{
unsignedtable_id
:8;
unsignedsection_syntax_indicator
:1;
unsignedzero
:1;
unsignedreserved_1
:2;
unsignedsection_length
:12;
unsignedtransport_stream_id
:16;
unsignedreserved_2
:2;
unsignedversion_number
:5;
unsignedcurrent_next_indicator
:1;
unsignedsection_number
:8;
unsignedlast_section_number
:8;
unsignedprogram_number
:16;
unsignedreserved_3
:3;
unsignednetwork_PID
:13;
unsignedprogram_map_PID
:13;
unsignedCRC_32
:32;
}TS_PAT;
再給出PAT表字段調整函數(shù)://AdjustPATtable
voidadjust_PAT_table(TS_PAT*packet,char*buffer)
{
intn=0,i=0;
int
len=0;
packet->table_id
=buffer[0];
packet->section_syntax_indicator
=buffer[1]>>7;
packet->zero
=buffer[1]>>6&0x1;
packet->reserved_1
=buffer[1]>>4&0x3;
packet->section_length
=(buffer[1]&0x0F)<<8|buffer[2];
packet->transport_stream_id=buffer[3]<<8|buffer[4];
packet->reserved_2
=buffer[5]>>6;
packet->version_number
=buffer[5]>>1&
0x1F;
packet->current_next_indicator
=(buffer[5]<<7)>>7;
packet->section_number
=buffer[6];
packet->last_section_number
=buffer[7];//GetCRC_32
len=3+packet->section_length;
packet->CRC_32=(buffer[len-4]&0x000000FF)<<24
|(buffer[len-3]&0x000000FF)<<16
|(buffer[len-2]&0x000000FF)<<8
|(buffer[len-1]&0x000000FF);//Parsenetwork_PIDorprogram_map_PID
for(n=0;n<packet->section_length-4;n++)
{
packet->program_number
=buffer[8]<<8|buffer[9];
packet->reserved_3
=buffer[10]>>5;
if(packet->program_number==0x0)
packet->network_PID=(buffer[10]<<3)<<5|buffer[11];
else
{
packet->program_map_PID=(buffer[10]<<3)<<5|buffer[11];
}
n+=5;
}
}
通過上面的分析,例子中的數(shù)據(jù)00B00D0001C10000
0001E020A2C32941就是具體的PAT表的內容,然后根據(jù)PAT結構體來具體分析PAT表。但是我們需要注意的是在PAT表里有program_number、network_PID的元素不只有一個,這兩個元素是通過循環(huán)來確定的。循環(huán)的次數(shù)通過section_length元素的確定。在這個例子中program_map_PID為20,所以下面來PMT分析時,就是查找474020的開頭的TS包。
下面來分析PMT表,先給出PMT(ProgramMapTable)的結構體:
//PMTtable
//ProgramMapTable
typedef
structTS_PMT
{
unsignedtable_id
:8;
unsignedsection_syntax_indicator
:1;
unsignedzero
:1;
unsignedreserved_1
:2;
unsignedsection_length
:12;
unsignedprogram_number
:16;
unsignedreserved_2
:2;
unsignedversion_number
:5;
unsignedcurrent_next_indicator
:1;
unsignedsection_number
:8;
unsignedlast_section_number
:8;
unsignedreserved_3
:3;
unsignedPCR_PID
:13;
unsignedreserved_4
:4;
unsignedprogram_info_length
:12;
unsignedstream_type
:8;
unsignedreserved_5
:3;
unsignedelementary_PID
:13;
unsignedreserved_6
:4;
unsignedES_info_length
:12;
unsignedCRC_32
:32;
}TS_PMT;
在給出調整字段函數(shù):
//AdjustPMTtable
voidadjust_PMT_table(TS_PMT*packet,char*buffer)
{
intpos=12,len=0;
inti=0;
packet->table_id
=buffer[0];
packet->section_syntax_indicator
=buffer[1]>>7;
packet->zero
=buffer[1]>>6;
packet->reserved_1
=buffer[1]>>4;
packet->section_length
=(buffer[1]&0x0F)<<8|buffer[2];
packet->program_number=buffer[3]<<8|buffer[4];packet->reserved_2
=buffer
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024年紡織染整助劑:凈洗劑項目申請報告
- 2024年高純金屬及氧化物項目提案報告范文
- 門窗制品安裝運輸合同
- 時尚珠寶店大門裝修協(xié)議
- 食品運輸合作協(xié)議樣本
- 新能源技術實驗室改造協(xié)議
- 水上冷藏貨物運輸合同模板
- 機場擴建渣土運輸合同
- 售樓處裝修合同
- 醫(yī)院病房改造合同參考范本
- 財產險理賠實務
- VTE健康宣傳手冊
- 醫(yī)療服務管理
- 云南省普洱市遴選筆試真題及解析(2021年11月27日)
- 機械臂本科生畢業(yè)設計(論文)范文
- 旅游學概論課件優(yōu)化版李天元第七版第3章旅游者旅游活動的主體
- 羽毛球混合團體比賽的邀請函-范例
- 2020年心肺復蘇指南解讀
- 鍋爐月度檢查表.docx
- 傲慢與偏見(中英對照)
- 幼兒園防拐騙演練方案三篇
評論
0/150
提交評論