ffmpeg录制mp4视频遇到的问题
Posted: 2024-06-07 11:25
您好,我按照您在这个链接viewtopic.php?p=2090#p2090提到的思路,实现ffmpeg封装h264流生成mp4文件的功能。现在出现了很奇怪的问题,我用第399行的代码可以实现录制mp4视频并播放,但是用第400行的代码录制的mp4视频就无法播放了。
从逻辑上,这仅仅是改变触发录制的时刻,不涉及ffmpeg录制的逻辑,难道是开发板还需要配置什么吗,您有什么排查的思路吗? 说明:
1、由于系统刚启动没有获取到摄像头画面是黑的,因此我添加了loopcount变量,用作一段延时。
2、如果有画面即录制,实时时间还没返回,因此第400行的目的只是检测当前系统时间然后再开启录制。
3、我尝试过clean重新编译,也是同样的现象。
修改rkipc的video.c的rkipc_get_venc_0函数如下:
主要就是在while中创建mp4文件,在获取到h264数据的时候写入到mp4,写入一定的帧数后关闭当前的mp4文件,创建下一个mp4文件。
使用ffmpeg的库创建mp4文件、写入视频帧、关闭mp4文件的代码如下图:
从逻辑上,这仅仅是改变触发录制的时刻,不涉及ffmpeg录制的逻辑,难道是开发板还需要配置什么吗,您有什么排查的思路吗? 说明:
1、由于系统刚启动没有获取到摄像头画面是黑的,因此我添加了loopcount变量,用作一段延时。
2、如果有画面即录制,实时时间还没返回,因此第400行的目的只是检测当前系统时间然后再开启录制。
3、我尝试过clean重新编译,也是同样的现象。
修改rkipc的video.c的rkipc_get_venc_0函数如下:
主要就是在while中创建mp4文件,在获取到h264数据的时候写入到mp4,写入一定的帧数后关闭当前的mp4文件,创建下一个mp4文件。
Code: Select all
static void *rkipc_get_venc_0(void *arg) {
LOG_DEBUG("#Start %s thread, arg:%p\n", __func__, arg);
prctl(PR_SET_NAME, "RkipcVenc0", 0, 0, 0);
VENC_STREAM_S stFrame;
VI_CHN_STATUS_S stChnStatus;
int ret = 0;
int loopCount = 0,flag=0;
stFrame.pstPack = malloc(sizeof(VENC_PACK_S));
AVFormatContext *output_context = NULL; //输出上下文
while (g_video_run_) {
//获取当前时间
time_t t = time(NULL);
struct tm tm = *localtime(&t);
loopCount++;
if(loopCount==250){
// if ((tm.tm_year + 1900 >= 2024)&&(record_is_run==0)){
record_tm = tm; //记录下开始录制的时间
strftime(filename, sizeof(filename), "/root/%Y%m%d%H%M%S.mp4", &record_tm);
output_context = create_mp4_file(filename);
mp4_frame_index = 0;
record_is_run = 1;
}
// 5.get the frame
ret = RK_MPI_VENC_GetStream(VIDEO_PIPE_0, &stFrame, 1000);
if (ret == RK_SUCCESS) {
void *data = RK_MPI_MB_Handle2VirAddr(stFrame.pstPack->pMbBlk);
if (g_rtsplive && g_rtsp_session_0) {
pthread_mutex_lock(&g_rtsp_mutex);
rtsp_tx_video(g_rtsp_session_0, data, stFrame.pstPack->u32Len,
stFrame.pstPack->u64PTS);
rtsp_do_event(g_rtsplive);
pthread_mutex_unlock(&g_rtsp_mutex);
}
if ((stFrame.pstPack->DataType.enH264EType == H264E_NALU_IDRSLICE) ||
(stFrame.pstPack->DataType.enH264EType == H264E_NALU_ISLICE) ||
(stFrame.pstPack->DataType.enH265EType == H265E_NALU_IDRSLICE) ||
(stFrame.pstPack->DataType.enH265EType == H265E_NALU_ISLICE)) {
rk_storage_write_video_frame(0, data, stFrame.pstPack->u32Len,
stFrame.pstPack->u64PTS, 1);
if (enable_rtmp)
rk_rtmp_write_video_frame(0, data, stFrame.pstPack->u32Len,
stFrame.pstPack->u64PTS, 1);
} else {
rk_storage_write_video_frame(0, data, stFrame.pstPack->u32Len,
stFrame.pstPack->u64PTS, 0);
if (enable_rtmp)
rk_rtmp_write_video_frame(0, data, stFrame.pstPack->u32Len,
stFrame.pstPack->u64PTS, 0);
}
if(record_is_run){
if(mp4_frame_index == 0){ //第一帧不写入
mp4_frame_index++;
}else{
write_video_frame(output_context, data, stFrame.pstPack->u32Len, (mp4_frame_index-1)*40);
mp4_frame_index++;
}
}
if(mp4_frame_index==250){
mp4_frame_index = 0;
close_mp4_file(output_context); //关闭mp4文件
printf("close file\n");
record_is_run = 0;
}
// 7.release the frame 释放当前帧
ret = RK_MPI_VENC_ReleaseStream(VIDEO_PIPE_0, &stFrame);
if (ret != RK_SUCCESS) {
LOG_ERROR("RK_MPI_VENC_ReleaseStream fail %x\n", ret);
}
} else {
LOG_ERROR("RK_MPI_VENC_GetStream timeout %x\n", ret);
}
}
if (stFrame.pstPack)
free(stFrame.pstPack);
return 0;
}