RKMEDIA--VENC/VDEC使用

news/2024/10/19 7:32:12/

前面两篇已经介绍了VI和VO的使用,本章节来介绍rkmedia且也是瑞芯微平台重点部分:编解码

目录

一、简介

二、编解码能力

三、编码

编码初始化:

在初始化VENC时需要注意几点:

venc编码帧率控制:

 编码添加osd位图:

四、解码

解码初始化:

五、编解码常见问题及调试

1、调试命令

2、编码常见问题

3、解码常见问题


一、简介

rkmedia编解码部分是对mpp接口进行封装提供给用户使用。

mpp是瑞芯微提供的媒体处理软件平台(Media Process Platform, 简称 MPP)是适用于瑞芯微芯片系列的通用媒体处理软件平台。只要是rk平台的的编解码都是用的mpp,区别在于编解码能力不同以及不同芯片支持的格式等不同。编解码都是硬件编解码,编解码资源是分开的。

MPP 提供的功能包括:
视频解码:
        H.265 / H.264 / H.263 / VP9 / VP8 / MPEG-4 / MPEG-2 / MPEG-1 / VC1 / MJPEG
视频编码:
        H.264 / VP8 / MJPEG

二、编解码能力

rv1126编解码能力如下:

 

rv1109编解码能力如下:

 以上编解码能力是总的编解码能力,如需多路编解码,可以自行换算。

三、编码

VENC 模块,即视频编码模块。此模块支持多路实时编码,且每路编码独立,编码协议和编码 profile 可以不同。支持视频编码同时,调度 Region 模块对编码图像内容进行叠加和遮挡。支持
H264/H265/MJPEG/JPEG编码,支持的码控类型为CBR和VBR。

编码初始化:

        以H264 CBR为例:

venc_chn_attr.stVencAttr.enType = RK_CODEC_TYPE_H264;
venc_chn_attr.stRcAttr.enRcMode = VENC_RC_MODE_H264CBR;
venc_chn_attr.stRcAttr.stH264Cbr.u32Gop = 30;
venc_chn_attr.stRcAttr.stH264Cbr.u32BitRate = u32Width * u32Height;
// frame rate: in 30/1, out 30/1.
venc_chn_attr.stRcAttr.stH264Cbr.fr32DstFrameRateDen = 1;
venc_chn_attr.stRcAttr.stH264Cbr.fr32DstFrameRateNum = 30;
venc_chn_attr.stRcAttr.stH264Cbr.u32SrcFrameRateDen = 1;
venc_chn_attr.stRcAttr.stH264Cbr.u32SrcFrameRateNum = 30;venc_chn_attr.stVencAttr.imageType = IMAGE_TYPE_NV12;
venc_chn_attr.stVencAttr.u32PicWidth = u32Width;
venc_chn_attr.stVencAttr.u32PicHeight = u32Height;
venc_chn_attr.stVencAttr.u32VirWidth = u32Width;
venc_chn_attr.stVencAttr.u32VirHeight = u32Height;
venc_chn_attr.stVencAttr.u32Profile = 77;
ret = RK_MPI_VENC_CreateChn(0, &venc_chn_attr);
if (ret) {printf("ERROR: create VENC[0] error! ret=%d\n", ret);return 0;
}

        设置jpeg/mjpeg编码时,可以设置zoom宽高,实际上是经过rga进行缩放后再送去编码:

  VENC_CHN_ATTR_S venc_chn_attr;memset(&venc_chn_attr, 0, sizeof(venc_chn_attr));venc_chn_attr.stVencAttr.enType = RK_CODEC_TYPE_JPEG;venc_chn_attr.stVencAttr.imageType = enPixFmt;venc_chn_attr.stVencAttr.u32PicWidth = u32SrcWidth;venc_chn_attr.stVencAttr.u32PicHeight = u32SrcHeight;venc_chn_attr.stVencAttr.u32VirWidth = u32SrcWidth;venc_chn_attr.stVencAttr.u32VirHeight = u32SrcHeight;/*********************************************************************/venc_chn_attr.stVencAttr.stAttrJpege.u32ZoomWidth = u32DstWidth;venc_chn_attr.stVencAttr.stAttrJpege.u32ZoomHeight = u32DstHeight;venc_chn_attr.stVencAttr.stAttrJpege.u32ZoomVirWidth = u32DstWidth;venc_chn_attr.stVencAttr.stAttrJpege.u32ZoomVirHeight = u32DstHeight;/*********************************************************************/venc_chn_attr.stVencAttr.enRotation = enRotation;venc_chn_attr.stVencAttr.stAttrJpege.bSupportDCF = RK_TRUE;venc_chn_attr.stVencAttr.stAttrJpege.stMPFCfg.u8LargeThumbNailNum = 2;venc_chn_attr.stVencAttr.stAttrJpege.stMPFCfg.astLargeThumbNailSize[0].u32Width = 164;venc_chn_attr.stVencAttr.stAttrJpege.stMPFCfg.astLargeThumbNailSize[0].u32Height = 128;venc_chn_attr.stVencAttr.stAttrJpege.stMPFCfg.astLargeThumbNailSize[1].u32Width = 128;venc_chn_attr.stVencAttr.stAttrJpege.stMPFCfg.astLargeThumbNailSize[1].u32Height = 164;ret = RK_MPI_VENC_CreateChn(0, &venc_chn_attr);if (ret) {printf("Create Venc failed! ret=%d\n", ret);return -1;}

在初始化VENC时需要注意几点:

        1、编码是没有缩放功能的,输入的分辨率要和配置的分辨率一样,否则执行过程会报错。如需要动态切换分分辨率,需要disable venc、解绑、重新配置vi分辨率、重新配置venc分辨率、绑定。

        2、帧率控制参数是比例关系。比如默认配置的是1 30 1 30,实际比例是1:1。所以代表输入多少帧率就编码多少帧率。很多人会错误的认为是实际帧率的关系,觉得帧率控制有问题。

        3、编码h26x视频编码协议都是基于YUV420的,所以如果是yuv422输入编码出来的数据会有色彩偏差,这一点一般用hdmi作为输入的时候容易遇到。因为mpp内部会把输入的非yuv420格式(yuv422、argb8888)转换成yuv420,造成色彩丢失。

        4、编码jpeg时会多样一些,因为是图像。图像和视频还是有区别的。

venc编码帧率控制:

默认情况下编码的qp值已经设置成

qpMin:8, qpMax:48, qpMinI:8, qpMaxI:48

如果对码率控制的比较严格的情况下需要自行修改qp值,至于qp值具体配置成什么,那要根据自己的实际情况自己慢慢去调整。

RK_MPI_VENC_GetRcParam(0,&stRcParam);
printf("pstRcParam->s32FirstFrameStartQp=%d\n",stRcParam.s32FirstFrameStartQp);
stRcParam.stParamH264.u32StepQp = 4;
stRcParam.stParamH264.u32MaxQp = 50;
stRcParam.stParamH264.u32MinQp = 23;
stRcParam.stParamH264.u32MaxIQp = 48;
stRcParam.stParamH264.u32MinIQp = 18;
RK_MPI_VENC_SetRcParam(0, &stRcParam);

 对于编码高级参数在rkmedia的手册中描述的不多,这边截取海思手册中的描述,总体使用都差不多。

在学习/使用编码高级参数还是需要多多去动手,多修改对应参数将保存的编码数据对比,这样才可以深入了解各个参数设置的意思。

 

 

 

 编码添加osd位图:

rkmedia的venc中添加位图,使用的是RK_MPI_VENC_RGN_SetBitMap 接口去实现。位图只支持ARGB8888的格式,且最多支持8个区域优先级从REGION_ID_0~REGION_ID_7递增。

#define TEST_ARGB32_YELLOW 	0xFFFFFF00
#define TEST_ARGB32_RED 	0xFFFF0000
#define TEST_ARGB32_GREEN 	0xFF00FF00
#define TEST_ARGB32_BLUE 	0xFF0000FF
#define TEST_ARGB32_TRANS 	0x00000000
#define TEST_ARGB32_WHITE 	0xF0FFFFFFstatic void set_argb8888_buffer(RK_U32 *buf, RK_U32 size, RK_U32 color) {for (RK_U32 i = 0; buf && (i < size); i++)*(buf + i) = color;
}RK_MPI_VENC_RGN_Init(0, NULL);BITMAP_S BitMap;
BitMap.enPixelFormat = PIXEL_FORMAT_ARGB_8888;
BitMap.u32Width = 160;
BitMap.u32Height = 160;
BitMap.pData = malloc(BitMap.u32Width * 4 * BitMap.u32Height);
RK_U8 *ColorData = (RK_U8 *)BitMap.pData;
RK_U16 ColorBlockSize = BitMap.u32Height * BitMap.u32Width;
set_argb8888_buffer((RK_U32 *)ColorData, ColorBlockSize / 4,TEST_ARGB32_WHITE);
set_argb8888_buffer((RK_U32 *)(ColorData + ColorBlockSize),ColorBlockSize / 4, TEST_ARGB32_TRANS);
set_argb8888_buffer((RK_U32 *)(ColorData + 2 * ColorBlockSize),ColorBlockSize / 4, TEST_ARGB32_RED);
set_argb8888_buffer((RK_U32 *)(ColorData + 3 * ColorBlockSize),ColorBlockSize / 4, TEST_ARGB32_BLUE);// Case 1: Canvas and bitmap are equal in size
OSD_REGION_INFO_S RngInfo;
RngInfo.enRegionId = REGION_ID_0;
RngInfo.u32PosX = 160;
RngInfo.u32PosY = 160;
RngInfo.u32Width = 160;
RngInfo.u32Height = 160;
RngInfo.u8Enable = 1;
RngInfo.u8Inverse = 0;
RK_MPI_VENC_RGN_SetBitMap(0, &RngInfo, &BitMap);

 注意点:

        1、编码的位图只支持256色,所以如果是叠加彩色图片会出现色彩有偏差的问题,可以换成RGA的位图叠加函数去实现。

        2、每次更新数据的时候,需要重新调用RK_MPI_VENC_RGN_SetBitMap接口去刷一遍数据

        3、想要显示文字osd,还是需要把文字的类型转成argb的数据,送进去显示。给个链接可以参考:海思3516a实现OSD叠加水印_烫手的热山药的博客-CSDN博客

四、解码

VDEC 模块,即视频解码模块。此模块支持多路实时解码,且每路解码独立,支持
H264/H265/MJPEG/JPEG解码。


解码初始化:

VDEC_CHN_ATTR_S stVdecAttr;
memset(&stVdecAttr, 0, sizeof(stVdecAttr));
stVdecAttr.enCodecType = enCodecType;
stVdecAttr.enMode = VIDEO_MODE_FRAME;if (stVdecAttr.enCodecType == RK_CODEC_TYPE_MJPEG) stVdecAttr.enMode = VIDEO_MODE_FRAME;
else stVdecAttr.enMode = VIDEO_MODE_STREAM;
stVdecAttr.enDecodecMode = VIDEO_DECODEC_HADRWARE;ret = RK_MPI_VDEC_CreateChn(0, &stVdecAttr);
if (ret) 
{printf("Create Vdec[0] failed! ret=%d\n", ret);return -1;
}

解码的初始化比较简单。解码的方式分为两种:帧模式流模式

帧模式需要在送数据前已经分好帧,流模式则是在内部分帧

注意:

        1、jpeg和mjpeg解码只支持帧模式,没有流模式。

        2、在解码中送数据的时间延时要自己控制,送的太快或者太慢都会导致解码器报错。

        3、解码时需要收到第一个I帧才会解码

五、编解码常见问题及调试

1、调试命令

编码:

查看编码信息cat /proc/mpp_service/session_summary
查看硬件编解码时间echo 0x100 > /sys/module/rk_vcodec/parameters/mpp_dev_debug

查看h26x编码频率

cat /sys/kernel/debug/clk/clk_summary | grep enc
查看mjpeg编码频率cat /sys/kernel/debug/clk/clk_summary | grep vepu
设置26x编码频率echo 600000000 > /proc/mpp_service/rkvenc/clk_core(594000000是最高频率)

解码:

查看jpeg解码频率cat /sys/kernel/debug/clk/clk_summary | grep jpeg

2、编码常见问题

1、jpeg的旋转不支持缩放旋转,只能单独旋转

2、jpeg编码不支持rgb格式,支持argb格式

3、不管是输入格式是i还是p  编码出来的都是p(P代表逐行扫描,i代表隔行扫描)

4、编码帧率达不到预期

原因:可能达到编码能力的瓶颈。

解决:以下步骤挨个测试

(1)抬高编码频率

(2)DDR定频 修改 rkbin/RKBOOT/RV1126MINIALL.ini 所有924改成1056

(3)cpu定频 

        echo userspace > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
        echo 1512000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed

(4)提高cpu优先级

        io -4 0xfe830008 0x202

 (5)关闭温控

        echo user_space > /sys/class/thermal/thermal_zone0/policy
        echo 0 > /sys/class/thermal/thermal_zone0/cdev0/cur_state

        echo 0 > /sys/class/thermal/thermal_zone0/cdev0/cur_state

3、解码常见问题

1、在获取vdec的yuv数据时,将获取的数据直接写入到文件中,打开后会出现一部分绿色的情况

   解决:主要是写文件的方式有问题

int width,height,h_stride,v_stride;
RK_U8 *base_y;
RK_U8 *base_c;  
while (!quit) {mb = RK_MPI_SYS_GetMediaBuffer(RK_ID_VDEC, 0, 500);if (!mb) {printf("RK_MPI_SYS_GetMediaBuffer get null buffer in 500ms...\n");return NULL;}sprintf(picname, "/userdata/rv1126_dec_%d", ccount++);vdec_file_save = fopen(picname, "w");base_y = RK_MPI_MB_GetPtr(mb);base_c = RK_MPI_MB_GetPtr(mb) + h_stride * v_stride;for (i = 0; i < height; i++, base_y += h_stride){fwrite(base_y, 1, width, vdec_file_save);}for (i = 0; i < height / 2; i++, base_c += h_stride){fwrite(base_c, 1, width, vdec_file_save);}fclose(vdec_file_save);memset(picname, 0 ,64);RK_MPI_MB_ReleaseBuffer(mb);}

2、在使用vdec解码jpeg时,会导致缓存逐渐增大。

解决:需要配置 /proc/mpp_service/vdpu/session_buffers 这个值,默认是40,可以将其改小

3、解码时出现

[ 669.352997] mpp_rkvdec2 fdf80200.rkvdec: resetting...

[ 669.353460] mpp_rkvdec2 fdf80200.rkvdec: reset done 打印

原因:mpp吧数据丢给硬件解码后设定了一个200ms的等待时间,如果超时硬件认为有异常,所以复位了。

解决:增加延时时间( kernel/drivers/video/rockchip/mpp)

暂时关于VENC/VENC部分写这么多,有新的建议后续加上来


http://www.ppmy.cn/news/671.html

相关文章

基于人工神经网络的车牌识别系统的研究(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜…

Spring Boot Logback启动流程

Spring Boot 默认使用的是 Logback 的日志框架、Logback 的组件主要通过 Spring Boot ApplicationListener 启动的 // LoggingApplicationListener Override public void onApplicationEvent(ApplicationEvent event) {if (event instanceof ApplicationStartingEvent) {onApp…

ARM-A架构入门基础(四)Cache

14天学习训练营导师课程&#xff1a;周贺贺《ARMv8/ARMv9架构-快速入门》 1. 定义 Cache是ARM中一块可高速访问的内存块&#xff0c;每块cache包含&#xff1a; 主要的内存地址信息&#xff1b;缓存数据。 2. Cache模型 速度方面&#xff1a;L1 cache > L2 cache > L…

[OpenCV实战]52 在OpenCV中使用颜色直方图

颜色直方图是一种常见的图像特征&#xff0c;顾名思义颜色直方图就是用来反映图像颜色组成分布的直方图。颜色直方图的横轴表示像素值或像素值范围&#xff0c;纵轴表示该像素值范围内像素点的个数或出现频率。颜色直方图属于计算机视觉中的基础概念&#xff0c;其常常被应用于…

11月动态|通过PWmat计算的离子浓度自由能相关文献发表在JCTC

11月 11月&#xff0c;龙讯旷腾完成Q-Flow和Q-Studio新版本的升级&#xff0c;完成了40余项功能的更新和上线&#xff1b;签约并行科技在高性能计算领域再下一城&#xff1b;汪林望博士受海河实验室邀请作线上主题报告&#xff1b;通过PWmat计算的离子浓度自由能相关文献发表在…

RK3588平台开发系列讲解(PWM篇)PWM及backlight的使用方法

平台内核版本安卓版本RK3588Linux 5.10Android12🚀返回专栏总目录 文章目录 一、PWM驱动二、DTS配置三、PWM在user space的使用四、PWM在背光中的使用4.1 Backlight DTS4.2 PWM Backlight 调试沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇将介绍PWM以及backli…

SpringBoot+MyBatis和MyBatisPlus+vue+ElementUl实现批量删除 我只能说太简单了

目录准备工作MySQL数据库表Result返回结果1、SpringBootMyBatisPlusvueElementUl实现批量删除1.1、演示GIF动态图1.2、实体类1.3、Dao接口1.4、Service接口1.5、ServiceImpl接口实现层1.6、Controller控制层1.7、Vue前端2、SpringBootMyBatisvueElementUl实现批量删除2.1、演示…

简单封装一个易拓展的Dialog

Dialog&#xff0c;每个项目中多多少少都会用到&#xff0c;肯定也会有自己的一套封装逻辑&#xff0c;无论如何封装&#xff0c;都是奔着简单复用的思想&#xff0c;有的是深层次的封装&#xff0c;也就是把相关的UI效果直接封装好&#xff0c;暴露可以修改的属性和方法&#…