http://blog.chinaunix.NET/uid-24322243-id-2620180.html
下面針對解復(fù)用程序詳細(xì)分析一下PAT,PMT和SDT三類表格的格式.
PAT---Program Association Table,節(jié)目關(guān)聯(lián)表?。PAT表攜帶以下信息:?
(1)?TS流ID--- transport_stream_id,該ID標(biāo)志唯一的流ID
(2)節(jié)目頻道號-- program_number,該號碼標(biāo)志TS流中的一個頻道,該頻道可以包含很多的節(jié)目(即可以包含多個Video PID和Audio PID)
(3)?PMT的PID--- program_map_PID,表示本頻道使用的哪個PID做為PMT的PID,因為可以有很多的頻道,因此DVB規(guī)定PMT的PID可以由用戶自己定義.
PAT表定義如下:?各字段含義如下:
table_id:8 bits,標(biāo)志本表格的類型,應(yīng)該是0x00
section_syntax_indicator:1 bit,段語法標(biāo)志,應(yīng)該是''1'' ''0'':固定的''0'',這是為了防止和ISO13818Video流格式中的控制字沖突而設(shè)置的.
Reserved:保留的2bits,保留位一般都是''0''
section_length:12bits的段大小,單位是Bytes.
transport_stream_id:16bits的當(dāng)前流ID,DVB內(nèi)唯一.(事實上很多都是自定義的TS ID)version_number:5bits版本號碼,標(biāo)注當(dāng)前節(jié)目的版本.這是個非常有用的參數(shù),當(dāng)檢測到這個字段改變時,說明TS流中的節(jié)目已經(jīng)變化?了,程序必須重新搜索節(jié)目.
current_next_indicator:1bit:當(dāng)前還是未來使用標(biāo)志符,一般情況下為''0''
section_number:8bits當(dāng)前段號碼
last_section_number:8bits最后段號碼(section_number和?last_section_number的功能是當(dāng)PAT內(nèi)容>184字節(jié)時,PAT表會分成多個段(sections),解復(fù)用程序必須在全部接?收完成后再進(jìn)行PAT的分析)
從for()開始,就是描述了當(dāng)前流中的頻道數(shù)目(N),每一個頻道對應(yīng)的PMT PID是什么.解復(fù)用程序需要和上圖類似的循環(huán)來接收所有的頻道號碼和對應(yīng)的PMT PID,并把這些信息在緩沖區(qū)中保存起來.在后部的處理中需要使用到PMT PID.
CRC_32:本段的CRC校驗值,一般是會忽略的.N是一個變量,計算方法是N=(section_length-9)/4.
從以上分析我們可以發(fā)現(xiàn),PAT表主要包含頻道號碼和每一個頻道對應(yīng)的PMT的PID號碼,這些信息我們在處理PAT表格的時候會保存起來,以后會使用到?這些數(shù)據(jù).例如我們可以定義這樣的數(shù)據(jù)結(jié)構(gòu)保存這些信息:
typedef struct
{
int channel_number;
int pmt_pid;
}PMT_ITEM;
PMT_ITEM pmt[64];
?
PMT, Program Map Table,節(jié)目影射表?如果一個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表中包含的數(shù)據(jù)如下:
(1)?當(dāng)前頻道中包含的所有Video數(shù)據(jù)的PID
(2)?當(dāng)前頻道中包含的所有Audio數(shù)據(jù)的PID
(3)?和當(dāng)前頻道關(guān)聯(lián)在一起的其他數(shù)據(jù)的PID(如數(shù)字廣播,數(shù)據(jù)通訊等使用的PID)
?
PMT定義如下:?各字段含義如下:
table_id:8bits的ID,應(yīng)該是0x02
section_syntax_indicator:1bit的段語法標(biāo)志,應(yīng)該是''1'' ''0'':固定是''0'',如果不是說明數(shù)據(jù)有錯.
reserved:2bits保留位,應(yīng)該是''00''
section_length:16bits段長度,從program_number開始,到CRC_32(包含)的字節(jié)總數(shù).?program_number:16bits的頻道號碼,表示當(dāng)前的PMT關(guān)聯(lián)到的頻道.換句話就是說,當(dāng)前描述的是program_number頻道的?信息.
reserved:2bits保留位,應(yīng)該是''00''
version_number:版本號碼,如果PMT內(nèi)容有更新,則version_number會遞增1通知解復(fù)用程序需要重新接收節(jié)目信息,否則?version_number是固定不變的.
current_next_indicator:當(dāng)前未來標(biāo)志符,一般是0
section_number:當(dāng)前段號碼
last_section_number:最后段號碼,含義和PAT中的對應(yīng)字段相同,請參考PAT部分.?reserved:3bits保留位,一般是''000''.
PCR_PID:13bits的PCR PID,具體請參考ISO13818-1,解復(fù)用程序不使用該參數(shù).
reserved:4bits保留位,一般是''0000''
program_info_length:節(jié)目信息長度(之后的是N個描述符結(jié)構(gòu),一般可以忽略掉,這個字段就代表描述符總的長度,單位是Bytes)?緊接著就是頻道內(nèi)部包含的節(jié)目類型和對應(yīng)的PID號碼了.
stream_type:8bits流類型,標(biāo)志是Video還是Audio還是其他數(shù)據(jù).
reserved:3 bits保留位.
elementary_PID:13bits對應(yīng)的數(shù)據(jù)PID號碼(如果stream_type是Video,那么這個PID就是Video PID,如果stream_type標(biāo)志是Audio,那么這個PID就是Audio PID)
reserved:4 bits保留位.
ES_info_length:和program_info_length類似的信息長度(其后是N2個描述符號)?CRC_32:32bits段末尾是本段的CRC校驗值,一般忽略.
?
從以上的分析可以看出,只要我們處理了PMT,那么我們就可以獲取頻道中所有的PID信息,例如當(dāng)前頻道包含多少個Video,共多少個Audio,和其?他數(shù)據(jù),還能知道每種數(shù)據(jù)對應(yīng)的PID分別是什么.?這樣如果我們要選擇其中一個Video和Audio收看,那么只需要把要收看的節(jié)目的Video PID和Audio PID保存起來,在處理Packet的時候進(jìn)行過濾即可實現(xiàn).?比較全面實現(xiàn)解復(fù)用的偽代碼如下:
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; }
} } }
以上偽代碼可以實現(xiàn)基本的解復(fù)用:檢測所有的頻道,檢測所有stream的PID,選擇特定的節(jié)目進(jìn)行播放.只要讀取每個Packet的188字節(jié)的內(nèi)?容,然后每次都調(diào)用Process_Packet()即可實現(xiàn)簡單的解復(fù)用.?介紹到這里,我們就可以總結(jié)一下DVB搜臺的原理了.(好!洗耳恭聽!)?機(jī)?頂盒先調(diào)整高頻頭到一個固定的頻率(如498MHZ),如果此頻率有數(shù)字信號,則COFDM芯片(如MT352)會自動把TS流數(shù)據(jù)傳送給MPEG- 2 decoder. MPEG-2 decoder先進(jìn)行數(shù)據(jù)的同步,也就是等待完整的Packet的到來.然后循環(huán)查找是否出現(xiàn)PID== 0x0000的Packet,如果出現(xiàn)了,則馬上進(jìn)入分析PAT的處理,獲取了所有的PMT的PID.接著循環(huán)查找是否出現(xiàn)PMT,如果發(fā)現(xiàn)了,則自動進(jìn)?入PMT分析,獲取該頻段所有的頻道數(shù)據(jù)并保存.如果沒有發(fā)現(xiàn)PAT或者沒有發(fā)現(xiàn)PMT,說明該頻段沒有信號,進(jìn)入下一個頻率掃描.?從以上描述可以看出,機(jī)頂盒搜索頻率是隨機(jī)發(fā)生的,要使每次機(jī)頂盒都能搜索到信號,則要求TS流每隔一段時間就發(fā)送一?次PAT和PMT.事實上DVB傳輸系統(tǒng)就是這么做的.因此無論何時接入終端系統(tǒng),系統(tǒng)都能馬上搜索到節(jié)目并正確解復(fù)用實現(xiàn)播放.不僅僅如此,其他數(shù)據(jù)也?都是交替?zhèn)魉偷?span lang="en-us">.比如第一個Packet可能是PAT,第二個Packet可能是PMT,而第三個Packet可能是Video 1,第四個Packet可能是Video 2,?只要系統(tǒng)傳輸速度足夠快(就是稱之為"碼率"的東東),實現(xiàn)實時播放是沒有任何問題的.?到這里雖然實現(xiàn)了解復(fù)用,但可以看出,使用的PID都是枯燥的數(shù)字,如果調(diào)臺要用戶自己輸入數(shù)字那可是太麻煩了,而且還容易輸入錯?誤,操作非常不直觀,即使做成一個菜單讓用戶選擇也是非常的呆板.針對這個問題,DVB系統(tǒng)提出了一個SDT表格,該表格標(biāo)志一個節(jié)目的名稱,并且能和?PMT中的PID聯(lián)系起來,這樣用戶就可以通過直接選擇節(jié)目名稱來選擇節(jié)目了.
?
SDT, Service description section,服務(wù)描述段
SDT可以提供的信息包括:
(1)?該節(jié)目是否在播放中
(2)?該節(jié)目是否被加密
(3)?該節(jié)目的名稱
SDT定義如下:?各字段定義如下:
table_id:8bits的ID,可以是0x42,表示描述的是當(dāng)前流的信息,也可以是0x46,表示是其他流的信息(EPG使用此參數(shù))
section_syntax_indicator:段語法標(biāo)志,一般是''1''
reserved_future_used:2bits保留未來使用
reserved:1bit保留位,防止控制字沖突,一般是''0'',也有可能是''1''
section_length:12bits的段長度,單位是Bytes,從transport_stream_id開始,到CRC_32結(jié)束(包含)
transport_stream_id:16bits當(dāng)前描述的流ID
reserved:2bits保留位
version_number:5bits的版本號碼,如果數(shù)據(jù)更新則此字段遞增1
current_next_indicator:當(dāng)前未來標(biāo)志,一般是''0'',表示當(dāng)前馬上使用.?original_netword_id:16bits的原始網(wǎng)絡(luò)ID號
reserved_future_use:8bits保留未來使用位?接下來是N個節(jié)目信息的循環(huán):
service_id:16 bits的服務(wù)器ID,實際上就是PMT段中的program_number.?reserved_future_used:6bits保留未來使用位
EIT_schedule_flag:1bit的EIT信息,1表示當(dāng)前流實現(xiàn)了該節(jié)目的EIT傳送?EIT_present_following_flag:1bits的EIT信息,1表示當(dāng)前流實現(xiàn)了該節(jié)目的EIT傳送?running_status:3bits的運行狀態(tài)信息:1-還未播放?2-幾分鐘后馬上開始,3-被暫停播出,4-正在播放,其他---保留
free_CA_mode:1bits的加密信息,''1''表示該節(jié)目被加密.?緊?接著的是描述符,一般是Service descriptor,分析此描述符可以獲取servive_id指定的節(jié)目的節(jié)目名稱.具體格式請參考?EN300468中的Service descriptor部分.
?
分析完畢,則節(jié)目名稱和節(jié)目號碼已經(jīng)聯(lián)系起來了.機(jī)頂盒程序就可以用這些節(jié)目名稱代替?PID讓用戶選擇,從而實現(xiàn)比較友好的用戶界面!?下面參考一下<>中的界面和顯示信息.?上?圖是<>打開三個不同的碼流文件(*.ts)形成的PID信息和節(jié)目名稱.用戶?可以通過切換節(jié)目名稱的下拉列表框切換節(jié)目,也可以通過"視頻流"和"音頻流"下拉列表框切換Video和Audio!這些數(shù)據(jù)都是通過分析PAT, PMT和SDT得到的.?(轉(zhuǎn)載自網(wǎng)路)
http://blog.csdn.net/blackboyofsnp/article/details/4665409
// 所有原創(chuàng)文章轉(zhuǎn)載請注明作者及鏈接
//?blackboycpp(AT)gmail.com
// QQ群: 135202158
對TS流的分析, 涉及到對PAT,PMT等等的分析, 具體內(nèi)容見iso/iec 13838系列文檔,
本文只給出自己寫的一些和TS分析想關(guān)的代碼, 簡單的分析足夠了, 不考慮復(fù)雜情況:
?
[cpp]?view plaincopy
//??//??//??TS流結(jié)構(gòu)定義??//??//????#ifndef?ZZQ_TS_H_??#define?ZZQ_TS_H_????#include?<vector>??using?namespace?std;??typedef??unsigned?char??byte;??typedef??unsigned?int???bits;????#define??TSPKT_LENGTH??188????//-----------------------------------------------------------------------------??//?結(jié)構(gòu)體??//-----------------------------------------------------------------------------??//?TS包構(gòu)成偽代碼????//?TS包頭部??//?WARNING!!!??暫時沒有考慮修改區(qū)以及修改區(qū)內(nèi)可選字段的處理??struct?ts_header??{??????bits??sync_byte????????????????????:?8;??????bits??transport_error_indicator????:?1;??????bits??payload_unit_start_indicator?:?1;??????bits??transport_priority???????????:?1;??????bits??PID??????????????????????????:?13;??????bits??transport_scrambling_control?:?2;??????bits??adaptation_field_control?????:?2;??????bits??continuity_counter???????????:?4;??};??//?TS包中的修改字段(adaptation?field)??struct?ts_adaptation_field??{??????bits??adaptation_field_length?:?8;??????bits??discontinuity_idicator??:?1;??????bits??random_access_indicator?:?1;??????bits??elementary_stream_priority_indicator?:?1;??????bits??flags???????????????????:?5;?//?5?flags??};????//?PAT中的可變段??struct?ts_pat_section??{??????bits??program_number?:?16;??????bits??reserved???????:?3;??????bits??PID????????????:?13;??};??typedef?vector<ts_pat_section>??vec_pat_section;??//?PAT表,?P138-PAT的結(jié)構(gòu),?文檔P61??struct?ts_pat??{??????bits??table_id?????????????????:?8;??//?0x00??????bits??section_syntax_indicator?:?1;??//?1??????bits??zero?????????????????????:?1;??//?0??????bits??reserved_1???????????????:?2;??//?11??????bits??section_length???????????:?12;???????bits??transport_stream_id??????:?16;?//?傳輸數(shù)據(jù)流識別??????bits??reserved_2???????????????:?2;??//?"11"??????bits??version_number???????????:?5;??????bits??current_next_indicator???:?1;??????bits??section_number???????????:?8;??????bits??last_section_number??????:?8;??????//?....?TODO??????vec_pat_section?network_section;??????vec_pat_section?pmt_section;??????bits??crc32????????????????????:?32;??};????//?Stream_type分配表,?P85??#define??ST_Reserved????????0x00?//?ITU-T?|?ISO/IEC?Reserved??#define??ST_VIDEO_1?????????0x01?//?ISO/IEC?11172?Video??#define??ST_VIDEO_2?????????0x02?//?ITU-T?Rec.?H.262?|?ISO/IEC?13818-2?Video?or?ISO/IEC?11172-2?constrained?parameter?video?stream??#define??ST_AUDIO_1?????????0x03?//?ISO/IEC?11172?Audio??#define??ST_AUDIO_2?????????0x04?//?ISO/IEC?13818-3?Audio??#define??ST_PRIVATE_SECTIONS????????0x05?//?ITU-T?Rec.?H.222.0?|?ISO/IEC?13818-1?private_sections??#define??ST_PES_PKT_PRIVATE_DATA????0x06?//?ITU-T?Rec.?H.222.0?|?ISO/IEC?13818-1?PES?packets?containing?private?data??#define??ST_MHEG????????????0x07?//?ISO/IEC?13522?MHEG??#define??ST_DSMCC???????????0x08?//?ITU-T?Rec.?H.222.0?|?ISO/IEC?13818-1?Annex?A?DSM?CC??#define??ST_H2221???????????0x09?//?ITU-T?Rec.?H.222.1??#define??ST_TYPEA???????????0x0A?//?ISO/IEC?13818-6?type?A??#define??ST_TYPEB???????????0x0B?//?ISO/IEC?13818-6?type?B??#define??ST_TYPEC???????????0x0C?//?ISO/IEC?13818-6?type?C??#define??ST_TYPED???????????0x0D?//?ISO/IEC?13818-6?type?D??#define??ST_AUXILIARY???????0x0E?//?ISO/IEC?13818-1?auxiliary??//?0x0F-0x7F:?ITU-T?Rec.?H.222.0?|?ISO/IEC?13818-1?Reserved??//?0x80-0xFF:?User?Private??//?PMT表中的ES段??struct?ts_pmt_es_section??{??????bits??stream_type??????????????:?8;??????bits??reserved_1???????????????:?3;??????bits??elementary_PID???????????:?13;??????bits??reserved_2???????????????:?4;??????bits??ES_info_length???????????:?12;??};??typedef?vector<ts_pmt_es_section>??vec_pmt_section;????//?PMT表,?書P138?-?PMT的結(jié)構(gòu)??struct?ts_pmt??{??????bits??table_id?????????????????:?8;??//?0x02??????bits??section_syntax_indicator?:?1;??//?1??????bits??zero?????????????????????:?1;??//?0??????bits??reserved_1???????????????:?2;??//?11??????bits??section_length???????????:?12;??????bits??program_number???????????:?16;??????bits??reserved_2???????????????:?2;??//?11??????bits??version_number???????????:?5;??????bits??current_next_indicator???:?1;??????bits??section_number???????????:?8;??????bits??last_section_number??????:?8;??????bits??reserved_3???????????????:?3;??//?111??????bits??PCR_PID??????????????????:?13;??????bits??reserved_4???????????????:?4;??//?1111??????bits??program_info_length??????:?12;??????vec_pmt_section??es_section;??????bits??crc32????????????????????:?32;??};????//?PES包構(gòu)成偽代碼??P43??????//?Steam?ID分配表,??文檔P47??#define??SID_PROGRAM_STREAM_MAP?????0xBC??#define??SID_PRIVATE_STREAM_1???????0xBD??#define??SID_PADDING_STREAM?????????0xBE??#define??SID_PRIVATE_STREAM_2???????0xBF??#define??SID_AUDIO_STREAM???????????0xC0?//?110x?xxxx,?stream?number?x?xxxx??#define??SID_VIDEO_STREAM???????????0xE0?//?1110?xxxx,?stream?number?xxxx??#define??SID_ECM_STREAM?????????????0xF0??#define??SID_EMM_STREAM?????????????0xF1??#define??SID_DSMCC_STREAM???????????0xF2??#define??SID_13522_STREAM???????????0xF3??#define??SID_TYPEA??????????????????0xF4??#define??SID_TYPEB??????????????????0xF5??#define??SID_TYPEC??????????????????0xF6??#define??SID_TYPED??????????????????0xF7??#define??SID_TYPEE??????????????????0xF8??#define??SID_ANCILLARY_STREAM???????0xF9??//?1111?1010?~?1111?1110,?reserved?data?stream??#define??SID_PROGRAM_STREAM_DIRECTORY???0xFF????//?PES包中的可選包頭部??struct?optional_pes_header??{??????bits??prefix???????????????????:?2;?//?"10"??????bits??pes_scrambling_control???:?2;??????bits??pes_priority?????????????:?1;??????bits??data_alignment_indicator?:?1;??????bits??copyright????????????????:?1;??????bits??original_or_copy?????????:?1;??????//?7?flags?start??????bits??PTS_DTS_flags????????????:?2;??????bits??ESCR_flag????????????????:?1;??????bits??ES_rate_flag?????????????:?1;??????bits??DSM_trick_mode_flag??????:?1;??????bits??additional_copy_info_flag:?1;??????bits??PES_CRC_flag?????????????:?1;??????bits??PES_extension_flag???????:?1;??????//?7?flags?end??????bits??pes_header_data_length???:?8;??????//?WARNING!!!?目前只使用?PTS,?DTS??????bits??PTS_H????????????????????:?3;??//?32..30??????bits??PTS_M????????????????????:?15;?//?29..15??????bits??PTS_L????????????????????:?15;?//?14..0??????bits??DTS_H????????????????????:?3;??//?32..30??????bits??DTS_M????????????????????:?15;?//?29..15??????bits??DTS_L????????????????????:?15;?//?14..0??};????//?PES包頭部,?文檔P43,?書P131??struct?pes_header??{??????bits??packet_start_code_prefix?:?24;??????bits??stream_id????????????????:?8;??????bits??pes_packet_length????????:?16;??????//?之后是optional?PES?header,?即任意包頭,?它的有無由stream_id決定??????bool??ophdr_flag;??????optional_pes_header?ophdr;??//?如果聲明為指針,?會帶來一些內(nèi)存問題??????//byte*??es_data;???//?實際數(shù)據(jù)指針??????int???offset;???//?實際數(shù)據(jù)偏移????????????pes_header()??????{??????????ophdr_flag?=?false;??????????offset?=?-1;??????}??????~pes_header()??????{}??};????//-----------------------------------------------------------------------------??//?位段結(jié)構(gòu)調(diào)整函數(shù)??//-----------------------------------------------------------------------------??int?adjust_ts_header(ts_header*?pkt,?byte*?buff);??int?adjust_ts_pat(ts_pat*?pkt,?byte*?buff);??int?adjust_ts_pmt(ts_pmt*?pkt,?byte*?buff);??int?adjust_ts_pes_header(pes_header*?pkt,?byte*?buff);??__int64??get_pts_from_pes(pes_header&?pkt);??__int64??get_dts_from_pes(pes_header&?pkt);??#endif?? ?
[cpp]?view plaincopy
//??//??//??TS流相關(guān)函數(shù)??//??//??#include?<stdio.h>??#include?"zzq_TS.h"????int?adjust_ts_header(ts_header*?pkt,?byte*?buff)??{??????if(pkt?==?NULL?||?buff?==?NULL)??????{???return?1;???}??????pkt->sync_byte?=?buff[0];??????pkt->transport_error_indicator?=?buff[1]?>>?7;??????pkt->payload_unit_start_indicator?=?buff[1]?>>?6?&?0x01;??????pkt->transport_priority?=?buff[1]?>>?5?&?0x01;??????pkt->PID?=?(buff[1]?&?0x1f)<<8?|?buff[2];??????pkt->transport_scrambling_control?=?buff[3]?>>?6;??????pkt->adaptation_field_control?=?buff[3]?>>?4?&?0x03;??????pkt->continuity_counter?=?buff[3]?&?0x03;??????return?0;??}????int?adjust_ts_pat(ts_pat*?pkt,?byte*?buff)??{??????if(pkt?==?NULL?||?buff?==?NULL)??????{???return?1;???}??????pkt->table_id?=?buff[0];??????pkt->section_syntax_indicator?=?buff[1]?>>?7;??????pkt->zero?=?buff[1]?>>?6?&?0x1;??????pkt->reserved_1?=?buff[1]?>>?4?&?0x3;??????pkt->section_length?=?(buff[1]?&?0x0f)?<<?8?|?buff[2];??????pkt->transport_stream_id?=?buff[3]?<<?8?|?buff[4];??????pkt->reserved_2?=?buff[5]?>>?6;??????pkt->version_number?=?buff[5]?>>?1?&?0x1f;??????pkt->current_next_indicator?=?(buff[5]?<<?7)?>>?7;??????pkt->section_number?=?buff[6];??????pkt->last_section_number?=?buff[7];??????//?get?crc32??????int?len?=?3?+?pkt->section_length;??????pkt->crc32?=?(buff[len-4]?&?0x000000ff)?<<?24?|???????????????????(buff[len-3]?&?0x000000ff)?<<?16?|???????????????????(buff[len-2]?&?0x000000ff)?<<?8??|???????????????????(buff[len-1]?&?0x000000ff);??????//?get?variable?section??????for(int?i=0;?i<pkt->section_length-4-8;?i+=4?)??????{??????????ts_pat_section?sec;??????????sec.program_number?=?buff[8+i]?<<?8?|?buff[9];??????????sec.reserved?=?buff[10+i]?>>?5;??????????sec.PID?=?(buff[10+i]?<<?3)?<<?5?|?buff[11+i];??????????if(sec.program_number?==?0x0)??????????????pkt->network_section.push_back(sec);??????????else??????????????pkt->pmt_section.push_back(sec);??????}??????return?0;??}????int?adjust_ts_pmt(ts_pmt*?pkt,?byte*?buff)??{??????if(pkt?==?NULL?||?buff?==?NULL)???????{???return?1;???}??????pkt->table_id?=?buff[0];??????pkt->section_syntax_indicator?=?buff[1]?>>?7;??????pkt->zero?=?buff[1]?>>?6;??????pkt->reserved_1?=?buff[1]?>>?4;??????pkt->section_length?=?(buff[1]?&?0x0f)?<<?8?|?buff[2];??????pkt->program_number?=?buff[3]?<<?8?|?buff[4];??????pkt->reserved_2?=?buff[5]?>>?6;??????pkt->version_number?=?buff[5]?>>?1?&?0x1f;??????pkt->current_next_indicator?=?(buff[5]?<<?7)?>>?7;??????pkt->section_number?=?buff[6];??????pkt->last_section_number?=?buff[7];??????pkt->reserved_3?=?buff[8]?>>?5;??????pkt->PCR_PID?=?((buff[8]?<<?8)?|?buff[9])?&?0x1fff;??????pkt->reserved_4?=?buff[10]?>>?4;??????pkt->program_info_length?=?(buff[10]?&?0x0f)?<<?8?|?buff[11];??????//?get?crc32??????int?len?=?pkt->section_length?+?3;??????pkt->crc32?=?(buff[len-4]?&?0x000000ff)?<<?24?|???????????????????(buff[len-3]?&?0x000000ff)?<<?16?|???????????????????(buff[len-2]?&?0x000000ff)?<<?8??|???????????????????(buff[len-1]?&?0x000000ff);??????//?skip?program?description??????int?pos?=?12?+?pkt->program_info_length;??????for(?;?pos?<=?(pkt->section_length-4);?pos+=5)??????{??????????ts_pmt_es_section?sec;??????????sec.stream_type?=?buff[pos];??????????sec.reserved_1?=?buff[pos+1]?>>?5;??????????sec.elementary_PID?=?((buff[pos+1]?<<?8)?|?buff[pos+2])?&?0x1fff;??????????sec.ES_info_length?=?(buff[pos+3]?&?0x0f)?<<?8?|?buff[pos+4];??????????pkt->es_section.push_back(sec);??????????pos?+=?sec.ES_info_length;??????}??????return?0;??}????int?adjust_ts_pes_header(pes_header*?pkt,?byte*?buff)??{??????if(pkt?==?NULL?||?buff?==?NULL)???????{???return?1;???}??????//?0000?0000?0000?0000?0000?0001?:?0x000001??????pkt->packet_start_code_prefix?=?(buff[0]?&?0x0000ff)?<<?16?|??????????????????????????????????????(buff[1]?&?0x0000ff)?<<?8??|??????????????????????????????????????(buff[2]?&?0x0000ff);??????//if(pkt->packet_start_code_prefix?!=?0x000001)??return?2;??????byte?sid?=?buff[3];?//?aux??????pkt->stream_id?=?buff[3];??????pkt->pes_packet_length?=?buff[4]?<<?8?|?buff[5];??????if(sid?!=?SID_PROGRAM_STREAM_MAP?&&?????????sid?!=?SID_PADDING_STREAM?&&?????????sid?!=?SID_PRIVATE_STREAM_2?&&?????????sid?!=?SID_ECM_STREAM?&&?????????sid?!=?SID_EMM_STREAM?&&?????????sid?!=?SID_PROGRAM_STREAM_DIRECTORY?&&?????????sid?!=?SID_DSMCC_STREAM?&&?????????sid?!=?SID_TYPEE????????)??????{??????????pkt->ophdr_flag?=?true;??????????pkt->ophdr.prefix?=?buff[6]?>>?6;?//?"10"?:?2??????????//if(pkt->ophdr->prefix?!=?2)?return?2;??????????pkt->ophdr.pes_scrambling_control?=?buff[6]?>>?4?&?0x03;??????????pkt->ophdr.pes_priority?=?buff[6]?>>?3?&?0x01;??????????pkt->ophdr.data_alignment_indicator?=?buff[6]?>>?2?&?0x01;??????????pkt->ophdr.copyright?=?buff[6]?>>?1?&?0x01;??????????pkt->ophdr.original_or_copy?=?buff[6]?&?0x01;??????????pkt->ophdr.PTS_DTS_flags?=?buff[7]?>>?6?&?0x03;??????????pkt->ophdr.ESCR_flag?=?buff[7]?>>?5?&?0x01;??????????pkt->ophdr.ES_rate_flag?=?buff[7]?>>?4?&?0x01;??????????pkt->ophdr.DSM_trick_mode_flag?=?buff[7]?>>?3?&?0x01;??????????pkt->ophdr.additional_copy_info_flag?=?buff[7]?>>?2?&?0x01;??????????pkt->ophdr.PES_CRC_flag?=?buff[7]?>>?1?&?0x01;??????????pkt->ophdr.PES_extension_flag??=?buff[7]?&?0x01;??????????pkt->ophdr.pes_header_data_length?=?buff[8];??????????if(pkt->ophdr.PTS_DTS_flags?==?0x2)?//?"10"??????????{??????????????//?以下移位操作,?都將各位串靠左對齊??????????????pkt->ophdr.PTS_H?=?buff[9]?<<?3?&?0xe0;?//?3?bits??????????????pkt->ophdr.PTS_M?=?(buff[10]?<<?8)?|?(buff[11]?&?0xfe);?//?15?bits??????????????pkt->ophdr.PTS_L?=?(buff[12]?<<?8)?|?(buff[13]?&?0xfe);?//?15?bits??????????}??????????else?if(pkt->ophdr.PTS_DTS_flags?==?0x3)?//?"11"??????????{??????????????//?以下移位操作,?都將各位串靠左對齊??????????????pkt->ophdr.PTS_H?=?buff[9]?<<?3?&?0xe0;?//?3?bits??????????????pkt->ophdr.PTS_M?=?(buff[10]?<<?8)?|?(buff[11]?&?0xfe);?//?15?bits??????????????pkt->ophdr.PTS_L?=?(buff[12]?<<?8)?|?(buff[13]?&?0xfe);?//?15?bits??????????????pkt->ophdr.DTS_H?=?buff[14]?<<?3?&?0xe0;??????????????pkt->ophdr.DTS_M?=?(buff[15]?<<?8)?|?(buff[16]?&?0xfe);?//?15?bits??????????????pkt->ophdr.DTS_L?=?(buff[17]?<<?8)?|?(buff[18]?&?0xfe);?//?15?bits??????????}??????????//??????????//??ESCR,?ES_rate之類的目前不處理??????????//?6?+?3:?(24+8+16)?+?(2+2+1+1+1+1+8+8)??????????pkt->offset?=?6?+?3?+?pkt->ophdr.pes_header_data_length;??????}??????else?if(sid?==?SID_PROGRAM_STREAM_MAP?||??????????????sid?==?SID_PRIVATE_STREAM_2?||??????????????sid?==?SID_ECM_STREAM?||??????????????sid?==?SID_EMM_STREAM?||??????????????sid?==?SID_PROGRAM_STREAM_DIRECTORY?||??????????????sid?==?SID_DSMCC_STREAM?||??????????????sid?==?SID_TYPEE?????????????)??????{??????????pkt->offset?=?6;??????}??????else?if(sid?==?SID_PADDING_STREAM)??????{??????????pkt->offset?=?-1;??????}????????????return?0;??}????__int64??get_pts_from_pes(pes_header&?pkt)??{??????if(pkt.ophdr_flag?==?false)?return?-1;??????if(pkt.ophdr.PTS_DTS_flags?!=?0x2?&&?pkt.ophdr.PTS_DTS_flags?!=?0x3)??????????return?-1;??????__int64?H?=?0,?M?=?0,?L?=?0;??????L?=?pkt.ophdr.PTS_L?>>?1?|?pkt.ophdr.PTS_M?<<?14;??????M?=?pkt.ophdr.PTS_M?>>?2?|?pkt.ophdr.PTS_H?<<?13;??????L?=?pkt.ophdr.PTS_H?>>?3;??????return?(H<<32)?|?(M<<16)?|?L;??}??__int64??get_dts_from_pes(pes_header&?pkt)??{??????if(pkt.ophdr_flag?==?false)?return?-1;??????if(pkt.ophdr.PTS_DTS_flags?!=?0x3)??????????return?-1;??????__int64?H?=?0,?M?=?0,?L?=?0;??????L?=?pkt.ophdr.DTS_L?>>?1?|?pkt.ophdr.DTS_M?<<?14;??????M?=?pkt.ophdr.DTS_M?>>?2?|?pkt.ophdr.DTS_H?<<?13;??????L?=?pkt.ophdr.DTS_H?>>?3;??????return?(H<<32)?|?(M<<16)?|?L;??}?
總結(jié)
以上是生活随笔為你收集整理的PAT、PMT、SDT详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。