核心问题
使用ffmpeg拉流并解码后,将AVFrame解码后的yuvj420p数据发送给venc编码失败
我的尝试
更换编码格式
将HI_PIXEL_FORMAT_YUV_PLANAR_420换为HI_PIXEL_FORMAT_YUV_SEMIPLANAR_420,即yuv420p格式换为420sp格式,并将avframe中的数据转换为yuv420sp格式后,成功编码,推测不是通道配置问题
将avframe中的yuvj420p数据改为yuv420p数据,采用HI_PIXEL_FORMAT_YUV_PLANAR_420格式,依旧失败
报错内容
代码参数
核心问题
使用ffmpeg拉流并解码后,将AVFrame解码后的yuvj420p数据发送给venc编码失败
我的尝试
更换编码格式
将HI_PIXEL_FORMAT_YUV_PLANAR_420换为HI_PIXEL_FORMAT_YUV_SEMIPLANAR_420,即yuv420p格式换为420sp格式,并将avframe中的数据转换为yuv420sp格式后,成功编码,推测不是通道配置问题
将avframe中的yuvj420p数据改为yuv420p数据,采用HI_PIXEL_FORMAT_YUV_PLANAR_420格式,依旧失败
报错内容
代码参数
int Dvpp_encode::dvpp_init() { hi_s32 ret = 0; ret = hi_mpi_sys_init(); if (ret != HI_SUCCESS) { ERROR_LOG("hi_mpi_sys_init failed ret:%x", ret); return -1; } hi_venc_chn chn = 0; hi_venc_chn_attr attr{}; memset(&attr, 0, sizeof(hi_venc_chn_attr)); attr.venc_attr.type = HI_PT_H264; attr.venc_attr.profile = 0; attr.venc_attr.max_pic_width = 640; attr.venc_attr.max_pic_height = 640; attr.venc_attr.pic_width = 640; attr.venc_attr.pic_height = 640; attr.venc_attr.buf_size = 640 * 640 * 3; attr.venc_attr.is_by_frame = HI_TRUE; attr.rc_attr.rc_mode = HI_VENC_RC_MODE_H264_VBR; attr.rc_attr.h264_vbr.gop = 30; attr.rc_attr.h264_vbr.stats_time = 1; attr.rc_attr.h264_vbr.src_frame_rate = 25; attr.rc_attr.h264_vbr.dst_frame_rate = 25; attr.rc_attr.h264_vbr.max_bit_rate = 4000; attr.gop_attr.gop_mode = HI_VENC_GOP_MODE_NORMAL_P; attr.gop_attr.normal_p.ip_qp_delta = 3; ret = hi_mpi_venc_create_chn(chn, &attr); if (ret != 0) { ERROR_LOG("hi_mpi_venc_create_chn failed"); return -1; } // 5.通知编码器启动接收输入数据 hi_venc_start_param recv_param{}; recv_param.recv_pic_num = -1; ret = hi_mpi_venc_start_chn(chn, &recv_param); return 0; }int Dvpp_encode::enc(yuv_block &yuv) { int ret; hi_venc_chn chn = 0; hi_video_frame_info frame{}; memset(&frame, 0, sizeof(hi_video_frame_info)); frame.mod_id = HI_ID_VENC; frame.v_frame.width = 640; frame.v_frame.height = 640; frame.v_frame.field = HI_VIDEO_FIELD_FRAME; // frame.v_frame.pixel_format = HI_PIXEL_FORMAT_YUV_SEMIPLANAR_420; frame.v_frame.pixel_format = HI_PIXEL_FORMAT_YUV_PLANAR_420; // frame.v_frame.pixel_format = HI_PIXEL_FORMAT_RGB_888; frame.v_frame.video_format = HI_VIDEO_FORMAT_LINEAR; frame.v_frame.compress_mode = HI_COMPRESS_MODE_NONE; // 预留参数 // frame.v_frame.dynamic_range = HI_DYNAMIC_RANGE_SDR8; // frame.v_frame.color_gamut = HI_COLOR_GAMUT_BT709; // 输入数据没问题,检测过了,是device数据且步长为640,320,320 frame.v_frame.virt_addr[0] = yuv.data[0]; frame.v_frame.virt_addr[1] = yuv.data[1]; frame.v_frame.virt_addr[2] = yuv.data[2]; frame.v_frame.width_stride[0] = yuv.linesize[0]; frame.v_frame.width_stride[1] = yuv.linesize[1]; frame.v_frame.width_stride[2] = yuv.linesize[2]; unsigned int idx = 0; /*是否使能slice_temporal_mvp_enabled_flag语法(表示帧间预测是否使用时域MV(MotionVector)预测), 取值范围如下,但仅H265协议下该参数生效: 0:slice_temporal_mvp_enabled_flag为True,表示使用时域MV预测。 1:slice_temporal_mvp_enabled_flag为False,表示不使用时域MV预测。*/ frame.v_frame.frame_flag = 1; // VENC编码场景下,针对每一帧设置该参数时,按照帧的顺序,该参数值需递增且为偶数,例如,第一帧时该参数值设置为2,第二帧时该参数值设置为4,以此类推。 frame.v_frame.time_ref = idx * 2; // 图像时间戳。 frame.v_frame.pts = idx * 30; idx++; ret = hi_mpi_venc_send_frame(chn, &frame, 1000); if (ret != 0) { ERROR_LOG("hi_mpi_venc_send_frame failed,error=%X", ret); return -1; } else { INFO_LOG("hi_mpi_venc_send_frame %d success", idx - 1); } int32_t epollFd = 0; int32_t fd = hi_mpi_venc_get_fd(0); // 预留字段,传入正数 ret = hi_mpi_sys_create_epoll(1, &epollFd); if (ret != 0) { ERROR_LOG("hi_mpi_sys_create_epoll failed"); return -1; } hi_dvpp_epoll_event event; event.events = HI_DVPP_EPOLL_IN; event.data = (void *)(unsigned long)(fd); ret = hi_mpi_sys_ctl_epoll(epollFd, HI_DVPP_EPOLL_CTL_ADD, fd, &event); int32_t eventCount = 0; // 编码完成前,会超时阻塞在这里,一旦完成,才会往下执行 ret = hi_mpi_sys_wait_epoll(epollFd, &event, 3, 1000, &eventCount); if (ret != 0) { ERROR_LOG("hi_mpi_sys_wait_epoll failed"); return -1; } hi_venc_chn_status stat; ret = hi_mpi_venc_query_status(chn, &stat); INFO_LOG("当前帧的码流包个数=%d", stat.cur_packs); hi_venc_stream stream; stream.pack_cnt = stat.cur_packs; stream.pack = new hi_venc_pack[stream.pack_cnt]; ret = hi_mpi_venc_get_stream(chn, &stream, 1000); if (ret != 0) { ERROR_LOG("hi_mpi_venc_get_stream failed"); return -1; } for (int i = 0; i < stream.pack_cnt; i++) { std::string out_path = std::to_string(i) + ".h264"; FILE *fp = fopen(out_path.c_str(), "wb"); // 打开文件用于写入二进制数据 fwrite(stream.pack[i].addr, 1, stream.pack[i].len * 2, fp); // 写入数据到文件 std::cout << "sucess" << std::endl; fclose(fp); char cmd[500]; sprintf(cmd, "ffmpeg -i %s -c:v mjpeg %d.jpg", out_path.c_str(), i); system(cmd); } // 8.释放输入内存和输出码流 ret = hi_mpi_venc_release_stream(chn, &stream); delete[] stream.pack; return 0; }