h.264 ES流转PS流 包括头文件定义部分

h.264 ES流转PS流 包括头文件定义部分  

2012-12-19 12:01:06|  分类: h.264 |字号 订阅

这些天一直在做h.264 ES流转PS流的方法。现在把我的一点小经验总结下。

1、将SPS,PPS和IDR帧组合成一个PES包,其他I、P、B帧分别为一个PES包。

2、每个IDR帧的封包顺序从外到里分为为PS头,PSM头,PES头。其他I、P、B帧从外到里为PS头,PES头。

3、可以将PES包里的PES_packet_length填写为0x00,但封装后的PS流,一般VLC和ffmjpeg可以播放,但storm不可以。如果要填充PES_packet_length的话,需要进行分包,因为PES_packet_length是两个字节,最大支持0xFFFF个字节,当数据包长度大于这个的时候需要分包。分包时不用管NALU的完整性。

4、时间戳和SRC的对应方法:时间戳(ms) = SRC/90 

 

 

其中包头打包的部分代码如下:

int make_ps_packet_header(unsigned char *_pHeader,unsigned int _iHeaderLen,unsigned int _iResolutionFlag,unsigned int _iFrameIndex)
{
 if (NULL == _pHeader || _iHeaderLen < sizeof(PS_HEADER_tag))
 {
  return -1;
 }

 PS_HEADER_tag ePSHeader;
 
 float fInterval = 33.3333333333;
 UINT64 ui64SCR = fInterval * _iFrameIndex * 90;
 ePSHeader.setSystem_clock_reference_base(ui64SCR);
 ePSHeader.setProgram_mux_rate(160001);

 memcpy(_pHeader,&ePSHeader,sizeof(PS_HEADER_tag));

 return sizeof(PS_HEADER_tag);
}

int make_pes_packet_header(unsigned char *_pHeader,unsigned int _iHeaderLen,unsigned int _iDataLen,unsigned int _iFrameIndex)
{
 if(NULL == _pHeader || _iHeaderLen < sizeof(PES_HEADER_tag) + sizeof(PTS_tag))
 {
  return -1;
 }

 PES_HEADER_tag ePESHeader;
 unsigned short sDataLen = sizeof(PES_HEADER_tag) + sizeof(PTS_tag) + _iDataLen;
 
/*
 memcpy(ePESHeader.PES_packet_length,&sDataLen,2);
 ePESHeader.PES_packet_length[0] = sDataLen >> 8;
 ePESHeader.PES_packet_length[1] = sDataLen & 0xFF;
*/

 ePESHeader.original_or_copy = 0;
 ePESHeader.copyright = 0;
 ePESHeader.data_alignment_indicator = 1;
 ePESHeader.PES_priority = 0;
 ePESHeader.PES_scrambling_control = 0;

 ePESHeader.PES_extension_flag = 0;
 ePESHeader.PES_CRC_flag = 0;
 ePESHeader.additional_copy_info_flag = 0;
 ePESHeader.DSM_trick_mode_flag = 0;
 ePESHeader.ES_rate_flag = 0;
 ePESHeader.ESCR_flag = 0;
 ePESHeader.PTS_DTS_flags = 0x02;

 ePESHeader.PES_header_data_length = 0x05;

 memcpy(_pHeader,&ePESHeader,sizeof(PES_HEADER_tag));

 PTS_tag ePTS;
 float fInterval = 33.3333333333;
 UINT64 ui64SCR = fInterval * _iFrameIndex * 90;
 ePTS.setPTS(ui64SCR);

 memcpy(_pHeader + sizeof(PES_HEADER_tag),&ePTS,sizeof(PTS_tag));

 return sizeof(PES_HEADER_tag) + sizeof(PTS_tag);
}

 

结构体的定义如下所示:

 

/* writer:Kevin.liu Date:2010-08-06 */ #ifndef __HEADER_PACK_HEADER_DEF_H__ #define __HEADER_PACK_HEADER_DEF_H__

 

#ifdef _WIN32 typedef unsigned __int64 UINT64; #else typedef long long UINT64; #endif

 

typedef struct PS_HEADER_tag {  unsigned char pack_start_code[4];  //'0x000001BA'

 

 unsigned char system_clock_reference_base21:2;  unsigned char marker_bit:1;  unsigned char system_clock_reference_base1:3;  unsigned char fix_bit:2;    //'01'    unsigned char system_clock_reference_base22;

 

 unsigned char system_clock_reference_base31:2;  unsigned char marker_bit1:1;  unsigned char system_clock_reference_base23:5;

 

 unsigned char system_clock_reference_base32;

 unsigned char system_clock_reference_extension1:2;  unsigned char marker_bit2:1;  unsigned char system_clock_reference_base33:5; //system_clock_reference_base 33bit

 

 unsigned char marker_bit3:1;  unsigned char system_clock_reference_extension2:7; //system_clock_reference_extension 9bit    unsigned char program_mux_rate1;

 

 unsigned char program_mux_rate2;

 unsigned char marker_bit5:1;  unsigned char marker_bit4:1;  unsigned char program_mux_rate3:6;

 

 unsigned char pack_stuffing_length:3;  unsigned char reserved:5;    PS_HEADER_tag()  {   pack_start_code[0] = 0x00;   pack_start_code[1] = 0x00;   pack_start_code[2] = 0x01;   pack_start_code[3] = 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 = 0;   system_clock_reference_extension2 = 0;  }    void getSystem_clock_reference_base(UINT64 &_ui64SCR)  {   _ui64SCR = (system_clock_reference_base1 << 30) | (system_clock_reference_base21 << 28)    | (system_clock_reference_base22 << 20) | (system_clock_reference_base23 << 15)    | (system_clock_reference_base31 << 13) | (system_clock_reference_base32 << 5)    | (system_clock_reference_base33);

 

 }

 void setSystem_clock_reference_base(UINT64 _ui64SCR)  {   system_clock_reference_base1 = (_ui64SCR >> 30) & 0x07;   system_clock_reference_base21 = (_ui64SCR >> 28) & 0x03;   system_clock_reference_base22 = (_ui64SCR >> 20) & 0xFF;   system_clock_reference_base23 = (_ui64SCR >> 15) & 0x1F;   system_clock_reference_base31 = (_ui64SCR >> 13) & 0x03;   system_clock_reference_base32 = (_ui64SCR >> 5) & 0xFF;   system_clock_reference_base33 = _ui64SCR & 0x1F;  }

 

 void getProgram_mux_rate(unsigned int &_uiMux_rate)  {   _uiMux_rate = (program_mux_rate1 << 14) | (program_mux_rate2 << 6) | program_mux_rate3;  }

 

 void setProgram_mux_rate(unsigned int _uiMux_rate)  {   program_mux_rate1 = (_uiMux_rate >> 14) & 0xFF;   program_mux_rate2 = (_uiMux_rate >> 6) & 0xFF;   program_mux_rate3 = _uiMux_rate & 0x3F;  }    }*pPS_HEADER_tag;

 

typedef struct PES_HEADER_tag {  unsigned char packet_start_code_prefix[3];  unsigned char stream_id;  unsigned char PES_packet_length[2];

 

 unsigned char original_or_copy:1;  unsigned char copyright:1;  unsigned char data_alignment_indicator:1;  unsigned char PES_priority:1;  unsigned char PES_scrambling_control:2;  unsigned char fix_bit:2;

 

 unsigned char PES_extension_flag:1;  unsigned char PES_CRC_flag:1;  unsigned char additional_copy_info_flag:1;  unsigned char DSM_trick_mode_flag:1;  unsigned char ES_rate_flag:1;  unsigned char ESCR_flag:1;  unsigned char PTS_DTS_flags:2;

 

 unsigned char PES_header_data_length;

 PES_HEADER_tag()  {   packet_start_code_prefix[0] = 0x00;   packet_start_code_prefix[1] = 0x00;   packet_start_code_prefix[2] = 0x01;

 

  PES_packet_length[0] = 0x00;   PES_packet_length[1] = 0x00;

 

  stream_id = 0xE0;   fix_bit = 0x02;  }

 

}*pPES_HEADER_tag;

typedef struct PTS_tag {  unsigned char marker_bit:1;  unsigned char PTS1:3;  unsigned char fix_bit:4;

 

 unsigned char PTS21;

 unsigned char marker_bit1:1;  unsigned char PTS22:7;

 

 unsigned char PTS31;

 unsigned char marker_bit2:1;  unsigned char PTS32:7;

 

 PTS_tag()  {   fix_bit = 0x02;   marker_bit = 0x01;   marker_bit1 = 0x01;   marker_bit2 = 0x01;  }

 

 void getPTS(UINT64 &_ui64PTS)  {   _ui64PTS = (PTS1 << 30) | (PTS21 << 22)    | (PTS22 << 15) | (PTS31 << 7) | (PTS32);     }

 

 void setPTS(UINT64 _ui64PTS)  {   PTS1 = (_ui64PTS >> 30) & 0x07;   PTS21 = (_ui64PTS >> 22) & 0xFF;   PTS22 = (_ui64PTS >> 15) & 0x7F;   PTS31 = (_ui64PTS >> 7) & 0xFF;   PTS32 = _ui64PTS & 0x7F;  } }*pPTS_tag;

 

typedef struct PSM_tag {  unsigned char packet_start_code_prefix[3];  unsigned char map_stream_id;  unsigned char program_stream_map_length[2];    unsigned char program_stream_map_version:5;  unsigned char reserved1:2;  unsigned char current_next_indicator:1;

 

 unsigned char marker_bit:1;  unsigned char reserved2:7;

 

 unsigned char program_stream_info_length[2];  unsigned char elementary_stream_map_length[2];  unsigned char stream_type;  unsigned char elementary_stream_id;  unsigned char elementary_stream_info_length[2];  unsigned char CRC_32[4];

 

 PSM_tag()  {   packet_start_code_prefix[0] = 0x00;   packet_start_code_prefix[1] = 0x00;   packet_start_code_prefix[2] = 0x01;     map_stream_id = 0xBC;   program_stream_map_length[0] = 0x00;   program_stream_map_length[1] = 0x0E;

 

  program_stream_map_version = 0x00;   current_next_indicator = 0x01;   reserved1 = 0x03;   program_stream_map_version = 0x00;

 

  reserved2 = 0x7F;   marker_bit = 0x01;

 

  program_stream_info_length[0] = 0x00;   program_stream_info_length[1] = 0x00;

 

  elementary_stream_map_length[0] = 0x00;   elementary_stream_map_length[1] = 0x04;      stream_type = 0x1B;   elementary_stream_id = 0xE0;

 

  elementary_stream_info_length[0] = 0x00;   elementary_stream_info_length[1] = 0x00;

 

  CRC_32[3] = 0x45;   CRC_32[2] = 0xBD;   CRC_32[1] = 0xDC;   CRC_32[0] = 0xF4;  } }*pPSM_tag;

 

#endif

你可能感兴趣的:(h.264 ES流转PS流 包括头文件定义部分)