MPEG-PS封装格式
据传输媒体的质量不同,MPEG-2中定义了两种复合信息流:传送流(TS:TransportStream)和节目流(PS:ProgramStream)

PS文件分为3层:ps层(Program Stream)、pes层(Packet Elemental Stream)、es层(Elementary Stream)。es层就是音视频数据,pes层是在音视频数据上加了时间戳等对数据帧的说明信息,ps层是在pes层上加入了数据流识别和传输的必要信息。
1.Ps和Ts的区别
2.Ps文件结构
一个完整的MPEG-2文件就是一个PS流文件。使用Elecard StreamAnalyzer打开一个MPEG-2文件,得到下面信息。

2.1.Ps层

Ps层主要由pack header和数据组成,pack header中各个bit的意义如下

我们可以通过分析一个示例文件来了解它

scr += packet_size * 90000LL / (mux_rate * 50LL);
struct pack_header
{
unsigned char pack_start_code[];
unsigned char system_clock_reference_base21 : ;
unsigned char marker_bit : ;
unsigned char system_clock_reference_base1 : ;
unsigned char fix_bit : ;
unsigned char system_clock_reference_base22;
unsigned char system_clock_reference_base31 : ;
unsigned char marker_bit1 : ;
unsigned char system_clock_reference_base23 : ;
unsigned char system_clock_reference_base32;
unsigned char system_clock_reference_extension1 : ;
unsigned char marker_bit2 : ;
unsigned char system_clock_reference_base33 : ;
unsigned char marker_bit3 : ;
unsigned char system_clock_reference_extension2 : ;
unsigned char program_mux_rate1;
unsigned char program_mux_rate2;
unsigned char marker_bit5 : ;
unsigned char marker_bit4 : ;
unsigned char program_mux_rate3 : ;
unsigned char pack_stuffing_length : ;
unsigned char reserved : ; pack_header()
{
pack_start_code[] = 0x00;
pack_start_code[] = 0x00;
pack_start_code[] = 0x01;
pack_start_code[] = 0xBA;
fix_bit = 0x01;
marker_bit = 0x01;
marker_bit1 = 0x01;
marker_bit2 = 0x01;
marker_bit3 = 0x01;
marker_bit4 = 0x01;
marker_bit5 = 0x01;
reserved = 0x1F;
pack_stuffing_length = 0x00;
system_clock_reference_extension1 = ;
system_clock_reference_extension2 = ;
} void getSystem_clock_reference_base(UINT64 &_ui64SCR)
{
_ui64SCR = (system_clock_reference_base1 << ) | (system_clock_reference_base21 << )
| (system_clock_reference_base22 << ) | (system_clock_reference_base23 << )
| (system_clock_reference_base31 << ) | (system_clock_reference_base32 << )
| (system_clock_reference_base33);
} void setSystem_clock_reference_base(UINT64 _ui64SCR)
{
system_clock_reference_base1 = (_ui64SCR >> ) & 0x07;
system_clock_reference_base21 = (_ui64SCR >> ) & 0x03;
system_clock_reference_base22 = (_ui64SCR >> ) & 0xFF;
system_clock_reference_base23 = (_ui64SCR >> ) & 0x1F;
system_clock_reference_base31 = (_ui64SCR >> ) & 0x03;
system_clock_reference_base32 = (_ui64SCR >> ) & 0xFF;
system_clock_reference_base33 = _ui64SCR & 0x1F;
} void getProgram_mux_rate(unsigned int &_uiMux_rate)
{
_uiMux_rate = (program_mux_rate1 << ) | (program_mux_rate2 << ) | program_mux_rate3;
} void setProgram_mux_rate(unsigned int _uiMux_rate)
{
program_mux_rate1 = (_uiMux_rate >> ) & 0xFF;
program_mux_rate2 = (_uiMux_rate >> ) & 0xFF;
program_mux_rate3 = _uiMux_rate & 0x3F;
}
};
这样的好处是可以直接通过
pack_header header;
header.setProgram_mux_rate();
header.setSystem_clock_reference_base();
os.write((char *)&header, sizeof(header));
来写入文件,但是不方便抽象成类,所以就参考ffmpeg使用了put_bits的方式
class PackHeader : public HeaderBase
{
public:
UINT64 SCRBase;
UINT8 SCRExt;
UINT32 programMuxRate;
UINT8 stuffingLength; PackHeader();
virtual ~PackHeader();
int Serialize();
};
然后在类中加一个序列化函数,来将整个类序列化
int PackHeader::Serialize()
{
int calcBinaryBitLen = //pack_start_code
+ // '01'
+ //system_clock_reference_base [32..30]
+ //marker_bit
+ //system_clock_reference_base [29..15]
+ //marker_bit
+ //system_clock_reference_base [14..0]
+ //marker_bit
+ //system_clock_reference_extension
+ //marker_bit
+ // program_mux_rate
+ //marker_bit
+ //marker_bit
+ //reserved
+ ; //pack_stuffing_length if (stuffingLength > )
{
for (int i = ; i < stuffingLength; i++)
{
calcBinaryBitLen += ;
}
} if ((calcBinaryBitLen / ) > binaryLen)
{
if (binary)
delete[] binary; binary = new BYTE[calcBinaryBitLen / ];
} binaryLen = calcBinaryBitLen / ; BYTE* p = binary;
bits_buffer_t bw; bits_initwrite(&bw, binaryLen, p);
bits_write(&bw, , PACK_HEADER_START_CODE); //pack_start_code
bits_write(&bw, , 0x1); // '01'
bits_write(&bw, , (SCRBase >> ) & 0x07); //system_clock_reference_base [32..30]
bits_write(&bw, , ); //marker_bit
bits_write(&bw, , (SCRBase >> ) & 0x7FFF); //system_clock_reference_base [29..15]
bits_write(&bw, , ); //marker_bit
bits_write(&bw, , SCRBase & 0x7FFF); //system_clock_reference_base [14..0]
bits_write(&bw, , ); //marker_bit
bits_write(&bw, , SCRExt); //system_clock_reference_extension
bits_write(&bw, , ); //marker_bit
bits_write(&bw, , programMuxRate & 0x3FFFFF); // program_mux_rate
bits_write(&bw, , ); //marker_bit
bits_write(&bw, , ); //marker_bit
bits_write(&bw, , 0x1F); //reserved
bits_write(&bw, , stuffingLength & 0x07); //pack_stuffing_length if (stuffingLength > )
{
for (int i = ; i < stuffingLength; i++)
{
bits_write(&bw, , 0xFF); //stuffing
}
}
return ;
}
对于DVD而言,一般开始的pack里面还有一个System header

我们也可以通过分析一个示例文件来了解它

2.2.Pes层
Pes层由编码的音频或视频数据(es)加上Pes头组成的,Pes头主要是通过PTS和DTS来提供音视频同步的信息,Pes头的各个bit的意义如下所示



Pes头之后紧跟着的就是编码的音频或视频数据(es)了,对于DVD而言,一个program pack的大小问0x800,所以一帧MPEG-2视频被分在多个Pes包里,不够一个包的就写在下一帧的第一个pack里,或在Pes Header后面填充FF(PES_header_data_length要加上填充的字节数)。
MPEG-PS封装格式的更多相关文章
- FFmpeg封装格式处理
本文为作者原创,转载请注明出处:https://www.cnblogs.com/leisure_chn/p/10506636.html FFmpeg封装格式处理相关内容分为如下几篇文章: [1]. F ...
- 音视频处理之PS封装的介绍与使用20180928
1.PS封装介绍MPEG2-PS是一种多路复用数字音频,视频等的封装容器.PS是Program Stream(程序流或节目流)的简称.程序流将一个或多个分组但有共同的时间基准的基本数据流(PES)合并 ...
- FLV封装格式及分析器工具
http://blog.csdn.net/leixiaohua1020/article/details/17934487 FLV封装原理 FLV格式的封装原理,贴上来辅助学习之用. FLV(F ...
- 最简单的基于FFmpeg的封装格式处理:视音频复用器(muxer)
===================================================== 最简单的基于FFmpeg的封装格式处理系列文章列表: 最简单的基于FFmpeg的封装格式处理 ...
- 最简单的基于FFmpeg的封装格式处理:视音频分离器(demuxer)
===================================================== 最简单的基于FFmpeg的封装格式处理系列文章列表: 最简单的基于FFmpeg的封装格式处理 ...
- 最简单的基于FFmpeg的封装格式处理:视音频分离器简化版(demuxer-simple)
===================================================== 最简单的基于FFmpeg的封装格式处理系列文章列表: 最简单的基于FFmpeg的封装格式处理 ...
- 视音频编解码学习工程:TS封装格式分析器
=====================================================视音频编解码学习工程系列文章列表: 视音频编解码学习工程:H.264分析器 视音频编解码学习工 ...
- 视音频编解码学习工程:FLV封装格式分析器
===================================================== 视音频编解码学习工程系列文章列表: 视音频编解码学习工程:H.264分析器 视音频编解码学习 ...
- 视频流PS,PS封装H264
出处: ISOIEC 13818-1 PS流: PS流由PSGOP组成,每个PSGOP是由I帧起始的多帧集合,每个GOP之间没有相互依赖信息,可以剪切拼接. | PSGOP0 | PSGOP1 | P ...
- 【多媒体封装格式详解】--- AAC ADTS格式分析
ADTS全称是(Audio Data Transport Stream),是AAC的一种十分常见的传输格式. 记得第一次做demux的时候,把AAC音频的ES流从FLV封装格式中抽出来送给硬件解码器时 ...
随机推荐
- 命令行编译vs10项目工程
参考网址: http://www.oschina.net/question/234345_42135 1. 1.1.使用的命令行为:开始-->所有程序--> vs2020 --> V ...
- Windows环境下CGAL的安装
1 准备工作 下载cmake 下载CGAL安装包 学习如何设置环境变量 安装Qt运行demos. libQGLViewer用来运行 3D CGAL demos. 确定Visual Studio 相应的 ...
- 51nod 1281 二分
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1281 隐藏话题 1281 山峰和旗子 题目来源: Codility 基准 ...
- python--关于if __name__==__main__的解释
在解释之前首先我们看下__name__这个变量存的是什么: #!/usr/bin/env python # -*- coding:utf-8 -*- print(__name__) 结果: __mai ...
- power designer 设计数据库生成到oracle数据库
一.概念模型设计 1. 创建工程,创建概念设计模型,在快捷菜单栏调出 palette 找到表格工具,在主界面中创建表格. 2. 创建出的表格,双击进入设计模式 -------------------- ...
- bzoj4513 储能表
求 $\sum\limits_{i=0}^{n-1} \sum\limits_{j=0}^{m-1} max((x \space xor \space j) - k,0)$ ,膜 $p$ $n,m \ ...
- Real-Time Rendering (2) - 变换和矩阵(Transforms and Matrics)
http://blog.csdn.net/silangquan/article/details/9970673 提要 在图形的计算中,比如旋转.缩放.平移.投影等操作,矩阵都扮演着极其重要的角色,它是 ...
- Oracle存储过程创建及调用
在大型数据库系统中,有两个很重要作用的功能,那就是存储过程和触发器.在数据库系统中无论是存储过程还是触发器,都是通过SQL 语句和控制流程语句的集合来完成的.相对来说,数据库系统中的触发器也是一种存储 ...
- bzoj 2839 集合计数 —— 二项式反演
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2839 设 \( f(i) \) 为至少 \( i \) 个选择,则 \( f(i) = C_ ...
- phpstorm win/mac git配置 破解
http://blog.csdn.net/fenglailea/article/details/53350080 phpstorm中git配置教程: http://blog.csdn.net/knig ...