Linux学习之视频编码模块---VENC模块讲解及实战

目录

一。VENC模块的介绍

1.1. VENC模块概述

1.2. 支持的编码格式

1.3. VENC模块的主要特性

二。VENC结构体定义

2.1 VENC_ATTR_S结构体(编码器基础属性结构体)

2.2 VENC_RC_ATTR_S结构体(编码码率控制属性结构体)

2.3:VENC_GOP_ATTR_S结构体(编码器GOP属性结构体)。

2.4:配置实例

三。VENC 创建API接口

四。实战:多线程获取VENC的H264码流数据

4.1 RV1126模块采并进行VENC编码的流程

4.2绑定函数

4.3 创建多线程读取VENC数据

4.4  关闭VI,VENC,和解绑

 五。调试记录

5.1 .第一次调试

5.2 第二次调试:

5.3 做h264和nv12的数据对比

5.3.1 运行RGA程序

5.3.2 运行VENC程序

5.3.3 总结:


一。VENC模块的介绍

1.1. VENC模块概述

VENC(Video ENCoder)是RV1126芯片中专门用于视频编码的硬件模块,它通过硬件加速实现高效的视频编码,大大降低了CPU的负担。

1.2. 支持的编码格式

编码格式特点应用场景
H.264高效率视频编码,压缩比高视频监控、网络直播、视频会议(最常用)
H.265比H.264压缩效率高40%,节省带宽4K/8K超高清视频、存储受限场景
MJPEG运动JPEG,每帧独立压缩医疗影像、工业检测、低速运动场景
JPEG静态图像压缩拍照、截图、封面生成

1.3. VENC模块的主要特性

编码性能

  • 支持多路同时编码(如:2路1080p@30fps)

  • 支持不同的分辨率同时输出

  • 低延迟编码

二。VENC结构体定义

/* the attribute of the venc chnl*/
typedef struct rkVENC_CHN_ATTR_S {
  VENC_ATTR_S stVencAttr;    // 编码器基础属性结构体 the attribute of video encoder
  VENC_RC_ATTR_S stRcAttr;   // 编码码率控制属性结构体 the attribute of rate  ctrl
  VENC_GOP_ATTR_S stGopAttr; // 编码器GOP属性结构体 the attribute of gop
} VENC_CHN_ATTR_S;

VENC_CHN_ATTRS主要包含三个结构体:

  1. VENC_ATTR_S结构体(编码器基础属性结构体)
  2. VENC_RC_ATTR_S结构体(编码码率控制属性结构体)
  3. VENC_GOP_ATTR_S结构体(编码器GOP属性结构体)。

2.1 VENC_ATTR_S结构体(编码器基础属性结构体)

  • stVencAttr - 编码器基础属性

    • 包含编码器类型、分辨率、像素格式等基本信息

    • 通常包括:

      • 编码格式(H.264/H.265/JPEG等)

      • 图像宽度和高度

      • 输入图像格式

      • 编码配置文件等

/* the attribute of the Venc*/
typedef struct rkVENC_ATTR_S {

  CODEC_TYPE_E enType;    // 编码器协议类型 RW; the type of encodec
  IMAGE_TYPE_E imageType; // 输入图像类型,通常来说venc的imageType和vi的imageType是一致的 the type of input image
  RK_U32 u32VirWidth;  //  stride width, same to buffer_width, must greater than
                       // width, often set vir_width=(width+15)&(~15)
  RK_U32 u32VirHeight; // stride height, same to buffer_height, must greater
                       // than height, often set vir_height=(height+15)&(~15)
  RK_U32 u32Profile;   // RW;
                       // H.264:   66: baseline; 77:MP; 100:HP;
                       // H.265:   default:Main;
                       // Jpege/MJpege:   default:Baseline
  RK_BOOL bByFrame;    // RW; Range:[0,1];
                       // get stream mode is slice mode or frame mode
  RK_U32 u32PicWidth;  // 编码图像宽度
  RK_U32 u32PicHeight; // 编码图像高度
  VENC_ROTATION_E enRotation;
  union {
    VENC_ATTR_H264_S stAttrH264e;   // attributes of H264e
    VENC_ATTR_H265_S stAttrH265e;   // attributes of H265e
    VENC_ATTR_MJPEG_S stAttrMjpege; // attributes of Mjpeg
    VENC_ATTR_JPEG_S stAttrJpege;   // attributes of jpeg
  };
} VENC_ATTR_S;

成员变量详解

  1. enType - 编码器协议类型

    • 指定使用的编码格式

    • 例如:RK_VIDEO_ID_AVC(H.264), RK_VIDEO_ID_HEVC(H.265), RK_VIDEO_ID_MJPEG, RK_VIDEO_ID_JPEG

      typedef enum rk_CODEC_TYPE_E {
        RK_CODEC_TYPE_NONE = -1,
        // Audio
        RK_CODEC_TYPE_AAC,
        RK_CODEC_TYPE_MP2,
        RK_CODEC_TYPE_VORBIS,
        RK_CODEC_TYPE_G711A,
        RK_CODEC_TYPE_G711U,
        RK_CODEC_TYPE_G726,
        // Video
        RK_CODEC_TYPE_H264,
        RK_CODEC_TYPE_H265,
        RK_CODEC_TYPE_JPEG,
        RK_CODEC_TYPE_MJPEG,
        RK_CODEC_TYPE_NB
      } CODEC_TYPE_E;
  2. imageType - 输入图像类型

    • 编码器输入的图像格式

    • 通常与VI(视频输入)模块的输出格式一致

    • 例如:IMAGE_TYPE_NV12, IMAGE_TYPE_NV16, IMAGE_TYPE_YUV420P

    • typedef enum rk_IMAGE_TYPE_E {
        IMAGE_TYPE_UNKNOW = 0,
        IMAGE_TYPE_GRAY8,
        IMAGE_TYPE_GRAY16,
        IMAGE_TYPE_YUV420P,
        IMAGE_TYPE_NV12,
        IMAGE_TYPE_NV21,
        IMAGE_TYPE_YV12,
        IMAGE_TYPE_FBC2,
        IMAGE_TYPE_FBC0,
        IMAGE_TYPE_YUV422P,
        IMAGE_TYPE_NV16,
        IMAGE_TYPE_NV61,
        IMAGE_TYPE_YV16,
        IMAGE_TYPE_YUYV422,
        IMAGE_TYPE_UYVY422,
        IMAGE_TYPE_RGB332,
        IMAGE_TYPE_RGB565,
        IMAGE_TYPE_BGR565,
        IMAGE_TYPE_RGB888,
        IMAGE_TYPE_BGR888,
        IMAGE_TYPE_ARGB8888,
        IMAGE_TYPE_ABGR8888,
        IMAGE_TYPE_JPEG,
      
        IMAGE_TYPE_BUTT
      } IMAGE_TYPE_E;
  3. u32VirWidth - 虚拟宽度(步长宽度)

    • 内存中对齐的宽度,必须大于等于实际图像宽度

    • 通常按16字节对齐:vir_width = (width + 15) & (~15)

  4. u32VirHeight - 虚拟高度(步长高度)

    • 内存中对齐的高度,必须大于等于实际图像高度

    • 通常按16字节对齐:vir_height = (height + 15) & (~15)

  5. u32Profile - 编码配置文件

    • H.264: 66-Baseline, 77-Main Profile, 100-High Profile

    • H.265: Main Profile (默认)

    • JPEG/MJPEG: Baseline (默认)

  6. bByFrame - 获取流模式

    • RK_TRUE: 按帧获取编码数据

    • RK_FALSE: 按片获取编码数据

  7. u32PicWidth - 编码图像实际宽度

  8. u32PicHeight - 编码图像实际高度

  9. enRotation - 旋转设置

    • 图像旋转角度:0°, 90°, 180°, 270°

  10. 联合体 - 具体编码格式属性

    • stAttrH264e: H.264编码特定属性

    • stAttrH265e: H.265编码特定属性

    • stAttrMjpege: MJPEG编码特定属性

    • stAttrJpege: JPEG编码特定属性

2.2 VENC_RC_ATTR_S结构体(编码码率控制属性结构体)

VENC_RC_ATTR_S 定义了视频编码的码率控制相关参数,支持多种码率控制模式和编码格式。

/* the attribute of rc*/
typedef struct rkVENC_RC_ATTR_S {
  /* RW; the type of rc*/
  VENC_RC_MODE_E enRcMode;
  union {
    VENC_H264_CBR_S stH264Cbr;
    VENC_H264_VBR_S stH264Vbr;
    VENC_H264_AVBR_S stH264Avbr;

    VENC_MJPEG_CBR_S stMjpegCbr;
    VENC_MJPEG_VBR_S stMjpegVbr;

    VENC_H265_CBR_S stH265Cbr;
    VENC_H265_VBR_S stH265Vbr;
    VENC_H265_AVBR_S stH265Avbr;
  };
} VENC_RC_ATTR_S;

成员变量详解

  1. enRcMode - 码率控制模式

    • 指定使用的码率控制算法类型

    • 常见模式:

      • VENC_RC_MODE_H264CBR / VENC_RC_MODE_H265CBR - 恒定码率

      • VENC_RC_MODE_H264VBR / VENC_RC_MODE_H265VBR - 可变码率

      • VENC_RC_MODE_H264AVBR / VENC_RC_MODE_H265AVBR - 自适应可变码率

      • MJPEG对应的码率控制模式

  2. 联合体 - 具体码率控制参数
    根据 enRcMode 和编码类型选择对应的结构体:

    H.264编码:

    • stH264Cbr - H.264恒定码率控制参数

    • stH264Vbr - H.264可变码率控制参数

    • stH264Avbr - H.264自适应可变码率控制参数

    H.265编码:

    • stH265Cbr - H.265恒定码率控制参数

    • stH265Vbr - H.265可变码率控制参数

    • stH265Avbr - H.265自适应可变码率控制参数

    MJPEG编码:

    • stMjpegCbr - MJPEG恒定码率控制参数

    • stMjpegVbr - MJPEG可变码率控制参数

2.3:VENC_GOP_ATTR_S结构体(编码器GOP属性结构体)。

VENC_GOP_ATTR_S 定义了视频编码的GOP相关参数,控制帧类型分布和QP调整。

/* the attribute of the gop*/
typedef struct rkVENC_GOP_ATTR_S {
  VENC_GOP_MODE_E enGopMode;
  RK_U32 u32GopSize;
  RK_S32 s32IPQpDelta;
  RK_U32 u32BgInterval;
  RK_S32 s32ViQpDelta;
} VENC_GOP_ATTR_S;

成员变量详解

  1. enGopMode - GOP模式

    • 指定GOP的结构模式

    • 常见模式:

      • VENC_GOPMODE_NORMAL - 常规GOP模式

      • VENC_GOPMODE_B - 包含B帧的GOP模式

      • VENC_GOPMODE_SMARTP - 智能P帧模式

      • VENC_GOPMODE_DUALP - 双P帧模式

  2. u32GopSize - GOP大小

    • 两个I帧之间的间隔(帧数)

    • 例如:30表示每30帧有一个I帧

    • 影响编码效率和随机访问能力

  3. s32IPQpDelta - I帧与P帧的QP差值

    • I帧相对于P帧的QP偏移量

    • 通常为负值,表示I帧使用更小的QP(更好的质量)

    • 例如:-5 表示I帧的QP比P帧小5

  4. u32BgInterval - 背景帧间隔

    • 背景参考帧的更新间隔

    • 用于长期参考帧管理

  5. s32ViQpDelta - 视觉感知QP差值

    • 基于视觉感知的QP调整值

    • 用于人眼敏感区域的QP优化

2.4:配置实例

    VENC_CHN_ATTR_S venc_chn_attr;
    //******     VENC Attr Set   ************************//
    venc_chn_attr.stVencAttr.enType = RK_CODEC_TYPE_H264;
    venc_chn_attr.stVencAttr.u32PicWidth = 1920;
    venc_chn_attr.stVencAttr.u32PicHeight = 1080;
    venc_chn_attr.stVencAttr.u32VirWidth = 1920;
    venc_chn_attr.stVencAttr.u32VirHeight = 1080;
    venc_chn_attr.stVencAttr.u32Profile = 66;
    venc_chn_attr.stVencAttr.imageType = IMAGE_TYPE_NV12;
    venc_chn_attr.stVencAttr.enRotation = VENC_ROTATION_0;

    //********* VENC RCMODE Set  *******************//
    venc_chn_attr.stRcAttr.enRcMode = VENC_RC_MODE_H264CBR;
    venc_chn_attr.stRcAttr.stH264Cbr.u32Gop = 25;
    //25/1 NUM/DEN == FrameRate
    venc_chn_attr.stRcAttr.stH264Cbr.u32SrcFrameRateDen = 1; //
    venc_chn_attr.stRcAttr.stH264Cbr.u32SrcFrameRateNum = 25;
    venc_chn_attr.stRcAttr.stH264Cbr.fr32DstFrameRateDen = 1;
    venc_chn_attr.stRcAttr.stH264Cbr.fr32DstFrameRateNum = 25;
    venc_chn_attr.stRcAttr.stH264Cbr.u32BitRate = 8388608; //1M
    ret = RK_MPI_VENC_CreateChn(VENC_CHN, &venc_chn_attr);

基础编码属性:

  • 编码格式:H.264

  • 分辨率:1920×1080

  • 像素格式:NV12

  • Profile:66(Baseline)

  • 无旋转

码率控制配置:

  • 模式:H.264 CBR(恒定码率)

  • GOP大小:25帧

  • 帧率:25fps

  • 码率:8,388,608 bps(实际约8.4Mbps)

常见的码率和计算发送

1 Kb = 1024 bit

1 KB = 1024 Byte

1 Mb = 1024 Kb

1 MB = 1024 KB

1 Byte = 8 bit

1 MB = 8Mb

1 Mb = 0.125 MB


1M = 1024字节 = 1024 b 
1b = 8bit  

1024 * 1024 * 8 = 8388608

更多的细节我就不展开了,大家可以看看源码

三。VENC 创建API接口

RK_S32 RK_MPI_VENC_CreateChn(VENC_CHN VeChn, const VENC_CHN_ATTR_S *pstAttr);

参数说明

  1. VENC_CHN VeChn - 编码通道号

    • 指定要创建的编码通道编号

    • 通常定义为:#define VENC_CHN 0

  2. const VENC_CHN_ATTR_S *pstAttr - 编码通道属性指针

    • 传入前面配置好的编码通道属性结构体

    • 包含编码器基础属性、码率控制属性、GOP属性等

返回值

  • RK_SUCCESS (0): 创建成功

  • 其他值: 创建失败,返回错误码

四。实战:多线程获取VENC的H264码流数据

4.1 RV1126模块采并进行VENC编码的流程

VI模块相关介绍和初始化在下面连接中,大家可以去问问

https://blog.youkuaiyun.com/ALIANG2000/article/details/154024292?spm=1011.2124.3001.6209https://blog.youkuaiyun.com/ALIANG2000/article/details/154024292?spm=1011.2124.3001.6209VENC模块初始化在 2.4 配置实例中有配置

4.2绑定函数

RK媒体处理系统中绑定两个模块通道的关键函数

ret = RK_MPI_SYS_Bind(&vi_chn_s, &venc_chn_s);

参数说明

  1. pstSrcChn - 源通道

    • 数据流的来源通道

    • 这里是指VI(视频输入)通道

  2. pstDestChn - 目标通道

    • 数据流的目的地通道

    • 这里是指VENC(视频编码)通道

返回值

  • RK_SUCCESS (0): 绑定成功

  • 其他值: 绑定失败,返回错误码

    MPP_CHN_S vi_chn_s;
    vi_chn_s.enModId = RK_ID_VI;
    vi_chn_s.s32ChnId = CAMERA_CHN;

    MPP_CHN_S venc_chn_s;
    venc_chn_s.enModId = RK_ID_VENC;
    venc_chn_s.s32ChnId = VENC_CHN;
    ret = RK_MPI_SYS_Bind(&vi_chn_s, &venc_chn_s);

4.3 创建多线程读取VENC数据

    pthread_t pid;
    pthread_create(&pid, NULL, get_h264_venc_thread, NULL);

    while (1)
    {
        sleep(1);
    }

void * get_h264_venc_thread(void * args)
{
    pthread_detach(pthread_self());
    FILE * h264_file = fopen("test_camera.h264", "w+");
    MEDIA_BUFFER mb;

    while (1)
    {
        mb = RK_MPI_SYS_GetMediaBuffer(RK_ID_VENC, VENC_CHN, -1);
        if(!mb)
        {
            printf("Get Venc Mb Break.....\n");
            break;
        }

        printf("Get H264 One Frame.......\n");
        fwrite(RK_MPI_MB_GetPtr(mb),RK_MPI_MB_GetSize(mb),1, h264_file);
        RK_MPI_MB_ReleaseBuffer(mb);
    }

    return NULL;
}

读取VENS数据具体流程和RGA流程基本一致:

创建h264文件,用于保存读取到的数据

定义 MEDIA_BUFFER mb 结构体,用于临时存储从VI中读取到数据

将mb的数据写入h264文件中

释放mb内存空间

4.4  关闭VI,VENC,和解绑

    RK_MPI_VI_DisableChn(CAMERA_ID, CAMERA_CHN);
    RK_MPI_VENC_DestroyChn(VENC_CHN);
    RK_MPI_SYS_UnBind(&vi_chn_s, &venc_chn_s);

 五。调试记录

5.1 .第一次调试

通过日志输出主要报错两个问题:

[RKMEDIA][SYS][Error]:invalid gop mode(352)!
[RKMEDIA][VENC][Error]:The resolution of the input buffer is wrong.

问题定位点:分辨率不匹配错误


mpp[1732]: h264e_api_v2: MPP_ENC_SET_PREP_CFG w:h [1920:1020] stride [1920:1080]
mpp[1732]: mpp_enc: send header for set cfg change input/format
[RKMEDIA][VENC][Info]:MPP Encoder: w x h(1920[1920] x 1020[1080])

5.2 第二次调试:

忘记在线程的输出中加入换行符号

void *get_h264_venc_thread(void * args)
{
    pthread_detach(pthread_self());//recall pthread 
    FILE * h264_file = fopen("test_camera.h264","w+");
    MEDIA_BUFFER mb;
    
    while(1)
    {
        mb = RK_MPI_SYS_GetMediaBuffer(RK_ID_VENC,VENC_CHN,-1);
        if(!mb)
        {
            printf("get Venc Mb failed....\n");
            break;
        }
        printf("Get H264 One Frame ....\n");//这里忘记加入\n 
        fwrite(RK_MPI_MB_GetPtr(mb),RK_MPI_MB_GetSize(mb),1,h264_file);
        RK_MPI_MB_ReleaseBuffer(mb);//realease the memory;otherwise,it will cause a memory lea;
    }
  

检查下是否生成 目标文件和目标文件的大小

一开始没有反应过来:采集的时间的稍微长一点

使用cmd 驱动ffplay显示采集的视频:

5.3 做h264和nv12的数据对比

5.3.1 运行RGA程序

问题:显示界面不对,而且时间短

可以看到已经生成了一个366.7M的nv12文件

看上去像是播放的分辨率不对

问题:RGA这个程序分辨率我修改成1280*720大小,但是在使用ffplay指令时设置成1920*1070导致读取数据错误

正确指令:

ffplay -f rawvideo -pix_fmt nv12 -video_size 1280x720 vi_rga_RGA_FLIP_V.nv12

5.3.2 运行VENC程序

需要杀死当前的进行,才可以运行,否则无法运行下次

发现已经生成了一个.h264文件,但是文件大小是空的

经过排查发现是.nv12空间过大,导致当前目录下的可用空间无了,无法写入数据导致的

删掉nv12程序,重新运行

直接使用这个指令  ffplay.exe test_camera.h264

5.3.3 总结:

RGA数据分辨率为1280*720,运行时长才8秒多,数据大小为309.9M

VENC数据分辨率为1980*1020,运行时长为32秒,数据大小才33M

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值