DVB SI/PSI分析和處理
SI是Specific Information的簡稱,PSI是program Specific Information.該機制允許DVB傳送各種各樣的訊息,比如節目名稱,電視台名稱,各種PID,私人資訊,甚至單獨傳送資料實現資料通訊等.這些功能的實現都歸功於SI/PSI.
在DVB 標準中,定義了一個標準的PID用來實現SI/PSI.這些PID是系統保留的,因此DVB編碼的時候並不會用這些PID做為Video PID或者 Audio PID或者其他PID.在一個簡單的解複用程式中,只需要提供處理PAT,PMT表格的程式即可實現解複用,當然如果需要更友好的介面和實現 更複雜的功能(如CA)則必須處理其他的SI表.在這裡僅僅分析PAT,PMT,SDT表格,其他SI表格的分析,請參考ISO13818-1(MPEG-2系統層標準)和EN300468(DVB SI標準)文檔.
DVB定義的SI保留的PID分別是:
上表格的PID就是DVB保留的PID,分配的其他PID一定不會佔用這些PID.解複用程式需要使用到的表格只有PAT,PMT,SDT,而CA應用還需要使用CAT,EPG應用還需要使用NIT,EIT,TDT,TOT等表格.所以在需要解複用的時候,虛擬碼需要這樣寫:
void Process_Packet(unsigned char*buff)
{
int PID=GETPID(buff);
if(PID==0x0000)
{
Process_PAT(buff+4);
}
else if(PID==......)
{
}
else
{
printf("Unknown PID!");
}
}
所 有的表格都開始於Packet中的184位元組的資料部分,但有的時候一個表格沒有184位元組,這時在Packet中就可能插入一些無效資訊用來填充使整個 Packet依然保持是188位元組.也可能用頭資訊中的payload_unit_start_indicator標誌表格有個位移位置(當 payload_unit_start_indicator=0表示表格式資料直接從Packet區的第四個位元組開始,否則表示有一個位移量位置開始,具體 請參考ISO13818-1,第4位元組到位移量間的資料是系統填充的無效資料).
下面針對解複用程式詳細分析一下PAT,PMT和SDT三類表格的格式.
PAT, Program Association Table,節目關聯表
PAT表攜帶以下資訊:
(1) TS流ID--- transport_stream_id,該ID標誌唯一的流ID
(2) 節目頻道號-- program_number,該號碼標誌TS流中的一個頻道,該頻道可以包含很多的節目(即可以包含多個Video PID和Audio PID)
(3) PMT的PID--- program_map_PID,表示本頻道使用的哪個PID做為PMT的PID,因為可以有很多的頻道,因此DVB規定PMT的PID可以由使用者自己定義.
PAT表定義如下:
各欄位含義如下:
table_id:8 bits,標誌本表格的類型,應該是0x00
section_syntax_indicator:1 bit,段文法標誌,應該是'1'
'0':固定的'0',這是為了防止和ISO13818Video流格式中的控制字衝突而設定的.
Reserved:保留的2bits,保留位一般都是'0'
section_length:12bits的段大小,單位是Bytes.
transport_stream_id:16bits的當前流ID,DVB內唯一.(事實上很多都是自訂的TS ID)
version_number:5bits版本號碼,標註當前節目的版本.這是個非常有用的參數,當檢測到這個欄位改變時,說明TS流中的節目已經變化了,程式必須重新搜尋節目.
current_next_indicator:1bit:當前還是未來使用標誌符,一般情況下為'0'
section_number:8bits當前段號碼
last_section_number:8bits最後段號碼(section_number和last_section_number的功能是當PAT內容>184位元組時,PAT表會分成多個段(sections),解複用程式必須在全部接收完成後再進行PAT的分析)
從for()開始,就是描述了當前流中的頻道數目(N),每一個頻道對應的PMT PID是什麼.解複用程式需要和類似的迴圈來接收所有的頻道號碼和對應的PMT PID,並把這些資訊在緩衝區中儲存起來.在後部的處理中需要使用到PMT PID.
CRC_32:本段的CRC校正值,一般是會忽略的.N是一個變數,計算方法是N=(section_length-9)/4.
從以上分析我們可以發現,PAT表主要包含頻道號碼和每一個頻道對應的PMT的PID號碼,這些資訊我們在處理PAT表格的時候會儲存起來,以後會使用到這些資料.例如我們可以定義這樣的資料結構儲存這些資訊:
typedef struct
{
int channel_number;
int pmt_pid;
}PMT_ITEM;
PMT_ITEM pmt[64];
PMT, Program Map Table,節目影射表
如果一個TS流中含有多個頻道,那麼就會包含多個PID不同的PMT表.檢測是否PMT的虛擬碼如下:
void Process_Packet(unsigned char*buff)
{
int I;
int PID=GETPID(buff);
if(PID==0x0000)
{
Process_PAT(buff+4);
}
else if(PID==.....)
{
}
else
{
for(i=0;i<64;i++)
{
if(PID==pmt[i].pmt_pid)
{
Process_PMT(buff+4);
break;
}
}
}
}
PMT表中包含的資料如下:
(1) 目前通道中包含的所有Video資料的PID
(2) 目前通道中包含的所有Audio資料的PID
(3) 和目前通道關聯在一起的其他資料的PID(如數位廣播,資料通訊等使用的PID)
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校正值,一般忽略.
從以上的分析可以看出,只要我們處理了PMT,那麼我們就可以擷取頻道中所有的PID資訊,例如目前通道包含多少個Video,共多少個Audio,和其他資料,還能知道每種資料對應的PID分別是什麼.
這樣如果我們要選擇其中一個Video和Audio收看,那麼只需要把要收看的節目的Video PID和Audio PID儲存起來,在處理Packet的時候進行過濾即可實現.
比較全面實現解複用的虛擬碼如下:
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);
}
else if(PID==Video_PID)
{
SaveToVideoBuffer(buff+4);
}
else if(PID==Audio_PID)
{
SaveToAudioBuffer(buff+4);
}
else
{
for( i=0;i<64;i++)
{
if(PID==pmt[i].pmt_pid)
{
Process_PMT(buff+4);
Break;
}
}
}
}
以上虛擬碼可以實現基本的解複用:檢測所有的頻道,檢測所有stream的PID,選擇特定的節目進行播放.只要讀取每個Packet的188位元組的內容,然後每次都調用Process_Packet()即可實現簡單的解複用.
介紹到這裡,我們就可以總結一下DVB搜台的原理了.(好!洗耳恭聽!)
機 頂盒先調整高頻頭到一個固定的頻率(如498MHZ),如果此頻率有數字訊號,則COFDM晶片(如MT352)會自動把TS流資料傳送給MPEG- 2 decoder. MPEG-2 decoder先進行資料的同步,也就是等待完整的Packet的到來.然後迴圈尋找是否出現PID== 0x0000的Packet,如果出現了,則馬上進入分析PAT的處理,擷取了所有的PMT的PID.接著迴圈尋找是否出現PMT,如果發現了,則自動進 入PMT分析,擷取該頻段所有的頻道資料並儲存.如果沒有發現PAT或者沒有發現PMT,說明該頻段沒有訊號,進入下一個頻率掃描.
從以上描述可以看出,機頂盒搜尋頻率是隨機發生的,要使每次機頂盒都能搜尋到訊號,則要求TS流每隔一段時間就發送一次PAT和PMT.事實上DVB傳輸系統就是這麼做的.因此無論何時接入終端系統,系統都能馬上搜尋到節目並正確解複用實現播放.不僅僅如此,其他資料也都是交替傳送的.比如第一個Packet可能是PAT,第二個Packet可能是PMT,而第三個Packet可能是Video 1,第四個Packet可能是Video 2,
只要系統傳輸速度足夠快(就是稱之為"碼率"的東東),實現即時播放是沒有任何問題的.
到這裡雖然實現瞭解複用,但可以看出,使用的PID都是枯燥的數字,如果調台要使用者自己輸入數字那可是太麻煩了,而且還容易輸入錯誤,操作非常不直觀,即使做成一個菜單讓使用者選擇也是非常的呆板.針對這個問題,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部分.分析完畢,則節目名稱和節目號碼已經聯絡起來了.機頂盒程式就可以用這些節目名稱代替 PID讓使用者選擇,從而實現比較友好的使用者介面!
下面參考一下<<Seekfor MPEG2 decoder>>中的介面和顯示資訊.
上 圖是<<Seekfor MPEG2 decoder>>開啟三個不同的碼流檔案(*.ts)形成的PID資訊和節目名稱.使用者 可以通過切換節目名稱的下拉式清單方塊切換節目,也可以通過"視頻流"和"音頻流"下拉式清單方塊切換Video和Audio!這些資料都是通過分析PAT, PMT和SDT得到的.