接口:
static int OpenInputFile(MP4FileHandle &hMP4File, MP4TrackId &m_videoTrackId, uint32_t &numSamples, const char *fileName);
static int ReadConfigData(MP4FileHandle &hMP4File, MP4TrackId &m_videoTrackId,unsigned char **sps, int *spsSize, unsigned char **pps, int *ppsSize);
static void CloseInputFile(MP4FileHandle &hMP4File);
static int ReadH264Data(MP4FileHandle &hMP4File, MP4TrackId &m_videoTrackId, uint32_t numSamples, int sampleId, unsigned char** ppData,int *size, int cfgsize);
static void ReleaseConfigData(unsigned char **sps, unsigned char **pps);
static void ReleaseH264Data(unsigned char** ppData);
打开输入文件,查找视频轨:
int Mp4v2Util::OpenInputFile(MP4FileHandle &hMP4File, MP4TrackId &m_videoTrackId, uint32_t &numSamples, const char *fileName)
{
if (hMP4File == NULL) {
DM_NATIVE_ERR_PRINT("open file %s.\n", fileName);
hMP4File = MP4Read(fileName);
if (hMP4File == MP4_INVALID_FILE_HANDLE) {
DM_NATIVE_ERR_PRINT("open file failed %s.\n", fileName);
return -1;
}
uint32_t trackId = MP4_INVALID_TRACK_ID;
uint32_t numOfTracks = MP4GetNumberOfTracks(hMP4File);
DM_NATIVE_ERR_PRINT("numOfTracks=%d\n", numOfTracks);
// find video track
for (uint32_t tmpTrackId = 1; tmpTrackId <= numOfTracks; tmpTrackId++) {
const char* trackType = MP4GetTrackType(hMP4File, tmpTrackId);
DM_NATIVE_ERR_PRINT("%d trackType=%s\n", tmpTrackId, trackType);
if (MP4_IS_VIDEO_TRACK_TYPE(trackType)) {
trackId = tmpTrackId;
break;
}
}
if (trackId == MP4_INVALID_TRACK_ID) {
DM_NATIVE_ERR_PRINT("Can't find video track\n");
CloseOutputFile(hMP4File);
return -1;
}
m_videoTrackId = trackId;
//DM_NATIVE_ERR_PRINT("m_videoTrackId=%d\n", m_videoTrackId);
numSamples = MP4GetTrackNumberOfSamples(hMP4File, m_videoTrackId);
}
return 0;
}
读取视频文件的SPS和PPS:
int Mp4v2Util::ReadConfigData(MP4FileHandle &hMP4File, MP4TrackId &m_videoTrackId,unsigned char **sps, int *spsSize, unsigned char **pps, int *ppsSize)
{
// read sps/pps
uint8_t **seqheader;
uint8_t **pictheader;
uint32_t *pictheadersize;
uint32_t *seqheadersize;
uint32_t ix;
const char nalHeader[] = {0x00, 0x00, 0x00, 0x01};
MP4GetTrackH264SeqPictHeaders(hMP4File, m_videoTrackId, &seqheader, &seqheadersize, &pictheader,
&pictheadersize);
int size = 4;
//sps
for (ix = 0; seqheadersize[ix] != 0; ix++) {
size += seqheadersize[ix];
}
*sps = (uint8_t *)malloc(size);
uint8_t *spsBase = *sps;
memcpy(spsBase, nalHeader, 4);
spsBase += 4;
for (ix = 0; seqheadersize[ix] != 0; ix++) {
memcpy(spsBase,seqheader[ix], seqheadersize[ix]);
spsBase += seqheadersize[ix];
free(seqheader[ix]);
}
free(seqheader);
free(seqheadersize);
*spsSize = size;
//pps
size = 4;
for (ix = 0; pictheadersize[ix] != 0; ix++) {
size += pictheadersize[ix];
}
*pps = (uint8_t *)malloc(size);
uint8_t *ppsBase = *pps;
memcpy(ppsBase, nalHeader, 4);
ppsBase += 4;
for (ix = 0; pictheadersize[ix] != 0; ix++) {
memcpy(ppsBase, pictheader[ix], pictheadersize[ix]);
ppsBase += pictheadersize[ix];
free(pictheader[ix]);
}
free(pictheader);
free(pictheadersize);
*ppsSize = size;
return 0;
}
读取H264裸流编码帧:
int Mp4v2Util::ReadH264Data(MP4FileHandle &hMP4File, MP4TrackId &m_videoTrackId, uint32_t numSamples, int sampleId, unsigned char** ppData,int *size, int cfgsize)
{
// read samples
uint8_t* pSample = NULL;
uint32_t sampleSize = 0;
const char nalHeader[] = {0x00, 0x00, 0x00, 0x01};
if (!MP4ReadSample(hMP4File, m_videoTrackId, sampleId, &pSample, &sampleSize)) {
DM_NATIVE_ERR_PRINT("read sampleId %u error\n", sampleId);
if (pSample != NULL) {
free(pSample);
pSample = NULL;
}
return -1;
}
if (pSample != NULL) {
uint32_t pktsize = pSample[0];
pktsize <<= 8;
pktsize |= pSample[1];
pktsize <<= 8;
pktsize |= pSample[2];
pktsize <<= 8;
pktsize |= pSample[3];
// DM_NATIVE_DEBUG_PRINT("test %02X %02X %02X %02X pktsize=%d sampleSize=%d\n",pSample[0],pSample[1],pSample[2],pSample[3], pktsize, sampleSize );
if((pktsize + 4) == sampleSize) {
memcpy(pSample, nalHeader, 4);
*ppData = pSample;
*size = sampleSize;
} else if((pktsize + 4) < sampleSize) {
int leftsize = sampleSize-cfgsize;
if (leftsize > 4) {
uint32_t pktsize1 = pSample[cfgsize+0];
pktsize1 <<= 8;
pktsize1 |= pSample[cfgsize+1];
pktsize1 <<= 8;
pktsize1 |= pSample[cfgsize+2];
uint32_t pktsize2 = pktsize1;
pktsize1 <<= 8;
pktsize1 |= pSample[cfgsize+3];
if ((pktsize2+3) == leftsize) {
memcpy(&pSample[cfgsize], &nalHeader[1], 3);
}else if ((pktsize2+4) == leftsize) {
memcpy(&pSample[cfgsize], &nalHeader[0], 4);
}
}
memcpy(pSample, nalHeader, 4);
*ppData = pSample;
*size = sampleSize;
} else {
DM_NATIVE_ERR_PRINT("ReadH264Data ERR %02X %02X %02X %02X\n",pSample[0],pSample[1],pSample[2],pSample[3] );
free(pSample);
*ppData = NULL;
*size = 0;
}
return 0;
}
return -2;
}
释放数据:
void Mp4v2Util::ReleaseConfigData(unsigned char **sps, unsigned char **pps)
{
if(*sps) {
free(*sps);
*sps = NULL;
}
if(*pps) {
free(*pps);
*pps = NULL;
}
}
void Mp4v2Util::ReleaseH264Data(unsigned char** ppData)
{
if(*ppData) {
free(*ppData);
*ppData = NULL;
}
}
关闭文件:
void Mp4v2Util::CloseInputFile(MP4FileHandle &hMP4File)
{
DM_NATIVE_DEBUG_PRINT("CloseOutputFile end\n");
if(hMP4File) MP4Close(hMP4File, 0);
hMP4File = NULL;
}