RKMEDIA--VENC/VDEC使用

前面两篇已经介绍了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 	0xF0FFFFFF

static 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部分写这么多,有新的建议后续加上来

 文章汇总:RKMEDIA使用简介_未_定的博客-CSDN博客

  • 0
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
这是一个命令行程序,通过运行 `./sample_vio` 命令启动,会列出多个模式选择。这个程序的功能是基于海思芯片的视频输入输出和处理,选择不同的模式可以测试不同的功能。 具体的模式解释如下: 1. all mode route:所有模式的线性路由,包括视频输入在线/离线,视频处理在线/离线,多路复用方式为线性模式。这种模式适用于多种场景。 2. wdr route:宽动态范围(WDR)模式,视频输入在线,视频处理离线,多路复用方式为线性模式。这种模式适用于需要处理宽动态范围视频的场景。 3. fpn calibrate & correct:前景亮点校正(FPN)校正和校正,视频输入在线,视频处理在线,多路复用方式为线性模式。这种模式适用于需要去除前景亮点的场景。 4. dis & 3dnr(VPSS):数字图像稳定(DIS)和三维数字降噪(3DNR)处理,视频输入在线,视频处理在线,多路复用方式为线性模式。这种模式适用于需要进行数字图像稳定和降噪处理的场景。 5. 3dnr(VI) & ldc:三维数字降噪(3DNR)和镜头畸变校正(LDC)处理,视频输入在线,视频处理在线,多路复用方式为线性模式。这种模式适用于需要进行数字降噪和镜头畸变校正处理的场景。 6. low delay:低延迟处理,视频输入在线,视频处理在线,多路复用方式为低延迟模式。这种模式适用于需要低延迟处理的场景,如实时视频通话等。 7. user pic:自定义图像处理,视频输入离线,视频处理在线,多路复用方式为线性模式。这种模式适用于需要处理自定义图像的场景。 8. two sensor:双摄像头模式,视频输入离线,视频处理在线,多路复用方式为线性模式。这种模式适用于需要处理双摄像头视频的场景。 9. switch mode:模式切换测试,从线性模式切换到WDR模式,视频输入在线,视频处理离线,多路复用方式为线性模式或WDR模式。这种模式适用于需要测试模式切换的场景。 10. switch resolution:分辨率切换测试,从FHD分辨率切换到720P分辨率或从4K分辨率切换到FHD分辨率,视频输入在线,视频处理在线,多路复用方式为线性模式。这种模式适用于需要测试分辨率切换的场景。 在程序提示输入时,选择相应的模式即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值