DTV_SI 汇总 兼谈LCN
生活随笔
收集整理的這篇文章主要介紹了
DTV_SI 汇总 兼谈LCN
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
前言 本章主要對數字廣播DVB做一個系統的概況的描述,以及一些spc的相關的內容,雖然流程分析的不多,但是做為后續 章節資料的源泉,也是不可或缺的。
一. ATSC和DVB數字電視系統的比較 本文的主要目的是幫助DVB開發人員了解ATSC標準。本文并不涉及兩種標準在物理層面(如調制解調)的差別,而主要討論上層協議的區別,主要集中在如下四個方面:?
1 .音頻壓縮 ATSC數字電視接收器必須具備Digital Audio Compression (AC-3)音頻壓縮算法的解碼能力,算法的具體細節可以參考文獻[2]。
AC-3算法與ISO/IEC 13818-3(參考文獻[3])相比,在多通道編碼方面的表現比較出色。AC-3一共包含有5.1個聲道:左前(L)、中央(C)、右前(R)、左環繞(Ls)、右環繞(Rs)和一個超重低音(LFE)。超重低音頻寬是其它幾個聲道的1/10,因此稱為5.1聲道。通道的結合方式有1/0、1+1/0、2+1/0、3+1/0、2/1、3/1、2/2、3/2這8種,其中斜杠前表示前聲道的個數,斜杠后表示后環繞聲的個數,在8種組合中都可選擇加設超低音通道
對比DVB DVB的音頻壓縮算法必須遵從ISO/IEC 13818-3[3]標準,因此ISO/IEC 13818-3模塊對DVB的接收系統來說是必不可少的;相比之下,ATSC采用的是AC-3標準,因此,ISO/IEC 13818-3對于ATSC接收器來說是可選模塊,而AC-3音頻解碼模塊是不可缺少的。 雖然在DVB和ATSC系統中都可以把AC-3的音頻流映射到MPEG的Multiplex上傳輸,但是在實現方式上還存在著一些差異。? 表1列出了AC-3音頻流在ATSC和DVB系統中的傳輸比較。其中registration descriptor僅僅存在于ATSC系統,因為在DVB系統中,AC-3 descriptor是公開的描述符,無需用registration descriptor來注冊。?
2? 服務信息表 電子節目指南(EPG)是數字電視中非常重要的部分,它相當于傳統報紙上的節目表。而電子節目指南則是基于TS流中的Service Information(SI)而構造的。 DVB和ATSC標準分別定義了各自不同的SI結構,采用不同的機制來產生EPG。本章后續部分將介紹ATSC的SI1系統,并將其與DVB進行對比。
● 層次結構
ATSC包含了層次化的表格來描述系統信息和節目指南數據(參考文獻[4])。其中,一個公用的基礎PID(Base?PID)是所有表格的入口,它被顯示定義為0x1FFB,根據Base?PID可以在地面廣播系統和有線電視系統中定位如下表格。
事件信息表(Event Information Table,?EIT)也是SI系統的一部分,它們的PID定義在MGT之中。每一個EIT都按照VCT里面所定義的虛擬頻道列出電視節目(事件)清單,并按照時間先后從EIT-0到EIT-127排序。ATSC標準規定,每一個EIT必須有3個小時的時間長度,而且所有EIT的開始時間都被限制在0:00(午夜),3:00,&nbs p; 6:00, 9:00,12:00(中午),15:00,18:00和21:00(所有的時間都是UTC制)。這樣,EIT-0代表的就是當前3個小時內的所有電視節目,EIT-1代表的是接下來3個小時的信息,而每隔三個小時,原先的EIT-0就被廢棄,之前的EIT-1將取代EIT-0的位置,依此類推。另外,ATSC還定義了可選的擴展文字表(Extended Text Table,ETT),ETT包含了有關EIT的相對比較長的文字描述,它們的PID也同樣包含在MGT中。
圖1描述了上述表格的層次結構。在一個數字電視TS流中,SI表格必須包含對當前TS流中所有的數字電視頻道的描述,同時為了方便起見,還可能包括了相關的模擬頻道信息以及其它TS流中的數字頻道信息。對于地面廣播系統,STT, TVCT(VCT的地面版本),MGT和前4個EIT都是強制要求的;對于有線電視系統,STT,CVCT(VCT的有線版本)或者TVCT,以及MGT都是必需的。
● 與DVB-SI的比較 圖 2說明了DVB SI表格的層次結構。總的來說,DVB-SI和ATSC-SI的目的都是為了構造EPG,他們在功能上是相似的。例如:ATSC的STT就時間同步功能來說等價于DVB中的TDT,ATSC的VCT就虛擬頻道(服務)描述來說和DVB中的SDT等價,ATSC和DVB中的EIT同樣提供TV節目清單。? (可見EIT里放的就是EPG了。。)
即便如此,ATSC-SI和DVB-SI仍然存在如下一些差異: 1. 節目標識:在DVB系統中,節目總是以original network id/ transport stream id/ service id的方式標識的。其中original network id是由授權中心頒發給經認證的運營商或者廣播商的。采用這種聯合方式來標識能夠方便收費和訂閱信息的管理。而在ATSC系統中,不存在original network id的標識,用戶能看到的是一個類似于2-1主次號結合的標識符,這里主號2是廣播商的NTSC牌照,該廣播商的所有服務都采用該主號來標識;次號1是用來在該主號群組中標識特定的服務,次號0預留給該廣播商的模擬頻道服務,1-999可以用來標識數字電視服務(圖3顯示的是采用主次頻道結合標識的一個例子)。這種機制使得transport stream id和service id對電視終端用戶不可見。?
2. 事件信息表(EIT):ATSC和DVB都有各自的EIT,雖然名字相同,但它們的結構有很大的差別。另外,ATSC中的每個EIT都只有3個小時的有效期,每隔3個小時,EIT-0會被廢棄,后繼的EIT會取代前繼EIT的位置(可以采用修改MGT中PID來實現)。另外,ATSC對EIT的開始時間也有限制。如果一個節目時間跨越了好幾個EIT,那么它必須同時出現在這些EIT之中,而且事件ID必須相同。而在DVB標準中,就不存在上述限制。
3. 定向頻道轉換(DCC):DCC是ATSC標準中的新特性,它在Base?PID(0x1FFB)的數據包中定義了2個表:定向頻道轉換表(DCCT)和定向頻道轉換選擇碼表(DCCSCT)。定向頻道轉換是提供給廣播公司的可選功能,它能把用戶導航到相關可選的廣播節目內容,這種定向轉換可以是自動的,也可以是交互式的。而類似的機制并沒有出現在DVB系統中。
4. 冗余表:DVB的TS流除了包含當前TS流中SI表之外,還可能包含了其它TS流的SI表,以方便頻道搜索。雖然ATSC也允許VCT中包含其它TS流的信息,但一般來說,出于加速訪問事件的目的,ATSC的SI表只包含了當前TS流的節目指南信息。
5. 跳過對PAT/PMT的解析:ATSC中TVCT包含了service location descriptor,這個描述符包含了PMT里面的所有信息,包括stream type和PID。也就是說,ATSC的解碼器可以跳過PAT和PMT的解析,直接從TVCT的信息跳轉到目標邏輯頻道。
6. 相關束表(BAT) :DVB中的BAT提供了相關服務的群組列表,方便用戶定購和瀏覽。而ATSC中并沒有類似的機制。
● EPG的構造過程 形成電子節目指南(EPG)是SI系統最終目的。參照圖 1可以得到如下的EPG構造過程: 1. 調頻到某個特定的RF頻道。 2. 過濾Base?PID,從Base?PID的TS數據包中構造MGT,TVCT 和 STT等。 3. 解析MGT,獲取EIT以及相關ETT的PID。 4. 把每個虛擬頻道和它相關的TV節目列表聯系起來。 5. 調頻到另一個RF頻道,跳轉到第2步。如果沒有其它的頻道,則跳轉到第6步。 6. 把所有的節目列表以及相關信息顯示給用戶,捕捉用戶的輸入指令,并根據指令查找對應的service location descriptor,解碼顯示用戶所選擇的電視節目。
與DVB EPG構造過程的比較: 1. DVB和ATSC結構上的不同,導致了EPG的構造過程的不同。 2. 調頻到某個RF頻道,基于這個頻道解析NIT表,獲取當前網絡的所有TS流信息。 3. 基于當前頻道來解析當前SDT和其它TS流的SDT表,或者掃描當前網絡中所有的頻道,一一獲取SDT信息。 4. 基于當前頻道獲取當前的EIT和其它TS流的EIT,或者掃描當前網絡中所有的頻道,一一獲取EIT信息。 5. 顯示用戶節目列表。當用戶轉換到某個節目,transport id以及相應的各個PID將從PAT和PMT中解析出來,以便解碼。
和DVB相比,ATSC-SI的結構試圖在不增加網絡帶寬的前提下,加速事件的處理。為了達到這個目的,ATSC采用了固定的PID,單獨的MGT來縮短PID解析的時間。但ATSC采用的機制是否真正比DVB有效,還有待檢驗。
3? 條件接收系統
完。
二、TS流概述 1.、TS流概述 ES流(Elementary Stream,基本流):數字電視各組成部分編碼后所形成的直接表示基本元素內容的流,包含視頻、音頻或數據的連續碼流。 PES流(Paketized Elementary Stream,打包基本碼流):是將基本的碼流ES流根據需要分成長度不等的數據包,并加上包頭就形成了打包的基本碼流PES流。 PS (Program Stream,節目流):將一個節目的多個組成部分按照它們之間的互相關系進行組織并加入各組成部分關系描述后的碼流。PS流是一種多路復用數字音頻、視頻等的封裝容器,它一個或多個具有共同的時間基準的PES流合并成一個整體流,主要用于節目存儲。其包長不固定,且較長,一旦失去同步信息,接收機無法確定下一包的同步位置,會造成失步,導致嚴重的信息丟失。PS流適用于誤碼小、信道較好的環境,如演播室、家庭環境和存儲介質中。 TS流(Transport Stream,傳輸流):是將一個節目的多個組成部分按照它們之間的互相關系進行組織并加入各組成部分關系描述和節目組成信息,并進一步封裝成傳輸包后的碼流。TS流是將視頻、音頻、PSI等數據打包成傳輸包進行傳送。主要用于節目傳輸。TS的傳輸包長度固定,一般為188字節。 TS流和PS流是MPEG-2標準中規定的兩種輸出碼流。TS格式中,從視頻流的任意一片斷開始都可以獨立解碼,而PS格式不可以。由于TS流具備較強的抵抗傳輸誤碼的能力,因此目前在傳輸媒體中進行傳輸的MPEG-2碼流基本上都采用了TS流的包格式。 TS流的播放:播放前將TS流文件的后綴名該為.mpg或者.mpeg,用可以直接播放MPEG-TS流的播放器(一般的播放器都可以)打開播放即可。
TS流的優點: 1、動態帶寬分配:由于TS的傳輸包長度是固定的,因此可過PID可以將規定的信道總頻帶在視頻、音頻和數據信息見進行實時的、靈活的分配。利用這一特性,可在廣播付費節目前實時地將解密鑰匙插入到TS流中送給廣大用戶。 2、可分級性:允許一個復用的傳輸碼流與其他視音頻基本碼流進行二次復用,生產占用頻帶給寬的更高一級的TS流。 3、可擴展性 4、抗干擾性 5、接收機成本低廉
TS流的形成過程: 1、 壓縮【顯示單元】產生【進入單元】,連續的【進入單元】組成一個基本碼流。ES 2、 對ES(基本碼流)進行打包形成PES。 就是帶包頭信息的ES 3、 在PES包中加入定時信息(PTS/DTS)。 4、 將PES包內容分配到一系列固定長度的傳輸包中。 5、 在傳輸包中加入定時信息(PCR)。 6、 在傳輸包中加入節目專用信息(PSI) 。 7、 連續輸出傳輸包形成具有恒定比特率的MPEG-TS流。
2、TS流傳輸包(簡稱TS包)結構分析 MPEG-2中規定TS傳輸包的長度為188 字節。但通信媒介會為包添加錯誤校驗字節,從而有了不同于188字節的包長。例如: DVB 規定中,使用204字節作為包長: 1、通過調制器時,在每個傳輸包后增加了16 字節的里德所羅門前向糾錯碼,因而形成了204字節的數據包。 調制 后總存在204 字節的數據包。 2、調制之前存復用器插入RS碼或虛構 的RS碼。 ATSC規定中,使用208字節作為包長:添加20 字節的 RS(Reed-Solomon)前向糾錯碼。與DVB不同,ATSC規定RS碼只能出現在調制的TS流中。 所有的TS包都分為包頭和凈荷部分。TS包中可以填入很多東西(填入的東西都是填入到凈荷部分),有:視頻、音頻、數據(包括PSI、SI以及其它任何形式的數據)。 2.1、TS包包頭 TS包的包頭提供關于傳輸方面的信息:同步、有無差錯、有無加擾、PCR(節目參考時鐘)等標志。TS包的包頭長度不固定,前32比特(4個字節)固定,后面可能跟有自適應字段(適配域)。32個比特(4個字節)是最小包頭。包頭的結構固定如下: 因此有的包頭可能不止32bit,那么又是如何區分的呢?原來是這個適配區搗的鬼!!
注意表里的數據是bit位數 typedef struct TS_packet_header { unsigned sync_byte : 8; 同步字節 unsigned transport_error_indicator : 1; 傳輸錯誤指示 unsigned payload_unit_start_indicator : 1; 開始指示 unsigned transport_priority : 1; 傳輸優先級 unsigned PID : 13; PID unsigned transport_scrambling_control : 2; 加擾控制 unsigned adaption_field_control : 2; 適配域控制 unsigned continuity_counter : 4; 連續性計數器 } TS_packet_header;
sync_byte (同步字節):固定為0100 0111 (0x47);該字節由解碼器識別,使包頭和有效負載可相互分離。 transport_error_indicator(傳輸錯誤指示): ‘1’表示在相關的傳輸包中至少有一個不可糾正的錯誤位。當被置1后,在錯誤被糾正之前不能重置為0。 payload_unit_start_indicator(開始指示):為1時,在前4個字節之后會有一個調整字節,其的數值為后面調整字段的長度length。因此有效載荷開始的位置應再偏移1+[length]個字節。原來有效負載是這樣來的 transport_priority(傳輸優先級):‘1’表明優先級比其他具有相同PID 但此位沒有被置‘1’的分組高。 PID:指示存儲與分組有效負載中數據的類型。PID 值 0x0000—0x000F 保留。其中0x0000為PAT保留;0x0001為CAT保留;0x1fff為分組保留,即空包。 transport_scrambling_control(加擾控制):表示TS流分組有效負載的加密模式。空包為‘00’,如果傳輸包包頭中包括調整字段,不應被加密。 adaptation_field_control(適配域控制):表示包頭是否有調整字段或有效負載。‘00’為ISO/IEC未來使用保留;‘01’僅含有效載荷,無調整字段;‘10’ 無有效載荷,僅含調整字段;‘11’ 調整字段后為有效載荷,調整字段中的前一個字節表示調整字段的長度length,有效載荷開始的位置應再偏移[length]個字節。空包應為‘10’。 continuity_counter(連續性計數器):隨著每一個具有相同PID的TS流分組而增加,當它達到最大值后又回復到0。范圍為0~15。 適配域:
2.2、TS包凈荷部分 TS包中凈荷所傳輸的信息包括兩種類型: 1、視頻、音頻的PES包以及輔助數據; 2、節目專用信息PSI。
當然,TS包也可以是空包。空包用來填充TS流,可能在重新進行多路復用時被插入或刪除。 在系統復用時,視頻、音頻的ES流需進行打包形成視頻、音頻的 PES流,輔助數據(如圖文電視信息)不需要打成PES包。PES包非定長,音頻的PES包小于等于64K,視頻的一般為一幀一個PES包。一幀圖象的PES包通常要由許多個TS包來傳輸。MPEG-2中規定,一個PES包必須由整數個TS包來傳輸。如果承載一個PES包的最后一個TS包沒能裝滿,則用填充字節來填滿;當下一個新的PES包形成時,需用新的TS包來開始傳輸。
節目專用信息PSI(Program Specific Information) 用來管理各種類型的TS數據包,需要有些特殊的TS包來確立各個TS數據包之間的關系。這些特殊的TS包里所包含的信息就是節目專用信息。在不同的標準中它有不同的名字: ? MPEG-2中稱為PSI; ? DVB標準根據實際需要,對PSI擴展,稱為SI信息; ? ATSC標準中為PSIP信息
MPEG-2中,規定的對PSI信息的描述方法有以下幾種: ? 1、表Table: 節目信息的結構性的描述; –節目關聯表Program Association Table (PAT) 0x0000 –節目映射表Program Map Tables (PMT) –條件接收表Conditional Access Table (CAT) 0x0001 –網絡信息表Network Information Table(NIT) 0x0010 –傳送流描述表Transport Stream Description Table (TSDT)
?2、節Section: 將表格的內容映射到TS流中; 專用段 Private_ section ? 3、描述符Descriptor:提供有關節目構成(視頻流、音頻流、語言、層次、系統時鐘和碼率等多方面)的信息; ITU-T Rec.H.222.0|ISO /IEC 13818-1 中定義的 PSI表可被分成一段或多段置于傳輸流分組中。一段就是一個語法結構,用來將 ITU-T Rec.H.222.0|ISO /IEC 13818-1 中定義的 PSI表映射到傳輸流分組中。
PAT: TS流中包含一個或者多個PAT表。PAT表由PID為0x0000的TS包傳送,其作用是為復用的每一路傳送流提供出所包含的節目和節目編號,以及對應節目的PMT的位置即PMT的TS包的PID值,同時還提供NIT的位置,即NIT的TS包的PID的值。
N loop中為:
table_id:固定為0x00,標志該表是PAT表。 section_syntax_indicator:段語法標志位,固定為1。 section_length:表示這個字節后面有用的字節數,包括CRC32。節目套數:(section length-9)/4 transport_stream_id:16位字段,表示該TS流的ID,區別于同一個網絡中其它多路復用流。 version_number:表示PAT的版本號。 current_next_indicator:表示發送的PAT表是當前有效還是下一個PAT有效。 section_number:表示分段的號碼。PAT可能分為多段傳輸,第一段為0,以后每個分段加1,最多可能有256個分段。 last_section_number:表示PAT最后一個分段的號碼。 Program number:節目號 network_PID:網絡信息表(NIT)的PID,節目號為0時對應ID為network_PID。 Program map PID:節目映射表(PMT)的PID號,節目號為大于等于1時,對應的ID為program_map_PID。一個PAT中可以有多個program_map_PID。 CRC_32:32位字段,CRC32校驗碼Cyclic RedundancyCheck。
PMT: PMT在傳送流中用于指示組成某一套節目的視頻、音頻和數據在傳送流中的位置,即對應的TS包的PID值,以及每路節目的節目時鐘參考(PCR)字段的位置。
N loop中為:
Table id :固定為0x02,標志該表是PMT表。 Section syntax indicator:對于PMT表,設置為1。 Section length:表示這個字節后面有用的字節數,包括CRC32。 Program number:它指出該節目對應于可應用的Program map PID。 Version number:指出PMT的版本號。 Current next indicator:當該位置’1’時,當前傳送的Program map section可用;當該位置’0’時,指示當前傳送的Program map section不可用,下一個TS流的Programmap section有效。 Section number:總是置為0x00(因為PMT表里表示一個service的信息,一個section的長度足夠)。 Last section number:該域的值總是0x00。 PCR PID:節目中包含有效PCR字段的傳送流中PID。 Program info length:12bit域,前兩位為00。該域指出跟隨其后對節目信息的描述的byte數。 Stream type:8bit域,指示特定PID的節目元素包的類型。該處PID由elementary PID指定。下表所示為對應原始流的類型。
原始流的類型
2.3 PMT結構定義: // 這個又是代表什么呢? typedef struct TS_PMT_Stream { unsigned stream_type?: 8; //指示特定PID的節目元素包的類型。該處PID由elementary PID指定 unsigned elementary_PID?: 13; //該域指示TS包的PID值。這些TS包含有相關的節目元 素 unsigned ES_info_length? : 12; //前兩位bit為00。該域指示跟隨其后的描述相關節目元素的byte數 unsigned descriptor; }TS_PMT_Stream; 注釋: 這個結構體并沒有顯示缺省的bit,注意下面的兩個缺省值 stream_type???????:0x1b??????????????????? //??8 reserved????????????0x07??????????????????//??3 elementary_PID????????:0x03 e9????//??13//該節目中包括的視頻流,音頻流等對應的TS分組的PID reserved????????????????????:0x0f??????????//??4 ES_info_length?????????:0x000???????????????//??12
//PMT 表結構體 ,這個就是所謂的PMT表了 typedef struct TS_PMT { unsigned table_id??????????????????????? : 8; //固定為0x02, 表示PMT表 unsigned section_syntax_indicator??????? : 1; //固定為0x01 (段語法標志位) unsigned zero??????????????????????????? : 1; //0x01 unsigned reserved_1????????????????????? : 2; //0x03 unsigned section_length?: 12;//首先兩位bit置為00,它指示段的byte數,由段長度域開始,包含 CRC。 unsigned program_number??????: 16;// 指出該節目對應于可應用的Program map PID它指出該節目 對應于可應用的Program map PID,就是節目號吧 unsigned reserved_2??????????????????????? : 2; //0x03 unsigned version_number??????????????????? : 5; //指出TS流中Program map section的版本號 unsigned current_next_indicator??????????? : 1; //當該位置1時,當前傳送的Program map section可 用;當該位置0時,指示當前傳送的Program map section不可用, 下一個TS流的Program map section有效。 unsigned section_number??????????????????? : 8; //固定為0x00 因為這個表一個section就夠了,所以為0 unsigned last_section_number??????????? : 8; //固定為0x00 因為這個表一個section就夠了,所以為0 unsigned reserved_3??????????????????????? : 3; //0x07 unsigned PCR_PID??????????????????????? : 13; //指明TS包的PID值,該TS包含有PCR域, //該PCR值對應于由節目號指定的對應節目。 //如果對于私有數據流的節目定義與PCR無關,這個域的值將為0x1FFF。 unsigned reserved_4??????????????????????? : 4; //預留為0x0F unsigned program_info_length??????????? : 12; //前兩位bit為00。該域指出跟隨其后對節目信息的描述的byte數。 std::vector<TS_PMT_Stream> PMT_Stream;??//每個元素包含8位, 指示特定PID的節目元素包的類 型。該處PID由elementary PID指定 unsigned reserved_5??????????????????????? : 3; //0x07 unsigned reserved_6??????????????????????? : 4; //0x0F unsigned CRC_32??????????????????????????? : 32;? } TS_PMT; 解析代碼為: HRESULT CTS_Stream_Parse::adjust_PMT_table ( TS_PMT * packet, unsigned char * buffer ) {? packet->table_id??????????????????????????? = buffer[0]; packet->section_syntax_indicator??????????? = buffer[1] >> 7; packet->zero??????????????????????????????? = buffer[1] >> 6 & 0x01;? packet->reserved_1??????????????????????????? = buffer[1] >> 4 & 0x03; packet->section_length??????????????????????? = (buffer[1] & 0x0F) << 8 | buffer[2];???? packet->program_number??????????????????????? = 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]; packet->reserved_3??????????????????????????? = buffer[8] >> 5; packet->PCR_PID??????????????????????????????? = ((buffer[8] << 8) | buffer[9]) & 0x1FFF; PCRID = packet->PCR_PID; packet->reserved_4??????????????????????????? = buffer[10] >> 4; packet->program_info_length??????????????????? = (buffer[10] & 0x0F) << 8 | buffer[11];? // Get CRC_32 int len = 0; len = packet->section_length + 3;???? packet->CRC_32??????????????? = (buffer[len-4] & 0x000000FF) << 24 | (buffer[len-3] & 0x000000FF) << 16 | (buffer[len-2] & 0x000000FF) << 8 | (buffer[len-1] & 0x000000FF); int pos = 12; // program info descriptor if ( packet->program_info_length != 0 ) pos += packet->program_info_length;???? // Get stream type and PID???? for ( ; pos <= (packet->section_length + 2 ) -? 4; ) { TS_PMT_Stream pmt_stream; pmt_stream.stream_type =??buffer[pos]; packet->reserved_5? =???buffer[pos+1] >> 5; pmt_stream.elementary_PID =??((buffer[pos+1] << 8) | buffer[pos+2]) & 0x1FFF; packet->reserved_6???? =?? buffer[pos+3] >> 4; pmt_stream.ES_info_length =?? (buffer[pos+3] & 0x0F) << 8 | buffer[pos+4]; pmt_stream.descriptor = 0x00; if (pmt_stream.ES_info_length != 0) { pmt_stream.descriptor = buffer[pos + 5]; for( int len = 2; len <= pmt_stream.ES_info_length; len ++ ) { pmt_stream.descriptor = pmt_stream.descriptor<< 8 | buffer[pos + 4 + len]; } pos += pmt_stream.ES_info_length; } pos += 5; packet->PMT_Stream.push_back( pmt_stream ); TS_Stream_type.push_back( pmt_stream ); } return 0; } 舉例如下: 長度0x12==18字節,紅色區域 0x47 0x43 0xe8 0x12?0x00?0x02 0xb0 0x120x00 0x01 0xc1 0x00 0x00 0xe3 0xe9 0xf0 0x00? 0x1b 0xe3 0xe9 0xf0 0x00 0xf0 0xaf 0xb4 0x4f 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
TS頭部 sync_byte???:0x47 transport_error_indicator: 0x00 payload_unit_start_indicator: 0x01 transport_priority??: 0x00 PID?????????????????????:0x03e8 transport_scrambling_control??:0x00 adaptation_field_control??:0x01????????????????????????????????????? continuity_counter???:0x02 PMT數據????????? table_id?????:0x02????????????????????????? // 8 section_syntax_indicator??:0x01????????????//??1 '0'????????????????:0x00?????????????????? //??1 reserved???????:0x03???????????????????????//??2 section_length?:??????0x012?????????????????//??12 program_number????:0x00 01????????????????????//??16 reserved???????????????:0x03???????????????//??2 version_number????:0x00????????????????????//??5 current_next_indicator???0x01?????????????//??1 section_number??????:0x00??????????????????//??8 last_section_number????:0x00?????????????? //??8? reserved???????????????????0x07???????????//??3 PCR_PID???????????:0x03 e9???//?PCR(節目參考時鐘)所在TS分組的PID????????? //??13 reserved???????:0x0f???????????????? //4 program_info_length?????:0x000????????????? //??12 stream_type???????:0x1b??????????????????? //??8 reserved????????????0x07??????????????????//??3 elementary_PID????????:0x03 e9????//??13//該節目中包括的視頻流,音頻流等對應的TS分組的PID reserved????????????????????:0x0f??????????//??4 ES_info_length?????????:0x000???????????????//??12 CRC??????? : 0xf0 af b4 4f
2.4 對TS包頭的解析
表標識符值(table_id)的分配 值 描述 0x00 節目關聯段(PAT) 0x01 條件接收段(CAT) 0x02 節目映射段(PMT) 0x03 傳輸流描述段 0x04 至 0x3F 預留 0x40 現行網絡信息段(NIT actual) 0x41 其它網絡信息段(NIT other) 0x42 現行傳輸流業務描述段(SDT actual) 0x43 至 0x45 預留使用 0x46 現行傳輸流業務描述段(SDT other) 0x47 至 0x49 預留使用 0x4A 業務群關聯段(BAT) 0x4B 至 0x4D 預留使用 0x4E 現行傳輸流事件信息段,當前/后續(EIT PF actual) 0x4F 其它傳輸流事件信息段,當前/后續(EIT PF other) 0x50 至 0x5F 現行傳輸流事件信息段,時間表(EIT Schedule actual) 0x60 至 0x6F 其它傳輸流事件信息段,時間表(EIT Schedule other) 0x70 時間-日期段(TDT) 0x71 運行狀態段(RST) 0x72 填充段(ST) 0x73 時間偏移段(TOT) 0x74 至 0x7D 預留使用 0x7E 不連續信息段 0x7F 選擇信息段 0x80 至 0xFE 用戶定義 0xFF 預留
業務信息的PID分配 表 ? ? ? ? ? ? ? ?PID 值 PAT ? ? ? ? ? ? ? 0x0000 CAT ? ? ? ? ? ? ? 0x0001 TSDT ? ? ? ? ? ? ?0x0002 預留 ? ? ? ? ? ? ? 0x0003 至0x000F NIT, ST ? ? ? ? ? 0x0010 SDT , BAT, ST ? ? 0x0011 EIT, ST ? ? ? ? ? 0x0012 RST, ST ? ? ? ? ? 0x0013 TDT, TOT, ST ? ? ?0x0014 網絡同步 ? ? ? ? ? 0x0015 預留使用 ? ? ? ? ? 0x0016 至 0x001B 帶內信令 ? ? ? ? ? 0x001C 測量 ? ? ? ? ? ? ? 0x001D DIT ? ? ? ? ? ? ? 0x001E SIT ? ? ? ? ? ? ? 0x001F
由pid和tid就可以確定并找到那些表了,如果TDT和TOT在同一個PID里,那么就要根據tid進行區分了
根據前一篇中各數據的定義及數據結構,對數據進行分別解析如下: TS包頭定義: typedef struct TS_packet_header { unsigned sync_byte??????????????????????? : 8; //同步字節, 固定為0x47,表示后面的是一個TS分組 unsigned transport_error_indicator??????? : 1; //傳輸誤碼指示符 unsigned payload_unit_start_indicator??? : 1; //有效荷載單元起始指示符 unsigned transport_priority????????????? : 1; //傳輸優先, 1表示高優先級,傳輸機制可能用到,解碼用不著 unsigned PID??????????????????????????? : 13; //PID unsigned transport_scrambling_control??? : 2; //傳輸加擾控制? unsigned adaption_field_control??????????? : 2; //自適應控制 01僅含有效負載,10僅含調整字段,11含 有調整字段和有效負載。為00解碼器不進行處理 unsigned continuity_counter??????????????? : 4; //連續計數器 一個4bit的計數器,范圍0-15 } TS_packet_header;
TS包頭解析代碼: HRESULT CTS_Stream_Parse::adjust_TS_packet_header( TS_packet_header* TS_header ) { unsigned char buf[4];? memcpy(buf, TS_header, 4); TS_header->transport_error_indicator??????? = buf[1] >> 7; TS_header->payload_unit_start_indicator??? = buf[1] >> 6 & 0x01; TS_header->transport_priority??????????????? = buf[1] >> 5 & 0x01; TS_header->PID??????????????????????????? = (buf[1] & 0x1F) << 8 | buf[2]; TS_header->transport_scrambling_control??? = buf[3] >> 6; TS_header->adaption_field_control??????????? = buf[3] >> 4 & 0x03; TS_header->continuity_counter??????????????? = buf[3] & 0x0F; // 四位數據,應為0x0F xyy 09.03.18 return 0; }
如下為一個TS包數據: 0x47 0x40 0x00 0x12?0x00?0x00 0xb0 0x0d 0x00 0x00 0xc1 0x00 0x00 0x00 0x01 0xe3 0xe8 0xf0 0x0b 0xd7 0x79 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
分析知道前四位0x47 0x40 0x00 0x12TS頭部即為TS包頭數據,解析如下: sync_byte???:0x47 transport_error_indicator: 0x00 payload_unit_start_indicator: 0x01 transport_priority??: 0x00 PID?????????????????????:0x0000 說明是PAT表 transport_scrambling_control??:0x00 adaptation_field_control??:0x01????????????????????????????????????? continuity_counter???:0x02 PID = 0x0000,表示此TS包的內容為PSI信息表格的PAT表格數據,在4字節的TS包頭之后的第一個字節的Point_field = 0x00, 表示偏移量為0,即緊隨其后的即為PAT的數據信息 嘗試著解析一下這個PAT table_id:固定為0x00,標志該表是PAT表。 //8bit section_syntax_indicator:段語法標志位,固定為1。//1 '0'????????????????:0x0?????????????????? //??1 reserved???????:0x3 //2 section_length:表示這個字節后面有用的字節數,包括CRC32。節目套數:(section length-9)/4 0xd 說明后面有13字節 //12 transport_stream_id:16位字段,表示該TS流的ID,區別于同一個網絡中其它多路復用流。 0x0 //16 reserved???????:0x3 //2 version_number:表示PAT的版本號。0x0 //5 current_next_indicator:表示發送的PAT表是當前有效還是下一個PAT有效。0x1 //1 section_number:表示分段的號碼。PAT可能分為多段傳輸,第一段為0,以后每個分段加1,最多可能有256個分段。 0x0 //8 last_section_number:表示PAT最后一個分段的號碼。 0x0 //8 Program number:節目號 0x01 //16 reserved???????:0x7 //3 network_PID:網絡信息表(NIT)的PID,節目號為0時對應ID為network_PID。 0x3e8 //13 Program map PID:節目映射表(PMT)的PID號,節目號為大于等于1時,對應的ID為 program_map_PID。一個PAT中可以有多個program_map_PID。 由于節目號是0x1 因此這里應該是PMT表,而不是NIT表的PID,所以PMT表的PID===0x3e8 注意如果節目號是0x0那么就不需要給PID了,因為NIT表的PID=0x10,所以緊隨其后的一定是 下一個節目號。 CRC_32:32位字段,CRC32校驗碼Cyclic RedundancyCheck。 0xf00bd779//32
2.5TS 流解碼過程: TS 流解碼過程: 1. 獲取TS中的PAT 2. 獲取TS中的PMT 3. 根據PMT可以知道當前網絡中傳輸的視頻(音頻)類型(H264),相應的PID,PCR的PID等信息。 4. 設置demux 模塊的視頻Filter 為相應視頻的PID和stream type等。 5. 從視頻Demux Filter 后得到的TS數據包中的payload 數據就是 one piece of PES,在TS header中有一些關于此 payload屬于哪個 PES的 第多少個數據包。 因此軟件中應該將此payload中的數據copy到PES的buffer中,用于拼接一個PES包。 6. 拼接好的PES包的包頭會有 PTS,DTS信息,去掉PES的header就是 ES。 7. 直接將 被拔掉 PES包頭的ES包送給decoder就可以進行解碼。解碼出來的數據就是一幀一幀的視頻數據,這些數據至少應當與PES中的PTS關聯一下,以便進行視音頻同步。 8. I,B,B,P 信息是在ES中的。
ES是直接從編碼器出來的數據流,可以是編碼過的視頻數據流,音頻數據流,或其他編碼數據流的統稱。ES流經過PES打包器之后,被轉換成PES包。PES包由包頭和payload組成.
在PES層,主要是在PES包頭信息中加入PTS(顯示時間標簽)和DTS(解碼時間標簽)用于視頻、音頻同步。其實,Mpeg-2用于視音頻同步以及系統時鐘恢復的時間標簽分別在ES,PES和TS這3個層次中。在ES層,與同步有關的主要是視頻緩沖驗證VBV(Video Buffer Verifier),用以防止解碼器的緩沖器出現上溢或下溢;在PES層,主要是在PES頭信息里出現的顯示時間標簽PTS(Presentation Time Stamp)和解碼時間標簽DTS(Decoding Time Stamp);在TS層中,TS頭信息包含了節目時鐘參考PCR(Program Clock Reference),用于恢復出與編碼端一致的系統時序時鐘STC(System Time Clock)。
基本流程如下: 首先MPEG-2壓縮編碼得到的ES基本流,這個數據流很大,并且只是I,P,B的這些視頻幀或音頻取樣信息,然后加入一些同步信息,打包成長度可變長度的數據包PES,原來是流的格式,現在成了數據包的分割形式。同時要注意的是,ES是只包含一種內容的數據流,如只含視頻,或只含音頻等,打包之后的PES也是只含一種性質的ES,如只含視頻ES的PES,只含音頻ES的PES等。可以知道,ES是編碼視頻數據流或音頻數據流,每個ES都由若干個存取單元(AU)組成,每個視頻AU或音頻AU都是由頭部和編碼數據兩部分組成,1個AU相當于編碼的1幅視頻圖像或1個音頻幀,也可以說,每個AU實際上是編碼數據流的顯示單元,即相當于解碼的1幅視頻圖像或1個音頻幀的取樣。PEG-2對視頻的壓縮產生I幀、P幀、B幀。把幀順序I1,P4,B2,B3,P7,B5,B6幀的編碼ES,通過打包并在每個幀中插入?PTS/DTS標志,變成PES。在插入PTS/DTS標志時,由于在B幀PTS和DTS相等,所以無須在B幀多插入DTS。而對于I幀?和P幀,由于經過復用后數據包的順序會發生變化,顯示前一定要存儲于視頻解碼器的從新排序緩存器中,經過從新排序后再顯示,所以一定要同時插入PTS和?DTS作為從新排序的依據。
其中,有否PTS/DTS標志,是解決視音頻同步顯示、防止解碼器輸入緩存器上溢或下溢的關鍵所在。PTS表明顯示單元出現在系統目標解碼器(STD- System?Target?Decoder)的時間,?DTS表明將存取單元全部字節從STD的ES解碼緩存器移走的時刻。視頻編碼圖像幀次序為?I1,P4,B2,B3,P7,B5,B6,I10,B8,B9的ES,加入PTS/DTS后,打包成一個個視頻PES包。每個PES包都有一個包頭,用于定義PES內的數據內容,提供定時資料。每個I、P、B幀的包頭都有一個PTS和DTS,但PTS與DTS對B幀都是一樣的,無須標出B幀的DTS。對I幀和P幀,顯示前一定要存儲于視頻解碼器的重新排序緩存器中,經過延遲(重新排序)后再顯示,一定要分別標明PTS和DTS。例如,解碼器輸入的圖像幀次序為I1,P4,B2,B3,P7,B5,B6,I10,B8,B9,依解碼器輸出的幀次序,應該P4比B2、B3在先,但顯示時P4一定要比B2、B3在后,即P4要在提前插入數據流中的時間標志指引下,經過緩存器重新排序,以重建編碼前視頻幀次序I1,B2,B3,P4,B5,B6,P7,B8,B9,I10。顯然,PTS/DTS標志表明對確定事件或確定信息解碼的專用時標的存在,依靠專用時標解碼器,可知道該確定事件或確定信息開始解碼或顯示的時刻。例如,PTS/DTS標志可用于確定編碼、多路復用、解碼、重建的時間。 PCR?? PCR是TS里面的,即TS packet的header里面可能會有,他用來指定所期望的該ts packet到達decoder的時間,他的作用于SCR類似
DTS, PTS 對于一個ES來說,比如視頻,他有許多I,P,B幀,而P, B幀都是以I,P幀作為參考。由于B幀是前向后向參考,因此要對B幀作decode的話,就必須先decode該B幀后面的幀(P,或者I幀),于是,decode的時間與幀的真正的present的時間就不一致了,按照DTS一次對各個幀進行decode,然后再按照PTS對各個幀進行展現。 有時候PES包頭里面也會有DTS,PTS,對于PTS來說,他代表了這個PES包得payload里面的第一個完整地audio access unit或者video access unit的PTS時間(并不是每個audio/video access unit都帶有PTS/DTS,因此,你可以在PES里面指定一個,作為開始)。 PES包頭的DTS也是這個原理,需要注意的是:對于video來說他的DTS和PTS是可以不一樣的,因為B幀的存在使其順序可以倒置。而對于audio來說,audio沒有雙向的預測,他的DTS和PTS可以看成是一個順序的,因此可一直采用一個,即可只采用PTS。
2.6TS流分析
1 從TS流開始 數字電視機頂盒接收到的是一段段的碼流,我們稱之為TS(Transport Stream,傳輸流),每個TS流都攜帶一些信息,如Video、Audio以及我們需要學習的PAT、PMT等信息。因此,我們首先需要了解TS流是什么,以及TS流是怎樣形成、有著怎樣的結構。 (一) TS流、PS流、PES流和ES流都是什么? ES流(Elementary Stream):基本碼流,不分段的音頻、視頻或其他信息的連續碼流。 PES流:把基本流ES分割成段,并加上相應頭文件打包成形的打包基本碼流。 PS流(Program Stream):節目流,將具有共同時間基準的一個或多個PES組合(復合)而成的單一數據流(用于播放或編輯系統,如m2p)。 TS流(Transport Stream):傳輸流,將具有共同時間基準或獨立時間基準的一個或多個PES組合(復合)而成的單一數據流(用于數據傳輸)。 *NOTE:TS流和PS流的區別:TS流的包結構是長度是固定的;PS流的包結構是可變長度的。這導致了TS流的抵抗傳輸誤碼的能力強于PS流(TS碼流由于采用了固定長度的包結構,當傳輸誤碼破壞了某一TS包的同步信息時,接收機可在固定的位置檢測它后面包中的同步信息,從而恢復同步,避免了信息丟失。而PS包由于長度是變化的,一旦某一?PS包的同步信息丟失,接收機無法確定下一包的同步位置,就會造成失步,導致嚴重的信息丟失。因此,在信道環境較為惡劣,傳輸誤碼較高時,一般采用TS碼流;而在信道環境較好,傳輸誤碼較低時,一般采用PS碼流。) 由于TS碼流具有較強的抵抗傳輸誤碼的能力,因此目前在傳輸媒體中進行傳輸的MPEG-2碼流基本上都采用了TS碼流的包格。
(二) TS流是如何產生的?
從上圖可以看出,視頻ES和音頻ES通過打包器和共同或獨立的系統時間基準形成一個個PES,通過TS復用器復用形成的傳輸流。注意這里的TS流是位流格式(分析Packet的時候會解釋),也即是說TS流是可以按位讀取的。
(三) TS流的格式是怎樣的? TS流是基于Packet的位流格式,每個包是188個字節(或204個字節,在188個字節后加上了16字節的CRC校驗數據,其他格式一樣)。整個TS流組成形式如下:
PID是TS流中唯一識別標志,Packet Data是什么內容就是由PID決定的。如果一個TS流中的一個Packet的Packet Header中的PID是0x0000,那么這個Packet的Packet Data就是DVB的PAT表而非其他類型數據(如Video、Audio或其他業務信息)。下表給出了一些表的PID值,這些值是固定的,不允許用于更改。
注釋:PID相同的表,最后根據tid來區分
下面以一個TS流的其中一個Packet中的Packet Header為例進行說明: sync_byte=01000111,?????????????????????? ?就是0x47,這是DVB TS規定的同步字節,固定是0x47. transport_error_indicator=0,??????????? ?表示當前包沒有發生傳輸錯誤. payload_unit_start_indicator=0,???? ?含義參考ISO13818-1標準文檔 transport_priority=0,????????????????????????表示當前包是低優先級. PID=00111 11100101即0x07e5,?????? Video PID transport_scrambling_control=00,??表示節目沒有加密 adaptation_field_control=01???????????即0x01,具體含義請參考ISO13818-1 continuity_counte=0010????????????????即0x02,表示當前傳送的相同類型的包是第3個
TS流的基本內容就是這些了。 回顧一下,TS流是一種位流(當然就是數字的),它是由ES流分割成PES后復用而成的;它經過網絡傳輸被機頂盒接收到;數字電視機頂盒接收到TS流后將解析TS流。 TS流是由一個個Packet(包)構成的,每個包都是由Packet Header(包頭)和Packet Data(包數據)組成的。其中Packet Header指示了該Packet是什么屬性的,并給出了該Packet Data的數據的唯一網絡標識符PID。 到這里,我們對TS流已經有了一定的了解,下面將從TS流轉向PAT表和PMT表的學習。
2 從TS流到PAT、PMT 說完了TS流的基本概念,就該開始對TS流進行更深入的研究了。首先需要想一想:TS流的本質是什么?它的確是一段碼流,并且是一段由數據包(Packet)組成的碼流。那么這些數據包究竟是怎樣的呢?它和我們收看的電視節目之間又有什么區別?這些都是這部分需要了解的內容。 在上一節中,我們可以看到PID這個被標紅的字段頻繁地出現。PID是當前TS流的Packet區別于其他Packet類型的唯一識別符,通過讀取每個包的Packet Header,我們可以知道這個Packet的數據屬于何種類型。上一節列出了幾項固定的PID值,它們用于識別存儲了特殊信息的Packet。下面要談的PAT表的PID值就是固定的0x0000。 (一) PAT表(Program Association Table,節目關聯表) 由于下面的內容比較繁雜,這里先給出一個大綱,方便查閱: 1. PAT表的描述(表格+分析) 2. PAT表的定義(代碼+分析) 3. PAT表的結構(代碼+分析) 4. PAT表的解析(代碼+分析) 5. 通過一段TS流中一個Packet分析PAT表(表格+分析) 下面,開始正式的分析!
1.?PAT表的描述(表格+分析) PAT表定義了當前TS流中所有的節目,其PID為0x0000,它是PSI的根節點,要查尋找節目必須從PAT表開始查找。 PAT表攜帶以下信息:
2. PAT表的定義(代碼+分析) PAT表主要包含頻道號碼和每一個頻道對應的PMT的PID號碼,這些信息我們在處理PAT表格的時候會保存起來,以后會使用到這些數據。下面將PAT表的定義給出: [cpp]?view plaincopy typedef?struct?TS_PAT_Program?? {?? ????unsigned?program_number???:??16;??//節目號?? ????unsigned?program_map_PID?:??13;?//?節目映射表的PID,節目號大于0時對應的PID,每個節目對應 一個?? }TS_PAT_Program??
3. PAT表的結構(代碼+分析)??????? 再將PAT表的結構體給出: [cpp]?view plaincopy typedef?struct?TS_PAT?? {?? ????unsigned?table_id?????????????????????:?8;?//固定為0x00?,標志是該表是PAT表?? ????unsigned?section_syntax_indicator?????:?1;?//段語法標志位,固定為1?? ????unsigned?zero?????????????????????????:?1;?//0?? ????unsigned?reserved_1???????????????????:?2;?//?保留位?? ?????unsigned?section_length???????????????:?12;?//表示從下一個字段開始到CRC32(含)之間有用的 字節數?? ????unsigned?transport_stream_id??????????:?16;?//該傳輸流的ID,區別于一個網絡中其它多路復用 的流??就是這個pat表的PID ????unsigned?reserved_2???????????????????:?2;//?保留位?? ????unsigned?version_number???????????????:?5;?//范圍0-31,表示PAT的版本號?? ????unsigned?current_next_indicator???????:?1;?//發送的PAT是當前有效還是下一個PAT有效?? ????unsigned?section_number???????????????:?8;?//分段的號碼。PAT可能分為多段傳輸,第一段為 00,以后每個分段加1,最多可能有256個分段?? ????unsigned?last_section_number??????????:?8;??//最后一個分段的號碼?? ??? ????std::vector<TS_PAT_Program>?program;?? ????unsigned?reserved_3????????????????????:?3;?//?保留位?? ????unsigned?network_PID????????????????????:?13;?//網絡信息表(NIT)的PID,節目號為0時對應 的PID為network_PID?,如果節目號不為0,則為這 個節目的PMT表的PID? ????unsigned?CRC_32????????????????????????:?32;??//CRC32校驗碼?? }?TS_PAT;???
4. PAT表的解析(代碼+分析) 接下來給出的是PAT表的解析代碼: [cpp]?view plaincopy HRESULT?CTS_Stream_Parse::adjust_PAT_table(?TS_PAT?*?packet,?unsigned?char?*?buffer)?? {?? ????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];??? ?? ????int?len?=?0;?? ????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);??? ??? ????int?n?=?0;?? ????for?(?n?=?0;?n?<?packet->section_length?-?12;?n?+=?4?)?? ????{?? ????????unsigned??program_num?=?buffer[8?+?n?]?<<?8?|?buffer[9?+?n?];???? ????????packet->reserved_3???????????=?buffer[10?+?n?]?>>?5;??? ???? ????????packet->network_PID?=?0x00;?? ????????if?(?program_num?==?0x00)?? ???????{???? ????????????packet->network_PID?=?(buffer[10?+?n?]?&?0x1F)?<<?8?|?buffer[11?+?n?];?? ?? ????????????TS_network_Pid?=?packet->network_PID;?//記錄該TS流的網絡PID?? ?? ?????????????TRACE("?packet->network_PID?%0x?/n/n",?packet->network_PID?);?? ????????}?? ????????else?? ????????{?? ???????????TS_PAT_Program?PAT_program;?? ??????????? PAT_program.program_map_PID?=?(buffer[10?+?n]?&?0x1F)?<<?8?|?buffer[11?+?n];?? ???????????PAT_program.program_number?=?program_num;?? ???????????packet->program.push_back(?PAT_program?);?? ???????????TS_program.push_back(?PAT_program?);//向全局PAT節目數組中添加PAT節目信息??????? ????????}??????????? ????}?? ????return?0;?? }?? 從for()開始,就是描述了當前流中的頻道數目(N),每一個頻道對應的PMT PID是什么。解復用程序需要接收所有的頻道號碼和對應的PMT 的PID,并把這些信息在緩沖區中保存起來。在后部的處理中需要使用到PMT的 PID。
5. 通過一段TS流中一個Packet分析PAT表(表格+分析) 這里我們分析一段TS流其中一個Packet的Packet Data部分: 首先給出一個數據包,其數據如下: 分析Packet Header如下表所示: PID == 0 說明這個是一個PAT表 根據包頭數據格式,我們可以知曉整個數據包的屬性,列表如下:
如上表所示,我們可以知道,首先Packet的Packet Data是PAT信息表,因為其PID為0x0000,并且在包頭后需要除去一個字節才是有效數據(payload_unit_start_indicator="1")。這樣,Packet Data就應該是“00 b0 11 00 01 c1 00 00 00 00 e0 1f 00 01 e1 00 24 ac48 84 ff ff …… ff ff”。
由以上幾個表可以分析出PAT表和PMT表有著內在的聯系。也就是之前提到的。PAT表描述了當前流的NIT(Network Information Table,網絡信息表)中的PID、當前流中有多少不同類型的PMT表及每個PMT表對應的頻道號。而PAT表和PMT表到底有什么深層次的聯系呢?在討論完了PMT表和SDT表后再做討論吧。 6. 過濾PAT表信息的偽代碼(代碼) [cpp]?view plaincopy int?Video_PID=0x07e5,Audio_PID=0x07e6;?? void?Process_Packet(unsigned?char*buff)?? {?int?I;?int?PID=GETPID(buff);?? ??if(PID==0x0000)?{?Process_PAT(buff+4);?}??//?如果PID為0x0000,則該Packet?Data為PAT信息, 因此調用處理PAT表的函數?? ??else{?????????????????????????????????????//?這里buff+4?意味著從Packet?Header之后進行解析 (包頭占4個字節)?? ????……?? ??}?? }??
(二) PMT表(Program Map Table,節目映射表)(Service Descriptor Table) 1. PMT表的描述????? 如果一個TS流中含有多個頻道,那么就會包含多個PID不同的PMT表。 PMT表中包含的數據如下: (1)?當前頻道中包含的所有Video數據的PID (2)?當前頻道中包含的所有Audio數據的PID (3)?和當前頻道關聯在一起的其他數據的PID(如數字廣播,數據通訊等使用的PID) 只要我們處理了PMT,那么我們就可以獲取頻道中所有的PID信息,如當前頻道包含多少個Video、共多少個Audio和其他數據,還能知道每種數據對應的PID分別是什么。這樣如果我們要選擇其中一個Video和Audio收看,那么只需要把要收看的節目的Video PID和Audio PID保存起來,在處理Packet的時候進行過濾即可實現。 2. PMT表的定義(代碼)?? [cpp]?view plaincopy <span?style="font-size:14px;">//PMT?表定義</span>?? [cpp]?view plaincopy <span?style="font-size:14px;"> typedef?struct?TS_PMT_Stream?? {?? ?unsigned?stream_type?????????:?8;?//指示特定PID的節目元素包的類型。該處PID由 elementary?PID指定?? ?unsigned?elementary_PID????? :?13;?//該域指示TS包的PID值。這些TS包含有相關的節目元素?? ?unsigned?ES_info_length?? :?12;?//前兩位bit為00。該域指示跟隨其后的描述相關節目元素 的byte數?? ?unsigned?descriptor;?? }TS_PMT_Stream;??? </span>?? 3. PMT表的結構體定義(代碼)?? [cpp]?view plaincopy //PMT?表結構體?? typedef?struct?TS_PMT?? {?? ????unsigned?table_id????????????????????????:?8;?//固定為0x02,?表示PMT表?? ?????unsigned?section_syntax_indicator????????:?1;?//固定為0x01?? ????unsigned?zero????????????????????????????:?1;?//0x01?? ????unsigned?reserved_1??????????????????????:?2;?//0x03?? ????unsigned?section_length??????????????????:?12;//首先兩位bit置為00,它指示段的byte數,由 段長度域開始,包含CRC。?? ?????unsigned?program_number????????????????????:?16;//?指出該節目對應于可應用的 Program?map?PID?? ????unsigned?reserved_2????????????????????????:?2;?//0x03?? ????unsigned?version_number????????????????????:?5;?//指出TS流中Program?map?section的版本號?? ?????unsigned?current_next_indicator????????????:?1;?//當該位置1時,當前傳送的 Program?map?section可用;?? ?????????????????????????????????????????????????????//當該位置0時,指示當前傳送的 Program?map?section不可用,下一個TS流的Program?map?section有效。?? ?????unsigned?section_number????????????????????:?8;?//固定為0x00?? ????unsigned?last_section_number????????????:?8;?//固定為0x00?? ????unsigned?reserved_3????????????????????????:?3;?//0x07?? ????unsigned?PCR_PID????????????????????????:?13;?//指明TS包的PID值,該TS包含有PCR域,?? ????????????//該PCR值對應于由節目號指定的對應節目。?? ????????????//如果對于私有數據流的節目定義與PCR無關,這個域的值將為0x1FFF。?? ?????unsigned?reserved_4????????????????????????:?4;?//預留為0x0F?? ????unsigned?program_info_length????????????:?12;?//前兩位bit為00。該域指出跟隨其后對節目信 息的描述的byte數。?? ?????? ?????std::vector<TS_PMT_Stream>?PMT_Stream;??//每個元素包含8位,?指示特定PID的節目元素包的類 型。該處PID由elementary?PID指定?? ?????unsigned?reserved_5????????????????????????:?3;?//0x07?? ????unsigned?reserved_6????????????????????????:?4;?//0x0F?? ????unsigned?CRC_32????????????????????????????:?32;??? }?TS_PMT;??
4. PMT表的解析(代碼)?? [cpp]?view plaincopy //PMT?表的解析?? [cpp]?view plaincopy HRESULT?CTS_Stream_Parse::adjust_PMT_table?(?TS_PMT?*?packet,?unsigned?char?*?buffer?)?? {??? ????packet->table_id????????????????????????????=?buffer[0];?? ????packet->section_syntax_indicator????????????=?buffer[1]?>>?7;?? ????packet->zero????????????????????????????????=?buffer[1]?>>?6?&?0x01;??? ????packet->reserved_1????????????????????????????=?buffer[1]?>>?4?&?0x03;?? ????packet->section_length????????????????????????=?(buffer[1]?&?0x0F)?<<?8?|?buffer[2];?????? ????packet->program_number????????????????????????=?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];?? ????packet->reserved_3????????????????????????????=?buffer[8]?>>?5;?? ????packet->PCR_PID??=?((buffer[8]?<<?8)?|?buffer[9])?&?0x1FFF;?? ?? ? PCRID?=?packet->PCR_PID;?? ?? ????packet->reserved_4???????????????????????????=?buffer[10]?>>?4;?? ????packet->program_info_length???????=?(buffer[10]?&?0x0F)?<<?8?|?buffer[11];??? ????//?Get?CRC_32?? ?int?len?=?0;?? ????len?=?packet->section_length?+?3;?????? ????packet->CRC_32????????????????=?(buffer[len-4]?&?0x000000FF)?<<?24?? ??|?(buffer[len-3]?&?0x000000FF)?<<?16?? ??|?(buffer[len-2]?&?0x000000FF)?<<?8?? ??|?(buffer[len-1]?&?0x000000FF);??? ?? ?int?pos?=?12;?? ????//?program?info?descriptor?? ????if?(?packet->program_info_length?!=?0?)?? ????????pos?+=?packet->program_info_length;?????? ????//?Get?stream?type?and?PID?????? ????for?(?;?pos?<=?(packet->section_length?+?2?)?-??4;?)?? ????{?? ??TS_PMT_Stream?pmt_stream;?? ??pmt_stream.stream_type?=??buffer[pos];?? ??packet->reserved_5??=???buffer[pos+1]?>>?5;?? ??pmt_stream.elementary_PID?=??((buffer[pos+1]?<<?8)?|?buffer[pos+2])?&?0x1FFF;?? ??packet->reserved_6?????=???buffer[pos+3]?>>?4;?? ??pmt_stream.ES_info_length?=???(buffer[pos+3]?&?0x0F)?<<?8?|?buffer[pos+4];?? ???? ??pmt_stream.descriptor?=?0x00;?? ??if?(pmt_stream.ES_info_length?!=?0)?? ??{?? ???pmt_stream.descriptor?=?buffer[pos?+?5];?? ????? ???for(?int?len?=?2;?len?<=?pmt_stream.ES_info_length;?len?++?)?? ???{?? ????pmt_stream.descriptor?=?pmt_stream.descriptor<<?8?|?buffer[pos?+?4?+?len];?? ???}?? ???pos?+=?pmt_stream.ES_info_length;?? ??}?? ??pos?+=?5;?? ??packet->PMT_Stream.push_back(?pmt_stream?);?? ??TS_Stream_type.push_back(?pmt_stream?);?? ????}?? ?return?0;?? }??
5. 通過一段TS流中一個Packet分析PMT表(表格+分析) 老樣子,還是通過分析一段TS流的數據包Packet來學習PMT表。 下面給出了一段TS流數據中的一個Packet(十六進制數) 首先解析Packet Header,分析如下: PID=0x03e8為其PID ,怎么就根據這個PID斷定他就是PMT呢?難道是PAT中有說明吧。 下面是詳細的解析表
因為payload_unit_start_indicator=‘1’,在解析數據包的時候需要去除Packet Data的第一個字節。下面是對Packet Data的詳細解析:
(三) 解復用模型(代碼)??????? [cpp]?view plaincopy int?Video_PID=0x07e5,Audio_PID=0x07e6;?? void?Process_Packet(unsigned?char*buff)?? {??? ??int?i;?int?PID=GETPID(buff);?? ??if(PID==0x0000)?{?Process_PAT(buff+4);?}??????????????//PAT表的PID為0x0000?? ??else?if(PID==Video_PID)?{?SaveToVideoBuffer(buff+4);?}??//PID指示該數據包為視頻包?? ??else?if(PID==Audio_PID)?{?SaveToAudioBuffer(buff+4);?}??//PID指示該數據包為音頻包?? ??else{???????????????????????????????//?buff+4?意味著要除去buff前4個字節(即包頭)?? ??for(?i=0;i<64;i++)?? ??{?if(PID==pmt[i].pmt_pid)?{?Process_PMT(buff+4);?Break;?}?? }?}?}?? ??? 解復用的意義在于,由于TS流是一種復用的碼流,里面混雜了多種類型的包;解復用TS流可以將類型相同的Packet存入相同緩存,分別處理。這樣就可以將Video、Audio或者其他業務信息的數據區分開來。
(四) DVB搜臺原理以及SDT表(Service Descriptor Table,業務描述表) 機頂盒先調整高頻頭到一個固定的頻率(如498MHZ),如果此頻率有數字信號,則COFDM芯片(如MT352)會自動把TS流數據傳送給MPEG- 2 decoder。 MPEG-2 decoder先進行數據的同步,也就是等待完整的Packet的到來.然后循環查找是否出現PID== 0x0000的Packet,如果出現了,則馬上進入分析PAT的處理,獲取了所有的PMT的PID。接著循環查找是否出現PMT,如果發現了,則自動進入PMT分析,獲取該頻段所有的頻道數據并保存。如果沒有發現PAT或者沒有發現PMT,說明該頻段沒有信號,進入下一個頻率掃描。 原來有沒有信號是通過判斷有沒有PAT或者PMT來的啊 在解析TS流的時候,首先尋找PAT表,根據PAT獲取所有PMT表的PID;再尋找PMT表,獲取該頻段所有節目數據并保存。這樣,只需要知道節目的PID就可以根據PacketHeade給出的PID過濾出不同的Packet,從而觀看不同的節目。這些就是PAT表和PMT表之間的關系。而由于PID是一串枯燥的數字,用戶不方便記憶、且容易輸錯,所以需要有一張表將節目名稱和該節目的PID對應起來,DVB設計了SDT表來解決這個問題。 該表格標志一個節目的名稱,并且能和PMT中的PID聯系起來,這樣用戶就可以通過直接選擇節目名稱來選擇節目了。(這就是PMT和SDT的聯系了) SDT可以提供的信息包括: (1)?該節目是否在播放中 (2)?該節目是否被加密 (3)?該節目的名稱
3、 從PAT開始,走向更遠 在本章的學習中,我們發現了一個特點:所有的TS流的解析都是從尋找PAT表開始的,只有找到了PAT表,我們才能繼續下一步的解析。因此,在進行了TS流、PAT表和PMT表的初步知識儲備后,在接下來的學習中將從PAT表開始,學習更多的PSI/SI相關的表,將走得更遠。
2.7PSI分析 "SI是對多個TS流的描述,它包含了PSI" PSI只提供了單個TS流的信息,使接收機能夠對單個TS流中的不同節目進行解碼;但是,它不能提供多個TS流的相關業務,也不能提供節目的類型、節目名稱、開始時間、節目簡介等信息。因此,DVB對PSI進行了擴展,提供了其他不同類型的表,形成了SI。 SI定義了PAT、PMT和CAT之外的9張表,通過組織SI提供的這些數據,可以生成類似節目報表的形式,方便用戶查看多種信息,這就是所謂的電子節目指南(EPG)。 下面給出了SI定義的十張表(NIT的由SI規定的)
SI定義的表,并不需要全部傳輸,其中,NIT、SDT、EIT和TDT是必須傳輸的;而又以NIT、SDT和EIT最為重要,利用這三個表可以構成功能不同的EPG,如提供節目附加信息、節目分類、節目預定和家長分級控制等。
解析 NIT描述了數字電視網絡中與網絡相關的信息" NIT描述了數字電視網絡中與網絡相關的信息,但這個表本身的信息有限,更多的信息是依靠插入表中的描述符來提供的。NIT常用的描述符有:網絡名稱描述符(network_name_descriptor)、有線傳送系統(cable_delivery_system_descriptor)、業務列表描述符(service_list_descriptor)和鏈接描述符(linkage_descriptor)。下圖是實際的一個例子中的兩種描述符。
NIT的表結構分析 網絡信息表(NIT)傳遞了與通過一個給定的網絡傳輸的復用流/TS流的物理結構相關的信息,以及與網絡自身特性相關的信息。 網絡信息段 Syntax (句法結構)???????? No. of bits(所占位數)?? Identifier(識別符)? Note(注釋)?? network_information_section(){ table_id????????????????????????????????????????????8??????????????????????uimsbf?????????????????????????????????????????????????? Section_syntax_indicator?????????????? 1????????????????????????? bslbf???????????? 通常設為“1” Reserved_future_use????????????????????? 1??????????????????????? bslbf Reserved?????????????????????????????????????????2??????????????????????? bslbf Section_length??????????????????????????????? 12????????????????????? uimsbf???????????????? 見注釋 Network_id????????????????????????????????????? 16?????????????????????? uimsbf???????????????? 見注釋 Reserved?????????????????????????????????????????2???????????????????????? bslbf Version_number????????????????????????????? 5???????????????????????? uimsbf???????????? 見注釋 Current_next_indicator?????????????????? 1????????????????????????? bslbf???????????????? 見注釋 Section_number????????????????????????????? 8????????????????????????? uimsbf??????????? 見注釋 last_section_number?????????????????????? 8????????????????????????? uimsbf??????????? 見注釋 Reserved_future_use????????????????????? 4????????????????????????? bslbf Network_descriptors_length??????? 12??????????????????????? uimsbf for(i=0;i<N;i++){ descriptor()??????//First descriptor loop } reserved_future_use???????????????????????? 4???????????????????? bslbf transport_stream_loop_length?????? 12????????????????? uimsbf?????????????? for(i=0;i<N;i++){ transport_stream_id???????????????????? 16????????????????? uimsbf???????????? 見注釋 original_network_id????????????????????? 16????????????????? uimsbf???????????? 見注釋 reserved_future_use????????????????????? 4????????????????? bslbf transport_descriptors_length???? 12?????????????????? uimsbf for(j=0;j<N;j++){ descriptor()?????//Second descriptor loop } } CRC_32?????????????????????????????????????????32????????????????? rpchof????????????????? 見注釋 } 在SI標準中規定:original_network_id和transport_stream_id兩個標識符相結合唯一確定了網絡中的TS流。各網絡被分配獨立的network_id值作為網絡的唯一識別碼。當NIT表在生成TS流的網絡上傳輸時,network_id和original_network_id將取同一值。
上圖提供的即是一個真實的NIT表,紅色框內有兩個描述符,分別是業務列表描述符service_list_descriptor和有線傳輸系統描述符cable_delivery_system_descriptor;它們都位于第二層循環。
NIT的業務列表描述符結構分析 業務列表描述符通過業務標識符和業務類型提供業務服務。其目的在于:告訴接收機每一個TS流中存在多少個業務以及每一個業務的類型。其結構如下: 業務列表描述符 Syntax(句法結構)??? No. of bits(所占位數)Identifier(識別符)? service_list_descriptor(){ descriptor_tag?????????????????????? 8?????????????????????? uimsbf descriptor_length?????????????????? 8?????????????????????? uimsbf for(i=0;i<N;i++){ service_id????????????????? 16????????????????????? uimsbf service_type?????????????? 8?????????????????????? uimsbf } } service_id(業務標識符):唯一標識TS中的一個業務,它與program_map_section中的program_number(參看PMT表結構)相同。但當業務類型為0x04時(即NVOD參考業務,service_id沒有對應的program_number)。 service_type(業務類型):指示業務的類型。如0x01為數字電視業務,0x02為數字音頻廣播業務,0x04為NVOD參考業務,0x05為NVOD時移業務。 HINT:下表給出了業務類型編碼方法
上圖所示只是其中一個section的業務列表描述符,如果將所有的section全解析,那么此網絡中所有TS流包含的所有service_id和service_type都可以獲得。這樣,用戶可以據此了解整個網絡業務的構成,并以此為基礎對業務進行分類、整合。
NIT的有線傳輸系統描述符結構分析 有線傳輸系統描述符(Cable_Delivery_System_descriptor)是NIT業務中重要的描述符,也是基本運營所必需的描述符。它主要描述了每一個TS流的物理參數(頻率、調制方式、符碼率等),使接收機能正確鎖頻、得到數據。其結構如下:
有線傳輸系統描述符 Syntax(句法結構)??? No. of bits(所占位數)Identifier(識別符)? cable_delivery_system_descriptor(){ descriptor_tag????????????????????? 8?????????? uimsbf???????? descriptor_length???????????????? 8?????????? uimsbf???????????????????????? frequency????????????????????????? ??32??????????bslbf reserved_future_use????????? ??12??????????bslbf FEC_outer????????????????????????? ????4?????????? bslbf???????????? 前向糾錯外碼 modulation??????????????????????? ??8???????????bslbf symbol_rate????????????????????? ???28??????????bslbf FEC_inner?????????????????????????? ??4???????????? bslbf?????????? 前向糾錯內碼 } Frequency(頻率):32位,以8個4位BCD碼給出頻率。其單位是MHz,小數點位于第四個BCD碼之后,如0312.0000MHz。 Modulation(調制方式):指出有線傳輸系統的調制方式。其定義如下表:
symbol_rate(符碼率):28位,以7個4位BCD碼表示符碼率。其單位是MSPS(兆符號每秒),小數點位于第三個BCD碼后,如027.4500 MSPS 上圖所示為一個真實TS流里的一個有線傳輸系統描述符。可以看到其頻率為331.0000MHz,符碼率為6.8750MSym/s,調制方式為64 QAM。
NIT的網絡名稱描述符結構分析 網絡名稱描述符的功能比較簡單,它以字符串的形式將網絡的名稱告訴接收機。下面是其描述符結構列表: 網絡名稱描述符 Syntax(句法結構)??? No. of bits(所占位數)Identifier(識別符)? network_name_descriptor(){ descriptor_tag?????????????????????? ??8?????????????????????? uimsbf descriptor_length?????????????????? 8?????????????????????? uimsbf for(i=0;i<N;i++){ char????????????????????????? ???????????????????8??????????????????? uimsbf } } char(字符):8位字段,一個字符串,給出NIT表指定的傳送系統的名稱。
NIT的鏈接描述符結構分析 ANALYZEOFTHE?STRUCTUREOFLINKAGE_DESCRIPTORINNIT 鏈接描述符 Syntax(句法結構)??? No. of bits(所占位數)Identifier(識別符)? linkage_descriptor(){ descriptor_tag???????????????????????? 8?????????? uimsbf???????? descriptor_length????????????? ???????8??????????uimsbf??? transport_stream_id????????????? ???16??????????uimsbf original_network_id???????????? ????16??????????uimsbf service_id????????????????????????????? ???16???????????uimsbf linkage_type??????????????????????? ??????8????????????? uimsbf for(i=0;i<N;i++){ private_data_byte????????????? ???8?????????????bslbf } }? 如果用戶要求得到SI系統描述的特定實體的進一步信息,則可以使用鏈接描述符。鏈接描述符包含的信息給出了該實體的位置。如:可以在一個NIT中使用一個鏈接描述符,給出網絡中可存放業務附加信息的位置;或者在BAT表中的鏈接描述符可鏈接到業務群的相關信息等。 使用鏈接描述符,也可以提供一種業務,以替換CA系統的功能。如果CA系統不能處理相應功能的時候,接收機就可以用這個業務來取代CA。 使用鏈接描述符,還可以以一種備用業務,用以替換主業務。若主業務的運行狀態被置為“not_running”,那么,接收機可以自動選擇被鏈接描述符指引的備用業務,以取代該業務。 使用鏈接描述符,還可以向移動接收機提供漫游功能。若現行業務其service_id下無法使用,IRD可以自動選擇該功能。hand-over_type指明link_descriptor是否鏈接到不同國家的同一業務,或者鏈接到本地變更業務或關聯業務。 總之,鏈接描述符為運營商提供了一種業務擴充功能,使得運營商可以更加靈活地組合各種業務。
NIT的軟件下載鏈接描述符結構分析 軟件下載描述符用于運營商在網絡內進行多于一個機頂盒的軟件下載更新標識,在網絡信息表NIT的第一個循環內,并且可能多次出現。針對同一組制造商號(manufacturer_id)、硬件類型(hw_model)、硬件版本(hw_version)和軟件類型(sw_model),可能有不只一組的不同軟件版本(sw_version)和開始時間(start_time)參數,并可能出現在同一個或多個鏈接描述符(linkage_descriptor)的各個循環內。
解析 "BAT將網絡中的所有業務分成了多個業務群,以此界定用戶" BAT即業務群關聯表(BouquetAssociation Table),它將網絡中所有的業務分成了多個業務群,以此界定用戶。例如,將網絡中所有業務分為兩個業務群,一個是境內節目業務群,另一個是境外節目業務群。這樣,國內的運營商就可以利用這樣劃分的業務群,充分利用節目資源,在不違反現有廣電總局規定的前提下,同時分別滿足境內用戶和境外用戶。 BAT本身可以跨網絡存在,但在國內運營體系來看幾乎沒有得到真正使用。國內的運營使用中,BAT還可以存在分級運營的運營體系中,用于區分不同的地域用戶。 BAT被切分為業務群關聯段,所有的業務群關聯段都在TS中傳輸,其PID為0x0011。所有的業務群關聯段的table_id都取0x4A。 HINT:SDT的TS包PID也為0x0011,其table_id為0x42或0x46。 BAT的表結構分析 下面給出了BAT表的段結構: 業務群關聯段 Syntax(句法結構)???????? No. ofbits(所占位數)?? Identifier(識別符)? Note(注釋) bouquet_association_section(){ table_id????????????????????????????????????????????8??????????????????????uimsbf?????????????????????????????????????????????????? Section_syntax_indicator?????????????? 1????????????????????????? bslbf???????? 通常設為“1” Reserved_future_use????????????????????? 1??????????????????????? bslbf Reserved?????????????????????????????????????????2??????????????????????? bslbf Section_length??????????????????????????????? 12????????????????????? uimsbf???????????????? 見注釋 bouquet_id????????????????????????????????????? 16?????????????????????? uimsbf???????????????? 見注釋 Reserved?????????????????????????????????????????2???????????????????????? bslbf Version_number????????????????????????????? 5???????????????????????? uimsbf???????????? 見注釋 Current_next_indicator?????????????????? 1????????????????????????? bslbf???????????????? 見注釋 Section_number????????????????????????????? 8????????????????????????? uimsbf??????????? 見注釋 last_section_number?????????????????????? 8????????????????????????? uimsbf??????????? 見注釋 Reserved_future_use????????????????????? 4????????????????????????? bslbf bouquet_descriptors_length??????? 12??????????????????????? uimsbf for(i=0;i<N;i++){ descriptor() } reserved_future_use???????????????????????? 4???????????????????? bslbf transport_stream_loop_length?????? 12????????????????? uimsbf?????????????? for(i=0;i<N;i++){ transport_stream_id???????????????????? 16????????????????? uimsbf???????????? 見注釋 original_network_id????????????????????? 16????????????????? uimsbf???????????? 見注釋 reserved_future_use????????????????????? 4????????????????? bslbf transport_descriptors_length???? 12?????????????????? uimsbf for(j=0;j<N;j++){ descriptor() } } CRC_32?????????????????????????????????????????32????????????????? rpchof????????????????? 見注釋 } 注意到BAT的結構和NIT類似,其作用和描述符的使用也與NIT大致雷同。其中,可以插入傳輸系統描述符、業務列表描述符等。這些表和NIT中的表已介紹,這里不再贅述。
BAT的業務群名稱描述符結構分析 下面給出的是業務群名稱描述符,它以文本方式給出了業務群的名稱: 業務群名稱描述符 Syntax(句法結構)??? No. of bits(所占位數)Identifier(識別符)? bouquet_name_descriptor(){ descriptor_tag???????????????????????? 8?????????? uimsbf??????????????????????????? descriptor_length????????????? ???????8??????????uimsbf???????????????????????? for(i=0;i<N;i++){ char??????????????????????????? ???????????8????????????uimsbf?????? } } char(字符):8位字段,用于描述BAT子表敘述的節目業務群名稱 業務名稱描述符和網絡名稱描述符類型,只是作為業務群的一個代號,其實際意義只存在于用戶界面上,可以給用戶一個良好的操作體驗。
SDT解析 "SDT描述了業務內容及信息,連接了NIT與EIT和PMT(PSI)" SDT即服務描述表(Service Description Table),它描述了一個業務中的內容以及信息,它承上啟下,以transport_stream_ID連接了NIT和EIT;SDT的servicID必須與PMT中的Program_no一致,因此,SDT又與PSI的信息連接。 對于一般的音視頻業務,SDT表中不會有太多的信息需要添加。如果是其他業務(如NVOD、馬賽克、數據廣播等),在SDT中需要插入相應業務的描述符。
SDT的表結構分析 SDT表被切分成業務描述段(service_description_section),由PID為0x0011的TS包傳輸(BAT段也由PID為0x0011的TS包傳輸,但table_id不同)。 描述現行TS(即包含SDT表的TS)的SDT表的任何段的table_id都為0x42,且具有相同的table_id_extension(transport_stream_id)以及相同的original_network_id。 指向非現行TS的SDT表的任何段的table_id都應取0x46。 下面給出了SDT的業務描述段:? 業務描述段 Syntax(句法結構)???????? No. ofbits(所占位數)?? Identifier(識別符)? Note(注釋)?? service_description_section(){ table_id????????????????????????????????????????????8??????????????????????uimsbf?????????????????????????????????????????????????? Section_syntax_indicator?????????????? 1????????????????????????? bslbf?????????????????? 通常設為“1” Reserved_future_use????????????????????? 1??????????????????????? bslbf Reserved?????????????????????????????????????????2??????????????????????? bslbf Section_length??????????????????????????????? 12????????????????????? uimsbf???????????????? 見注釋 transport_stream_id?????????????????????? 16?????????????????????? uimsbf????????????????給出TS識別號 Reserved?????????????????????????????????????????2???????????????????????? bslbf Version_number????????????????????????????? 5???????????????????????? uimsbf???????????? 見注釋 Current_next_indicator?????????????????? 1????????????????????????? bslbf???????????????? 見注釋 Section_number????????????????????????????? 8????????????????????????? uimsbf??????????? 見注釋 last_section_number?????????????????????? 8????????????????????????? uimsbf??????????? 見注釋 original_nerwork_id??????????????????????? 16???????????????????????? uimsbf??????????? 見注釋 reserved_future_use??????????????????????? 8????????????????????????? bslbf for(i=0;i<N;i++){ service_id???????????????????????????????????? 16???????????????????????? uimsbf?????????? 見注釋 reserved_future_use???????????????????? 6???????????????????????? bslbf EIT_schedule_flag???????????????????????? 1????????????????????????? bslbf??????????? 見注釋 EIT_present_following_flag????????? 1????????????????????????? bslbf??????????? 見注釋 running_status??????????????????????????????? 3???????????????????????? uimsbf??????? 見下面分析 freed_CA_mode??????????????????????????? 1???????????????????????? bslbf??????????? 見注釋 descriptors_loop_length??????????????? 12????????????????????? uimsbf for(j=0;j<N;j++){ descriptor() } } CRC_32???????????????????????????????????????????????32????????????????? rpchof????????????????? 見注釋 } running_status(運行狀態):表示業務狀態,下表給出了業務狀態
SDT是描述一個TS流中所有業務信息的一張表,重要的字段包含transport_stream_id,明確這些業務是屬于哪個TS流的;另一個重要字段時候service_id,這是作為頻道索引信息存在的。
SDT的業務描述符分析 業務描述符與業務類型一起,以文本形式給出業務提供者的名稱和業務名稱,如下表: 業務描述符 Syntax(句法結構)??? No. of bits(所占位數)Identifier(識別符)? service_descriptor(){ descriptor_tag?????????????????????? 8?????????????????????? uimsbf descriptor_length?????????????????? 8?????????????????????? uimsbf service_type????????????????????????? 8????????????????????? uimsbf service_provider_name_length? 8??????????????????? uimsbf for(i=0;i<N;i++){ Char???????????????????????????????? 8????????????????????? uimsbf } service_name_length??????????? 8????????????????????? uimsbf for(i=0;i<N;i++){ Char??????????????????????????????? 8????????????????????? uimsbf } } service_type(業務類型):這里的業務類型和NIT中的業務列表描述符中的service_type編碼是一致的:
業務描述符是SDT中最重要的描述符,也是運營商中必須的描述符。其中的service_type描述這個業務類型的域;service_name描述頻道名。
SDT的實例分析 這里主要演示SDT如何連接PSI和NIT。 首先,根據SDT描述符的service_id可以和PMT中的program_number建立連接。如圖所示,SDT的service_id=201=0xc9,與PMT中的program_number一致。
上圖所示,根據SDT的transport_stream_id和NIT的transport_stream_id,可以將SDT和NIT聯系起來。根據上圖的信息,我們可以根據SDT獲取該業務(頻道)的業務列表信息和有線傳輸信息(位于NIT中)。
EIT解析 "EIT按時間順序提供每一個業務所包含的事件信息" EIT即事件信息表(Event Information Table),它是EPG中絕大部分信息的攜帶者。事實上,EPG主要就是通過SDT和EIT信息的獲取和重組實現的。SDT只提供了頻道信息,而EIT則提供各頻道下的所有節目的信息。 EIT的主要信息也是通過插入的描述符來實現的。EIT按照時間順序提供每一個業務所包含的事件的相關信息(如節目名稱、節目簡介)。 按照不同的table_id,一共有四類EIT。其中,當前TS流的所有EIT子表都有相同的transport_stream_id和original_stream_id。下圖給出了一個實例的碼流中的EIT信息,這里一共有三類EIT表,觀察其table_id就可以知道它們代表什么類型的EIT 第一個EIT_PF_Actual應該是當前TS流的“當前/后續事件信息”;第二個EIT_PF_Other是其他TS流的“當前/后續事件信息”;第三個EIT_Schedule_Actual是當前TS流的“事件時間表信息”。
EIT的表結構分析 EIT表被切分成事件信息段。任何構成EIT的段都由PID=0x0012的TS包傳輸。下面給出的是事件信息段的結構: 事件信息段 Syntax(句法結構)???????? No. ofbits(所占位數)?? Identifier(識別符)? Note(注釋) event_information_section(){ table_id????????????????????????????????????????????8??????????????????????uimsbf?????????????????????????????????????????????????? Section_syntax_indicator?????????????? 1????????????????????????? bslbf?????????????????? 通常設為“1” Reserved_future_use????????????????????? 1??????????????????????? bslbf Reserved?????????????????????????????????????????2??????????????????????? bslbf Section_length??????????????????????????????? 12????????????????????? uimsbf???????????????? 見注釋 service_id??????????????????????????????????????? 16?????????????????????? uimsbf????????????????與PAT中的program_number一致 Reserved?????????????????????????????????????????2???????????????????????? bslbf Version_number????????????????????????????? 5???????????????????????? uimsbf???????????? 見注釋 Current_next_indicator?????????????????? 1????????????????????????? bslbf???????????????? 見注釋 Section_number????????????????????????????? 8????????????????????????? uimsbf??????????? 見注釋 last_section_number?????????????????????? 8????????????????????????? uimsbf??????????? 見注釋 transport_stream_id?????????????????????? 16???????????????????????? uimsbf??????????? 見注釋 original_nerwork_id??????????????????????? 16???????????????????????? uimsbf??????????? 見注釋 segment_last_section_number???? 8?????????????????????????? uimsbf??????????? 見注釋 last_table_id???????????????????????????????????? 8?????????????????????????? uimsbf??????????? 見注釋 for(i=0;i<N;i++){ event_id??????????????????????????????????????? 16???????????????????????? uimsbf??????????事件(節目)id start_time????????????????????????????????????? 40???????????????????????? bslbf???????????事件(節目)開始時間 duration????????????????????????????????????????24?????????????????????????bslbf???????????事件(節目)持續始時間 running_status??????????????????????????????? 3???????????????????????? uimsbf???????? 見注釋 freed_CA_mode??????????????????????????? 1???????????????????????? bslbf??????????? 見注釋 descriptors_loop_length??????????????? 12????????????????????? uimsbf for(j=0;j<N;j++){ descriptor() } } CRC_32???????????????????????????????????????????????32????????????????? rpchof????????????????? 見注釋 } start_time(開始時間):40位字段,指的是事件(節目)的開始時間,它包含以UTC和MJD形式表示的事件(節目)的起始時間及日期。此字段前16位表示MJD日期碼,其余24位按4位BCD編碼,表示6個數字。例如:93/10/13 12:45:00被編碼為:“0xc079124500” HINT:如果事件起始時間未定,則所有位都置為“1”,例如對NVOD業務的一個事件。 duration(持續時間):24位字段,表示事件的持續時間,以時、分、秒的格式表示,即由6個4位BCD碼顯示。如:01:45:30被編碼為“0x14530”。 running_status(運行狀態):參看SDT表解析部分。 下面給出一個具體的例子: EIT主要承載的信息就是Event的相關內容,即節目信息。其中,節目所在頻道(service_id)、開始時間(start_time)、結束時間(start_time+duration)可在EIT子表獲取;而節目描述、節目名稱、節目分類等信息就要在插入EIT的描述符中獲取了。
EIT的短事件描述符分析 短事件描述符(Short_event_descriptor)以文本方式提供了事件名稱和該事件的簡短描述。描述符結構如下: 短事件描述符 Syntax(句法結構)??? No. of bits(所占位數)Identifier(識別符)? short_event_descriptor(){ descriptor_tag?????????????????????? 8?????????????????????? uimsbf descriptor_length?????????????????? 8?????????????????????? uimsbf ISO_639_language_code????? 24????????????????????? bslbf event_name_length?????????????? 8?????????????????????? uimsbf for(i=0;i<event_name_length;i++){ event_name_char???????????? 8?????????????????????? uimsbf } text_length????????????????????????? 8?????????????????????? uimsbf for(i=0;i<text_length;i++){ text_char??????????????????????? 8?????????????????????? uimsbf } } ISO_639_language_code(ISO 639-2語言代碼):24位字段,指明后續文本字段的語言。該字段包含一個由ISO 639-2定義的3字符代碼。ISO 639-2/B和ISO 639-2/T均可使用。每個字符按照GB/T15273.1-1994編碼為8位,并依次插入24位字段。如:法語的3字符代碼“fre”,可編碼為:“0110 01100111 0010 0110 0101”。 event_name_char(事件名稱字符):一個字符串給出事件的名字。 text_char(文本字符):一個字符串給出事件的文本描述。 下面給出的是一個實際案例的短時間描述符,可見中文的3字符代碼是“chi”。
EIT的擴展事件描述符分析 擴展事件描述符(Extended_Event_Descriptor)拓展事件描述符給出了一個事件的詳細文本描述。如果一個事件的信息長度超過256字節,可以使用多于一個相關聯的擴展事件描述符來描述。文本信息可以分為兩個欄目,一欄為條目的描述,另一欄為條目的內容。 下面給出了擴展事件描述符的結構。 擴展事件描述符 Syntax(句法結構)??? No. of bits(所占位數)Identifier(識別符)? extended_event_descriptor(){ descriptor_tag???????????????????????? 8?????????? uimsbf???????? descriptor_length???????????????? 8?????????? uimsbf??? descriptor_number????????????????????? 4???????????? uimsbf last_descriptor_number??????????????? 4???????????? uimsbf ISO_639_language_code?????????? 24?????????? bslbf? length_of_items??????????????????????????? 8???????????? uimsbf for(i=0;i<N;i++){ item_description_length????????? 8?????????????? uimsbf for(j=0;j<N;j++){ item_description_char?????? 8??????????????? uimsbf } item_length for(j=0;j<N;j++){ item_char } }??? text_length for(i-0;i<N;i++){ text_char }????????????? } 下面給出的是一個實例截圖:
EIT的內容描述符分析 內容描述符的目的是為事件提供清晰的信息描述符。根據這個描述符的信息,接收機可以清晰地知道事件的分類,并告知觀眾。下面給出了內容描述符的結構: 內容描述符 Syntax(句法結構)??? No. of bits(所占位數)Identifier(識別符)? content_descriptor(){ descriptor_tag???????????????????????? 8?????????? uimsbf????? descriptor_length???????????????? 8?????????? uimsbf???????????????????????? for(i=0;i<N;i++){ content_nibble_level1?????? 4????????????? uimsbf?????? content_nibble_level2????? 4????????????? uimsbf?????? user_nibble???????????????????????? 4???????????? uimsbf?????? user_nibble???????????????????????? 4???????????? uimsbf?????? } } 這里主要需要介紹的就是?content_nibble_level1和content_nibble_level2:根據EN 300 468V1.3.1(1998-02)中的Table 18可以確定該節目的具體分類。 下面給出了一個實例。
TDT解析 "TDT僅傳送UTC時間和日期信息,只有一個段" TDT為時間和日期表(Time&Date?Table),它僅傳送UTC時間和日期信息。并且TDT僅包含一個段,其結構如下: 時間和日期段 Syntax(句法結構)???????? No. ofbits(所占位數)?? Identifier(識別符)? Note(注釋)?? time_date_section(){ table_id????????????????????????????????????????????8??????????????????????uimsbf?????????????????????????????????????????????????? Section_syntax_indicator?????????????? 1????????????????????????? bslbf???????????? 通常設為“1” Reserved_future_use????????????????????? 1??????????????????????? bslbf Reserved?????????????????????????????????????????2??????????????????????? bslbf Section_length??????????????????????????????? 12????????????????????? uimsbf???????????????? 見注釋 UTC_time???????????????????????????????????????????40??????????????????????bslbf???????????????????? 見注釋 } UTC_time(UTC時間):40位字段,包含以UTC和MJD形式表示的當前時間和日期。此字段前16位為MJD日期碼,后24位按4位BCD編碼,表示6個數字。如:93/10/13 12:45:00被編碼為“0xC079124500”。 下圖給出了一個實例: TOT解析 "TOT是TDT的一個擴展,增加了一個描述符" TOT為時間偏移表(Time Offset Table),它包含了UTC時間和日期信息及當地時間偏移。傳輸此表的TS包PID為0x0014,table_id=0x73。下面給出了時間偏移段的結構: 時間偏移段 Syntax(句法結構)???????? No. ofbits(所占位數)?? Identifier(識別符)? Note(注釋) time_offset_section(){ table_id????????????????????????????????????????????8??????????????????????uimsbf?????????????????????????????????????????????????? section_syntax_indicator?????????????? 1????????????????????????? bslbf???????? 通常設為“1” reserved_future_use????????????????????? 1??????????????????????? bslbf reserved?????????????????????????????????????????2??????????????????????? bslbf section_length??????????????????????????????? 12????????????????????? uimsbf???????????????? 見注釋 UTC_time???????????????????????????????????????????40??????????????????????bslbf???????????????????? 見注釋 reserved?????????????????????????????????????????4???????????????????????? bslbf descriptors_loop_length??????????????? 12????????????????? uimsbf?????????????? for(i=0;i<N;i++){ descriptor() } CRC_32?????????????????????????????????????????32????????????????? rpchof????????????????? 見注釋 } 這里的UTC_time和TDT表是一致的,都是以UTC和MJD形式表示當前時間和日期;其格式也與TDT的UTC_time相同,這里不再贅述。需要特別注意的是這里的描述符descriptor()。下面給出了本地時間偏移描述符的結構: 本地時間偏移描述符 Syntax(句法結構)??? No. of bits(所占位數)Identifier(識別符)? local_time_offset_descriptor(){ descriptor_tag???????????????????????? 8?????????? uimsbf???????? descriptor_length???????????????? 8?????????? uimsbf??? for(i=0;i<N;i++){ coutry_code?????????????????????????? 24???????????? bslbf country_region_id??????????????????? 6???????????? bslbf reserved????????????????????????????????? 1???????????? bslbf local_time_offset_polarity?????? 1???????????? bslbf local_time_offset??????????????????? 16??????????? bslbf time_of_change????????????????????? 40??????????? bslbf next_time_offset???????????????????? 16??????????? bslbf } } 國家代碼? country_code 24位字段,按照ISO 3166用3字符代碼指明國家。每個字符根據GB/T 15273.1-1994編碼為8位,并依次插入24位字段。假設3個字符代表了一個900至999的數字,那么country_code指定了一組ETSI定義的國家。其分配見ETR 162。國家組的國家代碼應該被限制在同一時區內。 例如:英國由3字符代碼“GBR”表示,編碼為:“01000111 0100 0010 0101 0010”。 國家區域標識符? country_region_id 6位字段,表示country_code指明的國家所在的時區。若國家內部里沒有時差,則置“000000”。
本地時間偏移極性?local_time_offset_polarity 1位字段,用于指明隨后的local_time_offset的極性。置“0”時,極性為正,說明本地時間早于UTC時間(通常在格林威治以東);置“1”時,極性為負,說明本地時間晚于UTC時間。 本地時間偏移?local_time_offset 16位字段,指出由country_code和country_region_id確定的區域的相對于UTC的時間偏移,范圍為-12小時至+13小時。16比特含有4個4位BCD碼,順序為小時的十位,小時的個位,分的十位,分的個位。 時間變化? time_of_change 40位字段,指明時間改變時當前的日期(MJD)與時間(UTC),見附錄C。該字段分為兩部分,前16位給出了LSB格式的日期(MJD),后24位給出了UTC時間(6個4位BCD碼)。 下一時間偏移? next_time_offset 16位字段,指出由country_code和country_region_id確定的區域,當UTC時間變化時的下一個時間偏移,范圍為-12小時至+13小時。此16比特域為4個4位BCD碼,依次為時的十位,時的個位,分的十位,分的個位。
小結 SI
1) SDT(業務描述表):描述了包含在特定TS流中的全部業務的相關信息。 業務描述表包含了描述系統中業務的數據,例如業務名稱、業務提供者等。 2) EIT(事件信息表):描述了包含在特定業務中的所有事件的相關信息。 事件信息表包含了與事件或節目相關的數據,例如事件名稱、始時間、持續時間等。 不同的描述符用于不同類型的事件信息的傳輸,例如不同的業務類型。 3) TDT(時間和日期表):時間和日期表給出了與當前的時間和日期相關的信息。 由于這些信息頻繁更新,所以需要使用一個單獨的表。 4) BAT (業務群關聯表) 給出業務群的名稱及其業務列表等信息 5) RST(運行狀態表) 6) TOT(時間偏移表) 給出了當前時間日期與本地時間偏移的信息 7) ST (填充表) 8) SIT(選擇信息表) 9) DIT (間斷信息表)
參考資料
預備知識1:PSI/SI關鍵字
不論是視頻、音頻、文字、圖片還是業務信息(包括PSI/SI)都將被劃分為最基本的ES,并將它們通過PES的形式組裝起來,經過復用形成TS流 對TS流的解析:首先獲取到TS流中的包Packet,根據其PID過濾出需要的包,根據其section的結構還原成section,再由上層協議來處理。 預備知識4:業務與事件 PRE-LEARNING4 關于業務(Service)與事件(Event)。 這里將會大量出現這兩個詞。那么什么是“業務”,什么是“事件”呢?一般來說,接下來所說的“業務”就是指“頻道”,“事件”就是“節目”。這里需要明確“節目”的概念,舉個例子:CCTV1是一個頻道,也就是我們所說的“業務(Service)”;《新聞聯播》是一個節目,也就是我們所說的“事件”。分清楚了這兩個概念,我們才能區分下面的很多SI信息。
"PSI是對單一TS流的描述,是TS流中的引導信息" PSI信息由節目關聯表PAT、條件接收表CAT、節目映射表PMT和網絡信息表NIT組成。這些表會被插入到TS流中。PSI信息是對單一TS流的描述,它是TS流的引導信息;PSI信息指定了如何從一個攜帶多個節目的傳輸流中找到指定的節目(見Q1)。 下面給出的是節目引導信息(或稱節目特定信息,PSI)的四個表結構。 雖然這四個結構可以視為簡單的表,但事實上,它們被進一步劃分為各個段,并插入到TS包中 PAT解析 PARSINGOF?PAT "PAT是機頂盒接收的入口點,是它獲取數據的開始" 節目關聯表PAT的意義在于,它描述了當前TS流中包含了哪些PID;只有根據獲得的PID,用戶才可以以此作為憑據找出其他表(如PMT表)及其信息。所以PAT是機頂盒接收的入口點,是它獲取數據的開始;要保證一個TS流能被正常接收,則至少要有一個完整有效的PAT。 下面給出了PID字段的取值要求:
PAT的表結構分析 首先,對PAT的表結構進行分析。下面給出了PAT表的基本結構: 節目關聯段 Syntax(句法結構)???????? No. ofbits(所占位數)?? Identifier(識別符)? Note(注釋) program_association_section(){ table_id????????????????????????????????????????????8??????????????????????uimsbf?????????????????????????????????????????????????? Section_syntax_indicator?????????????? 1????????????????????????? bslbf?????????????????? 通常設為“1” "0"?????????????????????????????????????????????????????1??????????????????????? bslbf Reserved?????????????????????????????????????????2??????????????????????? bslbf Section_length??????????????????????????????? 12????????????????????? uimsbf???????????????? 見注釋 transport_stream_id??????????????????????? 16?????????????????????? uimsbf??????????? 見注釋 Reserved?????????????????????????????????????????2???????????????????????? bslbf Version_number????????????????????????????? 5???????????????????????? uimsbf???????????? 見注釋 Current_next_indicator?????????????????? 1????????????????????????? bslbf???????????????? 見注釋 Section_number????????????????????????????? 8????????????????????????? uimsbf??????????? 見注釋 last_section_number?????????????????????? 8????????????????????????? uimsbf??????????? 見注釋 for(i=0;i<N;i++){ program_number???????????????????????? 16???????????????????????? uimsbf??????? 見注釋 reserved???????????????????????????????????????? 3????????????????????????? bslbf if(program_number == 0){ network_PID???????????????????????????? 13???????????????????????? uimsbf??????? 見注釋 } else{ program_map_PID???????????????? 13???????????????????????? uimsbf??????? 見注釋 } } CRC_32?????????????????????????????????????????32????????????????? rpchof????????????????? 見注釋 } 這里我們注意關注五個字段: table_id(賦值):PAT的table_id應為0x00 ??????????transport_stream_id(傳輸流標志):用以標識來源于網絡中任何其他復合流的TS流 program_number(節目號):規定program_map_PID可適用的節目。當值為0x0000時,其后的PID參照將是網絡PID。它可以作為一個指示符號,例如用于廣播通道。 network_PID(網絡PID):僅當program_number為0x00時使用 program_map_PID(節目映射PID):據此找出相應的PMT表
PAT的實例分析 借助碼流分析儀,我們可以很清楚地以實例的方式更加清晰地了解PAT的結構。下面給出的就是一個TS流的PAT分析情況: 根據上表可以看出,這個TS流里共有6套節目,其映射關系PID分別為0xc9、0xcb、0xce、0xcc、0xcd和0xca。(注:0xc9=201) 下面給出的是PMT的簡單解析: 兩相比較,可以很清楚地知道,PAT是如何鎖定各個PMT的(每個節目都有一個自己的PMT)。 Q1:如何找到一個特定的節目? 1.已知節目名稱(或id等信息) P248 首先要從節目關聯表PAT中獲取這個節目的節目映射表PMT的PID值,再從TS流中找出與此PID值相對應的節目映射表PMT;再從PMT中獲取構成這個節目的基本碼流的PID值,從而根據該PID過濾出相應的視頻、音頻和數據等基本碼流。最后解碼恢復為原始信號。
PMT解析 "PMT是連接節目號與節目元素的橋梁" 節目映射表PMT的意義在于,它給出了節目號與組成這個節目元素之間的映射;也就是說,PMT是連接節目號與節目元素的橋梁。我們知道,一個電視節目至少包含了視頻和音頻數據,而每一個節目的視音頻數據都是以包的形式在TS流中傳輸的;所以說,一個TS流包含了多個節目的視頻和音頻數據包。要想過濾出一個TS流中其中一個節目的視頻和音頻,則需要知道這個節目中視頻和音頻的標識號PID。PMT表的作用就在于,它提供了每個節目視頻、音頻(或其他)數據包的PID。
PMT的表結構分析 先給出PMT表的段結構: Syntax?(句法結構)???????? No. of bits(所占位數)?? Identifier(識別符)? Note(注釋) program_map_section(){ table_id??????????????????????????????????????????? ???8?????????????????????? uimsbf?????????????????????????????????????????????????? Section_syntax_indicator???????????? ????1????????????????????????? bslbf?????????????????? 通常設為“1” "0"????????????????????????????????????????????????????????1??????????????????????? bslbf Reserved?????????????????????????????????????? ???????2??????????????????????? bslbf Section_length?????????????????????????????? ????12????????????????????? uimsbf???????????????? 見注釋 program_number????????????????????????? ????16?????????????????????? uimsbf???????????? Reserved????????????????????????????????????????? ????2???????????????????????? bslbf Version_number???????????????????????????? ???5???????????????????????? uimsbf???????????? 見注釋 Current_next_indicator?????????????????? ?1????????????????????????? bslbf???????????????? 見注釋 Section_number???????????????????????????? ???8????????????????????????? uimsbf??????????? 見注釋 last_section_number??????????????????? ????8????????????????????????? uimsbf??????????? 見注釋 reserved??????????????????????????????????????????? ??3????????????????????????? bslbf PCR_PID???????????????????????????????????????? ????13?????????????????????????uimsbf?????????? 見注釋 reserved???????????????????????????????????????? ?????4????????????????????????? bslbf program_info_length???????????????????? ??12??????????????????????? uimsbf??????????? 頭兩位為"00" for(i=0;i<N;i++){ descriptor() } for(i=0;i<N1;i++){ stream_type????????????????????????????????8??????????????????????????uimsbf??????? 見注釋 reserved?????????????????????????????????????? 3?????????????????????????? bslbf elementary_PID?????????????????????????13????????????????????????uimsbf??????? 見注釋 reserved?????????????????????????????????????? 4?????????????????????????? bslbf ES_info_length??????????????????????????12????????????????????????uimsbf???????????? 頭兩位為"00" for(j=0;j<N2;j++){ descriptor(); } } CRC_32?????????????????????????????????????????32????????????????? rpchof????????????????? 見注釋 } 這里著重介紹兩個字段: elementary_PID:標識了該節目(program_number)攜帶的基本流的識別號PID stream_type:流類型,指出了PID為elementary_PID的基本流的類型 附:流類型取值說明
PMT的實例分析 下面給出了碼流分析儀分析一段TS流的PMT表:
首先,注意到這張PMT表的progam_number=0xc9,就是我們在上面解析PAT表得到的。 從上面可以知道,節目號為0xc9(即201)的節目有兩個單元流:
elementary_PID和stream_type的意義在于,告知接收機基本流的類型和識別PID。要想獲取這個節目的視頻,只需要對PID為0x21的數據包進行過濾,并交由視頻處理模塊處理。下圖所示(除了節目名稱,還需要SDT表信息)即為PAT和PMT共同獲取的信息。
CAT解析 PARSINGOF?CAT "CAT描述了節目的加密方式" 條件接收表CAT描述了節目的加密方式,它包含了節目的EMM注1識別PID。它給出了一個或多個CA系統、EMM流以及與CA相關的特定參數之間的關系。 注1:EMM(Entitlement?Management Message),即授權管理信息。描述了用戶可看的節目或時間段、用戶的付費等。 CA描述符既用于規定像EMM這樣的系統范圍條件接收管理信息,也用于規定像ECM這樣的基本流特定信息。
CAT的表結構分析 條件存取段 Syntax(句法結構)???????? No. ofbits(所占位數)?? Identifier(識別符)? Note(注釋) conditional_access_section(){ table_id????????????????????????????????????????????8??????????????????????uimsbf?????????????????????????????????????????????????? Section_syntax_indicator?????????????? 1????????????????????????? bslbf?????????????????? 通常設為“1” "0"?????????????????????????????????????????????????????1??????????????????????? bslbf Reserved?????????????????????????????????????????2??????????????????????? bslbf Section_length??????????????????????????????? 12????????????????????? uimsbf???????????????? 見注釋 reserved??????????????????????????????????????????18?????????????????????? bslbf Version_number????????????????????????????? 5???????????????????????? uimsbf???????????? 見注釋 Current_next_indicator?????????????????? 1????????????????????????? bslbf???????????????? 見注釋 Section_number????????????????????????????? 8????????????????????????? uimsbf??????????? 見注釋 last_section_number?????????????????????? 8????????????????????????? uimsbf??????????? 見注釋 for(i=0;i<N;i++){ descriptor() } CRC_32?????????????????????????????????????????32????????????????? rpchof????????????????? 見注釋 } 條件存取段主要作用是指示本TS流中存在加擾節目,并且在描述符循環中必須插入CA描述符來作進一步指引。下面給出的是條件接收的描述符 條件接收描述符 條件接收描述符 Syntax(句法結構)??? No. of bits(所占位數)Identifier(識別符)? CA_identifier_descriptor(){ descriptor_tag???????????????????????? 8?????????? ???????????????????????????????uimsbf??????????????????????? descriptor_length??????????????? ?????8?????????????????????????????????????????uimsbf???????? CA_system_ID???????????????????? ?????16????????? ?????????????????????????????uimsbf reserved????????????????????????????? ???????3?????????? ??????????????????????????????bslbf CA_PID??????????????????????????????????? 13??????? ???????????????????????????????uimsbf??????????????? for(i=0;i<N;i++){ private_data_byte??????????????? ????8 }} CA_system_ID(CA系統ID):指出用于相關ECM及(或)EMM流的CA系統類型。 CA_PID(CA PID):指出包含用于相關CA_system_ID所規定的CA系統的ECM或EMM信息傳輸流分組的PID(即在TS流中過濾出相應PID的分組)。 下面給出的TS流中并沒有CAT: 但在PMT表中有CA描述符:
PSI小結 上圖給出了在一個TS流中PSI各表之間的聯系。首先從PAT表出發,獲取當前有哪些節目號(program_map_PID),再根據這些節目號找出program_number相同的PMT;獲取到PMT后,即可根據elementary_PID和stream_type來確定要過濾哪些含有基本流的TS包,以及這些包里面是什么類型的數據。這樣,機頂盒就可以過濾出相應的節目(視頻和音頻數據)來收看了。
2.8Tuner數據處理流程
大概流程: 1.cable?ts 信號(signel)--》tuner--》demux-》video,audio解碼編碼-》輸出顯示 2.本地ts file--》demux-》video,audio解碼編碼-》輸出顯示 如果有解擾邏輯,則需要在demux后對video,audio包解擾處理。 3.對cable?ts?的錄制即: 信號(signel)--》tuner--》demux-》磁盤--》demux--》video,audio解碼編碼-》輸出顯示 即多了一個步驟,需要將解擾的流保存到磁盤中,如果需要播放磁盤中的文件,則將磁盤中的文件數據傳給demux,也就是一個逆向過程。 當然demux的處理牽涉到section,filter另做討論。
以下將分節討論: 1.TUNER?調諧器 一般有有線cable,衛星satellite,地面territory 3種type tuner工作需要知道頻率freq,符號率symb,QAM大小,tuner獲取到的信號signel有信號強度,誤碼率,質量,等級等,主要就是鎖住某個需要的頻點去獲取信息(模擬信號-》數字信號)。一般問題就是鎖不住頻點,拿不到signel。 目前一般是STB 的tuner某一時刻只能處理一個頻點信息,也許以后會啟動同時處理多個頻點或多個tuner的雙xx模式或多xx模式。終端屏幕的越來越大,完全是可以在一個屏上顯示多個流的。
2.Demux 終端主要是解復用,也就是解析自己想要的數據,并分類的處理。這塊需要專業的MPEG/DVB相關協議知識,主要是PSI/SI。 一般牽涉到的概念有filter,channel,section,pid等,一般來說一個Channel對應一個PID,對應多個Filter。 首現要知道頻點,需要tuner到某個頻點上去鎖頻,將模擬數據轉換為數字信號。 然后數字信號會送到Demux解復用,這一坨數據很多,你需要通過一定的規則去獲取你想要的數據。 filter過濾用,就是tuner拿到的那一坨數據有很多,但只需要將你想要的數據過濾出來。怎么過濾?一般我們要知道我們想要的數據在哪個PID,對應的段數據可能還需要再細分類,那你還需要將section前幾個字節(byte)傳下去,讓demux只過濾出PID下同時匹配section前幾個字節數據對應的包數據。比如。。。xx xx xx?01(PID)xx 02?03?04?05?06?07 xx 。。。當前頻點拿到的數據很多,但我只需要PID為0x1, section前3個字節為02.03.04的表的數據,首先filter會過濾出pid為0x01的所有的數據,然后在這些數據中過濾出前3個字節為02?03?04 的那些數據。再細化分類的話拿到這些數據你就要按SI/PSI協議或你自己私有的協議來了。 channe通道l我們可以認為是一個容器,或再簡單點就認為它是一塊內存。這塊容器就是用來裝我們filter出來的數據的,所以一般channel是掛在filter上的。一個filter可以有多個channels,或一個channel有多個filter,具體要看平臺實現需要。 當然由于硬件特性,signel環境,參數情況,可能獲取不到我們想要的數據,不可能一直讓filter,channel一直去那那個不存在或有問題的數據的,就需要有一個超時機制:在這個時間段無法拿到數據,通知上層,demux拿不到你想要的數據,你改干嘛干嘛去吧。同時demux釋放filter,channel等相關資源。 demux處理后,filter過濾的數據通過回調或其他方式給上層,上層拿到想要的數據再實現具體的應用。
3.video,audio 編解碼 一般來說解碼后就可以輸出output了。 目前常用的數據電視用到的制式有PAL,NTSC等 視頻輸出一般有CVBS,ypbpr,YUV,hdmi(高清用的多)等 視頻輸出一般用到視頻層,靜態層(still,IFRAME一般用到) 輸出節目長度寬度比國內一般有4/3,16/9 常用支持的視頻有:MPEG1,2,4;H264等 常用支持的音頻有:MPEG1,2,ADTS,AC3,DTS等
一般對音視頻會分配專門的固定的filter,channel。要播放某個節目,必須通過SI/PSI獲取到,freq,vpid,apid,pcrpid等。 播放音視頻就是讓tuner鎖對應freq的頻點,demux去過濾出vpid,apid的數據包。其中通過pcrpid可以獲取一個時間參考系。vpid拿到視頻包,其中有I,P,B幀; apid拿到音頻包,其中有I,P,B幀。音視頻同步就是通過I,P,B幀的PTS去同步pcrpid獲取的時間參考系。
2.9LCN 邏輯頻道號(DVB) 之 NIT表
LCN存在于NIT表中,描述符TAG=0x83,不過version2.0 好像TAG=0x87,并且語法結構也做了修改。 描述符基本結構如下: logical_channel_desciptor{ descriptor_tag?//8bit , 0x83 descriptor_length// =8bit for(i=0;i<N;i++) { service_id ?//16bit visible_service_flag//1bit reserved ?//5bit logical_channel_number//10bit } }
不同版本的LCN差異體現在logical_channel_number比特位的不同,NORDIG-Unified_ver_2.1版本中LCD V1的描述子結構為: logical_channel_desciptor{ descriptor_tag?//8bit , 0x83 descriptor_length// =8bit for(i=0;i<N;i++) { service_id ?//16bit visible_service_flag//1bit reserved ?//1bit logical_channel_number//14bit } } 當然,還有其他描述,此處不一一列舉。以上兩種TAG是一樣的,都是0x83 下面看一張,帶LCN的實例Svt_1.ts
這是一張NIT表,LCN就在transport_streams里,展開如下
找到transport_descriptors里的descriptor_tag==0x83 這個描述的就是LCN 把descriptor_data 數據放大:leng為32字節如下
03 f2 c0 0113 c4 c0 02 03 66 c0 6211 a8 40 00 11 9e 40 00 11 c6 40 00 14 32 c0 63 03 70 c0 61 根據描述符的基本結構如下:一個LCN應該占4字節32bit logical_channel_desciptor{ descriptor_tag?//8bit , 0x83 descriptor_length// =8bit for(i=0;i<N;i++) { service_id ?//16bit visible_service_flag//1bit reserved ?//5bit logical_channel_number//10bit } } 那么就根據結構來分析一下吧:這里的N==8 在分析之前,看看它的PAT表吧
根據pat可以看出總共6個節目
1. 03 f2 c0 01 service_id ?//16bit 是 03 f2 這個不正好是上面的program_number=0x03f2嗎 visible_service_flag//1bit 1 reserved ?//5bit logical_channel_number//10bit LCN = 0x001 2.13 c4 c0 02 service_id ?//16bit 是 13 c4 這個不正好是上面的program_number=0x13c4嗎 visible_service_flag//1bit 1 reserved ?//5bit logical_channel_number//10bit LCN = 0x002 3.03 66 c0 62 service_id ?//16bit 是 03 66 這個不正好是上面的program_number=0x0366嗎 visible_service_flag//1bit 1 reserved ?//5bit logical_channel_number//10bit LCN = 0x062 4. 11 a8 40 00 service_id ?//16bit 是 11 a8 這個好像沒有0x11a8這個臺,所以LCN也沒有,可能也正常吧 visible_service_flag//1bit 0 難道visible_service_flag 可以控制是否有臺? reserved ?//5bit logical_channel_number//10bit LCN = 0x0
5. 11 9e 40 00 service_id ?//16bit 是 11 9e 這個好像沒有0x11 9e這個臺,所以LCN也沒有,可能也正常吧 visible_service_flag//1bit 0 reserved ?//5bit logical_channel_number//10bit LCN = 0x0
6. 11 c6 40 00 service_id ?//16bit 是 11 c6 這個不正好是上面的program_number=0x11 c6嗎 visible_service_flag//1bit 0 但是這個臺RTK沒有搜到 reserved ?//5bit logical_channel_number//10bit LCN = 0x0 7. 14 32 c0 63 service_id ?//16bit 是 14 32 這個不正好是上面的program_number=0x14 32嗎 visible_service_flag//1bit 1 reserved ?//5bit logical_channel_number//10bit LCN = 0x63 8. 03 70 c0 61 service_id ?//16bit 是 03 70 這個不正好是上面的program_number=0x03 70嗎 visible_service_flag//1bit 1 reserved ?//5bit logical_channel_number//10bit LCN = 0x61
下面咱們再解釋為什么在NIT表中transport_streams有兩個transport_stream_id:0x03fd和0x03fe 那么就為難了,選哪一個呢,當然有辦法,不賣關子了,在pat表里:
來再看看pat表,看到了嗎?藍色的區域 明白了吧。
一. ATSC和DVB數字電視系統的比較 本文的主要目的是幫助DVB開發人員了解ATSC標準。本文并不涉及兩種標準在物理層面(如調制解調)的差別,而主要討論上層協議的區別,主要集中在如下四個方面:?
- ?音頻壓縮?
- ?服務信息系統?
- ?條件接收系統?
- ?數據廣播
1 .音頻壓縮 ATSC數字電視接收器必須具備Digital Audio Compression (AC-3)音頻壓縮算法的解碼能力,算法的具體細節可以參考文獻[2]。
AC-3算法與ISO/IEC 13818-3(參考文獻[3])相比,在多通道編碼方面的表現比較出色。AC-3一共包含有5.1個聲道:左前(L)、中央(C)、右前(R)、左環繞(Ls)、右環繞(Rs)和一個超重低音(LFE)。超重低音頻寬是其它幾個聲道的1/10,因此稱為5.1聲道。通道的結合方式有1/0、1+1/0、2+1/0、3+1/0、2/1、3/1、2/2、3/2這8種,其中斜杠前表示前聲道的個數,斜杠后表示后環繞聲的個數,在8種組合中都可選擇加設超低音通道
對比DVB DVB的音頻壓縮算法必須遵從ISO/IEC 13818-3[3]標準,因此ISO/IEC 13818-3模塊對DVB的接收系統來說是必不可少的;相比之下,ATSC采用的是AC-3標準,因此,ISO/IEC 13818-3對于ATSC接收器來說是可選模塊,而AC-3音頻解碼模塊是不可缺少的。 雖然在DVB和ATSC系統中都可以把AC-3的音頻流映射到MPEG的Multiplex上傳輸,但是在實現方式上還存在著一些差異。? 表1列出了AC-3音頻流在ATSC和DVB系統中的傳輸比較。其中registration descriptor僅僅存在于ATSC系統,因為在DVB系統中,AC-3 descriptor是公開的描述符,無需用registration descriptor來注冊。?
2? 服務信息表 電子節目指南(EPG)是數字電視中非常重要的部分,它相當于傳統報紙上的節目表。而電子節目指南則是基于TS流中的Service Information(SI)而構造的。 DVB和ATSC標準分別定義了各自不同的SI結構,采用不同的機制來產生EPG。本章后續部分將介紹ATSC的SI1系統,并將其與DVB進行對比。
● 層次結構
ATSC包含了層次化的表格來描述系統信息和節目指南數據(參考文獻[4])。其中,一個公用的基礎PID(Base?PID)是所有表格的入口,它被顯示定義為0x1FFB,根據Base?PID可以在地面廣播系統和有線電視系統中定位如下表格。
- ?System Time Table (STT)——包含同步所需的時間信息
- Master Guide Table (MGT)——包含其它相關表格的大小,PID以及版本號
- Rating Region Table (RRT)——包含不同地區和國家的節目等級信息?
- ?Virtual Channel Table (VCT)——包含節目導航和轉換的虛擬頻道表格
- The optional Directed Channel Change Table (DCCT)——在特定時間特定環境下要求接受者轉換到特定的虛擬頻道上去
- The optional Directed Channel Change Selection Code Table (DCCSCT)——基本種類列表和位置代碼表的擴展
事件信息表(Event Information Table,?EIT)也是SI系統的一部分,它們的PID定義在MGT之中。每一個EIT都按照VCT里面所定義的虛擬頻道列出電視節目(事件)清單,并按照時間先后從EIT-0到EIT-127排序。ATSC標準規定,每一個EIT必須有3個小時的時間長度,而且所有EIT的開始時間都被限制在0:00(午夜),3:00,&nbs p; 6:00, 9:00,12:00(中午),15:00,18:00和21:00(所有的時間都是UTC制)。這樣,EIT-0代表的就是當前3個小時內的所有電視節目,EIT-1代表的是接下來3個小時的信息,而每隔三個小時,原先的EIT-0就被廢棄,之前的EIT-1將取代EIT-0的位置,依此類推。另外,ATSC還定義了可選的擴展文字表(Extended Text Table,ETT),ETT包含了有關EIT的相對比較長的文字描述,它們的PID也同樣包含在MGT中。
圖1描述了上述表格的層次結構。在一個數字電視TS流中,SI表格必須包含對當前TS流中所有的數字電視頻道的描述,同時為了方便起見,還可能包括了相關的模擬頻道信息以及其它TS流中的數字頻道信息。對于地面廣播系統,STT, TVCT(VCT的地面版本),MGT和前4個EIT都是強制要求的;對于有線電視系統,STT,CVCT(VCT的有線版本)或者TVCT,以及MGT都是必需的。
● 與DVB-SI的比較 圖 2說明了DVB SI表格的層次結構。總的來說,DVB-SI和ATSC-SI的目的都是為了構造EPG,他們在功能上是相似的。例如:ATSC的STT就時間同步功能來說等價于DVB中的TDT,ATSC的VCT就虛擬頻道(服務)描述來說和DVB中的SDT等價,ATSC和DVB中的EIT同樣提供TV節目清單。? (可見EIT里放的就是EPG了。。)
即便如此,ATSC-SI和DVB-SI仍然存在如下一些差異: 1. 節目標識:在DVB系統中,節目總是以original network id/ transport stream id/ service id的方式標識的。其中original network id是由授權中心頒發給經認證的運營商或者廣播商的。采用這種聯合方式來標識能夠方便收費和訂閱信息的管理。而在ATSC系統中,不存在original network id的標識,用戶能看到的是一個類似于2-1主次號結合的標識符,這里主號2是廣播商的NTSC牌照,該廣播商的所有服務都采用該主號來標識;次號1是用來在該主號群組中標識特定的服務,次號0預留給該廣播商的模擬頻道服務,1-999可以用來標識數字電視服務(圖3顯示的是采用主次頻道結合標識的一個例子)。這種機制使得transport stream id和service id對電視終端用戶不可見。?
2. 事件信息表(EIT):ATSC和DVB都有各自的EIT,雖然名字相同,但它們的結構有很大的差別。另外,ATSC中的每個EIT都只有3個小時的有效期,每隔3個小時,EIT-0會被廢棄,后繼的EIT會取代前繼EIT的位置(可以采用修改MGT中PID來實現)。另外,ATSC對EIT的開始時間也有限制。如果一個節目時間跨越了好幾個EIT,那么它必須同時出現在這些EIT之中,而且事件ID必須相同。而在DVB標準中,就不存在上述限制。
3. 定向頻道轉換(DCC):DCC是ATSC標準中的新特性,它在Base?PID(0x1FFB)的數據包中定義了2個表:定向頻道轉換表(DCCT)和定向頻道轉換選擇碼表(DCCSCT)。定向頻道轉換是提供給廣播公司的可選功能,它能把用戶導航到相關可選的廣播節目內容,這種定向轉換可以是自動的,也可以是交互式的。而類似的機制并沒有出現在DVB系統中。
4. 冗余表:DVB的TS流除了包含當前TS流中SI表之外,還可能包含了其它TS流的SI表,以方便頻道搜索。雖然ATSC也允許VCT中包含其它TS流的信息,但一般來說,出于加速訪問事件的目的,ATSC的SI表只包含了當前TS流的節目指南信息。
5. 跳過對PAT/PMT的解析:ATSC中TVCT包含了service location descriptor,這個描述符包含了PMT里面的所有信息,包括stream type和PID。也就是說,ATSC的解碼器可以跳過PAT和PMT的解析,直接從TVCT的信息跳轉到目標邏輯頻道。
6. 相關束表(BAT) :DVB中的BAT提供了相關服務的群組列表,方便用戶定購和瀏覽。而ATSC中并沒有類似的機制。
● EPG的構造過程 形成電子節目指南(EPG)是SI系統最終目的。參照圖 1可以得到如下的EPG構造過程: 1. 調頻到某個特定的RF頻道。 2. 過濾Base?PID,從Base?PID的TS數據包中構造MGT,TVCT 和 STT等。 3. 解析MGT,獲取EIT以及相關ETT的PID。 4. 把每個虛擬頻道和它相關的TV節目列表聯系起來。 5. 調頻到另一個RF頻道,跳轉到第2步。如果沒有其它的頻道,則跳轉到第6步。 6. 把所有的節目列表以及相關信息顯示給用戶,捕捉用戶的輸入指令,并根據指令查找對應的service location descriptor,解碼顯示用戶所選擇的電視節目。
與DVB EPG構造過程的比較: 1. DVB和ATSC結構上的不同,導致了EPG的構造過程的不同。 2. 調頻到某個RF頻道,基于這個頻道解析NIT表,獲取當前網絡的所有TS流信息。 3. 基于當前頻道來解析當前SDT和其它TS流的SDT表,或者掃描當前網絡中所有的頻道,一一獲取SDT信息。 4. 基于當前頻道獲取當前的EIT和其它TS流的EIT,或者掃描當前網絡中所有的頻道,一一獲取EIT信息。 5. 顯示用戶節目列表。當用戶轉換到某個節目,transport id以及相應的各個PID將從PAT和PMT中解析出來,以便解碼。
和DVB相比,ATSC-SI的結構試圖在不增加網絡帶寬的前提下,加速事件的處理。為了達到這個目的,ATSC采用了固定的PID,單獨的MGT來縮短PID解析的時間。但ATSC采用的機制是否真正比DVB有效,還有待檢驗。
3? 條件接收系統
- ?PES級別加擾?
- ?加擾算法
- 事件加擾控制?
- ?可置換安全接口
- ?數據下載協議?
- ?數據預告
- 數據發現
- IP協議封裝
- 對DSM-CC標準的背離?
完。
二、TS流概述 1.、TS流概述 ES流(Elementary Stream,基本流):數字電視各組成部分編碼后所形成的直接表示基本元素內容的流,包含視頻、音頻或數據的連續碼流。 PES流(Paketized Elementary Stream,打包基本碼流):是將基本的碼流ES流根據需要分成長度不等的數據包,并加上包頭就形成了打包的基本碼流PES流。 PS (Program Stream,節目流):將一個節目的多個組成部分按照它們之間的互相關系進行組織并加入各組成部分關系描述后的碼流。PS流是一種多路復用數字音頻、視頻等的封裝容器,它一個或多個具有共同的時間基準的PES流合并成一個整體流,主要用于節目存儲。其包長不固定,且較長,一旦失去同步信息,接收機無法確定下一包的同步位置,會造成失步,導致嚴重的信息丟失。PS流適用于誤碼小、信道較好的環境,如演播室、家庭環境和存儲介質中。 TS流(Transport Stream,傳輸流):是將一個節目的多個組成部分按照它們之間的互相關系進行組織并加入各組成部分關系描述和節目組成信息,并進一步封裝成傳輸包后的碼流。TS流是將視頻、音頻、PSI等數據打包成傳輸包進行傳送。主要用于節目傳輸。TS的傳輸包長度固定,一般為188字節。 TS流和PS流是MPEG-2標準中規定的兩種輸出碼流。TS格式中,從視頻流的任意一片斷開始都可以獨立解碼,而PS格式不可以。由于TS流具備較強的抵抗傳輸誤碼的能力,因此目前在傳輸媒體中進行傳輸的MPEG-2碼流基本上都采用了TS流的包格式。 TS流的播放:播放前將TS流文件的后綴名該為.mpg或者.mpeg,用可以直接播放MPEG-TS流的播放器(一般的播放器都可以)打開播放即可。
TS流的優點: 1、動態帶寬分配:由于TS的傳輸包長度是固定的,因此可過PID可以將規定的信道總頻帶在視頻、音頻和數據信息見進行實時的、靈活的分配。利用這一特性,可在廣播付費節目前實時地將解密鑰匙插入到TS流中送給廣大用戶。 2、可分級性:允許一個復用的傳輸碼流與其他視音頻基本碼流進行二次復用,生產占用頻帶給寬的更高一級的TS流。 3、可擴展性 4、抗干擾性 5、接收機成本低廉
TS流的形成過程: 1、 壓縮【顯示單元】產生【進入單元】,連續的【進入單元】組成一個基本碼流。ES 2、 對ES(基本碼流)進行打包形成PES。 就是帶包頭信息的ES 3、 在PES包中加入定時信息(PTS/DTS)。 4、 將PES包內容分配到一系列固定長度的傳輸包中。 5、 在傳輸包中加入定時信息(PCR)。 6、 在傳輸包中加入節目專用信息(PSI) 。 7、 連續輸出傳輸包形成具有恒定比特率的MPEG-TS流。
2、TS流傳輸包(簡稱TS包)結構分析 MPEG-2中規定TS傳輸包的長度為188 字節。但通信媒介會為包添加錯誤校驗字節,從而有了不同于188字節的包長。例如: DVB 規定中,使用204字節作為包長: 1、通過調制器時,在每個傳輸包后增加了16 字節的里德所羅門前向糾錯碼,因而形成了204字節的數據包。 調制 后總存在204 字節的數據包。 2、調制之前存復用器插入RS碼或虛構 的RS碼。 ATSC規定中,使用208字節作為包長:添加20 字節的 RS(Reed-Solomon)前向糾錯碼。與DVB不同,ATSC規定RS碼只能出現在調制的TS流中。 所有的TS包都分為包頭和凈荷部分。TS包中可以填入很多東西(填入的東西都是填入到凈荷部分),有:視頻、音頻、數據(包括PSI、SI以及其它任何形式的數據)。 2.1、TS包包頭 TS包的包頭提供關于傳輸方面的信息:同步、有無差錯、有無加擾、PCR(節目參考時鐘)等標志。TS包的包頭長度不固定,前32比特(4個字節)固定,后面可能跟有自適應字段(適配域)。32個比特(4個字節)是最小包頭。包頭的結構固定如下: 因此有的包頭可能不止32bit,那么又是如何區分的呢?原來是這個適配區搗的鬼!!
| 同步字節 | 傳輸錯誤指示 | 開始指示 | 傳輸優先級 | PID | 加擾控制 | 適配域控制 | 連續性計數器 | 適配域 |
| 8bit | 1 | 1 | 1 | 13 | 2 | 2 | 4 | ? |
sync_byte (同步字節):固定為0100 0111 (0x47);該字節由解碼器識別,使包頭和有效負載可相互分離。 transport_error_indicator(傳輸錯誤指示): ‘1’表示在相關的傳輸包中至少有一個不可糾正的錯誤位。當被置1后,在錯誤被糾正之前不能重置為0。 payload_unit_start_indicator(開始指示):為1時,在前4個字節之后會有一個調整字節,其的數值為后面調整字段的長度length。因此有效載荷開始的位置應再偏移1+[length]個字節。原來有效負載是這樣來的 transport_priority(傳輸優先級):‘1’表明優先級比其他具有相同PID 但此位沒有被置‘1’的分組高。 PID:指示存儲與分組有效負載中數據的類型。PID 值 0x0000—0x000F 保留。其中0x0000為PAT保留;0x0001為CAT保留;0x1fff為分組保留,即空包。 transport_scrambling_control(加擾控制):表示TS流分組有效負載的加密模式。空包為‘00’,如果傳輸包包頭中包括調整字段,不應被加密。 adaptation_field_control(適配域控制):表示包頭是否有調整字段或有效負載。‘00’為ISO/IEC未來使用保留;‘01’僅含有效載荷,無調整字段;‘10’ 無有效載荷,僅含調整字段;‘11’ 調整字段后為有效載荷,調整字段中的前一個字節表示調整字段的長度length,有效載荷開始的位置應再偏移[length]個字節。空包應為‘10’。 continuity_counter(連續性計數器):隨著每一個具有相同PID的TS流分組而增加,當它達到最大值后又回復到0。范圍為0~15。 適配域:
2.2、TS包凈荷部分 TS包中凈荷所傳輸的信息包括兩種類型: 1、視頻、音頻的PES包以及輔助數據; 2、節目專用信息PSI。
當然,TS包也可以是空包。空包用來填充TS流,可能在重新進行多路復用時被插入或刪除。 在系統復用時,視頻、音頻的ES流需進行打包形成視頻、音頻的 PES流,輔助數據(如圖文電視信息)不需要打成PES包。PES包非定長,音頻的PES包小于等于64K,視頻的一般為一幀一個PES包。一幀圖象的PES包通常要由許多個TS包來傳輸。MPEG-2中規定,一個PES包必須由整數個TS包來傳輸。如果承載一個PES包的最后一個TS包沒能裝滿,則用填充字節來填滿;當下一個新的PES包形成時,需用新的TS包來開始傳輸。
節目專用信息PSI(Program Specific Information) 用來管理各種類型的TS數據包,需要有些特殊的TS包來確立各個TS數據包之間的關系。這些特殊的TS包里所包含的信息就是節目專用信息。在不同的標準中它有不同的名字: ? MPEG-2中稱為PSI; ? DVB標準根據實際需要,對PSI擴展,稱為SI信息; ? ATSC標準中為PSIP信息
MPEG-2中,規定的對PSI信息的描述方法有以下幾種: ? 1、表Table: 節目信息的結構性的描述; –節目關聯表Program Association Table (PAT) 0x0000 –節目映射表Program Map Tables (PMT) –條件接收表Conditional Access Table (CAT) 0x0001 –網絡信息表Network Information Table(NIT) 0x0010 –傳送流描述表Transport Stream Description Table (TSDT)
?2、節Section: 將表格的內容映射到TS流中; 專用段 Private_ section ? 3、描述符Descriptor:提供有關節目構成(視頻流、音頻流、語言、層次、系統時鐘和碼率等多方面)的信息; ITU-T Rec.H.222.0|ISO /IEC 13818-1 中定義的 PSI表可被分成一段或多段置于傳輸流分組中。一段就是一個語法結構,用來將 ITU-T Rec.H.222.0|ISO /IEC 13818-1 中定義的 PSI表映射到傳輸流分組中。
PAT: TS流中包含一個或者多個PAT表。PAT表由PID為0x0000的TS包傳送,其作用是為復用的每一路傳送流提供出所包含的節目和節目編號,以及對應節目的PMT的位置即PMT的TS包的PID值,同時還提供NIT的位置,即NIT的TS包的PID的值。
| Table ID | Section syntax indicator | 0 | ? | Section length | Transport stream ID | ? | Version number | Current next indicator | Section Number | Last section number | N loop |
| 8bit | 1 | 1 | 2 | 12 | 16 | 2 | 5 | 1 | 8 | 8 | ? |
| Program number0 | ? | Network PID | …… | Program number1 | ? | Program map PID-1 | …… | CRC 32 |
| 16bit | 3 | 13 | ? | 16 | 3 | 13 | ? | 32 |
table_id:固定為0x00,標志該表是PAT表。 section_syntax_indicator:段語法標志位,固定為1。 section_length:表示這個字節后面有用的字節數,包括CRC32。節目套數:(section length-9)/4 transport_stream_id:16位字段,表示該TS流的ID,區別于同一個網絡中其它多路復用流。 version_number:表示PAT的版本號。 current_next_indicator:表示發送的PAT表是當前有效還是下一個PAT有效。 section_number:表示分段的號碼。PAT可能分為多段傳輸,第一段為0,以后每個分段加1,最多可能有256個分段。 last_section_number:表示PAT最后一個分段的號碼。 Program number:節目號 network_PID:網絡信息表(NIT)的PID,節目號為0時對應ID為network_PID。 Program map PID:節目映射表(PMT)的PID號,節目號為大于等于1時,對應的ID為program_map_PID。一個PAT中可以有多個program_map_PID。 CRC_32:32位字段,CRC32校驗碼Cyclic RedundancyCheck。
PMT: PMT在傳送流中用于指示組成某一套節目的視頻、音頻和數據在傳送流中的位置,即對應的TS包的PID值,以及每路節目的節目時鐘參考(PCR)字段的位置。
| Table id | Section syntax indicator | 0 | ? | Section length | Transport stream id | ? | Version number | Current next indicator | Section number | Last section number | ? | PCR PID | ? | Program info length | N loop descriptors | N loop | CRC 32 |
| 8 | 1 | 1 | 2 | 12 | 16 | 2 | 5 | 1 | 8 | 8 | 3 | 13 | 4 | ? | ? | ? | ? |
N loop中為:
| Stream type | ? | Elementary PID | ? | ES info length | N loop descriptors |
| 8 | 3 | 13 | 4 | 12 | ? |
Table id :固定為0x02,標志該表是PMT表。 Section syntax indicator:對于PMT表,設置為1。 Section length:表示這個字節后面有用的字節數,包括CRC32。 Program number:它指出該節目對應于可應用的Program map PID。 Version number:指出PMT的版本號。 Current next indicator:當該位置’1’時,當前傳送的Program map section可用;當該位置’0’時,指示當前傳送的Program map section不可用,下一個TS流的Programmap section有效。 Section number:總是置為0x00(因為PMT表里表示一個service的信息,一個section的長度足夠)。 Last section number:該域的值總是0x00。 PCR PID:節目中包含有效PCR字段的傳送流中PID。 Program info length:12bit域,前兩位為00。該域指出跟隨其后對節目信息的描述的byte數。 Stream type:8bit域,指示特定PID的節目元素包的類型。該處PID由elementary PID指定。下表所示為對應原始流的類型。
原始流的類型
| 值 | 描述 |
| 0x00 | ITU-T|ISO/IEC保留 |
| 0x01 | ISO/IEC 11172視頻 |
| 0x02 | ITU-T Rec.H.262|ISO/IEC 13818-2視頻 |
| 0x03 | ISO/IEC 11172音頻 |
| 0x04 | ISO/IEC 13818-3音頻 |
| 0x05 | ITU-T Rec.H.222.0|ISO/IEC 13818-1私用分段 |
| 0x06 | 含有私用數據的ITU-T Rec.H.222.0|ISO/IEC 13818-1分組 |
| 0x07 | ISO/IEC 13522 MHEG |
| 0x08 | ITU-T Rec.H.222.0|ISO/IEC 13818-1 DSM CC |
| 0x09 | ITU-T Rec.H.222.0|ISO/IEC 13818-1/11172-1 |
| 0x10 ~ 0x7F | ITU-T Rec.H.222.0|ISO/IEC 13818-1保留 |
| 0x80 ~ 0xFF | 用戶私用 |
2.3 PMT結構定義: // 這個又是代表什么呢? typedef struct TS_PMT_Stream { unsigned stream_type?: 8; //指示特定PID的節目元素包的類型。該處PID由elementary PID指定 unsigned elementary_PID?: 13; //該域指示TS包的PID值。這些TS包含有相關的節目元 素 unsigned ES_info_length? : 12; //前兩位bit為00。該域指示跟隨其后的描述相關節目元素的byte數 unsigned descriptor; }TS_PMT_Stream; 注釋: 這個結構體并沒有顯示缺省的bit,注意下面的兩個缺省值 stream_type???????:0x1b??????????????????? //??8 reserved????????????0x07??????????????????//??3 elementary_PID????????:0x03 e9????//??13//該節目中包括的視頻流,音頻流等對應的TS分組的PID reserved????????????????????:0x0f??????????//??4 ES_info_length?????????:0x000???????????????//??12
//PMT 表結構體 ,這個就是所謂的PMT表了 typedef struct TS_PMT { unsigned table_id??????????????????????? : 8; //固定為0x02, 表示PMT表 unsigned section_syntax_indicator??????? : 1; //固定為0x01 (段語法標志位) unsigned zero??????????????????????????? : 1; //0x01 unsigned reserved_1????????????????????? : 2; //0x03 unsigned section_length?: 12;//首先兩位bit置為00,它指示段的byte數,由段長度域開始,包含 CRC。 unsigned program_number??????: 16;// 指出該節目對應于可應用的Program map PID它指出該節目 對應于可應用的Program map PID,就是節目號吧 unsigned reserved_2??????????????????????? : 2; //0x03 unsigned version_number??????????????????? : 5; //指出TS流中Program map section的版本號 unsigned current_next_indicator??????????? : 1; //當該位置1時,當前傳送的Program map section可 用;當該位置0時,指示當前傳送的Program map section不可用, 下一個TS流的Program map section有效。 unsigned section_number??????????????????? : 8; //固定為0x00 因為這個表一個section就夠了,所以為0 unsigned last_section_number??????????? : 8; //固定為0x00 因為這個表一個section就夠了,所以為0 unsigned reserved_3??????????????????????? : 3; //0x07 unsigned PCR_PID??????????????????????? : 13; //指明TS包的PID值,該TS包含有PCR域, //該PCR值對應于由節目號指定的對應節目。 //如果對于私有數據流的節目定義與PCR無關,這個域的值將為0x1FFF。 unsigned reserved_4??????????????????????? : 4; //預留為0x0F unsigned program_info_length??????????? : 12; //前兩位bit為00。該域指出跟隨其后對節目信息的描述的byte數。 std::vector<TS_PMT_Stream> PMT_Stream;??//每個元素包含8位, 指示特定PID的節目元素包的類 型。該處PID由elementary PID指定 unsigned reserved_5??????????????????????? : 3; //0x07 unsigned reserved_6??????????????????????? : 4; //0x0F unsigned CRC_32??????????????????????????? : 32;? } TS_PMT; 解析代碼為: HRESULT CTS_Stream_Parse::adjust_PMT_table ( TS_PMT * packet, unsigned char * buffer ) {? packet->table_id??????????????????????????? = buffer[0]; packet->section_syntax_indicator??????????? = buffer[1] >> 7; packet->zero??????????????????????????????? = buffer[1] >> 6 & 0x01;? packet->reserved_1??????????????????????????? = buffer[1] >> 4 & 0x03; packet->section_length??????????????????????? = (buffer[1] & 0x0F) << 8 | buffer[2];???? packet->program_number??????????????????????? = 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]; packet->reserved_3??????????????????????????? = buffer[8] >> 5; packet->PCR_PID??????????????????????????????? = ((buffer[8] << 8) | buffer[9]) & 0x1FFF; PCRID = packet->PCR_PID; packet->reserved_4??????????????????????????? = buffer[10] >> 4; packet->program_info_length??????????????????? = (buffer[10] & 0x0F) << 8 | buffer[11];? // Get CRC_32 int len = 0; len = packet->section_length + 3;???? packet->CRC_32??????????????? = (buffer[len-4] & 0x000000FF) << 24 | (buffer[len-3] & 0x000000FF) << 16 | (buffer[len-2] & 0x000000FF) << 8 | (buffer[len-1] & 0x000000FF); int pos = 12; // program info descriptor if ( packet->program_info_length != 0 ) pos += packet->program_info_length;???? // Get stream type and PID???? for ( ; pos <= (packet->section_length + 2 ) -? 4; ) { TS_PMT_Stream pmt_stream; pmt_stream.stream_type =??buffer[pos]; packet->reserved_5? =???buffer[pos+1] >> 5; pmt_stream.elementary_PID =??((buffer[pos+1] << 8) | buffer[pos+2]) & 0x1FFF; packet->reserved_6???? =?? buffer[pos+3] >> 4; pmt_stream.ES_info_length =?? (buffer[pos+3] & 0x0F) << 8 | buffer[pos+4]; pmt_stream.descriptor = 0x00; if (pmt_stream.ES_info_length != 0) { pmt_stream.descriptor = buffer[pos + 5]; for( int len = 2; len <= pmt_stream.ES_info_length; len ++ ) { pmt_stream.descriptor = pmt_stream.descriptor<< 8 | buffer[pos + 4 + len]; } pos += pmt_stream.ES_info_length; } pos += 5; packet->PMT_Stream.push_back( pmt_stream ); TS_Stream_type.push_back( pmt_stream ); } return 0; } 舉例如下: 長度0x12==18字節,紅色區域 0x47 0x43 0xe8 0x12?0x00?0x02 0xb0 0x120x00 0x01 0xc1 0x00 0x00 0xe3 0xe9 0xf0 0x00? 0x1b 0xe3 0xe9 0xf0 0x00 0xf0 0xaf 0xb4 0x4f 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
TS頭部 sync_byte???:0x47 transport_error_indicator: 0x00 payload_unit_start_indicator: 0x01 transport_priority??: 0x00 PID?????????????????????:0x03e8 transport_scrambling_control??:0x00 adaptation_field_control??:0x01????????????????????????????????????? continuity_counter???:0x02 PMT數據????????? table_id?????:0x02????????????????????????? // 8 section_syntax_indicator??:0x01????????????//??1 '0'????????????????:0x00?????????????????? //??1 reserved???????:0x03???????????????????????//??2 section_length?:??????0x012?????????????????//??12 program_number????:0x00 01????????????????????//??16 reserved???????????????:0x03???????????????//??2 version_number????:0x00????????????????????//??5 current_next_indicator???0x01?????????????//??1 section_number??????:0x00??????????????????//??8 last_section_number????:0x00?????????????? //??8? reserved???????????????????0x07???????????//??3 PCR_PID???????????:0x03 e9???//?PCR(節目參考時鐘)所在TS分組的PID????????? //??13 reserved???????:0x0f???????????????? //4 program_info_length?????:0x000????????????? //??12 stream_type???????:0x1b??????????????????? //??8 reserved????????????0x07??????????????????//??3 elementary_PID????????:0x03 e9????//??13//該節目中包括的視頻流,音頻流等對應的TS分組的PID reserved????????????????????:0x0f??????????//??4 ES_info_length?????????:0x000???????????????//??12 CRC??????? : 0xf0 af b4 4f
2.4 對TS包頭的解析
表標識符值(table_id)的分配 值 描述 0x00 節目關聯段(PAT) 0x01 條件接收段(CAT) 0x02 節目映射段(PMT) 0x03 傳輸流描述段 0x04 至 0x3F 預留 0x40 現行網絡信息段(NIT actual) 0x41 其它網絡信息段(NIT other) 0x42 現行傳輸流業務描述段(SDT actual) 0x43 至 0x45 預留使用 0x46 現行傳輸流業務描述段(SDT other) 0x47 至 0x49 預留使用 0x4A 業務群關聯段(BAT) 0x4B 至 0x4D 預留使用 0x4E 現行傳輸流事件信息段,當前/后續(EIT PF actual) 0x4F 其它傳輸流事件信息段,當前/后續(EIT PF other) 0x50 至 0x5F 現行傳輸流事件信息段,時間表(EIT Schedule actual) 0x60 至 0x6F 其它傳輸流事件信息段,時間表(EIT Schedule other) 0x70 時間-日期段(TDT) 0x71 運行狀態段(RST) 0x72 填充段(ST) 0x73 時間偏移段(TOT) 0x74 至 0x7D 預留使用 0x7E 不連續信息段 0x7F 選擇信息段 0x80 至 0xFE 用戶定義 0xFF 預留
業務信息的PID分配 表 ? ? ? ? ? ? ? ?PID 值 PAT ? ? ? ? ? ? ? 0x0000 CAT ? ? ? ? ? ? ? 0x0001 TSDT ? ? ? ? ? ? ?0x0002 預留 ? ? ? ? ? ? ? 0x0003 至0x000F NIT, ST ? ? ? ? ? 0x0010 SDT , BAT, ST ? ? 0x0011 EIT, ST ? ? ? ? ? 0x0012 RST, ST ? ? ? ? ? 0x0013 TDT, TOT, ST ? ? ?0x0014 網絡同步 ? ? ? ? ? 0x0015 預留使用 ? ? ? ? ? 0x0016 至 0x001B 帶內信令 ? ? ? ? ? 0x001C 測量 ? ? ? ? ? ? ? 0x001D DIT ? ? ? ? ? ? ? 0x001E SIT ? ? ? ? ? ? ? 0x001F
由pid和tid就可以確定并找到那些表了,如果TDT和TOT在同一個PID里,那么就要根據tid進行區分了
根據前一篇中各數據的定義及數據結構,對數據進行分別解析如下: TS包頭定義: typedef struct TS_packet_header { unsigned sync_byte??????????????????????? : 8; //同步字節, 固定為0x47,表示后面的是一個TS分組 unsigned transport_error_indicator??????? : 1; //傳輸誤碼指示符 unsigned payload_unit_start_indicator??? : 1; //有效荷載單元起始指示符 unsigned transport_priority????????????? : 1; //傳輸優先, 1表示高優先級,傳輸機制可能用到,解碼用不著 unsigned PID??????????????????????????? : 13; //PID unsigned transport_scrambling_control??? : 2; //傳輸加擾控制? unsigned adaption_field_control??????????? : 2; //自適應控制 01僅含有效負載,10僅含調整字段,11含 有調整字段和有效負載。為00解碼器不進行處理 unsigned continuity_counter??????????????? : 4; //連續計數器 一個4bit的計數器,范圍0-15 } TS_packet_header;
TS包頭解析代碼: HRESULT CTS_Stream_Parse::adjust_TS_packet_header( TS_packet_header* TS_header ) { unsigned char buf[4];? memcpy(buf, TS_header, 4); TS_header->transport_error_indicator??????? = buf[1] >> 7; TS_header->payload_unit_start_indicator??? = buf[1] >> 6 & 0x01; TS_header->transport_priority??????????????? = buf[1] >> 5 & 0x01; TS_header->PID??????????????????????????? = (buf[1] & 0x1F) << 8 | buf[2]; TS_header->transport_scrambling_control??? = buf[3] >> 6; TS_header->adaption_field_control??????????? = buf[3] >> 4 & 0x03; TS_header->continuity_counter??????????????? = buf[3] & 0x0F; // 四位數據,應為0x0F xyy 09.03.18 return 0; }
如下為一個TS包數據: 0x47 0x40 0x00 0x12?0x00?0x00 0xb0 0x0d 0x00 0x00 0xc1 0x00 0x00 0x00 0x01 0xe3 0xe8 0xf0 0x0b 0xd7 0x79 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
分析知道前四位0x47 0x40 0x00 0x12TS頭部即為TS包頭數據,解析如下: sync_byte???:0x47 transport_error_indicator: 0x00 payload_unit_start_indicator: 0x01 transport_priority??: 0x00 PID?????????????????????:0x0000 說明是PAT表 transport_scrambling_control??:0x00 adaptation_field_control??:0x01????????????????????????????????????? continuity_counter???:0x02 PID = 0x0000,表示此TS包的內容為PSI信息表格的PAT表格數據,在4字節的TS包頭之后的第一個字節的Point_field = 0x00, 表示偏移量為0,即緊隨其后的即為PAT的數據信息 嘗試著解析一下這個PAT table_id:固定為0x00,標志該表是PAT表。 //8bit section_syntax_indicator:段語法標志位,固定為1。//1 '0'????????????????:0x0?????????????????? //??1 reserved???????:0x3 //2 section_length:表示這個字節后面有用的字節數,包括CRC32。節目套數:(section length-9)/4 0xd 說明后面有13字節 //12 transport_stream_id:16位字段,表示該TS流的ID,區別于同一個網絡中其它多路復用流。 0x0 //16 reserved???????:0x3 //2 version_number:表示PAT的版本號。0x0 //5 current_next_indicator:表示發送的PAT表是當前有效還是下一個PAT有效。0x1 //1 section_number:表示分段的號碼。PAT可能分為多段傳輸,第一段為0,以后每個分段加1,最多可能有256個分段。 0x0 //8 last_section_number:表示PAT最后一個分段的號碼。 0x0 //8 Program number:節目號 0x01 //16 reserved???????:0x7 //3 network_PID:網絡信息表(NIT)的PID,節目號為0時對應ID為network_PID。 0x3e8 //13 Program map PID:節目映射表(PMT)的PID號,節目號為大于等于1時,對應的ID為 program_map_PID。一個PAT中可以有多個program_map_PID。 由于節目號是0x1 因此這里應該是PMT表,而不是NIT表的PID,所以PMT表的PID===0x3e8 注意如果節目號是0x0那么就不需要給PID了,因為NIT表的PID=0x10,所以緊隨其后的一定是 下一個節目號。 CRC_32:32位字段,CRC32校驗碼Cyclic RedundancyCheck。 0xf00bd779//32
2.5TS 流解碼過程: TS 流解碼過程: 1. 獲取TS中的PAT 2. 獲取TS中的PMT 3. 根據PMT可以知道當前網絡中傳輸的視頻(音頻)類型(H264),相應的PID,PCR的PID等信息。 4. 設置demux 模塊的視頻Filter 為相應視頻的PID和stream type等。 5. 從視頻Demux Filter 后得到的TS數據包中的payload 數據就是 one piece of PES,在TS header中有一些關于此 payload屬于哪個 PES的 第多少個數據包。 因此軟件中應該將此payload中的數據copy到PES的buffer中,用于拼接一個PES包。 6. 拼接好的PES包的包頭會有 PTS,DTS信息,去掉PES的header就是 ES。 7. 直接將 被拔掉 PES包頭的ES包送給decoder就可以進行解碼。解碼出來的數據就是一幀一幀的視頻數據,這些數據至少應當與PES中的PTS關聯一下,以便進行視音頻同步。 8. I,B,B,P 信息是在ES中的。
ES是直接從編碼器出來的數據流,可以是編碼過的視頻數據流,音頻數據流,或其他編碼數據流的統稱。ES流經過PES打包器之后,被轉換成PES包。PES包由包頭和payload組成.
在PES層,主要是在PES包頭信息中加入PTS(顯示時間標簽)和DTS(解碼時間標簽)用于視頻、音頻同步。其實,Mpeg-2用于視音頻同步以及系統時鐘恢復的時間標簽分別在ES,PES和TS這3個層次中。在ES層,與同步有關的主要是視頻緩沖驗證VBV(Video Buffer Verifier),用以防止解碼器的緩沖器出現上溢或下溢;在PES層,主要是在PES頭信息里出現的顯示時間標簽PTS(Presentation Time Stamp)和解碼時間標簽DTS(Decoding Time Stamp);在TS層中,TS頭信息包含了節目時鐘參考PCR(Program Clock Reference),用于恢復出與編碼端一致的系統時序時鐘STC(System Time Clock)。
基本流程如下: 首先MPEG-2壓縮編碼得到的ES基本流,這個數據流很大,并且只是I,P,B的這些視頻幀或音頻取樣信息,然后加入一些同步信息,打包成長度可變長度的數據包PES,原來是流的格式,現在成了數據包的分割形式。同時要注意的是,ES是只包含一種內容的數據流,如只含視頻,或只含音頻等,打包之后的PES也是只含一種性質的ES,如只含視頻ES的PES,只含音頻ES的PES等。可以知道,ES是編碼視頻數據流或音頻數據流,每個ES都由若干個存取單元(AU)組成,每個視頻AU或音頻AU都是由頭部和編碼數據兩部分組成,1個AU相當于編碼的1幅視頻圖像或1個音頻幀,也可以說,每個AU實際上是編碼數據流的顯示單元,即相當于解碼的1幅視頻圖像或1個音頻幀的取樣。PEG-2對視頻的壓縮產生I幀、P幀、B幀。把幀順序I1,P4,B2,B3,P7,B5,B6幀的編碼ES,通過打包并在每個幀中插入?PTS/DTS標志,變成PES。在插入PTS/DTS標志時,由于在B幀PTS和DTS相等,所以無須在B幀多插入DTS。而對于I幀?和P幀,由于經過復用后數據包的順序會發生變化,顯示前一定要存儲于視頻解碼器的從新排序緩存器中,經過從新排序后再顯示,所以一定要同時插入PTS和?DTS作為從新排序的依據。
其中,有否PTS/DTS標志,是解決視音頻同步顯示、防止解碼器輸入緩存器上溢或下溢的關鍵所在。PTS表明顯示單元出現在系統目標解碼器(STD- System?Target?Decoder)的時間,?DTS表明將存取單元全部字節從STD的ES解碼緩存器移走的時刻。視頻編碼圖像幀次序為?I1,P4,B2,B3,P7,B5,B6,I10,B8,B9的ES,加入PTS/DTS后,打包成一個個視頻PES包。每個PES包都有一個包頭,用于定義PES內的數據內容,提供定時資料。每個I、P、B幀的包頭都有一個PTS和DTS,但PTS與DTS對B幀都是一樣的,無須標出B幀的DTS。對I幀和P幀,顯示前一定要存儲于視頻解碼器的重新排序緩存器中,經過延遲(重新排序)后再顯示,一定要分別標明PTS和DTS。例如,解碼器輸入的圖像幀次序為I1,P4,B2,B3,P7,B5,B6,I10,B8,B9,依解碼器輸出的幀次序,應該P4比B2、B3在先,但顯示時P4一定要比B2、B3在后,即P4要在提前插入數據流中的時間標志指引下,經過緩存器重新排序,以重建編碼前視頻幀次序I1,B2,B3,P4,B5,B6,P7,B8,B9,I10。顯然,PTS/DTS標志表明對確定事件或確定信息解碼的專用時標的存在,依靠專用時標解碼器,可知道該確定事件或確定信息開始解碼或顯示的時刻。例如,PTS/DTS標志可用于確定編碼、多路復用、解碼、重建的時間。 PCR?? PCR是TS里面的,即TS packet的header里面可能會有,他用來指定所期望的該ts packet到達decoder的時間,他的作用于SCR類似
DTS, PTS 對于一個ES來說,比如視頻,他有許多I,P,B幀,而P, B幀都是以I,P幀作為參考。由于B幀是前向后向參考,因此要對B幀作decode的話,就必須先decode該B幀后面的幀(P,或者I幀),于是,decode的時間與幀的真正的present的時間就不一致了,按照DTS一次對各個幀進行decode,然后再按照PTS對各個幀進行展現。 有時候PES包頭里面也會有DTS,PTS,對于PTS來說,他代表了這個PES包得payload里面的第一個完整地audio access unit或者video access unit的PTS時間(并不是每個audio/video access unit都帶有PTS/DTS,因此,你可以在PES里面指定一個,作為開始)。 PES包頭的DTS也是這個原理,需要注意的是:對于video來說他的DTS和PTS是可以不一樣的,因為B幀的存在使其順序可以倒置。而對于audio來說,audio沒有雙向的預測,他的DTS和PTS可以看成是一個順序的,因此可一直采用一個,即可只采用PTS。
2.6TS流分析
1 從TS流開始 數字電視機頂盒接收到的是一段段的碼流,我們稱之為TS(Transport Stream,傳輸流),每個TS流都攜帶一些信息,如Video、Audio以及我們需要學習的PAT、PMT等信息。因此,我們首先需要了解TS流是什么,以及TS流是怎樣形成、有著怎樣的結構。 (一) TS流、PS流、PES流和ES流都是什么? ES流(Elementary Stream):基本碼流,不分段的音頻、視頻或其他信息的連續碼流。 PES流:把基本流ES分割成段,并加上相應頭文件打包成形的打包基本碼流。 PS流(Program Stream):節目流,將具有共同時間基準的一個或多個PES組合(復合)而成的單一數據流(用于播放或編輯系統,如m2p)。 TS流(Transport Stream):傳輸流,將具有共同時間基準或獨立時間基準的一個或多個PES組合(復合)而成的單一數據流(用于數據傳輸)。 *NOTE:TS流和PS流的區別:TS流的包結構是長度是固定的;PS流的包結構是可變長度的。這導致了TS流的抵抗傳輸誤碼的能力強于PS流(TS碼流由于采用了固定長度的包結構,當傳輸誤碼破壞了某一TS包的同步信息時,接收機可在固定的位置檢測它后面包中的同步信息,從而恢復同步,避免了信息丟失。而PS包由于長度是變化的,一旦某一?PS包的同步信息丟失,接收機無法確定下一包的同步位置,就會造成失步,導致嚴重的信息丟失。因此,在信道環境較為惡劣,傳輸誤碼較高時,一般采用TS碼流;而在信道環境較好,傳輸誤碼較低時,一般采用PS碼流。) 由于TS碼流具有較強的抵抗傳輸誤碼的能力,因此目前在傳輸媒體中進行傳輸的MPEG-2碼流基本上都采用了TS碼流的包格。
(二) TS流是如何產生的?
從上圖可以看出,視頻ES和音頻ES通過打包器和共同或獨立的系統時間基準形成一個個PES,通過TS復用器復用形成的傳輸流。注意這里的TS流是位流格式(分析Packet的時候會解釋),也即是說TS流是可以按位讀取的。
(三) TS流的格式是怎樣的? TS流是基于Packet的位流格式,每個包是188個字節(或204個字節,在188個字節后加上了16字節的CRC校驗數據,其他格式一樣)。整個TS流組成形式如下:
| Packet Header(包頭)信息說明 | |||
| 1 | sync_byte | 8bits | 同步字節 |
| 2 | transport_error_indicator | 1bit | 錯誤指示信息(1:該包至少有1bits傳輸錯誤) |
| 3 | payload_unit_start_indicator | 1bit | 負載單元開始標志(packet不滿188字節時需填充) |
| 4 | transport_priority | 1bit | 傳輸優先級標志(1:優先級高) |
| 5 | PID | 13bits | Packet ID號碼,唯一的號碼對應不同的包 |
| 6 | transport_scrambling_control | 2bits | 加密標志(00:未加密;其他表示已加密) |
| 7 | adaptation_field_control | 2bits | 附加區域控制 |
| 8 | continuity_counter | 4bits | 包遞增計數器 |
| 表 | PID 值 |
| PAT | 0x0000 |
| CAT | 0x0001 |
| TSDT | 0x0002 |
| EIT,ST | 0x0012 |
| RST,ST | 0x0013 |
| TDT,TOT,ST | 0x0014 |
下面以一個TS流的其中一個Packet中的Packet Header為例進行說明: sync_byte=01000111,?????????????????????? ?就是0x47,這是DVB TS規定的同步字節,固定是0x47. transport_error_indicator=0,??????????? ?表示當前包沒有發生傳輸錯誤. payload_unit_start_indicator=0,???? ?含義參考ISO13818-1標準文檔 transport_priority=0,????????????????????????表示當前包是低優先級. PID=00111 11100101即0x07e5,?????? Video PID transport_scrambling_control=00,??表示節目沒有加密 adaptation_field_control=01???????????即0x01,具體含義請參考ISO13818-1 continuity_counte=0010????????????????即0x02,表示當前傳送的相同類型的包是第3個
TS流的基本內容就是這些了。 回顧一下,TS流是一種位流(當然就是數字的),它是由ES流分割成PES后復用而成的;它經過網絡傳輸被機頂盒接收到;數字電視機頂盒接收到TS流后將解析TS流。 TS流是由一個個Packet(包)構成的,每個包都是由Packet Header(包頭)和Packet Data(包數據)組成的。其中Packet Header指示了該Packet是什么屬性的,并給出了該Packet Data的數據的唯一網絡標識符PID。 到這里,我們對TS流已經有了一定的了解,下面將從TS流轉向PAT表和PMT表的學習。
2 從TS流到PAT、PMT 說完了TS流的基本概念,就該開始對TS流進行更深入的研究了。首先需要想一想:TS流的本質是什么?它的確是一段碼流,并且是一段由數據包(Packet)組成的碼流。那么這些數據包究竟是怎樣的呢?它和我們收看的電視節目之間又有什么區別?這些都是這部分需要了解的內容。 在上一節中,我們可以看到PID這個被標紅的字段頻繁地出現。PID是當前TS流的Packet區別于其他Packet類型的唯一識別符,通過讀取每個包的Packet Header,我們可以知道這個Packet的數據屬于何種類型。上一節列出了幾項固定的PID值,它們用于識別存儲了特殊信息的Packet。下面要談的PAT表的PID值就是固定的0x0000。 (一) PAT表(Program Association Table,節目關聯表) 由于下面的內容比較繁雜,這里先給出一個大綱,方便查閱: 1. PAT表的描述(表格+分析) 2. PAT表的定義(代碼+分析) 3. PAT表的結構(代碼+分析) 4. PAT表的解析(代碼+分析) 5. 通過一段TS流中一個Packet分析PAT表(表格+分析) 下面,開始正式的分析!
1.?PAT表的描述(表格+分析) PAT表定義了當前TS流中所有的節目,其PID為0x0000,它是PSI的根節點,要查尋找節目必須從PAT表開始查找。 PAT表攜帶以下信息:
2. PAT表的定義(代碼+分析) PAT表主要包含頻道號碼和每一個頻道對應的PMT的PID號碼,這些信息我們在處理PAT表格的時候會保存起來,以后會使用到這些數據。下面將PAT表的定義給出: [cpp]?view plaincopy
4. PAT表的解析(代碼+分析) 接下來給出的是PAT表的解析代碼: [cpp]?view plaincopy
5. 通過一段TS流中一個Packet分析PAT表(表格+分析) 這里我們分析一段TS流其中一個Packet的Packet Data部分: 首先給出一個數據包,其數據如下: 分析Packet Header如下表所示: PID == 0 說明這個是一個PAT表 根據包頭數據格式,我們可以知曉整個數據包的屬性,列表如下:
| sync_byte | 0x47 | 固定同步字節 |
| transport_error_indicator | “0” | 沒有傳輸錯誤 |
| payload_unit_start_indicator | “1” | 在前4個字節后會有一個調整字節。所以實際數據應該為去除第一個字節后的數據。即上面數據中紅色部分不屬于有效數據包。 |
| transport_priority | “0” | 傳輸優先級低 |
| PID | 0x0000 | PID=0x0000說明數據包是PAT表信息 |
| transport_scrambling_control | “00” | 未加密 |
| adaptation_field_control | “01” | 附加區域控制 |
| continuity_counte | “0000” | 包遞增計數器 |
由以上幾個表可以分析出PAT表和PMT表有著內在的聯系。也就是之前提到的。PAT表描述了當前流的NIT(Network Information Table,網絡信息表)中的PID、當前流中有多少不同類型的PMT表及每個PMT表對應的頻道號。而PAT表和PMT表到底有什么深層次的聯系呢?在討論完了PMT表和SDT表后再做討論吧。 6. 過濾PAT表信息的偽代碼(代碼) [cpp]?view plaincopy
(二) PMT表(Program Map Table,節目映射表)(Service Descriptor Table) 1. PMT表的描述????? 如果一個TS流中含有多個頻道,那么就會包含多個PID不同的PMT表。 PMT表中包含的數據如下: (1)?當前頻道中包含的所有Video數據的PID (2)?當前頻道中包含的所有Audio數據的PID (3)?和當前頻道關聯在一起的其他數據的PID(如數字廣播,數據通訊等使用的PID) 只要我們處理了PMT,那么我們就可以獲取頻道中所有的PID信息,如當前頻道包含多少個Video、共多少個Audio和其他數據,還能知道每種數據對應的PID分別是什么。這樣如果我們要選擇其中一個Video和Audio收看,那么只需要把要收看的節目的Video PID和Audio PID保存起來,在處理Packet的時候進行過濾即可實現。 2. PMT表的定義(代碼)?? [cpp]?view plaincopy
4. PMT表的解析(代碼)?? [cpp]?view plaincopy
5. 通過一段TS流中一個Packet分析PMT表(表格+分析) 老樣子,還是通過分析一段TS流的數據包Packet來學習PMT表。 下面給出了一段TS流數據中的一個Packet(十六進制數) 首先解析Packet Header,分析如下: PID=0x03e8為其PID ,怎么就根據這個PID斷定他就是PMT呢?難道是PAT中有說明吧。 下面是詳細的解析表
| Packet Header分析 | |||
| ? | Packet Header:0x47 0x40 0x00 0x10 | ||
| 1 | sync_byte | 0x47 | 固定同步字節 |
| 2 | transport_error_indicator | “0” | 沒有傳輸錯誤 |
| 3 | payload_unit_start_indicator | “1” | 在前4個字節后會有一個調整字節。所以實際數據應該為去除第一個字節后的數據。 |
| 4 | transport_priority | “0” | 傳輸優先級低 |
| 5 | PID | 0x03e8 | PID=0x03e8說明數據包是PMT表信息 |
| 6 | transport_scrambling_control | “00” | 未加密 |
| 7 | adaptation_field_control | “01” | 附加區域控制 |
| 8 | continuity_counte | “0010” | 包遞增計數器 |
(三) 解復用模型(代碼)??????? [cpp]?view plaincopy
(四) DVB搜臺原理以及SDT表(Service Descriptor Table,業務描述表) 機頂盒先調整高頻頭到一個固定的頻率(如498MHZ),如果此頻率有數字信號,則COFDM芯片(如MT352)會自動把TS流數據傳送給MPEG- 2 decoder。 MPEG-2 decoder先進行數據的同步,也就是等待完整的Packet的到來.然后循環查找是否出現PID== 0x0000的Packet,如果出現了,則馬上進入分析PAT的處理,獲取了所有的PMT的PID。接著循環查找是否出現PMT,如果發現了,則自動進入PMT分析,獲取該頻段所有的頻道數據并保存。如果沒有發現PAT或者沒有發現PMT,說明該頻段沒有信號,進入下一個頻率掃描。 原來有沒有信號是通過判斷有沒有PAT或者PMT來的啊 在解析TS流的時候,首先尋找PAT表,根據PAT獲取所有PMT表的PID;再尋找PMT表,獲取該頻段所有節目數據并保存。這樣,只需要知道節目的PID就可以根據PacketHeade給出的PID過濾出不同的Packet,從而觀看不同的節目。這些就是PAT表和PMT表之間的關系。而由于PID是一串枯燥的數字,用戶不方便記憶、且容易輸錯,所以需要有一張表將節目名稱和該節目的PID對應起來,DVB設計了SDT表來解決這個問題。 該表格標志一個節目的名稱,并且能和PMT中的PID聯系起來,這樣用戶就可以通過直接選擇節目名稱來選擇節目了。(這就是PMT和SDT的聯系了) SDT可以提供的信息包括: (1)?該節目是否在播放中 (2)?該節目是否被加密 (3)?該節目的名稱
3、 從PAT開始,走向更遠 在本章的學習中,我們發現了一個特點:所有的TS流的解析都是從尋找PAT表開始的,只有找到了PAT表,我們才能繼續下一步的解析。因此,在進行了TS流、PAT表和PMT表的初步知識儲備后,在接下來的學習中將從PAT表開始,學習更多的PSI/SI相關的表,將走得更遠。
2.7PSI分析 "SI是對多個TS流的描述,它包含了PSI" PSI只提供了單個TS流的信息,使接收機能夠對單個TS流中的不同節目進行解碼;但是,它不能提供多個TS流的相關業務,也不能提供節目的類型、節目名稱、開始時間、節目簡介等信息。因此,DVB對PSI進行了擴展,提供了其他不同類型的表,形成了SI。 SI定義了PAT、PMT和CAT之外的9張表,通過組織SI提供的這些數據,可以生成類似節目報表的形式,方便用戶查看多種信息,這就是所謂的電子節目指南(EPG)。 下面給出了SI定義的十張表(NIT的由SI規定的)
| NIT | Network Information Table | 網絡信息表 | 描述整個網絡,如多少TS流、頻點和調制方式等信息 |
| SDT | Service Description Table | 業務描述表 | 包含業務數據(如業務名稱、起始時間、持續時間等) |
| BAT | Bouquet Association Table | 業務群關聯表 | 給出業務群的名稱及其業務列表等信息 |
| EIT | Event Information Table | 事件信息表 | 包含事件或節目相關數據,是生成EPG的主要表 |
| RST | Running Status Table | 運行狀態表 | 給出事件的狀態(運行/非運行) |
| TDT | Time&Date Table | 時間和日期表 | 給出當前事件和日期相關信息,更新頻繁 |
| TOT | Time Offset Table | 時間偏移表 | 給出了當前時間日期與本地時間偏移的信息 |
| ST | Stuffing Table | 填充表 | 用于使現有的段無效,如在一個傳輸系統的邊界 |
| SIT | ? | 選擇信息表 | 僅用于碼流片段中,如記錄的一段碼流,包含描述該碼流片段業務信息段的地方 |
| DIT | ? | 間斷信息表 | 僅用于碼流片段,如記錄的一段碼流中,它將插入到碼流片段業務信息間斷的地方 |
SI定義的表,并不需要全部傳輸,其中,NIT、SDT、EIT和TDT是必須傳輸的;而又以NIT、SDT和EIT最為重要,利用這三個表可以構成功能不同的EPG,如提供節目附加信息、節目分類、節目預定和家長分級控制等。
解析 NIT描述了數字電視網絡中與網絡相關的信息" NIT描述了數字電視網絡中與網絡相關的信息,但這個表本身的信息有限,更多的信息是依靠插入表中的描述符來提供的。NIT常用的描述符有:網絡名稱描述符(network_name_descriptor)、有線傳送系統(cable_delivery_system_descriptor)、業務列表描述符(service_list_descriptor)和鏈接描述符(linkage_descriptor)。下圖是實際的一個例子中的兩種描述符。
NIT的表結構分析 網絡信息表(NIT)傳遞了與通過一個給定的網絡傳輸的復用流/TS流的物理結構相關的信息,以及與網絡自身特性相關的信息。 網絡信息段 Syntax (句法結構)???????? No. of bits(所占位數)?? Identifier(識別符)? Note(注釋)?? network_information_section(){ table_id????????????????????????????????????????????8??????????????????????uimsbf?????????????????????????????????????????????????? Section_syntax_indicator?????????????? 1????????????????????????? bslbf???????????? 通常設為“1” Reserved_future_use????????????????????? 1??????????????????????? bslbf Reserved?????????????????????????????????????????2??????????????????????? bslbf Section_length??????????????????????????????? 12????????????????????? uimsbf???????????????? 見注釋 Network_id????????????????????????????????????? 16?????????????????????? uimsbf???????????????? 見注釋 Reserved?????????????????????????????????????????2???????????????????????? bslbf Version_number????????????????????????????? 5???????????????????????? uimsbf???????????? 見注釋 Current_next_indicator?????????????????? 1????????????????????????? bslbf???????????????? 見注釋 Section_number????????????????????????????? 8????????????????????????? uimsbf??????????? 見注釋 last_section_number?????????????????????? 8????????????????????????? uimsbf??????????? 見注釋 Reserved_future_use????????????????????? 4????????????????????????? bslbf Network_descriptors_length??????? 12??????????????????????? uimsbf for(i=0;i<N;i++){ descriptor()??????//First descriptor loop } reserved_future_use???????????????????????? 4???????????????????? bslbf transport_stream_loop_length?????? 12????????????????? uimsbf?????????????? for(i=0;i<N;i++){ transport_stream_id???????????????????? 16????????????????? uimsbf???????????? 見注釋 original_network_id????????????????????? 16????????????????? uimsbf???????????? 見注釋 reserved_future_use????????????????????? 4????????????????? bslbf transport_descriptors_length???? 12?????????????????? uimsbf for(j=0;j<N;j++){ descriptor()?????//Second descriptor loop } } CRC_32?????????????????????????????????????????32????????????????? rpchof????????????????? 見注釋 } 在SI標準中規定:original_network_id和transport_stream_id兩個標識符相結合唯一確定了網絡中的TS流。各網絡被分配獨立的network_id值作為網絡的唯一識別碼。當NIT表在生成TS流的網絡上傳輸時,network_id和original_network_id將取同一值。
- NIT表被切分為網絡信息段(network_information_section)
- 任何NIT的段都必須由PID為0x0010的TS包傳輸
- 現行網絡的NIT表任何段的table_id值應為0x40,且具有相同的table_id_extension即(network_id);
- 現行網絡以外的其他網絡NIT表的段table_id值應為0x41
| 第一層描述符 | 作用域是針對整個網絡的,如插入網絡名稱描述符、鏈接描述符等 |
| 第二層描述符 | 作用域是第一層循環所代表的一個TS流,如插入有線傳輸系統描述符 |
上圖提供的即是一個真實的NIT表,紅色框內有兩個描述符,分別是業務列表描述符service_list_descriptor和有線傳輸系統描述符cable_delivery_system_descriptor;它們都位于第二層循環。
NIT的業務列表描述符結構分析 業務列表描述符通過業務標識符和業務類型提供業務服務。其目的在于:告訴接收機每一個TS流中存在多少個業務以及每一個業務的類型。其結構如下: 業務列表描述符 Syntax(句法結構)??? No. of bits(所占位數)Identifier(識別符)? service_list_descriptor(){ descriptor_tag?????????????????????? 8?????????????????????? uimsbf descriptor_length?????????????????? 8?????????????????????? uimsbf for(i=0;i<N;i++){ service_id????????????????? 16????????????????????? uimsbf service_type?????????????? 8?????????????????????? uimsbf } } service_id(業務標識符):唯一標識TS中的一個業務,它與program_map_section中的program_number(參看PMT表結構)相同。但當業務類型為0x04時(即NVOD參考業務,service_id沒有對應的program_number)。 service_type(業務類型):指示業務的類型。如0x01為數字電視業務,0x02為數字音頻廣播業務,0x04為NVOD參考業務,0x05為NVOD時移業務。 HINT:下表給出了業務類型編碼方法
上圖所示只是其中一個section的業務列表描述符,如果將所有的section全解析,那么此網絡中所有TS流包含的所有service_id和service_type都可以獲得。這樣,用戶可以據此了解整個網絡業務的構成,并以此為基礎對業務進行分類、整合。
NIT的有線傳輸系統描述符結構分析 有線傳輸系統描述符(Cable_Delivery_System_descriptor)是NIT業務中重要的描述符,也是基本運營所必需的描述符。它主要描述了每一個TS流的物理參數(頻率、調制方式、符碼率等),使接收機能正確鎖頻、得到數據。其結構如下:
有線傳輸系統描述符 Syntax(句法結構)??? No. of bits(所占位數)Identifier(識別符)? cable_delivery_system_descriptor(){ descriptor_tag????????????????????? 8?????????? uimsbf???????? descriptor_length???????????????? 8?????????? uimsbf???????????????????????? frequency????????????????????????? ??32??????????bslbf reserved_future_use????????? ??12??????????bslbf FEC_outer????????????????????????? ????4?????????? bslbf???????????? 前向糾錯外碼 modulation??????????????????????? ??8???????????bslbf symbol_rate????????????????????? ???28??????????bslbf FEC_inner?????????????????????????? ??4???????????? bslbf?????????? 前向糾錯內碼 } Frequency(頻率):32位,以8個4位BCD碼給出頻率。其單位是MHz,小數點位于第四個BCD碼之后,如0312.0000MHz。 Modulation(調制方式):指出有線傳輸系統的調制方式。其定義如下表:
symbol_rate(符碼率):28位,以7個4位BCD碼表示符碼率。其單位是MSPS(兆符號每秒),小數點位于第三個BCD碼后,如027.4500 MSPS 上圖所示為一個真實TS流里的一個有線傳輸系統描述符。可以看到其頻率為331.0000MHz,符碼率為6.8750MSym/s,調制方式為64 QAM。
NIT的網絡名稱描述符結構分析 網絡名稱描述符的功能比較簡單,它以字符串的形式將網絡的名稱告訴接收機。下面是其描述符結構列表: 網絡名稱描述符 Syntax(句法結構)??? No. of bits(所占位數)Identifier(識別符)? network_name_descriptor(){ descriptor_tag?????????????????????? ??8?????????????????????? uimsbf descriptor_length?????????????????? 8?????????????????????? uimsbf for(i=0;i<N;i++){ char????????????????????????? ???????????????????8??????????????????? uimsbf } } char(字符):8位字段,一個字符串,給出NIT表指定的傳送系統的名稱。
NIT的鏈接描述符結構分析 ANALYZEOFTHE?STRUCTUREOFLINKAGE_DESCRIPTORINNIT 鏈接描述符 Syntax(句法結構)??? No. of bits(所占位數)Identifier(識別符)? linkage_descriptor(){ descriptor_tag???????????????????????? 8?????????? uimsbf???????? descriptor_length????????????? ???????8??????????uimsbf??? transport_stream_id????????????? ???16??????????uimsbf original_network_id???????????? ????16??????????uimsbf service_id????????????????????????????? ???16???????????uimsbf linkage_type??????????????????????? ??????8????????????? uimsbf for(i=0;i<N;i++){ private_data_byte????????????? ???8?????????????bslbf } }? 如果用戶要求得到SI系統描述的特定實體的進一步信息,則可以使用鏈接描述符。鏈接描述符包含的信息給出了該實體的位置。如:可以在一個NIT中使用一個鏈接描述符,給出網絡中可存放業務附加信息的位置;或者在BAT表中的鏈接描述符可鏈接到業務群的相關信息等。 使用鏈接描述符,也可以提供一種業務,以替換CA系統的功能。如果CA系統不能處理相應功能的時候,接收機就可以用這個業務來取代CA。 使用鏈接描述符,還可以以一種備用業務,用以替換主業務。若主業務的運行狀態被置為“not_running”,那么,接收機可以自動選擇被鏈接描述符指引的備用業務,以取代該業務。 使用鏈接描述符,還可以向移動接收機提供漫游功能。若現行業務其service_id下無法使用,IRD可以自動選擇該功能。hand-over_type指明link_descriptor是否鏈接到不同國家的同一業務,或者鏈接到本地變更業務或關聯業務。 總之,鏈接描述符為運營商提供了一種業務擴充功能,使得運營商可以更加靈活地組合各種業務。
NIT的軟件下載鏈接描述符結構分析 軟件下載描述符用于運營商在網絡內進行多于一個機頂盒的軟件下載更新標識,在網絡信息表NIT的第一個循環內,并且可能多次出現。針對同一組制造商號(manufacturer_id)、硬件類型(hw_model)、硬件版本(hw_version)和軟件類型(sw_model),可能有不只一組的不同軟件版本(sw_version)和開始時間(start_time)參數,并可能出現在同一個或多個鏈接描述符(linkage_descriptor)的各個循環內。
解析 "BAT將網絡中的所有業務分成了多個業務群,以此界定用戶" BAT即業務群關聯表(BouquetAssociation Table),它將網絡中所有的業務分成了多個業務群,以此界定用戶。例如,將網絡中所有業務分為兩個業務群,一個是境內節目業務群,另一個是境外節目業務群。這樣,國內的運營商就可以利用這樣劃分的業務群,充分利用節目資源,在不違反現有廣電總局規定的前提下,同時分別滿足境內用戶和境外用戶。 BAT本身可以跨網絡存在,但在國內運營體系來看幾乎沒有得到真正使用。國內的運營使用中,BAT還可以存在分級運營的運營體系中,用于區分不同的地域用戶。 BAT被切分為業務群關聯段,所有的業務群關聯段都在TS中傳輸,其PID為0x0011。所有的業務群關聯段的table_id都取0x4A。 HINT:SDT的TS包PID也為0x0011,其table_id為0x42或0x46。 BAT的表結構分析 下面給出了BAT表的段結構: 業務群關聯段 Syntax(句法結構)???????? No. ofbits(所占位數)?? Identifier(識別符)? Note(注釋) bouquet_association_section(){ table_id????????????????????????????????????????????8??????????????????????uimsbf?????????????????????????????????????????????????? Section_syntax_indicator?????????????? 1????????????????????????? bslbf???????? 通常設為“1” Reserved_future_use????????????????????? 1??????????????????????? bslbf Reserved?????????????????????????????????????????2??????????????????????? bslbf Section_length??????????????????????????????? 12????????????????????? uimsbf???????????????? 見注釋 bouquet_id????????????????????????????????????? 16?????????????????????? uimsbf???????????????? 見注釋 Reserved?????????????????????????????????????????2???????????????????????? bslbf Version_number????????????????????????????? 5???????????????????????? uimsbf???????????? 見注釋 Current_next_indicator?????????????????? 1????????????????????????? bslbf???????????????? 見注釋 Section_number????????????????????????????? 8????????????????????????? uimsbf??????????? 見注釋 last_section_number?????????????????????? 8????????????????????????? uimsbf??????????? 見注釋 Reserved_future_use????????????????????? 4????????????????????????? bslbf bouquet_descriptors_length??????? 12??????????????????????? uimsbf for(i=0;i<N;i++){ descriptor() } reserved_future_use???????????????????????? 4???????????????????? bslbf transport_stream_loop_length?????? 12????????????????? uimsbf?????????????? for(i=0;i<N;i++){ transport_stream_id???????????????????? 16????????????????? uimsbf???????????? 見注釋 original_network_id????????????????????? 16????????????????? uimsbf???????????? 見注釋 reserved_future_use????????????????????? 4????????????????? bslbf transport_descriptors_length???? 12?????????????????? uimsbf for(j=0;j<N;j++){ descriptor() } } CRC_32?????????????????????????????????????????32????????????????? rpchof????????????????? 見注釋 } 注意到BAT的結構和NIT類似,其作用和描述符的使用也與NIT大致雷同。其中,可以插入傳輸系統描述符、業務列表描述符等。這些表和NIT中的表已介紹,這里不再贅述。
BAT的業務群名稱描述符結構分析 下面給出的是業務群名稱描述符,它以文本方式給出了業務群的名稱: 業務群名稱描述符 Syntax(句法結構)??? No. of bits(所占位數)Identifier(識別符)? bouquet_name_descriptor(){ descriptor_tag???????????????????????? 8?????????? uimsbf??????????????????????????? descriptor_length????????????? ???????8??????????uimsbf???????????????????????? for(i=0;i<N;i++){ char??????????????????????????? ???????????8????????????uimsbf?????? } } char(字符):8位字段,用于描述BAT子表敘述的節目業務群名稱 業務名稱描述符和網絡名稱描述符類型,只是作為業務群的一個代號,其實際意義只存在于用戶界面上,可以給用戶一個良好的操作體驗。
SDT解析 "SDT描述了業務內容及信息,連接了NIT與EIT和PMT(PSI)" SDT即服務描述表(Service Description Table),它描述了一個業務中的內容以及信息,它承上啟下,以transport_stream_ID連接了NIT和EIT;SDT的servicID必須與PMT中的Program_no一致,因此,SDT又與PSI的信息連接。 對于一般的音視頻業務,SDT表中不會有太多的信息需要添加。如果是其他業務(如NVOD、馬賽克、數據廣播等),在SDT中需要插入相應業務的描述符。
SDT的表結構分析 SDT表被切分成業務描述段(service_description_section),由PID為0x0011的TS包傳輸(BAT段也由PID為0x0011的TS包傳輸,但table_id不同)。 描述現行TS(即包含SDT表的TS)的SDT表的任何段的table_id都為0x42,且具有相同的table_id_extension(transport_stream_id)以及相同的original_network_id。 指向非現行TS的SDT表的任何段的table_id都應取0x46。 下面給出了SDT的業務描述段:? 業務描述段 Syntax(句法結構)???????? No. ofbits(所占位數)?? Identifier(識別符)? Note(注釋)?? service_description_section(){ table_id????????????????????????????????????????????8??????????????????????uimsbf?????????????????????????????????????????????????? Section_syntax_indicator?????????????? 1????????????????????????? bslbf?????????????????? 通常設為“1” Reserved_future_use????????????????????? 1??????????????????????? bslbf Reserved?????????????????????????????????????????2??????????????????????? bslbf Section_length??????????????????????????????? 12????????????????????? uimsbf???????????????? 見注釋 transport_stream_id?????????????????????? 16?????????????????????? uimsbf????????????????給出TS識別號 Reserved?????????????????????????????????????????2???????????????????????? bslbf Version_number????????????????????????????? 5???????????????????????? uimsbf???????????? 見注釋 Current_next_indicator?????????????????? 1????????????????????????? bslbf???????????????? 見注釋 Section_number????????????????????????????? 8????????????????????????? uimsbf??????????? 見注釋 last_section_number?????????????????????? 8????????????????????????? uimsbf??????????? 見注釋 original_nerwork_id??????????????????????? 16???????????????????????? uimsbf??????????? 見注釋 reserved_future_use??????????????????????? 8????????????????????????? bslbf for(i=0;i<N;i++){ service_id???????????????????????????????????? 16???????????????????????? uimsbf?????????? 見注釋 reserved_future_use???????????????????? 6???????????????????????? bslbf EIT_schedule_flag???????????????????????? 1????????????????????????? bslbf??????????? 見注釋 EIT_present_following_flag????????? 1????????????????????????? bslbf??????????? 見注釋 running_status??????????????????????????????? 3???????????????????????? uimsbf??????? 見下面分析 freed_CA_mode??????????????????????????? 1???????????????????????? bslbf??????????? 見注釋 descriptors_loop_length??????????????? 12????????????????????? uimsbf for(j=0;j<N;j++){ descriptor() } } CRC_32???????????????????????????????????????????????32????????????????? rpchof????????????????? 見注釋 } running_status(運行狀態):表示業務狀態,下表給出了業務狀態
| 值 | 含義 |
| 0 | 未定義 |
| 1 | 未運行 |
| 2 | 幾秒后開始(如錄像) |
| 3 | 暫停 |
| 4 | 運行 |
| 5~7 | 預留 |
SDT的業務描述符分析 業務描述符與業務類型一起,以文本形式給出業務提供者的名稱和業務名稱,如下表: 業務描述符 Syntax(句法結構)??? No. of bits(所占位數)Identifier(識別符)? service_descriptor(){ descriptor_tag?????????????????????? 8?????????????????????? uimsbf descriptor_length?????????????????? 8?????????????????????? uimsbf service_type????????????????????????? 8????????????????????? uimsbf service_provider_name_length? 8??????????????????? uimsbf for(i=0;i<N;i++){ Char???????????????????????????????? 8????????????????????? uimsbf } service_name_length??????????? 8????????????????????? uimsbf for(i=0;i<N;i++){ Char??????????????????????????????? 8????????????????????? uimsbf } } service_type(業務類型):這里的業務類型和NIT中的業務列表描述符中的service_type編碼是一致的:
| service_type | 描述 |
| 0x00 | 預留使用 |
| 0x01 | 數字電視業務 |
| 0x02 | 數字音頻廣播業務 |
| 0x03 | 圖文電視業務 |
| 0x04 | NVOD參考業務 |
| 0x05 | NVOD時移業務 |
| 0x06 | 馬賽克業務 |
| 0x07 | PAL制編碼信號 |
| 0x08 | SECAM制編碼信號 |
| 0x09 | D/D2-MAC |
| 0x0A | 調頻廣播 |
| 0x0B | NTSC制信號 |
| 0x0C | 數據廣播業務 |
| 0x0D | 公共接口使用預留 |
| 0x0E | RCS映射(見EN 301 790) |
| 0x0F | RCS FLS(見EN 301 790) |
| 0x10 | DVB MHP業務 |
| 0x11~0x7F | 預留使用 |
| 0x80~0xFE | 用戶定義 |
| 0xFF | 預留使用 |
SDT的實例分析 這里主要演示SDT如何連接PSI和NIT。 首先,根據SDT描述符的service_id可以和PMT中的program_number建立連接。如圖所示,SDT的service_id=201=0xc9,與PMT中的program_number一致。
上圖所示,根據SDT的transport_stream_id和NIT的transport_stream_id,可以將SDT和NIT聯系起來。根據上圖的信息,我們可以根據SDT獲取該業務(頻道)的業務列表信息和有線傳輸信息(位于NIT中)。
EIT解析 "EIT按時間順序提供每一個業務所包含的事件信息" EIT即事件信息表(Event Information Table),它是EPG中絕大部分信息的攜帶者。事實上,EPG主要就是通過SDT和EIT信息的獲取和重組實現的。SDT只提供了頻道信息,而EIT則提供各頻道下的所有節目的信息。 EIT的主要信息也是通過插入的描述符來實現的。EIT按照時間順序提供每一個業務所包含的事件的相關信息(如節目名稱、節目簡介)。 按照不同的table_id,一共有四類EIT。其中,當前TS流的所有EIT子表都有相同的transport_stream_id和original_stream_id。下圖給出了一個實例的碼流中的EIT信息,這里一共有三類EIT表,觀察其table_id就可以知道它們代表什么類型的EIT 第一個EIT_PF_Actual應該是當前TS流的“當前/后續事件信息”;第二個EIT_PF_Other是其他TS流的“當前/后續事件信息”;第三個EIT_Schedule_Actual是當前TS流的“事件時間表信息”。
EIT的表結構分析 EIT表被切分成事件信息段。任何構成EIT的段都由PID=0x0012的TS包傳輸。下面給出的是事件信息段的結構: 事件信息段 Syntax(句法結構)???????? No. ofbits(所占位數)?? Identifier(識別符)? Note(注釋) event_information_section(){ table_id????????????????????????????????????????????8??????????????????????uimsbf?????????????????????????????????????????????????? Section_syntax_indicator?????????????? 1????????????????????????? bslbf?????????????????? 通常設為“1” Reserved_future_use????????????????????? 1??????????????????????? bslbf Reserved?????????????????????????????????????????2??????????????????????? bslbf Section_length??????????????????????????????? 12????????????????????? uimsbf???????????????? 見注釋 service_id??????????????????????????????????????? 16?????????????????????? uimsbf????????????????與PAT中的program_number一致 Reserved?????????????????????????????????????????2???????????????????????? bslbf Version_number????????????????????????????? 5???????????????????????? uimsbf???????????? 見注釋 Current_next_indicator?????????????????? 1????????????????????????? bslbf???????????????? 見注釋 Section_number????????????????????????????? 8????????????????????????? uimsbf??????????? 見注釋 last_section_number?????????????????????? 8????????????????????????? uimsbf??????????? 見注釋 transport_stream_id?????????????????????? 16???????????????????????? uimsbf??????????? 見注釋 original_nerwork_id??????????????????????? 16???????????????????????? uimsbf??????????? 見注釋 segment_last_section_number???? 8?????????????????????????? uimsbf??????????? 見注釋 last_table_id???????????????????????????????????? 8?????????????????????????? uimsbf??????????? 見注釋 for(i=0;i<N;i++){ event_id??????????????????????????????????????? 16???????????????????????? uimsbf??????????事件(節目)id start_time????????????????????????????????????? 40???????????????????????? bslbf???????????事件(節目)開始時間 duration????????????????????????????????????????24?????????????????????????bslbf???????????事件(節目)持續始時間 running_status??????????????????????????????? 3???????????????????????? uimsbf???????? 見注釋 freed_CA_mode??????????????????????????? 1???????????????????????? bslbf??????????? 見注釋 descriptors_loop_length??????????????? 12????????????????????? uimsbf for(j=0;j<N;j++){ descriptor() } } CRC_32???????????????????????????????????????????????32????????????????? rpchof????????????????? 見注釋 } start_time(開始時間):40位字段,指的是事件(節目)的開始時間,它包含以UTC和MJD形式表示的事件(節目)的起始時間及日期。此字段前16位表示MJD日期碼,其余24位按4位BCD編碼,表示6個數字。例如:93/10/13 12:45:00被編碼為:“0xc079124500” HINT:如果事件起始時間未定,則所有位都置為“1”,例如對NVOD業務的一個事件。 duration(持續時間):24位字段,表示事件的持續時間,以時、分、秒的格式表示,即由6個4位BCD碼顯示。如:01:45:30被編碼為“0x14530”。 running_status(運行狀態):參看SDT表解析部分。 下面給出一個具體的例子: EIT主要承載的信息就是Event的相關內容,即節目信息。其中,節目所在頻道(service_id)、開始時間(start_time)、結束時間(start_time+duration)可在EIT子表獲取;而節目描述、節目名稱、節目分類等信息就要在插入EIT的描述符中獲取了。
EIT的短事件描述符分析 短事件描述符(Short_event_descriptor)以文本方式提供了事件名稱和該事件的簡短描述。描述符結構如下: 短事件描述符 Syntax(句法結構)??? No. of bits(所占位數)Identifier(識別符)? short_event_descriptor(){ descriptor_tag?????????????????????? 8?????????????????????? uimsbf descriptor_length?????????????????? 8?????????????????????? uimsbf ISO_639_language_code????? 24????????????????????? bslbf event_name_length?????????????? 8?????????????????????? uimsbf for(i=0;i<event_name_length;i++){ event_name_char???????????? 8?????????????????????? uimsbf } text_length????????????????????????? 8?????????????????????? uimsbf for(i=0;i<text_length;i++){ text_char??????????????????????? 8?????????????????????? uimsbf } } ISO_639_language_code(ISO 639-2語言代碼):24位字段,指明后續文本字段的語言。該字段包含一個由ISO 639-2定義的3字符代碼。ISO 639-2/B和ISO 639-2/T均可使用。每個字符按照GB/T15273.1-1994編碼為8位,并依次插入24位字段。如:法語的3字符代碼“fre”,可編碼為:“0110 01100111 0010 0110 0101”。 event_name_char(事件名稱字符):一個字符串給出事件的名字。 text_char(文本字符):一個字符串給出事件的文本描述。 下面給出的是一個實際案例的短時間描述符,可見中文的3字符代碼是“chi”。
EIT的擴展事件描述符分析 擴展事件描述符(Extended_Event_Descriptor)拓展事件描述符給出了一個事件的詳細文本描述。如果一個事件的信息長度超過256字節,可以使用多于一個相關聯的擴展事件描述符來描述。文本信息可以分為兩個欄目,一欄為條目的描述,另一欄為條目的內容。 下面給出了擴展事件描述符的結構。 擴展事件描述符 Syntax(句法結構)??? No. of bits(所占位數)Identifier(識別符)? extended_event_descriptor(){ descriptor_tag???????????????????????? 8?????????? uimsbf???????? descriptor_length???????????????? 8?????????? uimsbf??? descriptor_number????????????????????? 4???????????? uimsbf last_descriptor_number??????????????? 4???????????? uimsbf ISO_639_language_code?????????? 24?????????? bslbf? length_of_items??????????????????????????? 8???????????? uimsbf for(i=0;i<N;i++){ item_description_length????????? 8?????????????? uimsbf for(j=0;j<N;j++){ item_description_char?????? 8??????????????? uimsbf } item_length for(j=0;j<N;j++){ item_char } }??? text_length for(i-0;i<N;i++){ text_char }????????????? } 下面給出的是一個實例截圖:
EIT的內容描述符分析 內容描述符的目的是為事件提供清晰的信息描述符。根據這個描述符的信息,接收機可以清晰地知道事件的分類,并告知觀眾。下面給出了內容描述符的結構: 內容描述符 Syntax(句法結構)??? No. of bits(所占位數)Identifier(識別符)? content_descriptor(){ descriptor_tag???????????????????????? 8?????????? uimsbf????? descriptor_length???????????????? 8?????????? uimsbf???????????????????????? for(i=0;i<N;i++){ content_nibble_level1?????? 4????????????? uimsbf?????? content_nibble_level2????? 4????????????? uimsbf?????? user_nibble???????????????????????? 4???????????? uimsbf?????? user_nibble???????????????????????? 4???????????? uimsbf?????? } } 這里主要需要介紹的就是?content_nibble_level1和content_nibble_level2:根據EN 300 468V1.3.1(1998-02)中的Table 18可以確定該節目的具體分類。 下面給出了一個實例。
TDT解析 "TDT僅傳送UTC時間和日期信息,只有一個段" TDT為時間和日期表(Time&Date?Table),它僅傳送UTC時間和日期信息。并且TDT僅包含一個段,其結構如下: 時間和日期段 Syntax(句法結構)???????? No. ofbits(所占位數)?? Identifier(識別符)? Note(注釋)?? time_date_section(){ table_id????????????????????????????????????????????8??????????????????????uimsbf?????????????????????????????????????????????????? Section_syntax_indicator?????????????? 1????????????????????????? bslbf???????????? 通常設為“1” Reserved_future_use????????????????????? 1??????????????????????? bslbf Reserved?????????????????????????????????????????2??????????????????????? bslbf Section_length??????????????????????????????? 12????????????????????? uimsbf???????????????? 見注釋 UTC_time???????????????????????????????????????????40??????????????????????bslbf???????????????????? 見注釋 } UTC_time(UTC時間):40位字段,包含以UTC和MJD形式表示的當前時間和日期。此字段前16位為MJD日期碼,后24位按4位BCD編碼,表示6個數字。如:93/10/13 12:45:00被編碼為“0xC079124500”。 下圖給出了一個實例: TOT解析 "TOT是TDT的一個擴展,增加了一個描述符" TOT為時間偏移表(Time Offset Table),它包含了UTC時間和日期信息及當地時間偏移。傳輸此表的TS包PID為0x0014,table_id=0x73。下面給出了時間偏移段的結構: 時間偏移段 Syntax(句法結構)???????? No. ofbits(所占位數)?? Identifier(識別符)? Note(注釋) time_offset_section(){ table_id????????????????????????????????????????????8??????????????????????uimsbf?????????????????????????????????????????????????? section_syntax_indicator?????????????? 1????????????????????????? bslbf???????? 通常設為“1” reserved_future_use????????????????????? 1??????????????????????? bslbf reserved?????????????????????????????????????????2??????????????????????? bslbf section_length??????????????????????????????? 12????????????????????? uimsbf???????????????? 見注釋 UTC_time???????????????????????????????????????????40??????????????????????bslbf???????????????????? 見注釋 reserved?????????????????????????????????????????4???????????????????????? bslbf descriptors_loop_length??????????????? 12????????????????? uimsbf?????????????? for(i=0;i<N;i++){ descriptor() } CRC_32?????????????????????????????????????????32????????????????? rpchof????????????????? 見注釋 } 這里的UTC_time和TDT表是一致的,都是以UTC和MJD形式表示當前時間和日期;其格式也與TDT的UTC_time相同,這里不再贅述。需要特別注意的是這里的描述符descriptor()。下面給出了本地時間偏移描述符的結構: 本地時間偏移描述符 Syntax(句法結構)??? No. of bits(所占位數)Identifier(識別符)? local_time_offset_descriptor(){ descriptor_tag???????????????????????? 8?????????? uimsbf???????? descriptor_length???????????????? 8?????????? uimsbf??? for(i=0;i<N;i++){ coutry_code?????????????????????????? 24???????????? bslbf country_region_id??????????????????? 6???????????? bslbf reserved????????????????????????????????? 1???????????? bslbf local_time_offset_polarity?????? 1???????????? bslbf local_time_offset??????????????????? 16??????????? bslbf time_of_change????????????????????? 40??????????? bslbf next_time_offset???????????????????? 16??????????? bslbf } } 國家代碼? country_code 24位字段,按照ISO 3166用3字符代碼指明國家。每個字符根據GB/T 15273.1-1994編碼為8位,并依次插入24位字段。假設3個字符代表了一個900至999的數字,那么country_code指定了一組ETSI定義的國家。其分配見ETR 162。國家組的國家代碼應該被限制在同一時區內。 例如:英國由3字符代碼“GBR”表示,編碼為:“01000111 0100 0010 0101 0010”。 國家區域標識符? country_region_id 6位字段,表示country_code指明的國家所在的時區。若國家內部里沒有時差,則置“000000”。
本地時間偏移極性?local_time_offset_polarity 1位字段,用于指明隨后的local_time_offset的極性。置“0”時,極性為正,說明本地時間早于UTC時間(通常在格林威治以東);置“1”時,極性為負,說明本地時間晚于UTC時間。 本地時間偏移?local_time_offset 16位字段,指出由country_code和country_region_id確定的區域的相對于UTC的時間偏移,范圍為-12小時至+13小時。16比特含有4個4位BCD碼,順序為小時的十位,小時的個位,分的十位,分的個位。 時間變化? time_of_change 40位字段,指明時間改變時當前的日期(MJD)與時間(UTC),見附錄C。該字段分為兩部分,前16位給出了LSB格式的日期(MJD),后24位給出了UTC時間(6個4位BCD碼)。 下一時間偏移? next_time_offset 16位字段,指出由country_code和country_region_id確定的區域,當UTC時間變化時的下一個時間偏移,范圍為-12小時至+13小時。此16比特域為4個4位BCD碼,依次為時的十位,時的個位,分的十位,分的個位。
小結 SI
1) SDT(業務描述表):描述了包含在特定TS流中的全部業務的相關信息。 業務描述表包含了描述系統中業務的數據,例如業務名稱、業務提供者等。 2) EIT(事件信息表):描述了包含在特定業務中的所有事件的相關信息。 事件信息表包含了與事件或節目相關的數據,例如事件名稱、始時間、持續時間等。 不同的描述符用于不同類型的事件信息的傳輸,例如不同的業務類型。 3) TDT(時間和日期表):時間和日期表給出了與當前的時間和日期相關的信息。 由于這些信息頻繁更新,所以需要使用一個單獨的表。 4) BAT (業務群關聯表) 給出業務群的名稱及其業務列表等信息 5) RST(運行狀態表) 6) TOT(時間偏移表) 給出了當前時間日期與本地時間偏移的信息 7) ST (填充表) 8) SIT(選擇信息表) 9) DIT (間斷信息表)
參考資料
| 《數字電視業務支撐系統》 | 廖洪濤、徐征著 | 電子工業出版社 |
| DVB和MPEG-II中的表格 | 網絡資料 | —— |
| 《中文SI版本1.0》 | 行業標準 | —— |
預備知識1:PSI/SI關鍵字
- HINT:上表中,綠色底紋的為PSI信息,藍色底紋的為SI信息。但是,雖然NIT是PSI信息,但NIT標準是由SI規定的。
-
- 生成EPG的數據來源于DVB碼流中的業務信息(SI)和節目引導信息(PSI)
- 視頻、音頻、圖片、文字等處理后成為數據,以MPEG-2標準打包成為固定長度(188字節)的傳送包,并將這些包復用形成傳輸流(TS流)
- 通常,一個頻道對應一個TS流,一個頻道的TS流由多個節目及業務組成
不論是視頻、音頻、文字、圖片還是業務信息(包括PSI/SI)都將被劃分為最基本的ES,并將它們通過PES的形式組裝起來,經過復用形成TS流 對TS流的解析:首先獲取到TS流中的包Packet,根據其PID過濾出需要的包,根據其section的結構還原成section,再由上層協議來處理。 預備知識4:業務與事件 PRE-LEARNING4 關于業務(Service)與事件(Event)。 這里將會大量出現這兩個詞。那么什么是“業務”,什么是“事件”呢?一般來說,接下來所說的“業務”就是指“頻道”,“事件”就是“節目”。這里需要明確“節目”的概念,舉個例子:CCTV1是一個頻道,也就是我們所說的“業務(Service)”;《新聞聯播》是一個節目,也就是我們所說的“事件”。分清楚了這兩個概念,我們才能區分下面的很多SI信息。
"PSI是對單一TS流的描述,是TS流中的引導信息" PSI信息由節目關聯表PAT、條件接收表CAT、節目映射表PMT和網絡信息表NIT組成。這些表會被插入到TS流中。PSI信息是對單一TS流的描述,它是TS流的引導信息;PSI信息指定了如何從一個攜帶多個節目的傳輸流中找到指定的節目(見Q1)。 下面給出的是節目引導信息(或稱節目特定信息,PSI)的四個表結構。 雖然這四個結構可以視為簡單的表,但事實上,它們被進一步劃分為各個段,并插入到TS包中 PAT解析 PARSINGOF?PAT "PAT是機頂盒接收的入口點,是它獲取數據的開始" 節目關聯表PAT的意義在于,它描述了當前TS流中包含了哪些PID;只有根據獲得的PID,用戶才可以以此作為憑據找出其他表(如PMT表)及其信息。所以PAT是機頂盒接收的入口點,是它獲取數據的開始;要保證一個TS流能被正常接收,則至少要有一個完整有效的PAT。 下面給出了PID字段的取值要求:
| 值 | 描述 |
| 0x0000 | PAT |
| 0x0001 | CAT |
| 0x0002~0x000F | 保留 |
| 0x0010~0x1FFE | 可賦給network_PID、Program_map_PID、elementary_PID或作其他用途 |
| 0x1FFF | 空的分組 |
PAT的表結構分析 首先,對PAT的表結構進行分析。下面給出了PAT表的基本結構: 節目關聯段 Syntax(句法結構)???????? No. ofbits(所占位數)?? Identifier(識別符)? Note(注釋) program_association_section(){ table_id????????????????????????????????????????????8??????????????????????uimsbf?????????????????????????????????????????????????? Section_syntax_indicator?????????????? 1????????????????????????? bslbf?????????????????? 通常設為“1” "0"?????????????????????????????????????????????????????1??????????????????????? bslbf Reserved?????????????????????????????????????????2??????????????????????? bslbf Section_length??????????????????????????????? 12????????????????????? uimsbf???????????????? 見注釋 transport_stream_id??????????????????????? 16?????????????????????? uimsbf??????????? 見注釋 Reserved?????????????????????????????????????????2???????????????????????? bslbf Version_number????????????????????????????? 5???????????????????????? uimsbf???????????? 見注釋 Current_next_indicator?????????????????? 1????????????????????????? bslbf???????????????? 見注釋 Section_number????????????????????????????? 8????????????????????????? uimsbf??????????? 見注釋 last_section_number?????????????????????? 8????????????????????????? uimsbf??????????? 見注釋 for(i=0;i<N;i++){ program_number???????????????????????? 16???????????????????????? uimsbf??????? 見注釋 reserved???????????????????????????????????????? 3????????????????????????? bslbf if(program_number == 0){ network_PID???????????????????????????? 13???????????????????????? uimsbf??????? 見注釋 } else{ program_map_PID???????????????? 13???????????????????????? uimsbf??????? 見注釋 } } CRC_32?????????????????????????????????????????32????????????????? rpchof????????????????? 見注釋 } 這里我們注意關注五個字段: table_id(賦值):PAT的table_id應為0x00 ??????????transport_stream_id(傳輸流標志):用以標識來源于網絡中任何其他復合流的TS流 program_number(節目號):規定program_map_PID可適用的節目。當值為0x0000時,其后的PID參照將是網絡PID。它可以作為一個指示符號,例如用于廣播通道。 network_PID(網絡PID):僅當program_number為0x00時使用 program_map_PID(節目映射PID):據此找出相應的PMT表
PAT的實例分析 借助碼流分析儀,我們可以很清楚地以實例的方式更加清晰地了解PAT的結構。下面給出的就是一個TS流的PAT分析情況: 根據上表可以看出,這個TS流里共有6套節目,其映射關系PID分別為0xc9、0xcb、0xce、0xcc、0xcd和0xca。(注:0xc9=201) 下面給出的是PMT的簡單解析: 兩相比較,可以很清楚地知道,PAT是如何鎖定各個PMT的(每個節目都有一個自己的PMT)。 Q1:如何找到一個特定的節目? 1.已知節目名稱(或id等信息) P248 首先要從節目關聯表PAT中獲取這個節目的節目映射表PMT的PID值,再從TS流中找出與此PID值相對應的節目映射表PMT;再從PMT中獲取構成這個節目的基本碼流的PID值,從而根據該PID過濾出相應的視頻、音頻和數據等基本碼流。最后解碼恢復為原始信號。
PMT解析 "PMT是連接節目號與節目元素的橋梁" 節目映射表PMT的意義在于,它給出了節目號與組成這個節目元素之間的映射;也就是說,PMT是連接節目號與節目元素的橋梁。我們知道,一個電視節目至少包含了視頻和音頻數據,而每一個節目的視音頻數據都是以包的形式在TS流中傳輸的;所以說,一個TS流包含了多個節目的視頻和音頻數據包。要想過濾出一個TS流中其中一個節目的視頻和音頻,則需要知道這個節目中視頻和音頻的標識號PID。PMT表的作用就在于,它提供了每個節目視頻、音頻(或其他)數據包的PID。
PMT的表結構分析 先給出PMT表的段結構: Syntax?(句法結構)???????? No. of bits(所占位數)?? Identifier(識別符)? Note(注釋) program_map_section(){ table_id??????????????????????????????????????????? ???8?????????????????????? uimsbf?????????????????????????????????????????????????? Section_syntax_indicator???????????? ????1????????????????????????? bslbf?????????????????? 通常設為“1” "0"????????????????????????????????????????????????????????1??????????????????????? bslbf Reserved?????????????????????????????????????? ???????2??????????????????????? bslbf Section_length?????????????????????????????? ????12????????????????????? uimsbf???????????????? 見注釋 program_number????????????????????????? ????16?????????????????????? uimsbf???????????? Reserved????????????????????????????????????????? ????2???????????????????????? bslbf Version_number???????????????????????????? ???5???????????????????????? uimsbf???????????? 見注釋 Current_next_indicator?????????????????? ?1????????????????????????? bslbf???????????????? 見注釋 Section_number???????????????????????????? ???8????????????????????????? uimsbf??????????? 見注釋 last_section_number??????????????????? ????8????????????????????????? uimsbf??????????? 見注釋 reserved??????????????????????????????????????????? ??3????????????????????????? bslbf PCR_PID???????????????????????????????????????? ????13?????????????????????????uimsbf?????????? 見注釋 reserved???????????????????????????????????????? ?????4????????????????????????? bslbf program_info_length???????????????????? ??12??????????????????????? uimsbf??????????? 頭兩位為"00" for(i=0;i<N;i++){ descriptor() } for(i=0;i<N1;i++){ stream_type????????????????????????????????8??????????????????????????uimsbf??????? 見注釋 reserved?????????????????????????????????????? 3?????????????????????????? bslbf elementary_PID?????????????????????????13????????????????????????uimsbf??????? 見注釋 reserved?????????????????????????????????????? 4?????????????????????????? bslbf ES_info_length??????????????????????????12????????????????????????uimsbf???????????? 頭兩位為"00" for(j=0;j<N2;j++){ descriptor(); } } CRC_32?????????????????????????????????????????32????????????????? rpchof????????????????? 見注釋 } 這里著重介紹兩個字段: elementary_PID:標識了該節目(program_number)攜帶的基本流的識別號PID stream_type:流類型,指出了PID為elementary_PID的基本流的類型 附:流類型取值說明
| 取值 | 描述 |
| 0x00 | 國際標準保留 |
| 0x01 | 視頻 |
| 0x02 | 視頻或受限參數視頻流 |
| 0x03 | 音頻 |
| 0x04 | 音頻 |
| 0x05 | private_sections |
| 0x06 | 包含專用數據的PES分組 |
| 0x07 | ISO/IEC 13533 MHEG |
| 0x08 | ? |
| 0x09 | ITU-T Rec.H.222.1 |
| 0x0A~0x0D | GB/T類型 |
| 0x0E | GB/T輔助 |
| 0x0F~0x7F | GB/T保留 |
| 0x80~0xFF | 用戶專用 |
首先,注意到這張PMT表的progam_number=0xc9,就是我們在上面解析PAT表得到的。 從上面可以知道,節目號為0xc9(即201)的節目有兩個單元流:
| 流名稱 | 標識號 | 類型 | 說明 |
| MPEG2視頻 | ES PID=0x21 | stream_type=0x02 | ES PID即為elementary_PID |
| MPEG1音頻 | ES PID=0x28 | stream_type=0x03 | ES PID即為elementary_PID |
CAT解析 PARSINGOF?CAT "CAT描述了節目的加密方式" 條件接收表CAT描述了節目的加密方式,它包含了節目的EMM注1識別PID。它給出了一個或多個CA系統、EMM流以及與CA相關的特定參數之間的關系。 注1:EMM(Entitlement?Management Message),即授權管理信息。描述了用戶可看的節目或時間段、用戶的付費等。 CA描述符既用于規定像EMM這樣的系統范圍條件接收管理信息,也用于規定像ECM這樣的基本流特定信息。
- 如果一個基本流(Elementary Stream)是加擾的,那么包含該基本流的節目信息PMT中需要一個CA描述符
- 如果一個TS流中有任何一個系統范圍的條件接收管理信息,則條件接收表中應有CA描述符。
CAT的表結構分析 條件存取段 Syntax(句法結構)???????? No. ofbits(所占位數)?? Identifier(識別符)? Note(注釋) conditional_access_section(){ table_id????????????????????????????????????????????8??????????????????????uimsbf?????????????????????????????????????????????????? Section_syntax_indicator?????????????? 1????????????????????????? bslbf?????????????????? 通常設為“1” "0"?????????????????????????????????????????????????????1??????????????????????? bslbf Reserved?????????????????????????????????????????2??????????????????????? bslbf Section_length??????????????????????????????? 12????????????????????? uimsbf???????????????? 見注釋 reserved??????????????????????????????????????????18?????????????????????? bslbf Version_number????????????????????????????? 5???????????????????????? uimsbf???????????? 見注釋 Current_next_indicator?????????????????? 1????????????????????????? bslbf???????????????? 見注釋 Section_number????????????????????????????? 8????????????????????????? uimsbf??????????? 見注釋 last_section_number?????????????????????? 8????????????????????????? uimsbf??????????? 見注釋 for(i=0;i<N;i++){ descriptor() } CRC_32?????????????????????????????????????????32????????????????? rpchof????????????????? 見注釋 } 條件存取段主要作用是指示本TS流中存在加擾節目,并且在描述符循環中必須插入CA描述符來作進一步指引。下面給出的是條件接收的描述符 條件接收描述符 條件接收描述符 Syntax(句法結構)??? No. of bits(所占位數)Identifier(識別符)? CA_identifier_descriptor(){ descriptor_tag???????????????????????? 8?????????? ???????????????????????????????uimsbf??????????????????????? descriptor_length??????????????? ?????8?????????????????????????????????????????uimsbf???????? CA_system_ID???????????????????? ?????16????????? ?????????????????????????????uimsbf reserved????????????????????????????? ???????3?????????? ??????????????????????????????bslbf CA_PID??????????????????????????????????? 13??????? ???????????????????????????????uimsbf??????????????? for(i=0;i<N;i++){ private_data_byte??????????????? ????8 }} CA_system_ID(CA系統ID):指出用于相關ECM及(或)EMM流的CA系統類型。 CA_PID(CA PID):指出包含用于相關CA_system_ID所規定的CA系統的ECM或EMM信息傳輸流分組的PID(即在TS流中過濾出相應PID的分組)。 下面給出的TS流中并沒有CAT: 但在PMT表中有CA描述符:
PSI小結 上圖給出了在一個TS流中PSI各表之間的聯系。首先從PAT表出發,獲取當前有哪些節目號(program_map_PID),再根據這些節目號找出program_number相同的PMT;獲取到PMT后,即可根據elementary_PID和stream_type來確定要過濾哪些含有基本流的TS包,以及這些包里面是什么類型的數據。這樣,機頂盒就可以過濾出相應的節目(視頻和音頻數據)來收看了。
2.8Tuner數據處理流程
大概流程: 1.cable?ts 信號(signel)--》tuner--》demux-》video,audio解碼編碼-》輸出顯示 2.本地ts file--》demux-》video,audio解碼編碼-》輸出顯示 如果有解擾邏輯,則需要在demux后對video,audio包解擾處理。 3.對cable?ts?的錄制即: 信號(signel)--》tuner--》demux-》磁盤--》demux--》video,audio解碼編碼-》輸出顯示 即多了一個步驟,需要將解擾的流保存到磁盤中,如果需要播放磁盤中的文件,則將磁盤中的文件數據傳給demux,也就是一個逆向過程。 當然demux的處理牽涉到section,filter另做討論。
以下將分節討論: 1.TUNER?調諧器 一般有有線cable,衛星satellite,地面territory 3種type tuner工作需要知道頻率freq,符號率symb,QAM大小,tuner獲取到的信號signel有信號強度,誤碼率,質量,等級等,主要就是鎖住某個需要的頻點去獲取信息(模擬信號-》數字信號)。一般問題就是鎖不住頻點,拿不到signel。 目前一般是STB 的tuner某一時刻只能處理一個頻點信息,也許以后會啟動同時處理多個頻點或多個tuner的雙xx模式或多xx模式。終端屏幕的越來越大,完全是可以在一個屏上顯示多個流的。
2.Demux 終端主要是解復用,也就是解析自己想要的數據,并分類的處理。這塊需要專業的MPEG/DVB相關協議知識,主要是PSI/SI。 一般牽涉到的概念有filter,channel,section,pid等,一般來說一個Channel對應一個PID,對應多個Filter。 首現要知道頻點,需要tuner到某個頻點上去鎖頻,將模擬數據轉換為數字信號。 然后數字信號會送到Demux解復用,這一坨數據很多,你需要通過一定的規則去獲取你想要的數據。 filter過濾用,就是tuner拿到的那一坨數據有很多,但只需要將你想要的數據過濾出來。怎么過濾?一般我們要知道我們想要的數據在哪個PID,對應的段數據可能還需要再細分類,那你還需要將section前幾個字節(byte)傳下去,讓demux只過濾出PID下同時匹配section前幾個字節數據對應的包數據。比如。。。xx xx xx?01(PID)xx 02?03?04?05?06?07 xx 。。。當前頻點拿到的數據很多,但我只需要PID為0x1, section前3個字節為02.03.04的表的數據,首先filter會過濾出pid為0x01的所有的數據,然后在這些數據中過濾出前3個字節為02?03?04 的那些數據。再細化分類的話拿到這些數據你就要按SI/PSI協議或你自己私有的協議來了。 channe通道l我們可以認為是一個容器,或再簡單點就認為它是一塊內存。這塊容器就是用來裝我們filter出來的數據的,所以一般channel是掛在filter上的。一個filter可以有多個channels,或一個channel有多個filter,具體要看平臺實現需要。 當然由于硬件特性,signel環境,參數情況,可能獲取不到我們想要的數據,不可能一直讓filter,channel一直去那那個不存在或有問題的數據的,就需要有一個超時機制:在這個時間段無法拿到數據,通知上層,demux拿不到你想要的數據,你改干嘛干嘛去吧。同時demux釋放filter,channel等相關資源。 demux處理后,filter過濾的數據通過回調或其他方式給上層,上層拿到想要的數據再實現具體的應用。
3.video,audio 編解碼 一般來說解碼后就可以輸出output了。 目前常用的數據電視用到的制式有PAL,NTSC等 視頻輸出一般有CVBS,ypbpr,YUV,hdmi(高清用的多)等 視頻輸出一般用到視頻層,靜態層(still,IFRAME一般用到) 輸出節目長度寬度比國內一般有4/3,16/9 常用支持的視頻有:MPEG1,2,4;H264等 常用支持的音頻有:MPEG1,2,ADTS,AC3,DTS等
一般對音視頻會分配專門的固定的filter,channel。要播放某個節目,必須通過SI/PSI獲取到,freq,vpid,apid,pcrpid等。 播放音視頻就是讓tuner鎖對應freq的頻點,demux去過濾出vpid,apid的數據包。其中通過pcrpid可以獲取一個時間參考系。vpid拿到視頻包,其中有I,P,B幀; apid拿到音頻包,其中有I,P,B幀。音視頻同步就是通過I,P,B幀的PTS去同步pcrpid獲取的時間參考系。
2.9LCN 邏輯頻道號(DVB) 之 NIT表
LCN存在于NIT表中,描述符TAG=0x83,不過version2.0 好像TAG=0x87,并且語法結構也做了修改。 描述符基本結構如下: logical_channel_desciptor{ descriptor_tag?//8bit , 0x83 descriptor_length// =8bit for(i=0;i<N;i++) { service_id ?//16bit visible_service_flag//1bit reserved ?//5bit logical_channel_number//10bit } }
不同版本的LCN差異體現在logical_channel_number比特位的不同,NORDIG-Unified_ver_2.1版本中LCD V1的描述子結構為: logical_channel_desciptor{ descriptor_tag?//8bit , 0x83 descriptor_length// =8bit for(i=0;i<N;i++) { service_id ?//16bit visible_service_flag//1bit reserved ?//1bit logical_channel_number//14bit } } 當然,還有其他描述,此處不一一列舉。以上兩種TAG是一樣的,都是0x83 下面看一張,帶LCN的實例Svt_1.ts
這是一張NIT表,LCN就在transport_streams里,展開如下
找到transport_descriptors里的descriptor_tag==0x83 這個描述的就是LCN 把descriptor_data 數據放大:leng為32字節如下
03 f2 c0 0113 c4 c0 02 03 66 c0 6211 a8 40 00 11 9e 40 00 11 c6 40 00 14 32 c0 63 03 70 c0 61 根據描述符的基本結構如下:一個LCN應該占4字節32bit logical_channel_desciptor{ descriptor_tag?//8bit , 0x83 descriptor_length// =8bit for(i=0;i<N;i++) { service_id ?//16bit visible_service_flag//1bit reserved ?//5bit logical_channel_number//10bit } } 那么就根據結構來分析一下吧:這里的N==8 在分析之前,看看它的PAT表吧
根據pat可以看出總共6個節目
1. 03 f2 c0 01 service_id ?//16bit 是 03 f2 這個不正好是上面的program_number=0x03f2嗎 visible_service_flag//1bit 1 reserved ?//5bit logical_channel_number//10bit LCN = 0x001 2.13 c4 c0 02 service_id ?//16bit 是 13 c4 這個不正好是上面的program_number=0x13c4嗎 visible_service_flag//1bit 1 reserved ?//5bit logical_channel_number//10bit LCN = 0x002 3.03 66 c0 62 service_id ?//16bit 是 03 66 這個不正好是上面的program_number=0x0366嗎 visible_service_flag//1bit 1 reserved ?//5bit logical_channel_number//10bit LCN = 0x062 4. 11 a8 40 00 service_id ?//16bit 是 11 a8 這個好像沒有0x11a8這個臺,所以LCN也沒有,可能也正常吧 visible_service_flag//1bit 0 難道visible_service_flag 可以控制是否有臺? reserved ?//5bit logical_channel_number//10bit LCN = 0x0
5. 11 9e 40 00 service_id ?//16bit 是 11 9e 這個好像沒有0x11 9e這個臺,所以LCN也沒有,可能也正常吧 visible_service_flag//1bit 0 reserved ?//5bit logical_channel_number//10bit LCN = 0x0
6. 11 c6 40 00 service_id ?//16bit 是 11 c6 這個不正好是上面的program_number=0x11 c6嗎 visible_service_flag//1bit 0 但是這個臺RTK沒有搜到 reserved ?//5bit logical_channel_number//10bit LCN = 0x0 7. 14 32 c0 63 service_id ?//16bit 是 14 32 這個不正好是上面的program_number=0x14 32嗎 visible_service_flag//1bit 1 reserved ?//5bit logical_channel_number//10bit LCN = 0x63 8. 03 70 c0 61 service_id ?//16bit 是 03 70 這個不正好是上面的program_number=0x03 70嗎 visible_service_flag//1bit 1 reserved ?//5bit logical_channel_number//10bit LCN = 0x61
下面咱們再解釋為什么在NIT表中transport_streams有兩個transport_stream_id:0x03fd和0x03fe 那么就為難了,選哪一個呢,當然有辦法,不賣關子了,在pat表里:
來再看看pat表,看到了嗎?藍色的區域 明白了吧。
?
轉載于:https://www.cnblogs.com/jiangzhaowei/p/7417879.html
總結
以上是生活随笔為你收集整理的DTV_SI 汇总 兼谈LCN的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 各国语言代号
- 下一篇: 2014年放假安排:除夕非法定假日