PES是打包过的ES,已经插入PTS和DTS,一般是一个pes包为一帧图像
PES包格式:

PES再打包成TS流或PS流,往往一个PES会分存到多个ts包中,
start_code: 0x00 00 01
PES 长: 为这个字节之后整个pes 长度--es 长度+剩余ps报头长
stream_id: --- video (1110xxxx) audio (110xxxxx) 所以打包的时候 h264 定义为0xE0 G711 音频定义为0xC0 其中后4位 xxxx 都为私有协议使用。

pes包头长: 整个pes 报头长字节 (不包括es长度)- 9;
信息区:包含附加信息以及PTS和DTS PTS ,DTS 都为5个字节的信息,所以pes 头一共长度为9+10 = 19 byte,至少是19个字节,后面可以自己进行扩展。
PS流:

每一个pes header包含pts和dts,在解码时,pes-->es,音视频的同步,除了使用pts和dts以外,还会用到SCR(system clock reference),在编码时,都是由STC(system time clock)生成
ps包长度是可变的
TS也是有多个pes组合而成,ts包由包头和包数据2部分组成,长度固定,包头长4bytes,包数据和自使用区共占184bytes

打包代码
typedef unsigned char BYTE;
typedef unsigned intUINT;
typedef unsigned long long UINT64;
// define the pes head PTS head for is little end type !!!!
static void setPTS(pPTS_tag t, UINT64 _ui64PTS, UINT64 _ui64DTS)
{
t->PTS1 = (_ui64PTS >> 30) & 0x07;
t->PTS21 = (_ui64PTS >> 22) & 0xFF;
t->PTS22 = (_ui64PTS >> 15) & 0x7F;
t->PTS31 = (_ui64PTS >> 7) & 0xFF;
t->PTS32 = _ui64PTS & 0x7F;
t->DTS1 = (_ui64DTS >> 30) & 0x07;
t->DTS21 = (_ui64DTS >> 22) & 0xFF;
t->DTS22 = (_ui64DTS >> 15) & 0x7F;
t->DTS31 = (_ui64DTS >> 7) & 0xFF;
t->DTS32 = _ui64DTS & 0x7F;
}
//size = 10 for PTS DTS info
typedef struct PTS_tag
{
BYTE marker_bit:1;
BYTE PTS1:3;
BYTE fix_bit:4;
BYTE PTS21;
BYTE marker_bit1:1;
BYTE PTS22:7;
BYTE PTS31;
BYTE marker_bit2:1;
BYTE PTS32:7;
/////////////////
BYTE marker_bit3:1;
BYTE DTS1:3;
BYTE fix_bit2:4;
BYTE DTS21;
BYTE marker_bit4:1;
BYTE DTS22:7;
BYTE DTS31;
BYTE marker_bit5:1;
BYTE DTS32:7;
} __attribute__ ((packed)) *pPTS_tag;
typedef struct PES_HEADER_tag//size =9
{
BYTE packet_start_code_prefix[3];
BYTE stream_id;
BYTE PES_packet_length[2];
BYTE original_or_copy:1;
BYTE copyright:1;
BYTE data_alignment_indicator:1;
BYTE PES_priority:1;
BYTE PES_scrambling_control:2;
BYTE fix_bit:2;
BYTE PES_extension_flag:1;
BYTE PES_CRC_flag:1;
BYTE additional_copy_info_flag:1;
BYTE DSM_trick_mode_flag:1;
BYTE ES_rate_flag:1;
BYTE ESCR_flag:1;
BYTE PTS_DTS_flags:2;
BYTE PES_header_data_length;
} __attribute__ ((packed)) *pPES_HEADER_tag;
int make_pes_head(BYTE *_pHeader,UINT _iDataLen,UINT _iFrameIndex,UINT _iFrameRate,int stream_id)
{
PES_HEADER_tag ePESHeader;
ePESHeader.packet_start_code_prefix[0] = 0x00;
ePESHeader.packet_start_code_prefix[1] = 0x00;
ePESHeader.packet_start_code_prefix[2] = 0x01;
ePESHeader.stream_id = stream_id;//标志是视频还是音频
ePESHeader.PES_packet_length[0] = (_iDataLen+13) >> 8;
ePESHeader.PES_packet_length[1] = (_iDataLen+13) & 0xFF;
ePESHeader.PES_scrambling_control = 0;
ePESHeader.PES_priority = 0;
ePESHeader.data_alignment_indicator = 1;
ePESHeader.copyright = 0;
ePESHeader.original_or_copy = 0;
ePESHeader.PTS_DTS_flags = 3;
ePESHeader.ESCR_flag = 0;
ePESHeader.ES_rate_flag = 0;
ePESHeader.DSM_trick_mode_flag = 0;
ePESHeader.additional_copy_info_flag = 0;
ePESHeader.PES_CRC_flag = 0;
ePESHeader.PES_extension_flag = 0;
ePESHeader.PES_header_data_length = 10;
memcpy(_pHeader,&ePESHeader,sizeof(PES_HEADER_tag));
PTS_tag ePTS;
float fInterval = 0;
UINT64 ui64SCR = 0;
fInterval = 90000.0/_iFrameRate;//33.3333333333;
ui64SCR = fInterval * _iFrameIndex;
//填写PTS,DTS
ePTS.setPTS(ui64SCR+3600,ui64SCR);
memcpy(_pHeader + sizeof(PES_HEADER_tag),&ePTS,sizeof(PTS_tag));
int size = sizeof(PES_HEADER_tag);
size +=sizeof(PTS_tag);
return sizeof(PES_HEADER_tag)+sizeof(PTS_tag);//19字节
}