ts包、表、子表、section的關系
我們經常接觸到創建 DEMUX,註冊 Filter 過濾數據, 通過回調過濾出 section 數據,然後我們對 section 數據做具體的解析或者其他操作。 我們這裏說的 section 就是段的概念,一個 section 可能包含一個或者多個TS 包,我們可以這樣理解,TS 是對數據內容發封裝,屬於傳輸層的格式,規定了傳輸數據的格式,它以 188 字節為單位組成一個 TS 包,在這一層,它不管封裝的內容是什麽,就是在傳輸的內容前加 上 4 個字節的頭信息組成包。而我們 filter 過濾出來的 section 數據是去掉了 TS 包頭的的有 效數據,可能是多個 TS 包組成起來的有效數據,我們解復用 DEMUX 中也包括對接收到的 TS 包數據,根據不同的 PID 來過濾出相應的 TS 包,然後去掉包頭,把相關的多個 TS 包有 效數據組織起來形成 section 數據返回給應用開發者調用。 下圖是我自己做的關於表,段,TS 包的結構關系:
一個表由一個或多個段構成 (具有相同的 table_id 和 table_id_extension, 不同 section_number 來區分,並且由 last_section_number 確定該表的最大 section 的數目) ;每個段由一個或多個 TS 數 據 包 的 數 據 組 成 , 比 如 一 個 新 的 section 數 據 , 那 麽 第 一 個 TS 包 的 payload_unit_start_indicator 一般為 1,後續該 section 的 TS 包的 payload_unit_start_indicator 為 0,直到另外的 section 數據到來時候 TS 包的 payload_unit_start_indicator 才變為 1(同時 也說明該 section 數據結束, section 數據的開始) 而 continuity_counter 隨著具有相同 PID 新 , 的 TS 包的增加而增加,這樣我們就可以方便我們組織各個 TS 包來獲取 section 數據。同時 我們的 section 數據就是去掉各個 TS 包頭後組織起來的有效載荷數據, 我們可以對比碼流分 析儀來分析。
一般一個 section 的長度是 1024,而 TS 包是 188,所以一般都是一個 section 是由多個 TS 包組成,當然也有可能一個 section 就是由一個 TS 的有效載荷數據組成(向 PAT 表一般都是這樣)
表是組成 SI 信息的一種數據結構。在 TS 中有很多不同節目的數據包,解碼器如何確定 哪個數據包屬於某個節目?其答案就是在 TS 中的 PSI 和 SI 信息裏, 這些信息精確地指引出 獲得某節目與該節目數據包的 PID 之間的關系。
由 MPEG-2 定義的 TS 裏面,數據包攜帶了兩類信息:一是音、視頻等素材的數據,二是 PSI 表。具有給定 PID 的數據包的有序排列就形成了 TS 流。PSI 表裏的承載的內容主要是 TS(本節目流)的描述參數。由 MPEG-2 定義的 PSI 主要包含有三個表:PAT、PMT、CAT。 每個表都可作為一個或多個 TS 包的凈荷插入 TS 中傳送。
一個 TS 數據包的凈荷為 188 個字節,當一個 PSI/SI 表的字節長度大於 184 字節時,就要 對這個表進行分割,形成段(section)來傳送。分段機制主要是將一個數據表分割成多個數 據段。在 PSI/SI 表到 TS 包的轉換過程中,段起到了中介的作用。由於一個數據包只有 188 字節,而段的長度是可變的,EIT 表的段限長 4096 字節,其余 PSI/SI 表的段限長為 1024 字 節。因此,一個段要分成幾部分插入到 TS 包的凈荷中。
PSI/SI 表的構成是:一個表由一個或多個子表構成,表用 table_id 來標識;不同的子表由 table_id 和 table_id_extension 來區分(具有相同的 table_id 和不同的 table_id_extension) ;一 個子表由一個或多個段構成 (具有相同的 table_id 和 table_id_extension, 不同 section_number 來區分) ;每個段由多個 TS數據包的數據組成,是 TS 數據包的數據,去掉了各個 TS 包的 包頭後的有效數據組成,然後會形成對應的表格式,然後我們可以通過 filter 過濾出來的 section 數據參考表格式對 section 數據來解析。比如 PAT 的 section 表格式如下:
每個段具有一個完整的數據結構,表的重要參數----描述符在段裏傳送。圖 3 所示是 SDT 表 的結構。
子表大於 1024 時,可把子表分割成兩個或更多個段,並通過 section_number 來區分,如圖 3-1 所示。
不同的信息表在 TS 中通過 PID 來區分,具有相同 PID 的不同表由 table_id(table_id 是表 標識) 來區分, 屬於同一個 table_id 的不同子表由 table_id_extension、 版本號(version_number) 進行區分, 屬於同一個子表的不同段由 section_number 區分。 表的擴展標識符有: network_id、 oringinal_network_id、boquet_id、 tansport_stream_id、service_id 等。
對於 NIT 表的子表具有相同的 table_id、network_id 和 version_number。
對於 BAT 表的子表具有相同的 table_id、bouquet_id 和 version_number。
對於 SDT 表的子表具有相同的 table_id、oringinal_network_id、tansport_stream _id 和 version_number。
對於 EIT 表的子表具有相同的 table_id、oringinal_network_id、tansport_stream _id、 service_id 和 version_number。
PAT的定義:
Table_id:為8bit字段,該字段標識節目關聯分段,對於PAT,置為0x00。
Section_syntax_indicator:1bit字段,對於PAT,置為0x01。
Reserved:2bit保留字段,用於將來擴展,置為11。
Section_length:12bit字段,指示當前section的長度,計數值從分段長度下一個字節開始,包括CRC校驗的4個字節,開頭兩位置為00,因此其大小不超過1021。
Transport_stream_id:16bit字段,當前TS流的ID,與網絡中其他TS流相區別,由運營商指定。
Reserved:2bit保留字段,用於將來擴展,置為11。
Version_number:5bit字段,指出PAT表的版本號,一旦PAT表有變化,其版本號增1,當增至31時,恢復至0。
Current_next_indicator:1bit,置為1時,表示傳送的PAT當前有效,置為0表示PAT下一次有效。
Section_number:8bit字段,表示section的數目,從0x00開始。
Last_section_number:8bit字段,指出最後一個section號,即PAT表section的最大數目。
Program_number:16bit字段,指出了節目對於哪一個PMT PID是可用的,當為0x00時,後面的PID對應於NIT。
Reserved:3bit保留字段,用於將來擴展,置為111。
Network_id:13bit字段,NIT PID。
Program_map_PID:13bit字段,對應於program_number所指定的節目的program_map_section的PID,從上面可看出:一個program用4字節來表示(包括16bit的program_number與13bit的PID)。
CRC:用來證實數據正確性的循環冗余校驗碼。
(section_number和 last_section_number的功能是當PAT內容>184字節時,PAT表會分成多個段(sections),解復用程序必須在全部接收完成後再進行PAT的分析)
PMT定義如下:
各字段含義如下:
table_id:8bits的ID,應該是0x02
section_syntax_indicator:1bit的段語法標誌,應該是‘‘1‘‘ ‘‘0‘‘:固定是‘‘0‘‘,如果不是說明數據有錯.
reserved:2bits保留位,應該是‘‘00‘‘
section_length:16bits段長度,從program_number開始,到CRC_32(包含)的字節總數.
program_number:16bits的頻道號碼,表示當前的PMT關聯到的頻道.換句話就是說,當前描述的是program_number頻道的信息.
reserved:2bits保留位,應該是‘‘00‘‘
version_number:版本號碼,如果PMT內容有更新,則version_number會遞增1通知解復用程序需要重新接收節目信息,否則version_number是固定不變的.
current_next_indicator:當前未來標誌符,一般是0
section_number:當前段號碼
last_section_number:最後段號碼,含義和PAT中的對應字段相同,請參考PAT部分.
reserved:3bits保留位,一般是‘‘000‘‘.
PCR_PID:13bits的PCR PID,具體請參考ISO13818-1,解復用程序不使用該參數.
reserved:4bits保留位,一般是‘‘0000‘‘
program_info_length:節目信息長度(之後的是N個描述符結構,一般可以忽略掉,這個字段就代表描述符總的長度,單位是Bytes) 緊接著就是頻道內部包含的節目類型和對應的PID號碼了.
stream_type:8bits流類型,標誌是Video還是Audio還是其他數據.
reserved:3 bits保留位.
elementary_PID:13bits對應的數據PID號碼(如果stream_type是Video,那麽這個PID就是Video PID,如果stream_type標誌是Audio,那麽這個PID就是Audio PID)
reserved:4 bits保留位.
ES_info_length:和program_info_length類似的信息長度(其後是N2個描述符號)
CRC_32:32bits段末尾是本段的CRC校驗值
SDT的定義
DVB系統提出了一個SDT表格,該表格標誌一個節目的名稱,並且能和 PMT中的PID聯系起來,這樣用戶就可以通過直接選擇節目名稱來選擇節目了. SDT, Service description section,服務描述段 SDT可以提供的信息包括: (1) 該節目是否在播放中 (2) 該節目是否被加密 (3) 該節目的名稱
SDT定義如下: 各字段定義如下:
table_id:8bits的ID,可以是0x42,表示描述的是當前流的信息,也可以是0x46,表示是其他流的信息(EPG使用此參數)
section_syntax_indicator:段語法標誌,一般是‘‘1‘‘
reserved_future_used:2bits保留未來使用
reserved:1bit保留位,防止控制字沖突,一般是‘‘0‘‘,也有可能是‘‘1‘‘
section_length:12bits的段長度,單位是Bytes,從transport_stream_id開始,到CRC_32結束(包含)
transport_stream_id:16bits當前描述的流ID
reserved:2bits保留位
version_number:5bits的版本號碼,如果數據更新則此字段遞增1
current_next_indicator:當前未來標誌,一般是‘‘0‘‘,表示當前馬上使用.
original_netword_id:16bits的原始網絡ID號
reserved_future_use:8bits保留未來使用位
接下來是N個節目信息的循環:
service_id:16 bits的服務器ID,實際上就是PMT段中的program_number.
reserved_future_used:6bits保留未來使用位
EIT_schedule_flag:1bit的EIT信息,1表示當前流實現了該節目的EIT傳送
EIT_present_following_flag:1bits的EIT信息,1表示當前流實現了該節目的EIT傳送
running_status:3bits的運行狀態信息:1-還未播放 2-幾分鐘後馬上開始,3-被暫停播出,4-正在播放,其他---保留
free_CA_mode:1bits的加密信息,‘‘1‘‘表示該節目被加密. 緊 接著的是描述符,一般是Service descriptor,分析此描述符可以獲取servive_id指定的節目的節目名稱.具體格式請參考 EN300468中的Service descriptor部分.
ts包、表、子表、section的關系