RV1126画面质量四:GOP改善画质

news2025/1/27 8:45:32

一. 什么是 GOP
GOP 实际上就是两个 I 帧的间隔,比方说分辨率是 1920 * 1080 50 帧,假设 GOP 为 5,那就是大概 2s 插入一个 I 帧。我们再
回顾下,H264/H265 的帧结构。H264/H265 分别分为三种帧类型:I 帧、P 帧、B 帧。

  1. I 帧:全称是帧内编码图像帧,意思是它不需要其他参考帧,只需要利用本帧就可以知道具体的信息
  2. P 帧:全称是预测编码图像帧,需要利用前面的 I 帧或者 P 帧,采用运动预测的方式去进行编码。P 帧的压缩比高于 I 帧
  3. B 帧:全称是双向预测编码图像帧,B 帧提供了最高的压缩比,它既需要参考前面的 P 帧或 I 帧、也需要参考后面的 P 帧、I 帧

按照字节数来说, I 帧> P 帧 > B 帧。在码率不变的情况,一个 GOP 的值越大,P、B 帧的数量就会越多,画面质量就会相对较好。 所以在开发中,我们可以适当增加 GOP 的长度去改善画面质量。但是值得注意的是,GOP 的长度不适合设置太长,由于 P 帧、B 帧复杂度远比 I 帧高。若过长的 GOP 就会使得 P 帧、B 帧数量非常多,从而导致编码器压力较大编码效率降低。通
常来说,GOP_SIZE 要设置成帧率的 1-10 倍。

为什么 GOP 较大时画面质量较好?

  1. 长时间内的视觉连续性:当 GOP 较大时,I 帧的数量减少,但 P 帧和 B 帧通过差异编码的方式,提供了更多的“相似性”信息,使得视频在相邻的帧之间能够保持较高的画面质量,尤其是在动作较为平稳或者变化不大的场景中。

  2. B 帧和 P 帧的高效编码:P 帧和 B 帧通常相对较小,因为它们只是记录和前后帧之间的差异,不需要完整的图像数据。这使得它们相对来说更加节省带宽。因此,GOP 较大时,会有更多的 P 和 B 帧来提高编码效率和压缩效果

  3. 在网络推流中尽量不要引入b帧,本地的4k视频就可以。

二. RV1126 中的 GOP 模式
        在 RV1126 中,GOP 分为两种常见模式。一种是普通 GOP 模式,另外一种是智能编码 GOP 模式。下面我们都分别介绍一下:


 2.1. 普通 GOP 模式:
        普通的 GOP 模式,也是我们最常见的场景。就是每隔一段 GOP_SIZE 就会插入一个 I 帧,如下图所示:

        上图没有B帧,因为网络中传播不需要I帧,I帧的解码时间就,要参考前后的I帧P帧。       

假设我的 GOP_SIZE = 5,就相当于每隔 5 个 P 帧(这里假设没有 B 帧)插入一个 I 帧,这种场景下。编码模块只能适用在那种切换不频繁的场景,如一个画面大部分是运动场景,或者大部分是静止,它不能很好处理那种场景切换很好的场景。 

2.2. 智能编码 P 模式:

        这种模式下,分成两种 I 帧。一种是普通 I 帧,另外一种是虚拟 I 帧(也称之为 SMARTP 模式)。

        普通 I 帧主要是检测画面的静止区域,当检测到静止区域的时候,编码器将会利用长参考帧的相关性,大幅度降低码率,并且尽量防止了静止画面的呼吸效应。 假设码率是5M,会把码率拉低到1M。因为禁止的画面远远低于远动画面,因为运动画面的细节比较多。所以要加大码率。上图就是长参考的I帧。

        这里的P帧是短的参考帧,参考上一帧,作用就是在这里检查是否有运动画面产生。所以运动画面是有这些普通P帧检测的,如果有运动画面就插入 SMARTP帧

         SMARTP并且把码率从5M提高到和合适的码率,检查运动画面

        而在运动区域,利用短期参考帧(P帧)进行运动估计,并插入虚拟 I 帧,SMARTP直接参考I帧,就是长参考。这样可最大拉长 I 帧间隔让其提高码率并最大限度提高画面质量。(注意:SMARTP 和虚拟 I 帧是同样的意思)。

        但是这样的也有一个问题,就是消耗cpu的能力,因为算力比较高,看实际选择。

三. RV1126 中的 GOP 模式的设置

   RK_S32 RK_MPI_VENC_SetGopMode(VENC_CHN VeChn, VENC_GOP_ATTR_S GopMode);

  1. 第一个传参数:编码通道号
  2. 第二个传参数:VENC_GOP_ATTR_S 的结构体
  3. 返回值:0 成功,非 0 失败

VENC_GOP_ATTR_S 数据结构,作用是定义编码器 GOP 属性结构体。

  1.  enGopMode:编码 Gop 类型填SMARTP和NORMALP多
  2. u32GopSize:编码 Gop 大小
  3. s32IPQpDelta:I 帧相对 P 帧对 QP 差值。比如这个花,消除马赛克和用于调节呼吸效应,默认值 6。6 代表的是打开纹理级别的编码,比如窗帘上面的一些花纹,如果你不打开这个可能是编码不出来的;当关闭的时候为 2,
  4. u32BgInterval:长期参考帧的间隔,若选中 SMARTP 则填这个值,否则不填。
  5. s32ViQpDelta:虚拟 I 帧相对于普通 P 帧的 QP 差值。用于调节呼吸效应,默认值 6。6 代表的是打开纹理级别的编码;当关闭的时候为 2

 

 编码普通模式下参数的配置:

VENC_GOP_ATTR_S venc_gop_attr;
venc_gop_attr.enGopMode = VENC_GOPMODE_NORMALP; //不要虚拟帧,就是普通帧
venc_gop_attr.s32ViQpDelta = 0;       //没有虚拟帧这些都不要
venc_gop_attr.s32IPQpDelta = 6;     //这个可以减少调节呼吸效应,代表的是打开纹理级别的编码;
venc_gop_attr.u32BgInterval = 0;   //没有虚拟I帧,所以不填
venc_gop_attr.u32GopSize = 30; //大小30
ret = RK_MPI_VENC_SetGopMode(venc_id, &venc_gop_attr);
注意:在普通模式下,u32BgInterval = 0,u32GopSize 是我们配置的 GOPSIZE 的值

智能 P 帧参数的配置:
VENC_GOP_ATTR_S venc_gop_attr;
venc_gop_attr.enGopMode = VENC_GOPMODE_SMARTP;  //选择虚拟I帧
venc_gop_attr.s32ViQpDelta = 6;        //用于调节呼吸效应和纹理级别的编码
venc_gop_attr.s32IPQpDelta = 6;        //用于调节呼吸效应和纹理级别的编码 基本一样

venc_gop_attr.u32BgInterval = 180; //一般是Gop_size的6~10倍
venc_gop_attr.u32GopSize = 30;         //大小30
ret = RK_MPI_VENC_SetGopMode(venc_id, &venc_gop_attr);

注意:在 SMARTP 模式下,有两个重要的参数配置 u32BgInterval 指的是长参考帧,一般都是 GOP_SIZE 的整数倍。u32GopSize 就是 GOPSIZE。u32BgInterval 具体填多少,要根据经验值进行判断,一般是 6-10 倍。

编码: 这里的编码用普通模式,因为我这里没有频繁切换的场景,改变不同的gop_size,看看画质

#include <stdio.h>
#include "rkmedia_public.h"

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

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

        printf("mmmmmm\n");
        //采集到的文件保存到文件中
        fwrite(RK_MPI_MB_GetPtr(mb), RK_MPI_MB_GetSize(mb), 1, h264_file);
        RK_MPI_MB_ReleaseBuffer(mb);
    }
    return NULL;
}

int main()
{
    RK_U32 u32Width = 1920;
    RK_U32 u32Height = 1080;
    RK_CHAR *pDeviceName = "rkispp_scale0";
    RK_CHAR *pOutPath = NULL;
    RK_CHAR *pIqfilesPath = NULL;
    CODEC_TYPE_E enCodecType = RK_CODEC_TYPE_H264;
    RK_CHAR *pCodecName = "H264";
    RK_S32 s32CamId = 0;
    RK_U32 u32BufCnt = 3;

    //isp的配置
    rk_aiq_working_mode_t hdr_mode = RK_AIQ_WORKING_MODE_NORMAL;
    SAMPLE_COMM_ISP_Init(hdr_mode, RK_FALSE);
    SAMPLE_COMM_ISP_Run();
    SAMPLE_COMM_ISP_SetFrameRate(30);

    
    int ret;
    RK_MPI_SYS_Init(); //初始化rkmedia

    //VI模块
    VI_CHN_ATTR_S vi_chn_attr;
    vi_chn_attr.pcVideoNode = pDeviceName;
    vi_chn_attr.u32BufCnt = u32BufCnt;
    vi_chn_attr.u32Width = u32Width;
    vi_chn_attr.u32Height = u32Height;
    vi_chn_attr.enPixFmt = IMAGE_TYPE_NV12;
    vi_chn_attr.enBufType = VI_CHN_BUF_TYPE_MMAP;
    vi_chn_attr.enWorkMode = VI_WORK_MODE_NORMAL;
    ret = RK_MPI_VI_SetChnAttr(s32CamId, 1, &vi_chn_attr);
    ret |= RK_MPI_VI_EnableChn(s32CamId, 1);
    if (ret)
    {
        printf("ERROR: create VI[0] error! ret=%d\n", ret);
        return 0;
    }


    //VENC模块
    VENC_CHN_ATTR_S venc_chn_attr;
    memset(&venc_chn_attr, 0, sizeof(venc_chn_attr));
    venc_chn_attr.stVencAttr.enType = RK_CODEC_TYPE_H264;
    venc_chn_attr.stRcAttr.enRcMode = VENC_RC_MODE_H264CBR;
    venc_chn_attr.stRcAttr.stH264Cbr.u32Gop = 5;
    venc_chn_attr.stRcAttr.stH264Cbr.u32BitRate = u32Width * u32Height * 3;
    // 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;
    }


    //配置gop模式
    VENC_GOP_ATTR_S venc_gop_attr;
    venc_gop_attr.enGopMode = VENC_GOPMODE_NORMALP; //普通gop模式
    venc_gop_attr.u32BgInterval = 0;
    venc_gop_attr.u32GopSize = 5;//5 60 这里大家可以试试一下,分别用60和50,看看效果
    venc_gop_attr.s32IPQpDelta = 6;
    venc_gop_attr.s32ViQpDelta = 0;
    ret = RK_MPI_VENC_SetGopMode(0, &venc_gop_attr);
    if (ret != 0)
    {
        printf("Gop Mode Success.....\n");
        return -1;
    }
    else
    {
        printf("Gop Mode Failed.....\n");
    }
    


    //绑定vi和venc
    MPP_CHN_S stSrcChn;
    stSrcChn.enModId = RK_ID_VI;
    stSrcChn.s32DevId = 0;
    stSrcChn.s32ChnId = 1;

    MPP_CHN_S stDestChn;
    stDestChn.enModId = RK_ID_VENC;
    stDestChn.s32DevId = 0;
    stDestChn.s32ChnId = 0;
    ret = RK_MPI_SYS_Bind(&stSrcChn, &stDestChn);
    if (ret)
    {
        printf("ERROR: Bind VI[0] and VENC[0] error! ret=%d\n", ret);
        return 0;
    }


    //开启线程采集
    pthread_t pid;
    ret = pthread_create(&pid, NULL, collect_venc_thread, NULL);
    if (ret != 0)
    {
        printf("Create Venc Thread Failed....\n");
    }

    while (1)
    {
        sleep(20);
    }

    return 0;
}

        效果演示后面不回来,开发板坏了,要寄回修了,没办法做实验         

gop调节效果 <   QP调节效果的,因为qp调节直接把编码器的一些细致弄出来。所以效果没有qp那么好,如果在码率不够的情况下也是经常可以用到的。以后得用那一种做开发,应该根据情况。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2283324.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【2025年数学建模美赛F题】(顶刊论文绘图)模型代码+论文

全球网络犯罪与网络安全政策的多维度分析及效能评估 摘要1 Introduction1.1 Problem Background1.2Restatement of the Problem1.3 Literature Review1.4 Our Work 2 Assumptions and Justifications数据完整性与可靠性假设&#xff1a;法律政策独立性假设&#xff1a;人口统计…

Vivado生成X1或X4位宽mcs文件并固化到flash

1.生成mcs文件 01.在vivado里的菜单栏选择"tools"工具栏 02.在"tools"里选择"生成内存配置文件" 03.配置参数 按照FPGA板上的flash型号进行选型&#xff0c;相关配置步骤可参考下图。 注意&#xff1a;Flash数据传输位宽如果需要选择X4位宽&am…

idea plugin插件开发——入门级教程(IntelliJ IDEA Plugin)

手打不易&#xff0c;如果转摘&#xff0c;请注明出处&#xff01; 注明原文&#xff1a;idea plugin插件开发——入门级教程&#xff08;IntelliJ IDEA Plugin&#xff09;-CSDN博客 目录 前言 官方 官方文档 代码示例 开发前必读 Intellij、Gradle、JDK 版本关系 plu…

Linux的常用指令的用法

目录 Linux下基本指令 whoami ls指令&#xff1a; 文件&#xff1a; touch clear pwd cd mkdir rmdir指令 && rm 指令 man指令 cp mv cat more less head tail 管道和重定向 1. 重定向&#xff08;Redirection&#xff09; 2. 管道&#xff08;Pipes&a…

docker 简要笔记

文章目录 一、前提内容1、docker 环境准备2、docker-compose 环境准备3、流程说明 二、打包 docker 镜像1、基础镜像2、国内镜像源3、基础的dockerfile4、打包镜像 四、构建运行1、docker 部分2、docker-compose 部分2.1、构建docker-compose.yml2.1.1、同目录构建2.1.2、利用镜…

Windows 与 Linux 文件权限的对比与转换

Windows和Linux在文件权限管理方面存在显著差异。了解它们的对比和转换方法对于跨平台操作和管理文件非常重要。以下是详细的对比和转换方法&#xff1a; 一、Windows 文件权限 1. 权限类型 Windows使用基于用户和组的权限模型&#xff0c;常见的权限类型包括&#xff1a; 读…

FireFox | Google Chrome | Microsoft Edge 禁用更新 final版

之前的方式要么失效&#xff0c;要么对设备有要求&#xff0c;这次梳理一下对设备、环境几乎没有要求的通用方式&#xff0c;universal & final 版。 1.Firefox 方式 FireFox火狐浏览器企业策略禁止更新_火狐浏览器禁止更新-CSDN博客 这应该是目前最好用的方式。火狐也…

华硕笔记本装win10哪个版本好用分析_华硕笔记本装win10专业版图文教程

华硕笔记本装win10哪个版本好用&#xff1f;华硕笔记本还是建议安装win10专业版。Win分为多个版本&#xff0c;其中家庭版&#xff08;Home&#xff09;和专业版&#xff08;Pro&#xff09;是用户选择最多的两个版本。win10专业版在功能以及安全性方面有着明显的优势&#xff…

Android多语言开发自动化生成工具

在做 Android 开发的过程中&#xff0c;经常会遇到多语言开发的场景&#xff0c;尤其在车载项目中&#xff0c;多语言开发更为常见。对应多语言开发&#xff0c;通常都是在中文版本的基础上开发其他国家语言&#xff0c;这里我们会拿到中-外语言对照表&#xff0c;这里的工作难…

Java数据结构 (链表反转(LinkedList----Leetcode206))

1. 链表的当前结构 每个方框代表一个节点&#xff0c;每个节点包含两个部分&#xff1a; 左侧的数字&#xff1a;节点存储的值&#xff0c;例如 45、34 等。右侧的地址&#xff08;如 0x90&#xff09;&#xff1a;表示该节点 next 指针指向的下一个节点的内存地址。 例子中&a…

LabVIEW 太阳能光伏发电系统智能监控

本文介绍了基于 LabVIEW 的太阳能光伏发电监控系统的设计与实现&#xff0c;着重探讨了其硬件配置、软件架构以及系统的实现方法。该系统能够有效提高太阳能光伏发电的监控效率和精确性&#xff0c;实现了远程监控和数据管理的智能化。 ​ 项目背景 在当前能源紧张与环境污染…

记录让cursor帮我给ruoyi-vue后台管理项目整合mybatis-plus

自己整合过程中会出现 work.web.exception.GlobalExceptionHandler :100 | 请求地址/admin/device/install/detail/1,发生未知异常. org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.fire.mapper.DeviceInstallMapper.selectById at o…

Prometheus+grafana实践:Doris数据库的监控

文章来源&#xff1a;乐维社区 Doris数据库背景 Doris&#xff08;Apache Doris&#xff09;是一个现代化的MPP&#xff08;Massive Parallel Processing&#xff0c;大规模并行处理&#xff09;数据库&#xff0c;主要用于在线分析处理&#xff08;OLAP&#xff09;场景。 D…

CYT3BB_4BB:Clock system

CYT3BB/4BB的时钟系统包括8-MHz IMO、2个ILO、4个看门狗计时器、4个PLL、一个FLL、5个时钟监控器(CSV)、一个8-33.34MHzECO和一个32.768-kHz WCO。   该时钟系统支持三个主时钟域: CLK_HF、CLK_SLOW和CLK_LF。 - CLK_HFx: CLK_HFx是活动模式的时钟。每个人都可以使用任…

神经网络|(四)概率论基础知识-古典概型

【1】引言 前序学习了线性回归的基础知识&#xff0c;了解到最小二乘法可以做线性回归分析&#xff0c;但为何最小二乘法如此准确&#xff0c;这需要从概率论的角度给出依据。 因此从本文起&#xff0c;需要花一段时间来回顾概率论的基础知识。 【2】古典概型 古典概型是我…

OpenFGA

1.什么是OpenFGA Fine-Grained Authorization 细粒度关系型授权 2.什么是细粒度授权 细粒度授权 (FGA) 意味着能够授予特定用户在特定资源中执行特定操作的权限。 精心设计的 FGA 系统允许您管理数百万个对象和用户的权限。随着系统不断添加对象并更新用户的访问权限&#…

C语言程序设计:算法程序的灵魂

文章目录 C语言程序设计&#xff1a;算法程序的灵魂算法数据结构程序数据结构算法数值运算算法非数值运算算法 简单的算法举例【例2.1】求12345【例2.2】有50个学生&#xff0c;要求输出成绩在80分以上的学生的学号和成绩 简单的算法举例【例2.3】判定2000—2500年中的每一年是…

React和Vue有什么区别,如何选择?

React和Vue有什么区别&#xff0c;如何选择&#xff1f; React 和 Vue 是当前最受欢迎的前端框架之一&#xff0c;两者在开发者中都有极高的声誉。它们都旨在帮助开发人员构建用户界面&#xff0c;但在实现方式和适用场景上有所不同。如果你正考虑在项目中选择 React 或 Vue&a…

寒假1.23

题解 web&#xff1a;[极客大挑战 2019]Secret File&#xff08;文件包含漏洞&#xff09; 打开链接是一个普通的文字界面 查看一下源代码 发现一个链接&#xff0c;点进去看看 再点一次看看&#xff0c;没什么用 仔细看&#xff0c;有一个问题&#xff0c;当点击./action.ph…

从spec到iso的koji使用

了解一下Linux发行版流程&#xff1a;:从spec到iso的koji使用 for Fedora 41。 Fedora 41有24235个包&#xff0c;我们选择 minimal 的几十个源码包&#xff0c;百多个rpm包构建。 配3台服务器 40C64G 48C64G 80C128G&#xff0c;有点大材小用&#xff0c;一台就够了 &#xf…