首先我們需要知道PS包流格式是怎么樣的:
(來自http://blog.csdn.net/chen495810242/article/details/39207305)
上面這是對數據流的一個整體封裝格式,下面我們來看看每個封裝中的每個部分:
(來自http://blog.csdn.net/wangjiannuaa/article/details/7679486)
首先是PSheader部分:(來自MPEG2標准中文文檔)
語法 | 位數 | 助記符 |
---|---|---|
pack_header() { | ||
pack_start_code | 32 | bslbf |
'01' | 2 | bslbf |
system_clock_reference_base[32..30] | 3 | bslbf |
marker_bit | 1 | bslbf |
system_clock_reference_base[29..15] | 15 | bslbf |
marker_bit | 1 | bslbf |
system_clock_reference_base[14..0] | 15 | bslbf |
marker_bit | 1 | bslbf |
system_clock_reference_extension | 9 | uimsbf |
marker_bit | 1 | bslbf |
program_mux_rate | 22 | uimsbf |
marker_bit | 1 | bslbf |
marker_bit | 1 | bslbf |
reserved | 5 | bslbf |
pack_stuffing_length | 3 | uimsbf |
for (i=0;i<pack_stuffing_length;i++){ | ||
stuffing_byte | 8 | bslbf |
} | ||
if (nextbits()==system_header_start_code) { | ||
system_header() | ||
} | ||
} |
節目流包(PS header)中各字段的語義定義:
包起始碼字段 pack_start_code
值為'0000 0000 0000 0000 0000 0001 1011 1010' (0x000001BA)的位串,用來標志一個包的開始。
系統時鍾參考字段 system_clock_reference_base,system_clock_reference_extenstion
系統時鍾參考(SCR)是一個分兩部分編碼的42位字段。第一部分system_clock_reference_base是一個長度為33位的字段,其值SCR_base(i)由式2-19給出;第二部分system_clock_reference_extenstion是一個長度為9位的字段,其值SCR_ext(i)由式2-20給出。SCR字段指出了基本流中包含ESCR_base最后一位的字節到達節目目標解碼器輸入端的期望時間。
SCR字段的編碼頻率要求見2.7.1。
標記位字段 marker_bit
1位字段,取值'1'。
節目復合速率字段 program_mux_rate
一個22位整數,規定P-STD在包含該字段的包期間接收節目流的速率。其值以50字節/秒為單位。不允許取0值。該字段所表示的值用於在2.5.2中定義P-STD輸入端的字節到達時間。該字段值在本標准中的節目多路復合流的不同包中取值可能不同。
包填充長度字段 pack_stuffing_length
3位整數,規定該字段后填充字節的個數。
填充字節字段 stuffing_byte
8位字段,取值恆為'1111 1111'。該字段能由編碼器插入,例如為了滿足通道的要求。它由解碼器丟棄。在每個包標題中最多只允許有7個填充字節。
它的定義字節順序,如下所示:
4B的包起始碼:
byte 0 | byte 1 | byte 2 | byte 3 | ||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0000 0000 0000 0000 0000 0001 start code | 1011 1010 PACK identifier |
PACK identifier -- 0xBA
系統時鍾基准(SCR-System Clock Reference)的基本部分、SCR的擴展部分:
PS復用速率:
byte 10 | byte 11 | byte 12 | byte 13 | ||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
Program_Mux_Rate | 1 | 1 | reserved | pack_stuffing_length |
==============================================================
接下來看看PS system header(即PS系統頭:節目流系統標題)部分的定義:(來自MPEG-2標准文檔)
表2-34 節目流系統標題
語 法 | 位數 | 助記符 |
---|---|---|
system_header() { | ||
system_header_start_code | 32 | bslbf |
header_length | 16 | uimsbf |
marker_bit | 1 | bslbf |
rate_bound | 22 | uimsbf |
marker_bit | 1 | bslbf |
audio_bound | 6 | uimsbf |
fixed_flag | 1 | bslbf |
CSPS_flag | 1 | bslbf |
system_audio_lock_flag | 1 | bslbf |
system_video_lock_flag | 1 | bslbf |
marker_bit | 1 | bslbf |
vedio_bound | 5 | uimsbf |
packet_rate_restriction_flag | 1 | bslbf |
reserved_bits | 7 | bslbf |
while (nextbits()=='1') { | ||
stream_id | 8 | uimsbf |
'11' | 2 | bslbf |
P-STD_buffer_bound_scale | 1 | bslbf |
P-STD_buffer_size_bound | 13 | uimsbf |
} | ||
} |
系統標題中各字段的語義定義:
系統標題起始碼字段 system_header_start_code
取值'0000 0000 0000 0000 0000 0001 1011 1011' (0x000001BB)的位串,指出系統標題的開始。
標題長度字段 header_length
16位字段。指出該字段后的系統標題的字節長度。在本規范將來的擴充中可能擴展該字段。
速率界限字段 rate_bound
22位字段,取值不小於編碼在節目流的任何包中的program_mux_rate字段的最大值。該字段可被解碼器用於估計是否有能力對整個流解碼。
音頻界限字段 audio_bound
6位字段,取值是在從0到32的閉區間中的整數,且不小於節目流中解碼過程同時活動的GB/T XXXX.3和GB/T AAAA.3音頻流的最大數目。在本小節中,若STD緩沖區非空或展現單元正在P-STD模型中展現,則GB/T XXXX.3和GB/T AAAA.3音頻流的解碼過程是活動的。
固定標志字段 fixed_flag
1位標志位。置'1'時表示比特率恆定的操作;置'0'時,表示操作的比特率可變。在恆定比特率的操作期間,復合的GB/T XXXX.1流中的system_clock_reference字段值應遵從下面的線性公式:
SCR_base(i)=((c1×i+c2) DIV 300) % 233 (2-22)
SCR_ext(i)=((c1×i+c2) DIV 300) % 300 (2-23)
其中:
c1 對所有i均有效的實型常數;
c2 對所有i均有效的實型常數;
i 在GB/T XXXX.1復合流中包含任何system_clock_reference字段的最后一位的字節索引。
CSPS**標志字段 CSPS_flag**
1位字段。置'1'時,節目流符合2.7.9中定義的限制。
系統音頻鎖定標志字段 system_audio_lock_flag
1位字段。表示在系統目標解碼器的音頻采樣率和system_clock_frequency之間存在規定的比率。system_clock_frequency在2.5.2.1中定義而音頻采樣率由GB/T XXXX.3規定。如果對節目流中所有音頻基本流的所有展現單元,system_clock_frequency和實際音頻采樣率的比例SCASR是恆定的,且對音頻流中所指出的標准采樣率和下表中數值相等,則該字段只能為'1'。
SCASR=(system_clock_frequency) / audio_sample_rate_in_the_P-STD (2-24)
記號X/Y表示實數除法。
標准音頻采樣頻率(kHz) | 16 | 32 | 22.05 | 44.1 | 24 | 48 |
---|---|---|---|---|---|---|
SCASR | 27 000 000--------16 000 | 27 000 000-------32 000 | 27 000 000------22 050 | 27 000 000------44 100 | 27 000 000------24 000 | 27 000 000--------48 000 |
系統視頻鎖定標志字段 system_video_lock_flag
1位字段。表示在系統目標解碼器的視頻幀速率和system_clock_frequency之間存在規定的比率。system_clock_frequency在2.5.2.1中定義而視頻幀速率由GB/T XXXX.2規定。如果對GB/T XXXX.1中所有視頻基本流的所有展現單元,system_clock_frequency和實際視頻幀速率的比例SCFR是恆定的,且對視頻流中所指出的標准幀速率和下表中數值相等,則該字段只能為'1'。
SCFR=system_clock_frequency / frame_rate_in_the_P-STD (2-25)
標准幀速率(Hz) | 23.976 | 24 | 25 | 29.97 | 30 | 50 | 59.94 | 60 |
---|---|---|---|---|---|---|---|---|
SCFR | 1 126 125 | 1 125 000 | 1 080 000 | 900 900 | 900 000 | 540 000 | 450 450 | 450 000 |
比率SCFR的值是精確的。對於23.976,29.97或59.94幀/秒的標准速率,實際的幀速率與標准速率略有不同。
視頻界限字段 video_bound
5位字段,取值是在從0到16的閉區間中的整數且不小於節目流中解碼過程同時活動的GB/T XXXX.2和GB/T AAAA.2流的最大數目。在本小節中,若P-STD緩沖區非空或展現單元正在P-STD模型中展現,則GB/T XXXX.2和GB/T AAAA.2視頻流的解碼過程是活動的。
分組速率限制標志字段 packet_rate_restriction_flag
1位標志位。若CSPS標識為'1',則該字段表示2.7.9中規定的哪個限制適用於分組速率。若CSPS標識為'0',則該字段的含義未定義。
保留位字段 reserved_bits
7位字段。被保留供ISO/IEC將來使用。它的值應為'111 1111',除非ISO/IEC對它作出其它規定。
流標識字段 stream_id
8位字段。指示其后的P-STD_buffer_bound_scale和P-STD_buffer_size_bound字段所涉及的流的編碼和基本流號碼。
若取值'1011 1000',則其后的P-STD_buffer_bound_scale和P-STD_buffer_size_bound字段指節目流中所有的音頻流。
若取值'1011 1001',則其后的P-STD_buffer_bound_scale和P-STD_buffer_size_bound字段指節目流中所有的視頻流。
若stream_id取其它值,則應該是大於或等於'1011 1100'的一字節值且應根據表2-18解釋為流的編碼和基本流號碼。
節目流中的每個基本流應在每個系統標題中通過這種機制精確地規定一次它的P-STD_buffer_bound_scale和P-STD_buffer_size_bound。
P-STD**緩沖區界限比例字段 P-STD_buffer_bound_scale**
1位字段。表示用於解釋后續P-STD_buffer_size_bound字段的比例系數。若前面的stream_id表示一個音頻流,則該字段值為'0'。若表示一個視頻流,則該字段值為'1'。對於所有其它的流類型,該字段值可以為'0'也可以為'1'。
P-STD**緩沖區大小界限字段 P-STD_buffer_size_bound**
13位無符號整數,取值不小於節目流中流n的所有分組的P-STD緩沖區大小BSn的最大值。若P-STD_buffer_bound_scale的值為'0',則該字段以128字節為單位來度量緩沖區大小的邊界。若P-STD_buffer_bound_scale的值為'1',則該字段以1024字節為單位來度量緩沖區大小的邊界。因此:
if (P-STD_buffer_bound_scale = = 0)
BSn≤P-STD_buffer_size_bound×128
else
BSn≤P-STD_buffer_size_bound×1024
所以對於系統頭部的解析,我們一般只要先首先判斷是否存在系統頭(根據系統頭的起始碼0x000001BB),然后我們讀取系統頭的頭部長度,即PS SYSTEM HEADER LENGTH部分,然后根據頭部的長度,跳過PS系統頭。進入下一個部分,即PS 節目流映射頭。
==========================================================
接着看看PS流的節目映射流部分(節目流映射)定義:(來自MPEG-2標准文檔)
表2-35 節目流映射
語 法 | 位數 | 助記符 |
---|---|---|
program_stream_map() { | ||
packet_start_code_prefix | 24 | bslbf |
map_stream_id | 8 | uimsbf |
program_stream_map_length | 16 | uimsbf |
current_next_indicator | 1 | bslbf |
reserved | 2 | bslbf |
program_stream_map_version | 5 | uimsbf |
reserved | 7 | bslbf |
marker_bit | 1 | bslbf |
program_stream_info_length | 16 | uimsbf |
for (i=0;i<N;i++){ | ||
descriptor() | ||
} | ||
elementary_stream_map_length | 16 | uimsbf |
for (i=0;i<N1;i++){ | ||
stream_type | 8 | uimsbf |
elementary_stream_id | 8 | uimsbf |
elementary_stream_info_length | 16 | uimsbf |
for (i=0;i<N2;i++) { | ||
descriptor() | ||
} | ||
} | ||
CRC_32 | 32 | rpchof |
} |
節目流映射中各字段的語義定義:
分組起始碼前綴字段 packet_start_code_prefix
24位碼。它和跟隨其后的map_stream_id共同組成一個分組起始碼以標志分組的開始。該字段是值為'0000 0000 0000 0000 0000 0001' (0x000001)的位串。
映射流標識字段 map_stream_id
8位字段,值為0xBC。
節目流映射長度字段 program_stream_map_length
16位字段。指示緊跟在該字段后的program_stream_map中的字節數。該字段的最大值為1018(0x3FA)。
當前下一個指示符字段 current_next_indicator
1位字段。置'1'時表示傳送的節目流映射當前是可用的。置'0'時表示傳送的節目流映射還不可用,但它將是下一個生效的表。
節目流映射版本字段 program_stream_map_version
5位字段,表示整個節目流映射的版本號。一旦節目流映射的定義發生變化,該字段將遞增1,並對32取模。在current_next_indicator為'1'時,該字段應該是當前適用的節目流映射的版本號;在current_next_indicator為'0'時,該字段應該是下一個適用的節目流映射的版本號。
節目流信息長度字段 program_stream_info_length
16位字段,指出緊跟在該字段后的描述符的總長度。
標記位字段 marker_bit
1位字段,取值為'1'。
基本流映射長度字段 elementary_stream_map_length
16位字段,指出在該節目流映射中的所有基本流信息的字節長度。它只包括stream_type、elementary_stream_id和elementary_stream_info_length字段。(這里注意一下,這里的基本流映射長度,他只包括他后面的指定的那幾個定義字段的總和,即從從這個長度,我們可以知道后面他根了幾種類型的流定義,因為一種流的這個定義字段:stream_type(1BYTE)、elementary_stream_id(1byte)和elementary_stream_info_length(2byte)字段總和為4個字節,所以用elementary_stream_map_length/4可以得到后面定義了幾個流類型信息。)
流類型字段 stream_type
8位字段,根據表2-29規定了流的類型。該字段只能標志包含在PES分組中的基本流且取值不能為0x05。
(這里我們暫時根據國標GB28181中的定義可以知道
1、MPEG-4 視頻流: 0x10;
2、H.264 視頻流: 0x1B;
3、SVAC 視頻流: 0x80;
4、G.711 音頻流: 0x90;
5、G.722.1 音頻流: 0x92;
6、G.723.1 音頻流: 0x93;
7、G.729 音頻流: 0x99;
8、SVAC音頻流: 0x9B。
因為節目映射流字段只有在關鍵幀打包的時候,才會存在,所以如果要判斷PS打包的流編碼類型,就根據這個字段來判斷。)
基本流標識字段 elementary_stream_id
8位字段,指出該基本流所在PES分組的PES分組標題中stream_id字段的值。
(這個字段的定義,其中0x(C0~DF)指音頻,0x(E0~EF)為視頻)
基本流信息長度字段 elmentary_stream_info_length
16位字段,指出緊跟在該字段后的描述符的字節長度。(即這個類型的流描述長度。這個后面的字段后面的指定長度不在elementary_stream_map_length指定的范圍類。)
CRC 32**字段 CRC_32**
32位字段,它包含CRC值以在處理完整個節目流映射后在附錄A中定義的解碼器寄存器產生0輸出值。
對於這個字段的解析,我們需要取值0x000001BC的位串,指出節目流映射的開始,暫時不需要處理,讀取Header Length直接跳過即可,如果需要解析流編碼類型,必須詳細解析這個字段。
=================PES包=============================
接下來我們來分析下PES包的內容:PES包=PES header+code raw data;
先看下PES header:(來自http://blog.csdn.net/chen495810242/article/details/39207305)
接着我們來看看解析步驟:(來自MPEG-2標准文檔)
表2-17 PES分組
語 法 | 位數 | 助記符 |
---|---|---|
PES_packet(){ | ||
packet_start_code_prefix | 24 | bslbf |
stream_id | 8 | uimsbf |
PES_packet_length | 16 | uimsbf |
if(stream_id != program_stream_map | ||
&& stream_id !=padding_stream | ||
&& stream_id !=private_stream_2 | ||
&& stream_id !=ECM | ||
&& stream_id !=EMM | ||
&& stream_id !=program_stream_directory | ||
&& stream_id !=DSMCC_stream | ||
&& stream_id !=ITU-T Rec.H.222.1 type E stream){ | ||
'10' | 2 | bslbf |
PES_scrambling_control | 2 | bslbf |
PES_priority | 1 | bslbf |
data_alignment_indicator | 1 | bslbf |
copyright | 1 | bslbf |
original_or_copy | 1 | bslbf |
PTS_DTS_flags | 2 | bslbf |
ESCR_flag | 1 | bslbf |
ES_rate_flag | 1 | bslbf |
DSM_trick_mode_flag | 1 | bslbf |
additional_copy_info_flag | 1 | bslbf |
PES_CRC_flag | 1 | bslbf |
PES_extension_flag | 1 | bslbf |
PES_header_data_length | 8 | uimsbf |
if(PTS_DTS_flags =='10'){ | ||
'0010' | 4 | bslbf |
PTS[32..30] | 3 | bslbf |
marker_bit | 1 | bslbf |
PTS[29..15] | 15 | bslbf |
marker_bit | 1 | bslbf |
PTS[14..0] | 15 | bslbf |
marker_bit | 1 | bslbf |
} | ||
if(PTS_DTS_flags =='11'){ | ||
'0011' | 4 | bslbf |
PTS[32..30] | 3 | bslbf |
marker_bit | 1 | bslbf |
PTS[29..15] | 15 | bslbf |
marker_bit | 1 | bslbf |
PTS[14..0] | 15 | bslbf |
marker_bit | 1 | bslbf |
'0001' | 4 | bslbf |
PTS[32..30] | 3 | bslbf |
marker_bit | 1 | bslbf |
PTS[29..15] | 15 | bslbf |
marker_bit | 1 | bslbf |
PTS[14..0] | 15 | bslbf |
marker_bit | 1 | bslbf |
} | ||
if(ESCR_flag =='1'){ | ||
reserved | 2 | bslbf |
ESCR_base[32..30] | 3 | bslbf |
marker_bit | 1 | bslbf |
ESCR_base[29..15] | 15 | bslbf |
marker_bit | 1 | bslbf |
ESCR_base[14..0] | 15 | bslbf |
marker_bit | 1 | bslbf |
ESCR_extension | 9 | uimsbf |
marker_bit | 1 | bslbf |
} | ||
if(ES_rate_flag =='1'){ | ||
marker_bit | 1 | bslbf |
ES_rate | 22 | uimsbf |
marker_bit | 1 | bslbf |
} | ||
if (DSM_trick_mode_flag =='1'){ | ||
trick_mode_control | 3 | uimsbf |
if ( trick_mode_control = =fast_forward ) { | ||
field_id | 2 | bslbf |
intra_slice_refresh | 1 | bslbf |
frequency_truncation | 2 | bslbf |
} | ||
else if ( trick_mode_control = = slow_motion ) { | ||
rep_cntrl | 5 | uimsbf |
} | ||
else if ( trick_mode _control = = freeze_frame ) { | ||
field_id | 2 | uimsbf |
reserved | 3 | bslbf |
} | ||
else if ( trick_mode _control = = fast_reverse ) { | ||
field_id | 2 | bslbf |
intra_slice_refresh | 1 | bslbf |
frequency_truncation | 2 | bslbf |
else if ( trick_mode_control = = slow_reverse ) { | ||
rep_cntrl | 5 | uimsbf |
} | ||
else | ||
reserved | 5 | bslbf |
} | ||
if ( additional_copy_info_flag = ='1'){ | ||
marker_bit | 1 | bslbf |
additional_copy_info | 7 | bslbf |
} | ||
if (PES_CRC_flag==‘1’){ | ||
previous_PES_packet_CRC | 16 | bslbf |
} | ||
if ( PES_extension_flag =='1') { | ||
PES_private_data_flag | 1 | bslbf |
pack_header_field_flag | 1 | bslbf |
program_packet_sequence_counter_flag | 1 | bslbf |
P-STD_buffer_flag | 1 | bslbf |
reserved | 3 | bslbf |
PES_extension_flag_2 | 1 | bslbf |
if(PES_private_data_flag =='1'){ | ||
PES_private_data | 128 | bslbf |
} | ||
if (pack_header_field_flag == '1'){ | ||
pack_field_length | 8 | uimsbf |
pack_header() | ||
} | ||
if (program_packer_sequence_counter_flag == '1'){ | ||
marker_bit | 1 | bslbf |
program_packet_sequence_counter | 7 | uimsbf |
marker-bit | 1 | bslbf |
MPEG1_MPEG2_indentifier | 1 | bslbf |
original_stuff_length | 6 | uimsbf |
} | ||
if (P-STD_buffer_flag = = '1'({ | ||
'01' | 2 | bslbf |
P-STD_buffer_scale | 1 | bslbf |
P-STD_buffer_size | 13 | uimsbf |
} | ||
if (PES_extension_flag_2 == '1'{ | ||
marker_bit | 1 | bslbf |
PES_extension_field_length | 7 | uimsbf |
for(i=0;i<PES_extension_field_length;i++){ | ||
reserved | 8 | bslbf |
} | ||
} | ||
} | ||
for (i=0;i<N1;i++)} | ||
stuffing_byte | 8 | bslbf |
} | ||
for (i=0;i<N2;i++){ | ||
PES_packet_data_byte | 8 | bslbf |
} | ||
} | ||
else if (stream_id = = program_stream_map | ||
|| stream_id = = private_stream_2 | ||
|| stream_id = = ECM | ||
|| stream_id = = EMM | ||
|| stream_id = = program_stream_directory | ||
|| stream_id = = DSMCC_stream | ||
|| stream_id = = ITU-T Rec. H.222.1 type E stream ){ | ||
for (i=0;i<PES_packet_length;i++){ | ||
PES_packet_data_byte | 8 | bslbf |
} | ||
} | ||
else if (steam_id = = padding_stream){ | ||
for (i=0;i<PES_packet_length;i++){ | ||
padding_byte | 8 | bslbf |
} | ||
} | ||
} |
其中:
表2-18 Stream_id賦值
stream_id | 注 | 流 編 碼 |
---|---|---|
1011 1100 | 1 | program_stream_map(0xBC) |
1011 1101 | 2 | private_stream_1(0xBD) |
1011 1110 | padding_stream(0xBE) | |
1011 1111 | 3 | private_stream-2(0xBF) |
110x xxxx | GB/T XXXX.3或GB/T AAAA.3音頻流編號xxxx(0xC0~0xDF) | |
1110 xxxx | GB/T XXXX.2或GB/T AAAA.2視頻流編號xxxx(0xE0~0xEF) | |
1111 0000 | 3 | ECM_stream(0xF0) |
1111 0001 | 3 | EMM_stream(0xF1) |
1111 0010 | 5 | GB/T XXXX.1附錄B或GB/T XXXX.6_DSMCC_stream(0xF2) |
1111 0011 | 2 | ISO/IEC_13522_stream(0xF3) |
1111 0100 | 6 | ITU-T Rec. H.222.1類型A |
1111 0101 | 6 | ITU-T Rec. H.222.1類型B |
1111 0110 | 6 | ITU-T Rec. H.222.1類型C |
1111 0111 | 6 | ITU-T Rec. H.222.1類型D |
1111 1000 | 6 | ITU-T Rec. H.222.1類型E |
1111 1001 | 7 | ancillary_stream(0xF9) |
1111 1010…1111 1110 | 保留數據流 | |
1111 1111 | 4 | program_stream_directory(0xFF) |
符號x表示值'0'或'1'均被允許且可產生相同的流類型。流號碼由x的取值決定。注1 類型為program_stream_map的PES分組有唯一的語法,在2.5.4.1中作了規定。2 類型為private_stream_1和ISO/IEC_13352_stream的PES分組與GB/T XXXX.2及GB/T XXXX.3音頻流服從相同的PES分組語法。3 類型為private_stream_2,ECM_stream和EMM_stream的PES分組與private_stream_1相似,除了在PES_packet_length字段后未規定語法。4 類型為program_stream_directory的PES分組有唯一的語法,在2.5.5中作了規定。5 類型為DSM_CC_stream的PES分組有唯一的語法,在GB/T XXXX.6中作了規定。6 stream_id與表2-29中的stream_type 0x09相關聯。7 stream_id僅用於PES分組。PES分組在傳輸流中攜帶了來源於節目流或GB/T AAAA.1系統流的數據(參見2.4.3.7)。 |
PES分組中各字段的語義定義
分組起始碼前綴字段 packet_start_code_prefix
24位代碼,它和后面的stream_id構成了標識分組開始的分組起始碼。它是一個值為'0000 0000 0000 0000 0000 0001' (0x000001)的位串。
流標識字段 stream_id
在節目流中,它規定了基本流的號碼和類型。定義參見表2-18。在傳輸流中,它可以被設定為正確描述表2-18中定義的基本流類型的任何有效值。在傳輸流中,基本流類型在2.4.4的節目特定信息中作了規定。
PES**分組長度字段 PES_packet_length**
16位字段,指出了PES分組中跟在該字段后的字節數目。值為0表示PES分組長度要么沒有規定要么沒有限制。這種情況只允許出現在有效負載包含來源於傳輸流分組中某個視頻基本流的字節的PES分組中。
PES**加擾控制字段 PES_scrambling_control**
2位字段,表示PES分組有效負載的加擾方式。當加擾發生在PES層,PES分組標題,如果有可選字段的話也包括在內,不應被加擾(參見2-19)。
PES**優先級字段 PES_priority**
1位字段,指示PES分組中有效負載的優先級。'1'表示PES分組中有效負載的優先級高於該字段為'0'的PES分組有效負載。多路復合器能使用該字段來區分安排基本流中數據的優先級。傳輸機制不應改動該字段。
數據對齊指示符字段 data_alignment_indicator
1位標志。置'1'時表示PES分組標題后緊跟着在2.6.10中的data_alignment_indicator所指出的視頻起始碼或音頻同步字,如果有data_alignment_indicator描述符的話。若其值為'1'且無該描述符,則需要在表2-47和2-48中alignment_type '01'所表示的對齊。當值為'0'時,沒有定義是否有任何此種的對齊。
版權字段 copyright
1位字段。置'1'時表示相關PES分組有效負載的材料受到版權保護。當值為'0'時,沒有定義該材料是否受到版權保護。2.6.24中描述的版權描述符與包含PES分組的基本流相關。若描述符作用於包含PES分組的材料,則版權標志被置為'1'。
原始或拷貝字段 original_or_copy
1位字段。置'1'時表示相關PES分組有效負載的內容是原始的;值為'0'表示相關PES分組有效負載的內容是一份拷貝。
PTS DTS**標志字段 PTS_DTS_flags**
2位字段。當值為'10'時,PTS字段應出現在PES分組標題中;當值為'11'時,PTS字段和DTS字段都應出現在PES分組標題中;當值為'00'時,PTS字段和DTS字段都不出現在PES分組標題中。值'01'是不允許的。
ESCR**標志字段 ESCR_flag**
1位標志。置'1'時表示ESCR基礎和擴展字段出現在PES分組標題中;值為'0'表示沒有ESCR字段。
ES**速率標志字段 ES_rate_flag**
1位標志。置'1'時表示ES_rate字段出現在PES分組標題中;值為'0'表示沒有ES_rate字段。
DSM**特技方式標志字段 DSM_trick_mode_flag**
1位標志。置'1'時表示有8位特技方式字段;值為'0'表示沒有該字段。
附加版權信息標志字段 additional_copy_info_flag
1位標志。置'1'時表示有附加拷貝信息字段;值為'0'表示沒有該字段。
PES CRC**標志字段 PES_CRC_flag**
1位標志。置'1'時表示CRC字段出現在PES分組標題中;值為'0'表示沒有該字段。
PES**擴展標志字段 PES_extension_flag**
1位標志。置'1'時表示PES分組標題中有擴展字段;值為'0'表示沒有該字段。
PES**標題數據長度字段 PES_header_data_length**
8位字段。指出包含在PES分組標題中的可選字段和任何填充字節所占用的總字節數。該字段之前的字節指出了有無可選字段。
標記位字段 marker_bit
值為'1'的1位字段。
展現時間戳字段 PTS
展現時間與解碼時間的關系如下:PTS是一個編碼在三個分離字段中的33位數字。它指出了基本流n的第k個展現單元在系統目標解碼器中的展現時間tpn(k)。PTS的值以系統時鍾頻率的1/300(即90 kHz)為單位。展現時間由PTS根據式2-11計算而來。對編碼展現時間戳頻率的約束參見2.7.4。
PTS(k)=((system_clock_frequency×tpn(k)) DIV 300) % 233 (2-11)
其中,tpn(k)是展現單元Pn(k)的展現時間。
對音頻而言,若PES分組標題中有PTS,則它是指PES分組中開始的第一個存取單元。若PES分組中有音頻存取單元的首字節,則有一個音頻存取單元開始於該PES分組中。
對視頻而言,若PES分組標題中有PTS,則它是指包含PES分組中開始的第一個畫面起始碼的存取單元。若PES分組中有畫面起始碼的首字節,則有一個畫面起始碼開始於該PES分組中。
對音頻展現單元(PU),low_delay序列中的視頻PU以及B畫面,展現時間tpn(k)應等於tdn(k)。
對於非low_delay中的I畫面和P畫面,在存取單元(AU) k和k'之間無解碼不連續時,展現時間tpn(k)應等於下一個傳輸的I畫面或P畫面的解碼時間tdn(k) (參見2.7.5)。若有解碼不連續或流終止,則tpn(k)和tdn(k)之間的差別應與初始流一直延續,沒有不連續也沒有終止時完全相同。
注1: low_delay序列是low_delay標志被設置的視頻序列(參見GB/T XXXX.2中的6.2.2.3)。
若音頻中有濾波,則系統模型假定濾波不會導致延遲。因此,編碼時PTS所涉及的采樣與解碼時PTS所涉及的采樣是相同的。對於可伸縮編碼,參見2.7.6。
解碼時間戳字段 DTS
DTS是一個編碼在三個分離字段中的33位數字。它指出了基本流n的第j個展現單元在系統目標解碼器中的解碼時間tdn(j)。DTS的值以系統時鍾頻率的1/300 (即90 kHz)為單位。解碼時間由DTS根據式2-12計算而來:
DTS(j)=((system_clock_frequency×tdn(j)) DIV 300) % 233 (2-12)
其中,tdn(j)是存取單元An(j)的解碼時間。
對視頻而言,若PES分組標題中有DTS,則它是指包含PES分組中開始的第一個畫面起始碼的存取單元。若PES分組中有畫面起始碼的首字節,則該畫面起始碼開始於該PES分組中。
對於可伸縮編碼,參見2.7.6。
ESCR**字段 ESCR_base,ESCR_extension**
42位字段,分兩部分編碼。第一部分是一個長度為33位的字段,其值ESCR_base(i)由式2-14給出;第二部分是一個長度為9位的字段,其值ESCR_ext(i)由式2-15給出。ESCR字段指出了基本流中包含ESCR_base最后一個比特的字節到達PES-STD輸出端的期望時間(參見2.5.2.4)。
特別地
ESCR(i)=ESCR_base(i)×300+ESCR_ext(i) (2-13)
其中:
ESCR_base(i)=((system_clock_frequency×t(i)) DIV 300) % 233 (2-14)
ESCR _ext(i)=((system_clock_frequency×t(i)) DIV 1) % 300 (2-15)
ESCR和ES_rate字段(參見下面緊接的語義)包含與PES流序列相關的時間信息。這些字段應滿足2.7.3中定義的約束。
基本流速率字段 ES_rate
22位無符號整數。對於PES流而言,它指出了系統目標解碼器接收PES分組的速率。該字段在它所屬的PES分組以及同一個PES流的后續PES分組中一直有效,直到遇到一個新的ES_rate字段。該字段的值以50字節/秒為單位,且不能為0。該字段用於定義PES流的字節到達P-STD輸入端的時間(參見2.5.2.4中的定義)。在各個PES分組中,編碼在該字段中的值可能不同。
特技方式控制字段 trick_mode_control
3位字段。它表示作用於相關視頻流的特技方式。對其它類型的基本流,該字段及其后5位的含義沒有定義。trick_mode狀態的定義參見2.4.2.3的特技模式部分。
當trick_mode狀態為假時,對GB/T XXXX.2視頻而言,解碼過程輸出漸進序列中每幅畫面的次數N由repeat_first_field和top_field_first字段來規定。對GB/T AAAA.2視頻而言,由序列標題決定。
對於隔行序列,當trick_mode狀態為假時,對GB/T XXXX.2視頻而言,次數N由repeat_first_field和progressive_frame字段來規定。
當trick_mode狀態為真時,畫面的播放次數依賴於值N。
表2-20 特技方式控制值
值 | 描 述 |
---|---|
'000' | 快進 |
'001' | 慢動作 |
'010' | 凍結幀 |
'011' | 快倒 |
'100' | 慢倒 |
'101'-'111' | 保留 |
當該字段值發生變化或特技模式操作停止時,可能會出現下列情況的任意組合:
l 時基不連續;
l 解碼不連續;
l 連續性計數器不連續;
在特技模式的情況下,解碼和展現的非標准速度可能會導致視頻基本流數據中定義的某些字段值不正確。同樣,片段結構的語義約束也可能無效。這些例外所涉及的視頻語法元素為:
l bit_rate;
l vbv_delay;
l repeat_first_field;
l v_axis_positive;
l field_sequence;
l subcarrier;
l burst_amplitude;
l subcarrier_phase;
在特技模式中,解碼器不應該依賴於編碼在這些字段中的值。
標准並不要求解碼器能解碼trick_mode_control字段。但是,能解碼該字段的解碼器應能滿足以下標准要求。
快進fast forword
trick_mode_control字段中的值'000'。當該值出現時,它表示一個快進視頻流並定義了PES分組標題中后續5位的含義。intra_slice_refresh位可以被設定為'1'以指出可能有丟失的宏塊。解碼器可以用前一個解碼畫面中相同位置的宏塊來代替。表2-21中定義的field_id字段,表示應該顯示哪個或哪些字段。frequency_truncation字段指出了可能包括的一個系數受限集合。該字段值的含義如表2-22所示。
慢動作 slow motion
trick_mode_control字段中的值'001'。當該值出現時,它表示一個慢動作視頻流,並定義了PES分組標題中后續5個比特的含義。對漸進序列而言,該畫面應被顯示N×rep_cntrl時間,其中N定義如上。
對GB/T AAAA.2視頻和GB/T XXXX.2視頻漸進序列而言,該畫面應被顯示N×rep_cntrl時間,其中N定義如上。
對GB/T XXXX.2隔行序列而言,該畫面應被顯示N×rep_cntrl時間。若該畫面是一個幀畫面,則待顯示的第一個字段在top_field_first為1時應該是頂字段,在top_field_first為0時,應該是底字段(參見GB/T XXXX.2)。該字段被顯示N×rep_cntrl / 2時間。該畫面的其它字段被顯示N-N×rep_cntrl / 2時間。
凍結幀 freeze frame
trick_mode_control字段中的值'010'。當該值出現時,它表示凍結幀視頻流,並定義了PES分組標題中后續5位的含義。表2-21中定義的field_id字段,表示應該顯示哪個(些)字段。field_id字段指出了包含該字段的PES分組中開始的第一個視頻存取單元,除非該PES分組包含0個有效負載字節。在后一種情況下,field_id字段指出了最近的前一個視頻存取單元。
快倒 fast reverse
trick_mode_control字段中的值'011'。當該值出現時,它表示一個快倒視頻流並定義了PES分組標題中后續5位的含義。intra_slice_refresh位可以被設定為'1'以指出可能有丟失的宏塊。解碼器可以用前一個解碼畫面中相同位置的宏塊來代替。表2-21中定義的field_id字段,表示應該顯示哪個或哪些字段。frequency_truncation字段指出了可能包括的一個系數受限集合。該字段值的含義如表2-22“系數選擇值”所示。
慢倒 slow reverse
trick_mode_control字段中的值'100'。當該值出現時,它表示一個慢倒視頻流並定義了PES分組標題中后續5位的含義。對GB/T AAAA.2視頻和GB/T XXXX.2視頻漸進序列而言,該畫面應被顯示N×rep_cntrl時間,其中N定義如上。
對GB/T XXXX.2隔行序列而言,該畫面應被顯示N×rep_cntrl時間。若該畫面是一個幀畫面,則待顯示的第一個字段在top_field_first為1時應該是底字段,在top_field_first為'0'時,應該是頂字段(參見GB/T XXXX.2)。該字段被顯示N×rep_cntrl/2時間。該畫面的其它字段被顯示N-N×rep_cntrl / 2時間。
字段標識字段 field_id
2位字段,表示應該顯示哪個(些)字段。根據表2-21對其進行編碼。
表2-21 field_id字段控制值
值 | 描 述 |
---|---|
'00' | 僅自頂向下播放 |
'01' | 僅自底向上播放 |
'10' | 播放所有幀 |
'11' | 保留 |
片內參考字段 intra_slice_refresh
1位標志。置'1'時表示PES分組的視頻數據編碼片中可能有丟失的宏塊;置'0'時,表示上述情況可能不出現。更多的信息可參見GB/T XXXX.2。解碼器可以用前一個解碼畫面中同一個位置的宏塊來代替丟失的宏塊。
頻率截斷字段 frequency_truncation
2位字段。指出在對PES分組中數據進行編碼時可能用到受限系數集合。其值定義於表2-22。
表2-22 系數選擇值
值 | 描述 |
---|---|
'00' | 僅DC系數非0 |
'01' | 僅前三個系數非0 |
'10' | 僅前六個系數非0 |
'11' | 所有系數均可能非0 |
顯示次數控制字段 rep_cntrl
5位字段,指出隔行畫面中每一字段的顯示次數或漸進畫面顯示次數。對隔行畫面而言,頂字段或底字段是否應首先顯示是視頻序列標題中trick_mode_control字段和top_field_first字段的功能。該字段值不能為'0'。
附加版權信息字段 additional_copy_info
7位字段,包含與版權信息有關的專用數據。
前PES**分組CRC字段 previous_PES_packet_CRC**
16位字段。在對前一個PES分組(不包括該PES分組的標題)進行處理后,該字段包含一個在解碼器的16個寄存器中生成0輸出的CRC值。該CRC值與附錄A中所定義的相類似,但具有以下多項式:
x16+x12+x5+1
注2: 該CRC值是為了用於網絡維護,例如將有間隙性錯誤的源隔離開來,而不是為了供基本流解碼器使用。它僅用於計算數據字節,因為在傳輸過程中PES分組標題數據可能被修改。
PES**專用數據標志字段 PES_private_data_flag**
1位標志。置'1'時表示PES分組標題中包含專用數據;置'0'時表示PES分組標題中無專用數據。
包標題字段標志字段 pack_header_field_flag
1位標志。置'1'時表示PES分組標題中有GB/T AAAA.2包標題或節目流包標題。若該字段在包含於節目流中的PES分組中,其值應為'0'。在傳輸流中,當值為'0'時表示PES標題中無包標題。
節目分組序列計數標志字段 program_packet_sequence_counter_flag
1位標志。值為'1'時表示PES分組有program_packet_sequence_counter,MPEG1_MPEG2_identifier和original_stuff_length字段。值為'0'時表示PES分組標題中無這些字段。
P-STD**緩沖區標志字段 P-STD_buffer_flag**
1位標志。置'1'時表示PES分組標題中有P-STD_buffer_scale和P-STD_buffer_size字段。值為'0'時表示PES標題中無這些字段。
PES**擴展標志字段 PES_extension_flag_2**
1位標志,置'1'時表示有PES_extension_field_length及相關字段。
PES**專用數據字段 PES_private_data**
16位字段。包含專用數據。這些數據與其前后的字段組合在一起時,不能與packet_start_code_prefix (0x000001)沖突。
包字段長度字段 pack_field_length
8位字段。表示pack_header_field()以字節為單位時的長度。
節目分組序列計數字段 program_packet_sequence_counter
7位字段。它是一個可選的計數器,隨着來自於節目流或GB/T AAAA.1流的每一個后續的PES分組或傳輸流中具有單個節目定義的PES分組而遞增,以提供與連續性計數器(參見2.4.3.2)相似的功能。它能用於檢索節目流或原始GB/T AAAA.1流中的初始PES分組序列。該計數器在達到最大值后回卷為0。PES分組不能出現重復。因此,復合節目中任何兩個連續的PES分組不應具有相同的program_packet_sequence_counter值。
MPEG1 MPEG2**標識符字段 MPEG1_MPEG2_identifier**
1位標志。置'1'時表示PES分組攜帶的信息來自於GB/T AAAA.1流;置'0'時表示PES分組攜帶的信息來自於節目流。
初始填充長度字段 original_stuff_length
6位字段。指定用於初始GB/T XXXX.1分組標題或初始GB/T AAAA.1分組標題中的填充字節數。
P-STD**緩沖區比例字段 P-STD_ buffer_scale**
1位字段。僅當該PES分組包含於節目流中時才有意義。它指出了用來解釋后續P-STD_buffer_size字段的比例因子。若前面的stream_id表示一個音頻流,該字段值應為'0';若前面的stream_id表示一個視頻流,該字段值應為'1'。對於所有的其它流類型,其值可以為'0'或'1'。
P-STD**緩沖區大小字段 P-STD_buffer_size**
13位無符號整數。僅當該PES分組包含於節目流中時才有意義。它定義了P-STD輸入緩沖區的大小BSn。若P-STD_ buffer_scale的值為'0',那么P-STD_buffer_size以128字節為單位來度量緩沖區的大小。若P-STD_buffer_scale的值為'1',那么P-STD_buffer_size以1024字節為單位來度量緩沖區的大小。因此:
if ( P-STD_buffer_scale == 0)
BSn=P-STD_buffer_size×128 (2-16)
else
BSn=P-STD_buffer_size×1024 (2-17)
當該字段被GB/T XXXX.1系統目標解碼器收到后,其編碼值立即生效。
PES**擴展字段長度字段 PES_extension_field_length**
7位字段。指出了跟在該字段之后在PES擴展字段中直到且包括任何保留字節的數據的字節長度。
填充字節字段 stuffing_byte
8位字段,其值恆定為'1111 1111'。可以由編碼器插入以滿足通道的需求等。解碼器丟棄該字段。一個PES分組標題中只能出現32個填充字節。
PES**分組數據字節字段 PES_packet_data_byte**
該字段應該是來自於由分組的stream_id或PID所指定的基本流的連續數據字節。當基本流數據符合GB/T XXXX.2或GB/T XXXX.3時,該字段應該是與本標准的字節相對齊的字節。基本流的字節序應得到保持。該字段的字節數N由PES_packet_length字段規定。N應等於PES_packet_length減去在PES_packet_length字段的最后一個字節與第一個 PES_packet_data_byte間的字節數。
填料字節字段 padding_byte
8位字段,其值恆定為'1111 1111'。該字段被解碼器丟棄。
==================================================