

●PES:置為1,標識TS包的有效凈荷以PES包的第一個字節開始,即此TS包為PES包的起始包,且此TS分組中有且只有一個PES包的起始字段;置為0,表示TS包不是PES包的起始包,是后面的數據包。●PSI:置為1,表示TS包中帶有PSI數據分段的第一個字節,即這個TS包是PSI Section的起始包,則此TS包的負載(payload)的第一個字節帶有pointer_field,用來指示PSI數據的在payload 中的位置;置為0,表示TS包不帶有PSI Section的第一個字節,即此TS包不是PSI的起始包,即在有效負載中沒有point_field,有效負載的開始就是PSI的數據內容。point_field的定義將在下面的PSI節中進行介紹;對於空包的包,payload_unit_start_indicator應該置為0。例如:若TS包載荷為PAT,則當接收到的TS包的payload_unit_start_indicator為1時,表明這個TS包包含了PAT頭信息,從這個包里面解析出section_length和continuity_counter,然后繼續收集后面的payload_unit_start_indicator = 0的TS包,並判斷continuity_counter的連續性,不斷讀出TS包中的凈載荷(也就是PAT數據),用section_length作為收集TS包結束條件。
●0x0000代表PAT●0x0001代表CAT●0x0002-0x000F保留●0x1FFF表示空包
●總結
如果adaptation_field_control == 1x,表示后面跟有自適應字段;
如果adaptation_field_control == x1,表示后面跟有沒有自適應字段;

➣ adaptation_field_length:調整字段長度標示,標示此字節后面調整字段的長度,占位8bit;值為0時,表示在TS分組中插入一個調整字節,后面沒有調整字段,緊跟着的是有效負載;adaptation_field_control == ‘11’時,此值在0~182之間,adaptation_field_control == ‘10’時,此值為183,若字段沒這么長則填充0xFF字段;后面的字段都是在adaptation_field_length>0的時候才會出現,順序如下:
➣ discontinuity_indicator:不連續狀態指示符,占位1bit,置位1時表示此TS分組的不連續狀態為真;
➣ random_access_indicator:隨機訪問指示符,占位1bit;
➣ elementary_stream_priority_indicator:原始流數據優先級指示符,占位1bit,置位1表示此原始流數據比相同PID的TS包中的其他原始流優先級高;
➣ PCR_flag:PCR標志位,占位1bit,置位1表示調整字段中包含PCR字段,置位0則沒有PCR字段;
PCR字段:當PCR_flag == 1時,此字段才存在,占位48bit,依次順序為:
●program_clock_reference_base字段: 占位33bit;
●reserved字段: 占位6bit;
●program_clock_reference_extension字段:占位9bit;
OPCR字段:當OPCR_flag == 1時,此字段才存在,占位48bit,依次順序為:
●original_program_clock_reference_base字段: 占位33bit;
●reserved字段: 占位6bit;
●original_program_clock_reference_extension字段:占位9bit;
splice_countdown字段:當splicing_point_flag == 1時此字段存在,占位8bit;
transport_private_data字段:私有數據字段,當transport_private_data_flag == 1時此字段存在,占位N*8bit,字節順序為:
●transport_private_data_length:表明私有數據的字節長度,占位8bit;
●private_data_byte:私有數據,長度由前面的長度字段確定;
➣ adaptation_field_extension_flag:調整字段擴展標志位,占位1bit,置位1表示含有調整字段擴展字段,置位0則無擴展字段;
adaptation_field_extension字段:調整字段擴展字段,占用長度不確定,當adaptation_field_extension_flag == 1時此字段存在,字段中也有3個標志位,來確定一些字段存不存在,其具體字節順序如下:
●adaptation_field_extension_length:調整字段擴展字段的長度,占位8bit;
●ltw_flag:ltw字段標志位,置位1時表示此字段存在,占位1bit;
●piecewise_rate_flag:piecewise_rate字段標志位,置位1時此字段存在,占位1bit;
●seamless_splice_flag:seamless_splice標志位,置位1時此字段存在,占位1bit;
●Reserved:保留字段,占位5bit;
●Ltw字段:當ltw_flag == 1時此字段存在,占位16bit,其由以下兩個字段組成
ltw_valid_flag:占位1bit,當ltw_valid_flag == 1時,ltw_offset才有效;
ltw_offset:占位15bit;
●piecewise_rate字段:當piecewise_rate_flag == 1時此字段存在,占位24bit,其字節順序如下:
reserved字段:保留字段,占位2bit;
piecewise_rate字段:占位22bit;此字段只有在當ltw_flag == 1和ltw_valid_flag == 1時才有定義,有定義時此字段是一個正整數;
●seamless_splice字段:當seamless_splice_flag == 1時此字段存在,占位40bit;字節順序依次為:
splice_type字段:占位4bit;標識delay和rate值;
DTS_next_AU[32..30]:占位3bit;
marker_bit字段:占位1bit;
DTS_next_AU[29..15]字段:占位15bit;
marker_bit:占位1bit;
DTS_next_AU[14..0]:占位15bit;
marker_bit:占位1bit;
●stuffing_byte:填充字段,固定為0xFF
➣Payload_bytes:有效負載字段,字節來自PES包,PSI部分等;

可以看出,PES包是由固定包頭,可選包頭和負載三部分組成,其中固定包頭固定6個字節;PES包長度字段占位16bit,最大值為65536,故一幀可能會分為多個PES包;下面依次介紹其每個字段的含義:
➣Packet start code prefix:包頭起始碼,固定為0x000001,占位24bit;
➣Stream id:(UI)PES包中的負載流類型,一般視頻為0xe0,音頻為0xc0,占位8bit;
➣PES packet length:(UI)PES包長度,包括此字節后的可選包頭和負載的長度,占位16bit;
Optional PES Header,順序依次為:
➣'10'字段:占位2bit;
➣PES scrambling control:加密模式,占2bit;00未加密,01或10或11由用戶定義;
➣PES priority:有效負載的優先級,占位1bit;值為1比值為0的負載優先級高;
➣Data alignment indicator:數據定位指示器,占位1bit;
➣Copyright:版權信息,1為有版權,0無版權,占位1bit;
➣Original or copy:原始或備份,1為原始,0為備份,占位1bit;
☢ 后面是7個flags,對應的flag 如果被置1 , 就在PES header data length字段后追加相應的數據(一般我們關注的就是PTS DTS的標志位):
➣PTS_DTS_flags:PTS和DTS標志位,占位2bit;10表示首部有PTS字段,11表示有PTS和DTS字段,00表示都沒有,01被禁止,不會出現此種情況;
PTS/DTS字段:顯示時間戳/解碼時間戳,占位40bit,當PTS_DTS_flags == 1x時此字段存在;時間占用33個bit,PTS和DTS的內容是在這40bit中取33位,方式相同;
PTS(presentation time stamp)顯示時間戳和DTS(Decoding Time Stamp)解碼時間戳,是用來音視頻同步的,是打在PES包的包頭里面的,PTS/DTS是相對SCR(系統參考)的時間戳,是以90000為單位的,PTS/DTS到ms的轉換公式是PTS/90,系統時鍾頻率(H264采樣頻率?)為90Khz,所以轉換到秒為PTS/90000,所以如果是以ms為單位的播放器,PTS/DTS是要使用公式ms=pts/90來轉換才行的,而如果是以時鍾頻率為單位的話,則直接將PTS/DTS送進去解碼即可;如果沒有B幀,PTS和DTS的順序應該是一致的,如果有B幀,則需要先解碼P幀,才能解出來B幀,所以需要PTS和DTS來控制解碼時間和顯示時間;

字節順序依次:
●start_code:起始碼,占位4bit;若PTS_DTS_flags == ‘10’,則說明只有PTS,起始碼為0010;若PTS_DTS_flags == ‘11’,則PTS和DTS都存在,PTS的起始碼為0011,DTS的起始碼為0001;(PTS的起始碼后2個bit與flag相同)
●PTS[32..30]:占位3bit;
●marker_bit:占位1bit;
●PTS[29..15]:占位15bit;
●marker_bit:占位1bit;
●PTS[14..0]:占位15bit;
●marker_bit:占位1bit;
PTS/DTS = (PTS1 & 0x0e) << 29 + (PTS2 & 0xfffe) << 14 + (PTS3 & 0xfffe ) >> 1;
➣ESCR_flag:ESCR標志,占位1bit;1表示首部有ESCR字段,0則無此字段
ESCR字段:此字段占位48bit,由33bit的ESCR_base字段和9bit的ESCR_extension字段組成,ESCR_flag == 1時此字段存在;數據依次順序:
●Reserved:保留字段,占位2bit;
●ESCR_base[32..30]:占位3bit;
●marker_bit:占位1bit;
●ESCR_base[29..15]:占位15bit;
●marker_bit:占位1bit;
●ESCR_base[14..0]:占位15bit;
●marker_bit:占位1bit;
●ESCR_extension:(UI)占位9bit;周期數,取值范圍0~299;循環一次,base+1;
●marker_bit:占位1bit;
➣ES_rate_flag:ES_rate字段,占位1bit;1表示首部有此字段,0無此字段;
ES rate字段:目標解碼器接收PES分組字節速率,禁止為0,占位24bit,ES_rate_flag == 1時此字段存在;數據順序為:
●marker_bit:占位1bit;
●ES_rate:占位22bit;
●marker_bit:占位1bit;
➣DSM_trick_mode_flag:占位1bit;1表示有8位的DSM_trick_mode_flag字段,0無此字段;
Trick mode control字段:表示哪種trick mode被應用於相應的視頻流,占位8個bit,DSM_ trick_mode_flag == 1時此字段存在;其中trick_mode_control占前3個bit,根據其值后面有5個bit的不同內容;
如果trick_mode_control == ‘000’,依次字節順序為:
●field_id:占位2bit;
●intra_slice_refresh :占位1bit;
●frequency_truncation:占位2bit;
如果trick_mode_control == ‘001’,依次字節順序為:
●rep_cntrl:占位5bit;
如果trick_mode_control == ‘010’,依次字節順序為:
●field_id:占位2bit;
●Reserved:占位3bit;
如果trick_mode_control == ‘011’,依次字節順序為:
●field_id:占位2bit;
●intra_slice_refresh:占位1bit;
●frequency_truncation:占位2bit;
如果trick_mode_control== ‘100’,依次字節順序為:
●rep_cntrl:占位5bit;
其他情況,字節順序為:
●reserved :占位5bit;
➣Additional_copy_info_flag:占位1bit;1表示首部有此字段,0表示無此字段;
Additional copy info字段:占8個bit,Additional_copy_info_flag == 1時此字段存在;數據順序為:
●marker_bit:占位1bit;
●copy info字段:占位7bit;表示和版權相關的私有數據;
➣PES_CRC_flag:占位1bit;置1表示PES分組有CRC字段,0無此字段;
●Previous PES CRC字段:占位16bit字段,包含CRC值,PES_CRC_flag == 1時此字段存在;
➣PES_extension_flag:占位1bit;擴展標志位,置1表示有擴展字段,0無此字段
PES exten sion字段:PES擴展字段,PES_extension_flag == 1時此字段存在;內容如下,字節順序依次為:
●PES_private_data_flag:占位1bit,置1表示有私有數據,0則無;
PES_private_data字段:私有數據內容,占位128bit,PES_private_data_flag == 1時此字段存在;
●Pack_header_field_flag:占位1bit,置1表示有Pack_header_field字段,0則無;
Pack_header_field字段:Pack_header_field_flag == 1時此字段存在;字段組成順序如下:
Pack_field_length字段:(UI)指定后面的field的長度,占位8bit;
pack_header_field():長度為Pack_field_length指定;
●Program_packet_sequence_counter_flag:占位1bit,置1表示有此字段,0則無;
Program_packet_sequence_counter字段:計數器字段,16個bit;當flag字段Program_packet_sequence_counter_flag == 1時此字段存在;字節順序依次為:
marker_bit:占位1bit;
packet_sequence_counter字段:(UI)占位7bit;
marker_bit:占位1bit;
MPEG1_MPEG2_identifier:占位1bit;置位1表示此PES包的負載來自MPEG1流,置位0表示此PES包的負載來自PS流;
original_stuff_length:(UI)占位6bit;表示PES頭部填充字節長度;
●P-STD_buffer_flag:占位1bit,置1表示有P-STD_buffer字段,0則無此字段;
P-STD_buffer字段:表示P-STD_buffer內容,占位16bit;P-STD_buffer_flag == '1'時此字段存在;字節順序依次為:
’01’字段:占位2bit;
P-STD_buffer_scale:占位1bit;表示用來解釋后面P-STD_buffer_size字段的比例因子;如果之前的stream_id表示音頻流,則此值應為0,若之前的stream_id表示視頻流,則此值應為1,對於其他stream類型,此值可以0或1;
P-STD_buffer_size:占位13bit;無符號整數;大於或等於所有P-STD輸入緩沖區大小BSn的最大值;若P-STD_buffer_scale == 0,則P-STD_buffer_size以128字節為單位;若P-STD_buffer_scale == 1,則P-STD_buffer_size以1024字節為單位;
●Reserved字段:3個bit;
●PES_extension_flag_2:占位1bit,置1表示有擴展字段,0則無此字段;
PES_extension2字段:擴展字段的擴展字段;占用N*8個bit,PES_extension_flag_2 == '1'時此字段存在;字節順序依次為:
marker_bit:占位1bit;
PES_extension_field_length:占位7bit,表示擴展區域的長度;
Reserved字段:占位8*PES_extension_field_length個bit;
Stuffing bytes:填充字段,固定為0xFF;不能超過32個字節;
PES_packet_data_byte:PES包負載中的數據,即ES原始流數據
➣PES header data length:(UI)PES首部中可選字段和填充字段的長度;占位8bit;可選字段的內容由上面7個flags來進行控制;