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