是参考 sample_venc实现的功能,最大的分辨率修改为2592*1944,麻烦看看问题可能 出在了哪里,谢谢
代码:
通道绑定
static void sample_vi_bind_venc(k_s32 vicap_dev, k_s32 vicap_chn, k_s32 venc_chn)
{
k_mpp_chn venc_mpp_chn;
k_mpp_chn vi_mpp_chn;
k_s32 ret;
vi_mpp_chn.mod_id = K_ID_VI;
vi_mpp_chn.dev_id = vicap_dev;//0
vi_mpp_chn.chn_id = vicap_chn;//1
venc_mpp_chn.mod_id = K_ID_VENC;
venc_mpp_chn.dev_id = vicap_dev;//0
venc_mpp_chn.chn_id = venc_chn;//0
ret = kd_mpi_sys_bind(&vi_mpp_chn, &venc_mpp_chn);
if (ret)
{
printf("kd_mpi_sys_bind failed:0x%x\n", ret);
}
return;
}
一、以下为vb池配置
//初始化视频缓存区
static k_s32 sample_vicap_vb_init(vicap_device_obj *dev_obj)
{
k_s32 ret = 0;
k_vb_config config;
k_vb_supplement_config supplement_config;
memset(&config, 0, sizeof(config));
config.max_pool_cnt = 64;
printf("%s, enable dev(0)\n", __func__);
printf("%s, enable chn(0), k(0)\n", __func__);
/**ch0 **/
k_u16 out_width = dev_obj->out_win[0].width; //输出宽度
k_u16 out_height = dev_obj->out_win[0].height; //输出高度
config.comm_pool[0].blk_cnt = VICAP_OUTPUT_BUF_NUM; //缓冲区数量 6
config.comm_pool[0].mode = VB_REMAP_MODE_NOCACHE; //无缓存重映射
config.comm_pool[0].blk_size = VICAP_ALIGN_UP((out_width * out_height * 3 / 2) + 4096, VICAP_ALIGN_1K);//计算每个缓冲区的大小,并且进行对齐
dev_obj->buf_size[0] = config.comm_pool[0].blk_size;//每个缓冲区大小
printf("%s, dev(0) chn(0) pool(0) buf_size(%d) blk_cnt(%d)\n", __func__,dev_obj->buf_size[0], config.comm_pool[0].blk_cnt);
/**ch1 **/
config.comm_pool[1].blk_cnt = INPUT_BUF_CNT * 1;//缓冲区数量 6
config.comm_pool[1].blk_size = FRAME_BUF_SIZE;//计算每个缓冲区的大小,并且进行对齐
config.comm_pool[1].mode = VB_REMAP_MODE_NOCACHE;//无缓存重映射
dev_obj->buf_size[1] = config.comm_pool[1].blk_size;//每个缓冲区大小
printf("%s, dev(0) chn(1) pool(1) buf_size(%d) blk_cnt(%d)\n", __func__,dev_obj->buf_size[1], config.comm_pool[1].blk_cnt);
config.comm_pool[2].blk_cnt = OUTPUT_BUF_CNT ;//15*1
config.comm_pool[2].blk_size = STREAM_BUF_SIZE;
config.comm_pool[2].mode = VB_REMAP_MODE_NOCACHE;//没有缓存重新映射
dev_obj->buf_size[2] = config.comm_pool[2].blk_size;//每个缓冲区大小
printf("%s, dev(0) venc(0) pool(2) buf_size(%d) blk_cnt(%d)\n", __func__,dev_obj->buf_size[2], config.comm_pool[2].blk_cnt);
ret = kd_mpi_vb_set_config(&config); //设置MPP视频缓存池属性
if (ret) {
printf("vb_set_config failed ret:%d\n", ret);
return ret;
}
memset(&supplement_config, 0, sizeof(supplement_config));
supplement_config.supplement_config |= VB_SUPPLEMENT_JPEG_MASK;
ret = kd_mpi_vb_set_supplement_config(&supplement_config);//设置 VB 内存的附加信息,这里增加的是DCF信息,如拍摄的时间、拍摄的时候是否有闪光灯、数码缩放倍数等
if (ret) {
printf("vb_set_supplement_config failed ret:%d\n", ret);
return ret;
}
ret = kd_mpi_vb_init();//初始化 MPP 视频缓存池
if (ret) {
printf("vb_init failed ret:%d\n", ret);
return ret;
}
return 0;
}
二、相机通道1设置
//
//通道1,输出 25921944
/*/
memset(&chn_attr, 0, sizeof(k_vicap_chn_attr));
//vicap channel attr set
chn_attr.out_win.width = device_obj.out_win[1].width; //设置输出图像宽度
chn_attr.out_win.height = device_obj.out_win[1].height; //设置输出图像高度
chn_attr.crop_win.width = device_obj.in_width;//sensor input
chn_attr.crop_win.height = device_obj.in_height;//sensor input
chn_attr.scale_win = chn_attr.out_win;
chn_attr.crop_enable = device_obj.crop_enable[0];
chn_attr.scale_enable = K_FALSE; //缩放关闭
chn_attr.chn_enable = K_TRUE; //通道使能
chn_attr.alignment = 12;//venc需要待编码的数据物理地址4K对齐
chn_attr.pix_format = device_obj.out_format[0];//图像格式yuv420
chn_attr.buffer_num = VICAP_OUTPUT_BUF_NUM;//缓冲区数量
chn_attr.buffer_size = device_obj.buf_size[1];//缓冲区大小
printf("sample_vicap, set dev(0) chn(1) attr, buffer_size(%d), out size[%dx%d]\n", \
chn_attr.buffer_size, chn_attr.out_win.width, chn_attr.out_win.height);
printf("sample_vicap out_win h_start is %d ,v_start is %d \n", chn_attr.out_win.h_start, chn_attr.out_win.v_start);
ret = kd_mpi_vicap_set_chn_attr(0, 1, chn_attr);//设置VICAP设备通道属性
三、解码通道设置
//
//设置解码通道
//
k_venc_rc_mode rc_mode = K_VENC_RC_MODE_MJPEG_FIXQP;///mjpeg固定QP模式/
k_payload_type type = K_PT_JPEG;//有效负载类型
k_u32 q_factor = 45;//因素
k_venc_chn_attr venc_attr;
memset(&g_venc_conf, 0, sizeof(venc_conf_t));//清空应用结构体
memset(&venc_attr, 0, sizeof(k_venc_chn_attr));//清零
venc_attr.venc_attr.pic_width = enc_width;/通道图片宽度/
venc_attr.venc_attr.pic_height = enc_height;/通道图片高度/
venc_attr.venc_attr.stream_buf_size = STREAM_BUF_SIZE;/单输出vb大小/
venc_attr.venc_attr.stream_buf_cnt = OUTPUT_BUF_CNT;/输出vb计数/
venc_attr.venc_attr.type = type;/流负载类型/
venc_attr.rc_attr.rc_mode = rc_mode;//设置为固定jpeg模式
venc_attr.rc_attr.mjpeg_fixqp.src_frame_rate = 30;/* venc通道的输入帧率*/
venc_attr.rc_attr.mjpeg_fixqp.dst_frame_rate = 30;/* venc通道的目标帧率*/
venc_attr.rc_attr.mjpeg_fixqp.q_factor = q_factor;/*图像质量:45*/
venc_debug("payload type is JPEG\n");//有效载荷类型为JPEG
ret = kd_mpi_venc_create_chn(0, &venc_attr);//创建解码通道
CHECK_RET(ret, __func__, __LINE__);//判断返回值
g_venc_sample_status = VENC_SAMPLE_STATUS_INIT;//状态标记为已初始化
ret = kd_mpi_venc_start_chn(0);//启动编码通道
CHECK_RET(ret, __func__, __LINE__);//判断返回值
g_venc_sample_status = VENC_SAMPLE_STATUS_START;//状态标记为已开始
四、输入字符d,开始编码一张图片
case 'd': //获设备中转储(dump)一帧图像数据,并将其保存到文件中
printf("vivo_venc dump fream\n");
printf("sample_vicap, dev(0) chn(1) dump frame.\n");
k_venc_chn_status status;//定义通道状态变量
k_venc_stream output;//定义编码流信息
int out_cnt, out_frames;
int i;
k_char filename[256];
k_u32 total_len = 0;
out_cnt = 0;
out_frames = 0;
output_info info;//定义输出信息
memset(filename, 0 , sizeof(filename));//清空文件名
memset(&info, 0, sizeof(info));//清空结构体
info.ch_id = 0;//输出通道0
info.output_frames = 10;//输出帧率
g_venc_sample_status = VENC_SAMPLE_STATUE_RUNING;//状态标记为运行
uint64_t start = get_ticks(); //获取当前时间戳
printf("%s ,start venc time %ld\r\n",__func__,start);//打印开始时间
snprintf(filename, sizeof(filename), "/sharefs/app/dev_0_chn_1_2592x1944_%04d.jpg", dump_count);//生成文件名
printf("save dump data to file(%s)\n", filename);//打印文件名
if ((output_file = fopen(filename, "wb")) == NULL)//只写打开或新建一个二进制文件;只允许写数据
{
venc_debug("Cannot open output file\n");
}
printf("filename: %s\n", filename);
ret = kd_mpi_venc_query_status(info.ch_id, &status);//查找编码器通道的状态
CHECK_RET(ret, __func__, __LINE__);
printf("%s status.cur_packs = %d\r\n",__func__,status.cur_packs);
if (status.cur_packs > 0)
output.pack_cnt = status.cur_packs;
else
output.pack_cnt = 1;
printf("%s output.pack_cnt = %d\r\n",__func__,output.pack_cnt);
output.pack = malloc(sizeof(k_venc_pack) * output.pack_cnt);//申请一段内存
ret = kd_mpi_venc_get_stream(info.ch_id, &output, -1);//从编码器中获取流,-1表示阻塞
CHECK_RET(ret, __func__, __LINE__);
out_cnt += output.pack_cnt;
for (i = 0; i < output.pack_cnt; i++)
{
if (output.pack[i].type != K_VENC_HEADER)
{
out_frames++;
}
k_u8 *pData;
pData = (k_u8 *)kd_mpi_sys_mmap(output.pack[i].phys_addr, output.pack[i].len);//存储映射,返回起始地址
if (output_file){
fwrite(pData, 1, output.pack[i].len, output_file);
printf("%s i = %d output.pack[i].len = %d\r\n",__func__,i,output.pack[i].len);
}
kd_mpi_sys_munmap(pData, output.pack[i].len);
total_len += output.pack[i].len;
}
printf("%s total_len = %d\r\n",__func__,total_len);
ret = kd_mpi_venc_release_stream(info.ch_id, &output);
CHECK_RET(ret, __func__, __LINE__);
free(output.pack);//释放内存
if (output_file){//关闭文件
fclose(output_file);
}
venc_debug("%s>done, ch %d: out_frames %d, size %d bits\n", __func__, info.ch_id, out_frames, total_len * 8);
uint64_t end = get_ticks();//获取结束时间
printf("%s ,end venc time %ld\r\n",__func__,end);
printf("dump cost %lu us\n", (end - start) / 27);//打印dump消耗时间
dump_count++;