分享

MP4v2

 海漩涡 2018-06-04
//
#include "CMp4Encoder.h"
#include "debug.h"
#include "ahead.h"

//
//
CMp4Encoder::CMp4Encoder()
: m_vWidth(1280),
  m_vHeight(720),
  m_vFrateR(15),
  m_vTimeScale(90000),
  m_mp4FHandle(NULL),
  m_aTrackId(MP4_INVALID_TRACK_ID),
  m_vTrackId(MP4_INVALID_TRACK_ID),
  m_vFrameDur(3000),
  m_lastVPTS(0),
  m_lastAPTS(0)
{
}

bool CMp4Encoder::InitMp4Encoder(const char *mp4_path)
{
//------------------------------------------------------------------------------------- file handle
m_mp4FHandle = MP4Create(mp4_path, 0); 
if (m_mp4FHandle == MP4_INVALID_FILE_HANDLE){
msg(M_INFO, "mp4fileHandle Error!");
return false;  
}
MP4SetTimeScale(m_mp4FHandle, m_vTimeScale);

//------------------------------------------------------------------------------------- audio track

m_aTrackId = MP4AddAudioTrack(m_mp4FHandle, 16000, 2048, MP4_MPEG4_AUDIO_TYPE);
if (m_aTrackId == MP4_INVALID_TRACK_ID){
msg(M_INFO, "AudioTrack Error!");
return false;
}

MP4SetAudioProfileLevel(m_mp4FHandle, 0x2);
uint8_t aacConfig[2] = {0x15, 0x88}; // OK base on faac source code
MP4SetTrackESConfiguration(m_mp4FHandle,m_aTrackId,aacConfig,2);

//-------------------------------------------------------------------------------------
return true;
}


//------------------------------------------------------------------------------------------------- Mp4Encode说明
// 【x264编码出的NALU规律】
// 第一帧 SPS【0 0 0 1 0x67】 PPS【0 0 0 1 0x68】 SEI【0 0 1 0x6】 IDR【0 0 1 0x65】
// p帧      P【0 0 0 1 0x41】
// I帧    SPS【0 0 0 1 0x67】 PPS【0 0 0 1 0x68】 IDR【0 0 1 0x65】
// 【mp4v2封装函数MP4WriteSample】
// 此函数接收I/P nalu,该nalu需要用4字节的数据大小头替换原有的起始头,并且数据大小为big-endian格式
//-------------------------------------------------------------------------------------------------

void CMp4Encoder::Mp4VEncode(unsigned char * _naluData,int _naluSize, unsigned long long pts)
{
int index = -1;

if (_naluData == NULL)
{
printf("_naluData=NULL\n");
return;
}

// printf("%d:%02x %02x %02x %02x %02x\n", _naluSize, _naluData[0], _naluData[1], _naluData[2], _naluData[3], _naluData[4]);
if(_naluData[0]==0 && _naluData[1]==0 && _naluData[2]==0 && _naluData[3]==1 && _naluData[4]==0x67){
index = _NALU_SPS_;
}
if(index != _NALU_SPS_ && m_vTrackId == MP4_INVALID_TRACK_ID){
return;
}
if(_naluData[0]==0 && _naluData[1]==0 && _naluData[2]==0 && _naluData[3]==1 && _naluData[4]==0x68){
index = _NALU_PPS_;
}
if(_naluData[0]==0 && _naluData[1]==0 && _naluData[2]==0 && _naluData[3]==1 && _naluData[4]==0x65){
index = _NALU_I_;
}
if(_naluData[0]==0 && _naluData[1]==0 && _naluData[2]==0 && _naluData[3]==1 && _naluData[4]==0x61){
index = _NALU_P_;
}
switch(index){
case _NALU_SPS_:     
if(m_vTrackId == MP4_INVALID_TRACK_ID){
m_vTrackId = MP4AddH264VideoTrack  
(m_mp4FHandle,   
m_vTimeScale,   
m_vTimeScale / m_vFrateR,  
m_vWidth,      // width  
m_vHeight,    // height  
_naluData[5], // sps[1] AVCProfileIndication  
_naluData[6], // sps[2] profile_compat  
_naluData[7], // sps[3] AVCLevelIndication  
3);            // 4 bytes length before each NAL unit  
if (m_vTrackId == MP4_INVALID_TRACK_ID)  
{  
msg(M_INFO,"add video track failed ");  
return;  
}
MP4SetVideoProfileLevel(m_mp4FHandle, 1); //  Simple Profile @ Level 3
}  
MP4AddH264SequenceParameterSet(m_mp4FHandle, m_vTrackId, _naluData + 4, _naluSize - 4); 

break;
case _NALU_PPS_:
MP4AddH264PictureParameterSet(m_mp4FHandle, m_vTrackId, _naluData + 4, _naluSize - 4);  
break;

case _NALU_I_: 
case _NALU_P_:
{
unsigned int* p = (unsigned int*)_naluData; 
*p = htonl(_naluSize - 4);
//
if(!MP4WriteSample\
(m_mp4FHandle, m_vTrackId, _naluData, _naluSize, \
m_lastVPTS == 0 ? MP4_INVALID_DURATION : ( (pts - m_lastVPTS) / 100 * 9)/*m_vFrameDur/44100*90000*/, 0, 1)){  
printf("write video P sample err,m_vTrackId=%u\n", m_vTrackId);
return;  
}
m_lastVPTS = pts;
m_vFrameDur = 0;
break;
}

}

}

void CMp4Encoder::Mp4AEncode(unsigned char * _aacData,int _aacSize, unsigned long long pts)
{
if(m_vTrackId == MP4_INVALID_TRACK_ID){
return;
}

// unsigned long long diff = 0;
// diff = pts - m_lastVPTS;
MP4WriteSample(m_mp4FHandle, m_aTrackId, _aacData, _aacSize ,\
m_lastAPTS == 0 || (pts - m_lastVPTS) > 200 * 1000 ? MP4_INVALID_DURATION : ( (pts - m_lastAPTS) / 1000 * 16), \
0, 1);
m_lastAPTS = pts;

// printf("v:%llu\ta:%llu\t%llu\n", m_lastVPTS, m_lastAPTS, m_lastAPTS - m_lastVPTS);
m_vFrameDur += 1024;
}

void CMp4Encoder::CloseMp4Encoder()
{
if(m_mp4FHandle){  
MP4Close(m_mp4FHandle);  
m_mp4FHandle = NULL;  
}

m_aTrackId = MP4_INVALID_TRACK_ID;
m_vTrackId = MP4_INVALID_TRACK_ID;
m_lastVPTS = 0;
m_lastAPTS = 0;
m_vFrameDur = 0;
}

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多