基于富瀚6630移植mp4v2库将h264流保存为mp4文件
移植mp4v2库
mp4v2-2.0.0.tar下载
- 编译静态库
cd mp4v2-2.0.0/
rm -fr build/
mkdir build/
cd build/
../configure --host=arm-mol-linux-uclibcgnueabihf --prefix=/home/lxr/lxr/test/
/*--host用来指定生成库工具的编译器,如果是在x86上面执行的,则默认的就可以,即不用配置。
--prefix用来指定生成工具的路径
*/
make
make install
make install-man
- 把生成的头文件和库拷贝到富瀚工程路径中,并修改Makefile
富瀚工程添加h264转化Mp4代码
#ps:注意看我//mp4:带头的注释,这里我就只粗略解释一下几个关键函数
详细问题可以私聊我
static void *_thread_venc_data(void *param)
{
FY_S32 i,j,k;
FY_S32 s32ChnTotal;
VENC_STREAM_S stStream;
FY_S32 s32Ret;
FY_S32 VencFd[LXR_VENC_MAX_CHN_NUM];
FY_S32 maxfd = 0;
struct timeval TimeoutVal;
fd_set read_fds;
LXRFrame_t stVideoData;
FY_S32 streamID = 0;
FY_S32 conn = 0;
//prctl(PR_SET_NAME, "GetVeuStream");
s32ChnTotal = LXR_VENC_MAX_CHN_NUM;
/******************************************
step 1: check & prepare save-file & venc-fd
******************************************/
for (i = 0; i < s32ChnTotal; i++)
{
/* Set Venc Fd. */
VencFd[i] = FY_MPI_VENC_GetFd(i);
if (VencFd[i] < 0)
{
printf("HI_MPI_VENC_GetFd failed with %#x!\n", VencFd[i]);
return NULL;
}
if (maxfd <= VencFd[i])
{
maxfd = VencFd[i];
}
}
memset(&stStream, 0, sizeof(stStream));
stStream.pstPack = (VENC_PACK_S*)malloc(sizeof(VENC_PACK_S) * 10);
if (NULL == stStream.pstPack)
{
printf("malloc stream pack failed!\n");
return NULL;
}
/******************************************
step 2: Start to get streams of each channel.
******************************************/
//mp4:CreateMP4File创建mp4文件
MP4FileHandle hMp4File = CreateMP4File("pfileMp4.mp4",1920,1080);
FY_S32 file_length = 1*10;
FY_S32 start_record = _mrecord_getsec();
while (1)
{
FY_S32 now = _mrecord_getsec();
if((now-start_record)>=file_length){
//mp4:录像时间结束关闭录像
CloseMP4File(hMp4File);
printf("record finish\n");
break;
}
FD_ZERO(&read_fds);
for (i = 0; i < s32ChnTotal; i++)
{
FD_SET(VencFd[i], &read_fds);
}
TimeoutVal.tv_sec = 2;
TimeoutVal.tv_usec = 0;
s32Ret = select(maxfd+1, &read_fds, NULL, NULL, &TimeoutVal);
if (s32Ret < 0)
{
printf("venc select failed!\n");
break;
}
else if (0 == s32Ret)
{
usleep(40000);
printf("venc select time out!\n");
continue;
}
else
{
for (i = 0; i < s32ChnTotal; i++)
{
int vi_chn = i%VI_CHN_NUM;
if(LXR_Vi_GetConnectStatus(vi_chn) == 0)
{
continue;
}
if (FD_ISSET(VencFd[i], &read_fds))
{
/*******************************************************
step 2.1 : query how many packs in one-frame stream.
*******************************************************/
VENC_CHN_STAT_S stStat;
s32Ret = FY_MPI_VENC_Query(i, &stStat);
if (FY_SUCCESS != s32Ret)
{
printf("FY_MPI_VENC_Query chn[%d] failed with %#x!\n", i, s32Ret);
break;
}
/*******************************************************
step 2.2 :suggest to check both u32CurPacks and u32LeftStreamFrames at the same time,for example:
if(0 == stStat.u32CurPacks || 0 == stStat.u32LeftStreamFrames)
{ SAMPLE_PRT("NOTE: Current frame is NULL!\n");
continue;
}
*******************************************************/
//printf("dcy test porting FY_MPI_VENC_Query =%d \n", stStat.u32LeftStreamFrames);
if (0 == stStat.u32LeftStreamFrames)
{
//SAMPLE_PRT("NOTE: chn%d is null!\n", i);
//u32ContinQueryFailCnt++;
continue;
}
/*******************************************************
step 2.4 : call mpi to get one-frame stream
*******************************************************/
stStream.u32PackCount = stStat.u32CurPacks;
if(stStream.u32PackCount > 0)
{
//printf("dcy test porting enc ch=%d\n", i);
s32Ret = FY_MPI_VENC_GetStream(i, &stStream, FY_TRUE);
}
if (FY_SUCCESS != s32Ret)
{
printf("dcy test get stream fail\n");
continue;
}
else
{
//只接受第一通道数据
if(i==0){
for (k= 0; k < stStream.u32PackCount; k++)
{
printf("[lxr_test_venc][func=%s][LINE=%d][data0=%d][data1=%d][data2=%d][data3=%d]\n",__func__,__LINE__,\
stStream.pstPack[k].pu8Addr[0],stStream.pstPack[k].pu8Addr[1],stStream.pstPack[k].pu8Addr[2],stStream.pstPack[k].pu8Addr[3]);
stVideoData.buffer = stStream.pstPack[k].pu8Addr + stStream.pstPack[k].u32Offset;
printf("[lxr_test_venc][func=%s][LINE=%d][data0=%d][data1=%d][data2=%d][data3=%d][nalu_head=0x%x]\n",__func__,__LINE__,\
stVideoData.buffer[0],stVideoData.buffer[1],stVideoData.buffer[2],stVideoData.buffer[3],stVideoData.buffer[4]);
stVideoData.len = stStream.pstPack[k].u32Len - stStream.pstPack[k].u32Offset;
//mp4:从富瀚获取流接口接受到数据后,通过WriteH264Data_lxr解析到MP4文件
WriteH264Data_lxr(hMp4File,&stVideoData);
//u32Offset:码流包中有效数据与码流包首地址 pu8Addr 的偏移
}
}
}
/*******************************************************
step 2.6 : release stream
*******************************************************/
s32Ret = FY_MPI_VENC_ReleaseStream(i, &stStream);
if (FY_SUCCESS != s32Ret)
{
break;
}
}
//usleep(10*1000);
}
make
make myboard=mc6630/demoboard test