前言
本章主要對數字廣播DVB作一個系統的概況的描述,以及一些spc的相關的內容,雖然流程分析的很少,可是作爲後續 章節資料的源泉,也是不可或缺的。
本文的主要目的是幫助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/一、3/一、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級別加擾
- 加擾算法
- 事件加擾控制
- 可置換安全接口
4 數據廣播
- 數據下載協議
- 數據預告
- 數據發現
- IP協議封裝
- 對DSM-CC標準的背離
完。
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流的優勢:
一、動態帶寬分配:因爲TS的傳輸包長度是固定的,所以可過PID能夠將規定的信道總頻帶在視頻、音頻和數據信息見進行實時的、靈活的分配。利用這一特性,可在廣播付費節目前實時地將解密鑰匙插入到TS流中送給廣大用戶。
二、可分級性:容許一個複用的傳輸碼流與其餘視音頻基本碼流進行二次複用,生產佔用頻帶給寬的更高一級的TS流。
三、可擴展性
四、抗干擾性
五、接收機成本低廉
TS流的造成過程:
一、 壓縮【顯示單元】產生【進入單元】,連續的【進入單元】組成一個基本碼流。ES
二、 對ES(基本碼流)進行打包造成PES。 就是帶包頭信息的ES
三、 在PES包中加入定時信息(PTS/DTS)。
四、 將PES包內容分配到一系列固定長度的傳輸包中。
五、 在傳輸包中加入定時信息(PCR)。
六、 在傳輸包中加入節目專用信息(PSI) 。
七、 連續輸出傳輸包造成具備恆定比特率的MPEG-TS流。
二、TS流傳輸包(簡稱TS包
)結構分析
MPEG-2中規定TS傳輸包的長度爲188 字節。但通訊媒介會爲包添加錯誤校驗字節,從而有了不一樣於188字節的包長。例如:
DVB 規定中,使用204字節做爲包長:
一、經過調製器時,在每一個傳輸包後增長了16 字節的裏德所羅門前向糾錯碼,於是造成了204字節的數據包。
調製 後總存在204 字節的數據包。
二、調製以前存複用器插入RS碼或虛構
的RS碼。
ATSC規定中,使用208字節做爲包長:添加20 字節的 RS(Reed-Solomon)前向糾錯碼。與DVB不一樣,ATSC規定RS碼只能出如今調製的TS流中。
全部的TS包都分爲包頭和淨荷部分。TS包中能夠填入不少東西(填入的東西都是填入到淨荷部分),有:視頻、音頻、數據(包括PSI、SI以及其它任何形式的數據)。
2.一、TS包包頭
TS包的包頭提供關於傳輸方面的信息:同步、有無差錯、有無加擾、PCR(節目參考時鐘)等標誌。TS包的包頭長度不固定,前32比特(4個字節)固定,後面可能跟有自適應字段(適配域)。32個比特(4個字節)是最小包頭。包頭的結構固定以下:
所以有的包頭可能不止32bit,那麼又是如何區分的呢?原來是這個適配區搗的鬼!!
同步字節 |
傳輸錯誤指示 |
開始指示 |
傳輸優先級 |
PID |
加擾控制 |
適配域控制 |
連續性計數器 |
適配域 |
8bit |
1 |
1 |
1 |
13 |
2 |
2 |
4 |
|
注意表裏的數據是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.二、
TS包
淨荷部分
TS包中淨荷所傳輸的信息包括兩種類型:
一、視頻、音頻的PES包以及輔助數據;
二、節目專用信息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信息的描述方法有如下幾種:
• 一、表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)
•二、節Section: 將表格的內容映射到TS流中;
專用段 Private_ section
• 三、描述符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 |
|
N loop中爲:
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
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比B二、B3在先,但顯示時P4必定要比B二、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。
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是TS流中惟一識別標誌,Packet Data是什麼內容就是由PID決定的。若是一個TS流中的一個Packet的Packet Header中的PID是0x0000,那麼這個Packet的Packet Data就是DVB的PAT表而非其餘類型數據(如Video、Audio或其餘業務信息)。下表給出了一些表的PID值,這些值是固定的,不容許用於更改。
表 |
PID 值 |
PAT |
0x0000 |
CAT |
0x0001 |
TSDT |
0x0002 |
EIT,ST |
0x0012 |
RST,ST |
0x0013 |
TDT,TOT,ST |
0x0014 |
註釋: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表的定義給出:
- typedef struct TS_PAT_Program
- {
- unsigned program_number : 16; //節目號
- unsigned program_map_PID : 13; // 節目映射表的PID,節目號大於0時對應的PID,每一個節目對應
- 一個
- }TS_PAT_Program
-
3. PAT表的結構(代碼+分析)
再將PAT表的結構體給出:
- 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表的解析代碼:
- 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表
根據包頭數據格式,咱們能夠知曉整個數據包的屬性,列表以下:
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」 |
包遞增計數器 |
如上表所示,咱們能夠知道,首先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表信息的僞代碼(代碼)
- 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表的定義(代碼)
- <span style="font-size:14px;">//PMT 表定義</span>
- <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表的結構體定義(代碼)
- //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表的解析(代碼)
- //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;
- }
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」 |
包遞增計數器 |
由於payload_unit_start_indicator=‘1’,在解析數據包的時候須要去除Packet Data的第一個字節。下面是對Packet Data的詳細解析:
(三) 解複用模型(代碼)
- 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) 該節目的名稱
三、 從PAT開始,走向更遠
在本章的學習中,咱們發現了一個特色:全部的TS流的解析都是從尋找PAT表開始的,只有找到了PAT表,咱們才能繼續下一步的解析。所以,在進行了TS流、PAT表和PMT表的初步知識儲備後,在接下來的學習中將從PAT表開始,學習更多的PSI/SI相關的表,將走得更遠。
"
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是描述一個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編碼是一致的:
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中最重要的描述符,也是運營商中必須的描述符。其中的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 (間斷信息表)
參考資料
《數字電視業務支撐系統》 |
廖洪濤、徐徵著 |
電子工業出版社 |
DVB和MPEG-II中的表格 |
網絡資料 |
—— |
《中文SI版本1.0》 |
行業標準 |
—— |
預備知識
1
:
PSI/SI
關鍵字
- HINT:上表中,綠色底紋的爲PSI信息,藍色底紋的爲SI信息。可是,雖然NIT是PSI信息,但NIT標準是由SI規定的。
-
預備知識
2
:常識
PRE-LEARNING2
- 生成EPG的數據來源於DVB碼流中的業務信息(SI)和節目引導信息(PSI)
- 視頻、音頻、圖片、文字等處理後成爲數據,以MPEG-2標準打包成爲固定長度(188字節)的傳送包,並將這些包複用造成傳輸流(TS流)
- 一般,一個頻道對應一個TS流,一個頻道的TS流由多個節目及業務組成
預備知識
3
:
ES
、
PES
、
PS
和
TS
PRE-LEARNING3
ES流(ElementaryStream):基本碼流,不分段的音頻、視頻或其餘信息的連續碼流。
PES流:把基本流ES分割成段,並加上相應頭文件打包成形的打包基本碼流。
PS流(ProgramStream):節目流,將具備共同時間基準的一個或多個PES組合(複合)而成的單一數據流(用於播放或編輯系統,如m2p)。
TS流(TransportStream):傳輸流,將具備共同時間基準
或獨立時間基準的一個或多個PES組合(複合)而成的單一數據流(用於數據傳輸)。
不管是視頻、音頻、文字、圖片仍是業務信息(包括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
"
P
AT
是機頂盒接收的入口點,是它獲取數據的開始
"
節目關聯表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分別爲0xc九、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的實例分析
下面給出了碼流分析儀分析一段TS流的PMT表:
首先,注意到這張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 |
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這樣的基本流特定信息。
- 若是一個基本流(Elementary Stream)是加擾的,那麼包含該基本流的節目信息PMT中須要一個CA描述符
- 若是一個TS流中有任何一個系統範圍的條件接收管理信息,則條件接收表中應有CA描述符。
下圖給出的PMT表便是基本流加擾的狀況,所以PMT表須要有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包,以及這些包裏面是什麼類型的數據。這樣,機頂盒就能夠過濾出相應的節目(視頻和音頻數據)來收看了。
大概流程:
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獲取的時間參考系。
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表,看到了嗎?藍色的區域 明白了吧。