编译环境:Ubuntu16.04 64位
交叉编译工具:arm-hisiv500-linux-gcc
下载合适版本的mp2v2源码,我下载的是2.0.0的bz包mp4v2_2.0.0~dfsg0.orig.tar.bz2
tar jxf mp4v2_2.0.0~dfsg0.orig.tar.bz2
cd mp4v2-2.0.0;./configure --host=arm-hisiv500-linux CC=arm-hisiv500-linux-gcc CXX=arm-hisiv500-linux-g++ --disable-debug
make
生成的libmp4v2.a在目录.libs
头文件位于include/mp4v2目录,头文件需要拷贝完全,代码中仅需要包含mp4v2.h
#include "mp4v2/mp4v2.h"
注意:移植后,链接libmp4v2.a需要加上-lstdc++选项。
注意:代码基于hi3519平台。
MP4FileHandle hMP4File = MP4CreateEx(fileName, 0, 1, 1, 0, 0, 0, 0);
MP4SetTimeScale(hMP4File, 90000);
MP4Close(hMP4File, 0);
typedef struct _MP4ENC_NaluUnit
{
int type;
int size;
unsigned char *data;
}MP4ENC_NaluUnit;
typedef struct _MP4ENC_INFO
{
unsigned int u32FrameRate;
unsigned int u32Width;
unsigned int u32Height;
unsigned int u32Profile;
}MP4ENC_INFO;
static HI_S32 Sample_MP4_ReadNalu(HI_U8 *pPack, HI_U32 nPackLen, unsigned int offSet, MP4ENC_NaluUnit *pNaluUnit)
{
int i = offSet;
while (i < nPackLen)
{
if (pPack[i++] == 0x00 && pPack[i++] == 0x00 && pPack[i++] == 0x00 && pPack[i++] == 0x01)// 开始码
{
int pos = i;
while (pos < nPackLen)
{
if (pPack[pos++] == 0x00 && pPack[pos++] == 0x00 && pPack[pos++] == 0x00 && pPack[pos++] == 0x01)
break;
}
if (pos == nPackLen)
pNaluUnit->size = pos - i;
else
pNaluUnit->size = (pos - 4) - i;
pNaluUnit->type = pPack[i] & 0x1f;
pNaluUnit->data = (unsigned char *)&pPack[i];
return (pNaluUnit->size + i - offSet);
}
}
return 0;
}
static HI_S32 Sample_MP4_WRITE(MP4FileHandle hFile, MP4TrackId *pTrackId,VENC_STREAM_S *pstStream, MP4ENC_INFO *stMp4Info)
{
int i = 0;
for (i = 0; i < pstStream->u32PackCount; i++)
{
HI_U8 *pPack = pstStream->pstPack[i].pu8Addr + pstStream->pstPack[i].u32Offset;
HI_U32 nPackLen = pstStream->pstPack[i].u32Len - pstStream->pstPack[i].u32Offset;
MP4ENC_NaluUnit stNaluUnit;
memset(&stNaluUnit, 0, sizeof(stNaluUnit));
int nPos = 0, nLen = 0;
while ((nLen = Sample_MP4_ReadNalu(pPack, nPackLen, nPos, &stNaluUnit)) != 0)
{
switch (stNaluUnit.type)
{
case H264E_NALU_SPS:
if (*pTrackId == MP4_INVALID_TRACK_ID)
{
*pTrackId = MP4AddH264VideoTrack(hFile, 90000, 90000 / stMp4Info->u32FrameRate, stMp4Info->u32Width, stMp4Info->u32Height, stNaluUnit.data[1], stNaluUnit.data[2], stNaluUnit.data[3], 3);
if (*pTrackId == MP4_INVALID_TRACK_ID)
{
return HI_FAILURE;
}
MP4SetVideoProfileLevel(hFile, stMp4Info->u32Profile);
MP4AddH264SequenceParameterSet(hFile,*pTrackId,stNaluUnit.data,stNaluUnit.size);
}
break;
case H264E_NALU_PPS:
if (*pTrackId == MP4_INVALID_TRACK_ID)
{
break;
}
MP4AddH264PictureParameterSet(hFile,*pTrackId,stNaluUnit.data,stNaluUnit.size);
break;
case H264E_NALU_IDRSLICE:
case H264E_NALU_PSLICE:
{
if (*pTrackId == MP4_INVALID_TRACK_ID)
{
break;
}
int nDataLen = stNaluUnit.size + 4;
unsigned char *data = (unsigned char *)malloc(nDataLen);
data[0] = stNaluUnit.size >> 24;
data[1] = stNaluUnit.size >> 16;
data[2] = stNaluUnit.size >> 8;
data[3] = stNaluUnit.size & 0xff;
memcpy(data + 4, stNaluUnit.data, stNaluUnit.size);
if (!MP4WriteSample(hFile, *pTrackId, data, nDataLen, MP4_INVALID_DURATION, 0, 1))
{
free(data);
return HI_FAILURE;
}
free(data);
}
break;
default :
break;
}
nPos += nLen;
}
}
return HI_SUCCESS;
}
以上代码没有封装音频,可以稍作修改,用作其他平台。
mp4v2貌似不支持h265,后续将使用其他的开源库做封装,详见我的另一篇博客《使用gpac封装mp4》。
转载请注明出处,如有错漏之处,敬请指正。