使用venc编码出来的图片,为啥图片两边会有紫色和绿色的条?

Viewed 102

dev_0_chn_1_2592x1944_0002.jpg
是参考 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,输出 2592
1944
/
*/
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++;
1 Answers

请参考编解码demo实现,可能的原因是代码中内存没处理导致。你修改后的demo要实现什么功能,请详细描述下。

重新贴了源码,应用是移植sample_venc的,麻烦看一下是不是哪里配置错误了,谢谢

为什么这个编码图片的时候,前两张都是奇怪的图片,第一张是黑色的,第二张是别的场景,第三张图片的画面是编码第一张图片时候的画面,第四张图片画面则是编码第二张图片时的画面,以此类推

请将你的完整代码发送到邮箱:sunxiaopeng@canaan-creative.com,代码确保能正常编译通过