// #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; } |
|
来自: 海漩涡 > 《openSourceProject》