PS流(ISO13818和GB28181)分析

1、理论基础:

PSM(PS System map)提供了对PS流中的原始流和他们之间的相互关系的描述信息;PSM是作为一个PES分组出现,当stream_id == 0xBC时,说明此PES包是一个PSM;PSM是紧跟在系统头部后面的;PSM是作为PS包的payload存在的;

PS头( pack_header):0x000001BA

系统头部( system_header):0x000001BB我们一般只要先首先判断是否存在系统头,然后我们读取系统头的头部长度,即PS SYSTEM HEADER LENGTH部分,然后根据头部的长度,跳过PS系统头。进入下一个部分,即PS 节目流映射头

节目流映射( program_stream_map):0x000001BC的位串,指出节目流映射的开始,暂时不需要处理,读取Header Length直接跳过即可,如果需要解析流编码类型,必须详细解析这个字段。

GB28181 对RTP 传输的数据负载类型有规定(参考GB28181 附录B),负载类型中96-127,RFC2250 建议96 表示PS 封装,建议97 为MPEG-4,建议98 为H264

即我们接收到的RTP 包首先需要判断负载类型,若负载类型为96,则采用PS 解复用,将音视频分开解码。若负载类型为98,直接按照H264 的解码类型解码。注:此方法不一定准确,取决于打包格式是否标准。

PES视频流:0x000001E0

PES音频流:0x000001C0

针对H264 做如下PS 封装:每个IDR NALU 前一般都会包含SPS、PPS 等NALU,因此将SPS、PPS、IDR 的NALU 封装为一个PS 包,包括ps 头,然后加上PS system header,PS system map,PES header+h264 raw data。所以一个IDR NALU PS 包由外到内顺序是:PSheader| PS system header | PS system Map | PES header | h264 raw data。对于其它非关键帧的PS 包,就简单多了,直接加上PS头和PES 头就可以了。顺序为:PS header | PES header | h264raw data。以上是对只有视频video 的情况,如果要把音频Audio也打包进PS 封装,也可以。当有音频数据时,将数据加上PES header 放到视频PES 后就可以了。顺序如下:PS 包=PS头|PES(video)|PES(audio),再用RTP 封装发送就可以了。

PS码流文件分析:

mpeg-ps里面是没有音视频的编码信息的,如果是像pcm或pcma、pcmu这类音频,是不知道声道、采样率、采样位数的,所以就无法播放。实际上mpeg-ps中pcma、pcmu的声道、采样率、采样位数一般是1,8000,16,特别是28181协议中。

注:后面跟着就是自定义的描述内容(海康在这里放入了复合流的私有描述:两字节复合流描述字(40 0E)+内容(用于放置全局时间,编码设备型号等相关信息)+两字节复合流描述字(41 12)(可选)+内容(用于描述设备与通道号),所以长度就不是00 00)

 

接着我们来看看解析步骤:(来自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'){

'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

'0001'

 4

bslbf

DTS[32..30]

 3

bslbf

marker_bit

 1

bslbf

DTS[29..15]

15

bslbf

marker_bit

 1

bslbf

DTS[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)。

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值