1. 简介

PS的封装格式需要支持MPEG2/MPEG4/H.264等视频和MPEG系列的音频,支持在多个层次加入私有数据,方便解码、拖动和加入延时,同时考虑到标准的PS、TS 和 RTP 封装方式间的相互转换,提高处理效率。

2. PS流封装标准

一个 PS 流或者文件可以视为多个 PS GOP,每个 GOP 是以 I 帧起始的多帧集合,各 GOP 之间的信息没有相互依赖性,可以进行剪切拼接。一个 PS GOP 由一个或多个 PS 包组成,一个 PS 包内包含一个 PSH(PS Header)和若干个 PES 包,每个 PS GOP 的第一个 PS 包应当在包头 PSH 后立即跟随一个PSM 包。PSM 包是一种特殊的 PE包,含有对其他 PES 负载数据类型的描述。PS 包内的其他 PES 的出现顺序和内容没有特殊约束,即一个 PS 包内可以包含交错出现的视频、音频和私有流等 PES 包,各 PES 包根据 PSM 的描述进行拆分。

ps流载荷h264

2.1 PSH结构

PSH (Program Stream pack Header)是 PS 包的包头,主要包含系统时间信息。常用的 PSH 的语法定义如下:

PSH (){                                  位数:  注释:
pack_start_code                             32 bit  0x 00 00 01 BA
‘01’                                        2       MPEG2 标志
system_clock_reference_base [32..30]        3
marker_bit                                  1
system_clock_reference_base [29..15]        15
marker_bit                                  1
system_clock_reference_base [14..0]         15
marker_bit                                  1
system_clock_reference_extension            9
marker_bit                                  1
program_mux_rate                            22
marker_bit                                  1
marker_bit                                  1
reserved                                    5       “1”
pack_stuffing_length                        3       此字段之后填充字节的数目
for( i = 0 ; i < pack_stuffing_length ; i++){stuffing_byte;                       8        0x FF; 每个组头不能多于 7 个}
}
  • pack_start_code32 bit 值为 0x 00 00 01 BA
  • system_clock_reference_base: 33bit。单位为 90kHz 时钟,为了处理方便建议输入接口取其高 32 位,即 45kHz 时钟;
  • system_clock_reference_extension: 9bit
SCR, system clock reference, 把系统频率的 1/300 编成 33 位码。再加上 9 位余数。
system_clock_reference_base: (system_clock_frequency* t ( ))DIV 300%2^33;
system_clock_reference_extension: (system_clock_frequency* t ( ))%300
system_clock_frequency: 27MHz
由于大部分系统不需要如此精确的时钟,建议 system_clock_reference_extension = 0。
  • marker_bit: 1bit 值为1
  • program_mux_rate: 22bit。表示接收此字段所在分组的程序流的速率。值以每秒 50 字节为单位。禁止0值。
  • pack_stuffing_length:3bit 此字段之后填充字节的数目;
  • stuffing_byte: 8bit; 值为 0x FF;考虑到 4 字节对齐问题,建议 pack_stuffing_length = 6
需要注意的是,PSH 主要包含了系统同步时间,MPEG2 part 1 并没有定义 PSH 与其后数据之间的必然关系。虽然 PSH 是一个PS包的包头,但PSH本身并不包含PS包负载数据的内容和长度信息,这些信息存在于作为PS包负载的PES包内,一个 PS包内包含的PES包个数、类型和长度没有限制。也就是说,一个PS流文件只需要有头上一个PSH,后面的视频、音频和私有数据PES包可以交错排列。但是作为系统同步的需要,PSH 应当以一定的频率在流中出现。

2.2 PES包结构

  • packet_start_code_prefix: 24bit ; 值为 0x 000001(网络序,下同);
  • stream_id: 用来区分 PES 分组负载,例如,0x e0~0x ef 表示负载为视频 PES;
stream_id 定义如下(bit 表示):
1110 xxxx 视频 PES
110x xxxx 音频 PES
1011 1101 包含时标数据的私有 PES
1011 1110 填充 PES(填充数据为 0xff)
1011 1111 不含时标数据的私有 PES,不需要与其他流同步时使用
  • PES_packet_length: 16bit。此字段后 PES 分组的字节数。‘0’表明对 PES 分组长度既没有说明也没有限制,这种情况只有在 PES 分组的有效负载是 TS 流分组中的视频原始流时才允许;
  • PES_scrambling_control: 2bit。表示 PES 分组有效负载的加密模式,不加密时建议置 0,否则置 01,10 和 11 保留。
  • PES_priority: 1bit。指示 PES 分组负载的优先级。1高优先级,0低优先级。非参考帧(包括 B 帧和海康流中使用E 帧时的 P 帧)应置 0,其余帧置 1;
  • data_alignment_indicator: 1bit。置1表明此 PES 分组头部之后是 data_stream_alignment_descriptor 所定义的访问单元数据类型。若为‘0’,则没有定义是否对准。建议当是输入单元的第一个包时置 1,其余置 0;
  • copyright: 1bit。置‘1’,表明相应 PES 分组的有效负载中的数据是有版权的,建议置 0;
  • original_or_copy: 1bit。建议置 1;
  • PTS_DTS_flag:2bit。标志 PES 首部含有 PTS, DTS 的状态。‘1x’表明 PES 首部含有 PTS,若为‘x1’, 则首部含有DTS。PTS, presentation_time_stamp, DTS, decoding_time_stamp, 建议置‘10’或‘00’;
  • ESCR_flag: 1bit。置‘1’表示 ESCR 的 base 和 extension 字段都在 PES 分组首部出现;建议置 0;
  • ES_rate_flag: 1bit。置‘1’表示 PES 首部有 ES_rate 字段;建议置 0;
  • DSM_trick_mode_flag: 1bit。置‘1’表示 PES 首部有 8bit 的 trick_mode_field;建议置 0;
  • additional_copy_info_flag: 1bit。置‘1’表示有 additional_copy_info 字段;建议置 0;
  • PES_CRC_flag: 1bit。置‘1’表示在 PES 首部分组中有 CRC 字段;建议置 0;
  • PES_extension_flag: 1bit。置‘1’可选字段出现,当需要在每帧添加私有数据时建议置 1,其余情况置 0;
  • PES_header_data_length: 8bit。表示 PES 分组首部中可选字段和填充字节的总字节数;
  • marker_bit: 1bit, 值为1;
  • PTS: 33bit。Presentation Time Stamp,表示该 PES 所包含的元素流单元的显示时刻;
  • PES_private_data_flag: 1bit。置‘1’表示 PES 分组首部中含有私有数据;当需要在每帧添加私有数据时建议置 1,其余情况置 0;
  • pack_header_field_flag: 1bit。置‘1’表示一个 ISO/IEC 11172 组首部或程序流组首部存储在此 PES 分组首部,建议置 0;
  • program_packet_sequence_counter_flag: 1bit。置‘1’表示 PES 分组中有 program_packet_sequence_counter 和 original_stuff_length 字段。建议置 0;
  • P-STD_buffer_flag: 1bit。置‘1’表示 PES 分组首部中有 P-STD_buffer_scale 和 P-STD_buffer_size 字段;建议置 0;
  • PES_private_data: 128bit 用户私有数据;
  • PES_extension_flag2: 置‘1’表示出现 PES_extension_field; 建议置 0;
  • stuffing_byte: 填充字节,根据标准编码其应当在此填入 0xff,解码器端应当将这些字节抛弃。但为
    了减少解码延时;
需要注意的是,当对原始流进行 PES 分组,尤其是需要将一帧信息断开分成多个 PES 分组时,
从第二个分组开始不需要 PTS,PES_header_data_length 和它前面的一个字节又都为 0x00,很可能与后面断开的数据组合形成 0x00 00 01 等类似的伪起始码或关键字,令解码端在收到流不完整时产生误判,因此填充字节 stuffing_byte 至少必须加入 1 byte 以确保这种误判不会发生。同时为了入一些私有信息,目前规定 stuffing_byte 至少必须加入 2byte

2.3 PSM包结构

program_stream_map(PSM)节目流映射提供了关于节目流中原始流以及它们之间相互关系的描述。作为一个 PES 分组出现

  • packet_start_code_prefix:24bit 0x00 00 01;
  • map_stream_id: 8bit 其值为 0xBC;
  • program_stream_map_length: 16bit。表示在此字段之后节目流映射的字节总数。最大为 1024;
  • current_next_indicator: 1bit。‘1’ 表示该表当前可用。‘0’表示当前不可用,下一个有效,建议置 1;
  • program_stream_map_version: 5bit。节目流映射的版本号。此版本号随着节目流映射定义的每次改变而加1。其值达到 31 后,回复到0;
  • program_stream_info_length: 16bit。表示此字段之后 descriptor 的总长度;
  • marker_bit: 1bit。值为1;
  • elementary_stream_map_length: 16bit。规定在此节目流映射中所有原始流信息的总字节数;
  • stream_type: 8bit
    对节目中各个流的编码方式进行标志,详细定义参考下表。

本文在此基础上,在 User Private 字段添加如下定义

  • elementary_stream_id: 8bit。表示此原始流所在 PES 分组的首部中 stream_id 的
  • elementary_stream_info_length: 16bit。表示此字段之后描述子的字节数。
  • CRC_32: 32bit。32bit CRC 校验码;

表中的 descriptor()描述了关于节目流和各个原始流的一些基本特征,其结构如下

3. PS封装规则

3.1 h264流封装规则

  • 一个网络抽象单元(NALu)视为一个处理单元,编码器一帧编码后输出可能是多个处理单元;
  • 除 B 帧外的帧输出的多个单元封装时应当在第一个单元头部添加 PSH;
  • 当一个 NALu 单元长度超过系统 PES 包长限制时,可以将该 NALu 分割成多个 PES 包,但每个 PES 包内不应当包含多于 1 个 NALu 的数据;
  • 每个帧的第一个处理单元所封装成的第一个 PES 包包头应当带有 PTS;
  • 每个 I 帧封装时应当在 PSH 之后添加 PSM;
  • 当元素流的基本特性(编码格式,帧率,分辨率,场编码等)发生变化时,变化后的第一帧封装时必须在 PSH 之后添加 PSM;

3.2 音频流封装规则

  • 在音视频同步时序条件允许的情况下,连续的一个或多个音频帧可以合并,每帧视为一个处理单元;
  • 当音频帧长度不大于 PES 包负载或网络传输单元所能承受的最大长度时,建议将每个音频帧封装成一个单独的 PES 包;
  • 每次处理的第一个音频帧所形成的第一个 PES 包头应当带有 PTS,其余音频帧所形成的第一个 PES 包头建议带有 PTS;
  • 当系统不包含视频流时,PSH 在流中出现的间隔应当小于 1 秒,PSM 的出现间隔应当小于 4 秒;当音频参数(码率,采样率,声道数等)发生变化时,必须在变化后立即出现 PSH 和 PSM;

3.3 私有信息封装规则

  • 在 PS 流中传输的海康私有信息一般一帧对应的一种信息视为一个处理单元;
  • 当一个处理单元的长度不大于 PES 包负载或网络传输单元所能承受的最大长度时,建议将其封装成一个单独的 PES 包;
  • 每个处理单元的第一个 PES 包包头应当带有 PTS;

关于h264相关介绍可参考:https://blog.csdn.net/www_dong/article/details/125686721

音视频学习(十)——ps流相关推荐

  1. 音视频学习-h264裸流的解析

    h264的解析代码,来自雷神的博客 //============================================================================ // ...

  2. Android音视频学习系列(十) — 基于FFmpeg + OpenSL ES实现音频万能播放器

    系列文章 Android音视频学习系列(一) - JNI从入门到精通 Android音视频学习系列(二) - 交叉编译动态库.静态库的入门 Android音视频学习系列(三) - Shell脚本入门 ...

  3. Android音视频学习系列(七) — 从0~1开发一款Android端播放器(支持多协议网络拉流本地文件)

    系列文章 Android音视频学习系列(一) - JNI从入门到精通 Android音视频学习系列(二) - 交叉编译动态库.静态库的入门 Android音视频学习系列(三) - Shell脚本入门 ...

  4. Android音视频学习系列(五) — 掌握音频基础知识并使用AudioTrack、OpenSL ES渲染PCM数据

    系列文章 Android音视频学习系列(一) - JNI从入门到精通 Android音视频学习系列(二) - 交叉编译动态库.静态库的入门 Android音视频学习系列(三) - Shell脚本入门 ...

  5. Android音视频学习系列(八) — 基于Nginx搭建(rtmp、http)直播服务器

    系列文章 Android音视频学习系列(一) - JNI从入门到精通 Android音视频学习系列(二) - 交叉编译动态库.静态库的入门 Android音视频学习系列(三) - Shell脚本入门 ...

  6. iOS完整推流采集音视频数据编码同步合成流

    1.实现原理 采集: 采集视频帧使用AVCaptureSession,采集音频帧使用Audio Unit 编码: 编码视频数据使用VideoToolbox中vtCompresssion硬编,编码音频数 ...

  7. Android音视频学习系列(九) — Android端实现rtmp推流

    系列文章 Android音视频学习系列(一) - JNI从入门到精通 Android音视频学习系列(二) - 交叉编译动态库.静态库的入门 Android音视频学习系列(三) - Shell脚本入门 ...

  8. Android音视频学习系列(六) — 掌握视频基础知识并使用OpenGL ES 2.0渲染YUV数据

    系列文章 Android音视频学习系列(一) - JNI从入门到精通 Android音视频学习系列(二) - 交叉编译动态库.静态库的入门 Android音视频学习系列(三) - Shell脚本入门 ...

  9. android音视频工程师,音视频学习 (十三) Android 中通过 FFmpeg 命令对音视频编辑处理(已开源)...

    ## 音视频学习 (十三) Android 中通过 FFmpeg 命令对音视频编辑处理(已开源) ## 视音频编辑器 ## 前言 有时候我们想对音视频进行加工处理,比如视频编辑.添加字幕.裁剪等功能处 ...

  10. 音视频 | 音视频学习-01

    音视频 | 音视频学习1 1.说一下播放器的设计过程 这里的话主要分以下几步完成: 开启一个线程进行解封装操作 .读取音频.视频的压缩数据,并进行区分.若视频数据则插入视频队列,音频数据则插入音频队列 ...

最新文章

  1. Hologres揭秘:深度解析高效率分布式查询引擎
  2. VTK读取序列化图像
  3. Android之实现Room升级需要给一个表增加一个字段
  4. 禁用win10触摸屏手势_Win10平板边缘滑动手势大全及开启/关闭方法
  5. USACO 简易题解(蒟蒻的题解)
  6. Docker的使用、底层原理及常用软件docker下载
  7. windos系统快捷键 2015-05-08 23:31 24人阅读 评论(0) 收藏...
  8. IT报表开发者必看:别加班了,真正解放双手的低代码开发神器来了
  9. CSS3过渡详解-遁地龙卷风
  10. Android 微信支付
  11. 斐讯路由器k2p a1刷官改只能刷入k2p_57_v*_*固件无法刷入k2p_mtk_v*_*版本--刷入后无法进入主页面/刷入后无法启动
  12. DM6437的学习过程
  13. c 语言条件运算符,C 语言条件运算符详细讲解
  14. solidity 函数修饰器 modifier
  15. 如何做抖音GIF表情包
  16. [沟通能力] 述职,你搞定了吗?
  17. How to recover from #39;programmers burnout(转)
  18. SpringBoot集成shiro框架
  19. AMF、UPF、SMF
  20. Java分割字符串、拼接字符串

热门文章

  1. 【数论】第1章 整数的可除性(1) 整除概念与带余除法(2) 素数
  2. Android 设置字体加粗,斜体,中划线(删除线)下划线,上标,下标,文字表情等
  3. Android Studio——简单绘图板
  4. 58同城数据库软件架构设计与实践
  5. 《第一行代码》Android学习笔记(6)数据存储
  6. 【站长工具】域名批量查询历史权重流量软件
  7. 基于单片机汽车超声波防盗系统设计(毕设课设资料)
  8. oracle 11g R2安装与配置
  9. 北京交通大学计算机考研资料汇总
  10. PerformancePoint Server 词汇表[转自MSDN]