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

PS流(ISO13818和GB28181)分析相关推荐

  1. Gb28181之Ps流解析H264

    gb28181发送码流选择PS流,PS流在封装H264的数据.本文详细描述如何通过ps流解析H264码流. *************************PSM流解析*************** ...

  2. 使用ffmpeg来探测GB28181的ps流

    GB28181 GB28181 是我国内的标准,现在到2016修订后比较成熟,有很多可取之处,当然,依然是建立在sip协议之上,比起rtmp协议来说,他的优点是复用了rtp协议和sdp协议,这一点很优 ...

  3. GB28181 PS流传输格式详解

    1.PS流传输格式预览 1.视频关键帧的封装 RTP + PS header + PS system header + PS system Map + PES header +h264 data 2. ...

  4. ps流 转发_VAG.Node: GB28181 信令服务服务,支持PS流到RTMP流的转码和转发功能

    VAG.Node GB28181 VAG(Video Agent Gateway) ,主要应用将 GB28181协议 摄像机/硬盘录像机 的PS流(H264/H265)打包推送到RTMP服务器发布. ...

  5. javaCV简单解析gb28181的rtp ps流,并推流到rtmp服务

    本文转自javacv社区三群管理员"赶在时间前面":过去的过去了的博客,感谢大佬倾情贡献,支持javacv社区发展和壮大. 国标gb28181全系列都可以参考过去的过去了的博客,再 ...

  6. RTP载荷PS流全面分析

    1.PS流封包格式 视频关键帧的封装:    RTP|PS header|PS system header|PS system Map|PES header|H264 data 视频非关键帧的封装:R ...

  7. gb28181 ps流文件解析

    基础 假定是udp上接收包,端口 5060 ,如果是tcp是要加一些额外得代码, 可以使用jrtplib,或者自己写udpserver 放出udp socket 接收包,当然使用jrtplib等稍微简 ...

  8. 最简单的h264/h265/svac和g711封装成ps流符合gb28181过检码流要求

    最近做国标级联,鼓捣了个简单的ps流封装,做分享做笔记. #include <stdint.h> #include <string> #include <memory.h ...

  9. gb28181简单解包rtp ps流,推出rtmp(java版基于springboot):六、解包rtp ps流,推出rtmp

    解析流程参考 https://blog.csdn.net/chen495810242/article/details/39207305 代码基于github上的修改 https://github.co ...

最新文章

  1. 51js 的json编辑器
  2. 用Javascript为DropDownList添加一个Item至定义索引位置
  3. mysql 查看某个表缓存情况_MySQL 查询缓存 QUERY_CACHE
  4. 电脑常用音频剪辑软件_如何使用音频剪辑软件,快速剪辑任意格式音频!
  5. git项目比对_Argo 项目入驻 CNCF,一文解析 Kubernetes 原生工作流
  6. android 蓝牙通知,android – 蓝牙低能耗通知
  7. iis8使用url2.0模块实现http跳转到https
  8. Centos启用rz/sz命令
  9. 俄罗斯网络间谍被指攻击斯洛伐克政府长达数月
  10. python气象数据处理与绘图(9)_《利用Python进行数据分析·第2版》第9章 绘图和可视化...
  11. Red Hat Linux 启动流程图
  12. Docker零基础入门指南(一):Docker介绍
  13. 数学建模灵敏度分析是什么?为什么获奖论文基本都有!【科研交流】
  14. Word文件怎么在方框里面打对勾
  15. 达梦数据库如何把EXCEL的数据导入到表中?
  16. java获取汉字拼音_Java获取汉字对应的拼音(全拼或首字母)
  17. Flutter 全能型选手GetX —— 依赖管理
  18. 《大明王朝》雪崩前,精英们的狂欢
  19. 刘韧:和人物共同创作人物故事
  20. 一键实现前程无忧(51job)简历不停刷新(selenium)

热门文章

  1. requests基操/爬取调用百度翻译
  2. 装机部落GhostXP_SP3国庆装机版2013
  3. 一款基于jQuery仿淘宝红色分类导航
  4. Android 集成QQ登录,获取头像与昵称
  5. 图像特征提取(纹理特征)
  6. 最干净的U盘启动工具:微PE
  7. Spring Security + OAuth2.0
  8. ICC_floorplan流程笔记
  9. 企业微信监控服务器数据接入,如何在alertmanager报警中添加企业微信监控报警
  10. 支付宝开放平台入驻流程及失败解决