PSI SI表的深度摘要 2

2021-07-24 02:18:57 字數 3473 閱讀 4918

psi標準裡面沒說:分段也是具有結構性的,各種psi表的分段結構基本一致,參見psi_section_st結構體。nit和bat表基本可以用乙個函式實現的。本文用c#實現,需注意的就是arraylist的結構體新增的元素需匹配,需要在除錯的時候看見其具體元素型別,一旦不匹配直接報錯退出,比較傷腦筋的。

舉例乙個很複雜的sdt表(一般情況是僅含當前流):

1.該錶由乙個當前流table_id=0x42,n個其他流組成table_id=0x46;則首先就是1個當前sdt段和n個其他sdt段構成;即n+1個段;各個sdt段的table_id和transport_stream_id是相同的(sdt多要求乙個original_network_id相同);

2.如果某個sdt段由6個188包裝填(最大1021位元組),比如

當前流的sdt段仍不能裝下,那需要將該當前sdt段由

分段來填充實現:讓section_number由0~m編號(m<=0xff)即最大256個分段構成該段,即256*6個包=1k*256=256k位元組的內容;同時,總的分段數量=n + m +1個,需顯示這麼多個分段;

談論psi段:

1.主要的psi表結構:

(1).pat,pmt,sdt,cat,nit,bat,eit分段都是有結構的,需總結出來。除了eit分段section_length最大4093(24個188b包)外,其餘最大1021b(6個188b包);

(2).段和分段的概念:

我的理解:

表由多個子表組成;子表至少為相同的table_id的分段構成,一般為當前傳輸流和其他傳輸流的段構成(它們的table_id就不同的了);當1021b還沒裝完該段時,需用分段號為0~255的section_number來裝填該段,一般就能完成的了。

表和段之間:表由多個段描述來實現其整個內容,子表由1~256個分段來實現其內容;

以下是各種概念定義:

表  table

由具有相同的表識別符號(table_id)的一系列子表構成。

table_id_extension:表識別符號擴充套件,我寫的程式裡面全部用x_id代替;

子表  sub_table

子表是指具有相同表識別符號(table_id)的段的集合,並且

對網路資訊表(nit): 具有相同的table_id_extension(network_id)和version_number;

對業務群關聯表(bat): 具有相同的table_id_extension(bouquet_id)和version_number;

對業務描述表(sdt): 具有相同的table_id_extension(transport_stream_id),相同的original_network_id 和version_number;

對事件資訊表(eit):具有相同的table_id_extension (service_id),相同的transport_stream_id 、original_network_id和version_number。

當段語法指示(section_syntax_indicator)欄位置「1」時,表識別符號擴充套件 (table_id_extension)字段等同於段的第四和第五位元組。

(3).分段的結構:

各種psi表的結構大致相同,我們可以看成以下結構體:table_id,段長,段號,最後乙個分段號,段內容,校驗字段。見附後的段結構體;

表頭部分:section_data段內容前的都是表頭部分,均為8位元組;只需注意reserved_future_use:pat,pmt,cat=0,其餘為1(一般保留位均置1);

(4).

段長:這裡是必須注意的, section_length指該字段的下乙個位元組開始的本段的位元組長度(包括crc32)。而我們使用程式處理整個段的時候用到的是trueseclen(整個段的長度),比如將整個段內容裝填到6個188包中,需從段頭開始裝填的,每裝滿1個包trueseclen減去對應長度,為trueseclen=0則段內容打包完畢;故標準定義的這個段長真的是比較混淆的概念。

//真正的段長 = seclen+3(1位元組table_id + 2位元組段長) 【即該字段後的所有位元組數量】

trueseclen= section_length + 3;

(5).程式的實現:

psi表由於其含有眾多的描述符,比較複雜,所以,乙個良好的結構和高效通用的函式來實現是比較重要的。

段一般可以看做2層迴圈,loop1和loop2(各psi表在該迴圈時改個名稱就是),參照psi表結構:

只有一層迴圈的表:

pat(loop1:programs loop):無描述符

cat(loop1:descriptors loop):loop1下只能新增ca_descriptor

sdt(loop1:service_descriptors loop):loop1下可以新增descriptors loop

eit(loop1:event loop):loop1下可以新增descriptors loop

兩層迴圈的表(迴圈下可新增描述符):

pmt(loop1:program_info_descriptors loop; loop2:stream loop),實際loop2下還新增了loop3(stream_info_descriptors loop)

bat和nit結構完全可以看成一致的:

nit(loop1:network_descriptors loop; loop2:transport_stream loop),實際loop2下還新增了loop3(transport_descriptors loop)

bat(loop1:bouquet_descriptors loop; loop2:transport_stream loop),實際loop2下還新增了loop3(transport_descriptors loop)

目前,我是在表上儲存資料的(node.tag來儲存資料),拿nit表舉例:

思路:psi表由treeview顯示,根節點為psi表,nit表節點為l0層,以下l1,l2以此類推;這樣,可能占用內容大一些,但非常直觀地可以看到資料是否正確的,訪問也非常方便,方便匯入匯出psi為ts流。用batnodes_menuadd_l0的方式能明顯看出現在正在操作bat的哪一層(bat根節點為l0層,這是l0層右鍵選單的操作)

l0層儲存的【表結構體】,packeted188_set_al為188包的集合,該集合就是需發給fpga的psi表的資訊,fpga改變包的計數即可;很直觀地看到需傳送的包的內容;section_set_al存的是分段的內容;可能2個段10個包的情況,也可能出現2個段2個包的情況。

l1層:顯示段結構體,段的內容在此儲存;

<1>.表結構   

public struct psi_table_st  //每乙個表的根節點的tag裝此結構體

<2>.段結構

public struct psi_section_st

<3>.各種迴圈描述結構,即描述子

public struct descriptor_st     //commdes_st 通用描述符

public int tag;

public byte data;

}

PSI SI表的深度摘要 3

以前理解psi的包和段都還不夠深刻,以至於寫的復用部分,表生成部分邏輯性,可用性不高,雖然使用沒啥問題的。在寫復用模組的時候,對psi理解度不夠的話,再去改復用模組,挺麻煩的,很費神。常用的psi si表 psi表 4類 pat,pmt,cat,nit nit當前網路 和 nit其他網路 si表 b...

表的建立與管理(章節摘要)

1,資料庫中常用的基本型別number,varchar2,date,clob。2,表的建立使用create table語法完成,建立表時需要為表中定義若干個列,每個列上可以通過default設定列的預設值。3,表的刪除操作使用drop table語法來完成,但是從oracle 10g起,如果要徹底刪...

MIT的《深度學習》精讀(2)

看完了 皮格馬利翁 和 伽拉泰亞 galatea 的故事,已經很讓人感動,接著下來,又來看看 代達羅斯 和 塔羅斯 talos 的傳奇故事 藝術家代達羅斯是位建築師和雕刻家。人們說他的雕像是具有靈魂的創造物,從前的大師創作石像時,都讓石像閉上眼睛,雙手連著身體,無力地垂落下來。而他第乙個讓雕刻的人像...