openh264 码率控制原理框架

openh264

OpenH264 是一个开源的 H.264 视频编码库,由 Cisco Systems, Inc. 开发并提供。它支持 H.264
的主要编码特性,包括但不限于:

  • 支持基线、主要、高和高10配置文件
  • 支持帧内预测、帧间预测、变换编码、量化、环路滤波等
  • 支持多线程编码
  • 支持可变编码速度

OpenH264库被广泛用于视频编码和转码,特别是在需要高性能和低延迟的场景中。由于它是开源的,许多开发者和公司将其集成到他们的产品中,以提供视频压缩和传输功能。

码率控制

码率控制是数字视频和音频编码中的一个重要概念,它涉及到如何分配和控制数据的传输速率。在视频编码中,码率控制(Rate Control)通常用于确保视频数据在传输或存储时符合特定的带宽限制或文件大小要求。以下是一些常见的码率控制方法:

  1. 恒定码率(CBR, Constant Bitrate):以固定的速率编码视频,不管场景的复杂度如何,码率保持不变。

  2. 可变码率(VBR, Variable Bitrate):根据视频内容的复杂度动态调整码率,复杂场景使用更高码率,简单场景使用更低码率。

  3. 平均码率(ABR, Average Bitrate):介于CBR和VBR之间,设定一个平均码率值,允许在一定范围内波动。

  4. 质量可伸缩性(Quality Scalability):在编码时,生成多个质量层的视频流,用户可以根据网络条件选择不同质量的视频。

  5. 帧内码率控制(Intra-frame Rate Control):对每一帧进行码率控制,确保每帧的质量。

  6. 帧间码率控制(Inter-frame Rate Control):考虑帧与帧之间的关系,通过调整帧之间的码率来控制整体视频质量。

  7. 基于场景的码率控制(Scene-based Rate Control):根据视频场景的变化动态调整码率。

  8. 基于内容的码率控制(Content-based Rate Control):分析视频内容,如运动、纹理等,来决定码率分配。

码率控制对于视频压缩和传输非常重要,它可以帮助在保持视频质量的同时,减少所需的存储空间和带宽。不同的编码标准和应用场景可能需要不同的码率控制策略。

openh264 码率控制框架

函数调用关系

在这里插入图片描述

码控函数框架

在这里插入图片描述

码率控制方式

  • RC_QUALITY_MODE:质量模式
  • RC_BITRATE_MODE:码率模式
  • RC_BUFFERBASED_MODE:缓存状态模式
  • RC_TIMESTAMP_MODE:基于时间戳模式
  • RC_BITRATE_MODE_POST_SKIP:内置码控方式,算法调整后删除
  • RC_OFF_MODE:关闭码控
/**
* @brief Enumerate the type of rate control mode
*/
typedef enum {
  RC_QUALITY_MODE = 0,     ///< quality mode
  RC_BITRATE_MODE = 1,     ///< bitrate mode
  RC_BUFFERBASED_MODE = 2, ///< no bitrate control,only using buffer status,adjust the video quality
  RC_TIMESTAMP_MODE = 3, //rate control based timestamp
  RC_BITRATE_MODE_POST_SKIP = 4, ///< this is in-building RC MODE, WILL BE DELETED after algorithm tuning!
  RC_OFF_MODE = -1,         ///< rate control off mode
} RC_MODES;

码控初始化

  • 通过WelsRcInitFuncPointers函数完成码控模块的初始化;具体根据不同的码控方式,调用不同的函数实现不同的码控逻辑。
void  WelsRcInitFuncPointers (sWelsEncCtx* pEncCtx, RC_MODES iRcMode) {
  SWelsRcFunc*   pRcf = &pEncCtx->pFuncList->pfRc;
  switch (iRcMode) {
  case RC_OFF_MODE:
    pRcf->pfWelsRcPictureInit = WelsRcPictureInitDisable;
    pRcf->pfWelsRcPicDelayJudge = NULL;
    pRcf->pfWelsRcPictureInfoUpdate = WelsRcPictureInfoUpdateDisable;
    pRcf->pfWelsRcMbInit = WelsRcMbInitDisable;
    pRcf->pfWelsRcMbInfoUpdate = WelsRcMbInfoUpdateDisable;
    pRcf->pfWelsCheckSkipBasedMaxbr = NULL;
    pRcf->pfWelsUpdateBufferWhenSkip = NULL;
    pRcf->pfWelsUpdateMaxBrWindowStatus = NULL;
    pRcf->pfWelsRcPostFrameSkipping = NULL;
    break;
  case RC_BUFFERBASED_MODE:
    pRcf->pfWelsRcPictureInit = WelRcPictureInitBufferBasedQp;
    pRcf->pfWelsRcPicDelayJudge = NULL;
    pRcf->pfWelsRcPictureInfoUpdate = WelsRcPictureInfoUpdateDisable;
    pRcf->pfWelsRcMbInit = WelsRcMbInitDisable;
    pRcf->pfWelsRcMbInfoUpdate = WelsRcMbInfoUpdateDisable;
    pRcf->pfWelsCheckSkipBasedMaxbr = NULL;
    pRcf->pfWelsUpdateBufferWhenSkip = NULL;
    pRcf->pfWelsUpdateMaxBrWindowStatus = NULL;
    pRcf->pfWelsRcPostFrameSkipping = NULL;
    break;
  case RC_BITRATE_MODE:
    pRcf->pfWelsRcPictureInit = WelsRcPictureInitGom;
    pRcf->pfWelsRcPicDelayJudge = NULL;
    pRcf->pfWelsRcPictureInfoUpdate = WelsRcPictureInfoUpdateGom;
    pRcf->pfWelsRcMbInit = WelsRcMbInitGom;
    pRcf->pfWelsRcMbInfoUpdate = WelsRcMbInfoUpdateGom;
    pRcf->pfWelsCheckSkipBasedMaxbr = CheckFrameSkipBasedMaxbr;
    pRcf->pfWelsUpdateBufferWhenSkip = UpdateBufferWhenFrameSkipped;
    pRcf->pfWelsUpdateMaxBrWindowStatus = UpdateMaxBrCheckWindowStatus;
    pRcf->pfWelsRcPostFrameSkipping = WelsRcPostFrameSkipping;
    break;
  case RC_BITRATE_MODE_POST_SKIP:
    pRcf->pfWelsRcPictureInit = WelsRcPictureInitGom;
    pRcf->pfWelsRcPicDelayJudge = NULL;
    pRcf->pfWelsRcPictureInfoUpdate = WelsRcPictureInfoUpdateGom;
    pRcf->pfWelsRcMbInit = WelsRcMbInitGom;
    pRcf->pfWelsRcMbInfoUpdate = WelsRcMbInfoUpdateGom;
    pRcf->pfWelsCheckSkipBasedMaxbr = CheckFrameSkipBasedMaxbr;
    pRcf->pfWelsUpdateBufferWhenSkip = UpdateBufferWhenFrameSkipped;
    pRcf->pfWelsUpdateMaxBrWindowStatus = UpdateMaxBrCheckWindowStatus;
    pRcf->pfWelsRcPostFrameSkipping = WelsRcPostFrameSkipping;
    break;
  case RC_TIMESTAMP_MODE:

    pRcf->pfWelsRcPictureInit = WelsRcPictureInitGom;
    pRcf->pfWelsRcPictureInfoUpdate = WelsRcPictureInfoUpdateGomTimeStamp;
    pRcf->pfWelsRcMbInit = WelsRcMbInitGom;
    pRcf->pfWelsRcMbInfoUpdate = WelsRcMbInfoUpdateGom;

    pRcf->pfWelsRcPicDelayJudge = WelsRcFrameDelayJudgeTimeStamp;
    pRcf->pfWelsCheckSkipBasedMaxbr = NULL;
    pRcf->pfWelsUpdateBufferWhenSkip = NULL;
    pRcf->pfWelsUpdateMaxBrWindowStatus = NULL;
    pRcf->pfWelsRcPostFrameSkipping = NULL;
    break;
  case RC_QUALITY_MODE:
  default:
    pRcf->pfWelsRcPictureInit = WelsRcPictureInitGom;
    pRcf->pfWelsRcPicDelayJudge = NULL;
    pRcf->pfWelsRcPictureInfoUpdate = WelsRcPictureInfoUpdateGom;
    pRcf->pfWelsRcMbInit = WelsRcMbInitGom;
    pRcf->pfWelsRcMbInfoUpdate = WelsRcMbInfoUpdateGom;
    pRcf->pfWelsCheckSkipBasedMaxbr = CheckFrameSkipBasedMaxbr;
    pRcf->pfWelsUpdateBufferWhenSkip = UpdateBufferWhenFrameSkipped;
    pRcf->pfWelsUpdateMaxBrWindowStatus = UpdateMaxBrCheckWindowStatus;
    pRcf->pfWelsRcPostFrameSkipping = NULL;
    break;
  }
}

码控模块销毁

  • 通过WelsRcFreeMemory函数完成码控模块的销毁逻辑。
void  WelsRcFreeMemory (sWelsEncCtx* pEncCtx) {
  SWelsSvcRc* pWelsSvcRc = NULL;
  int32_t i = 0;
  for (i = 0; i < pEncCtx->pSvcParam->iSpatialLayerNum; i++) {
    pWelsSvcRc  = &pEncCtx->pWelsSvcRc[i];
    RcFreeLayerMemory (pWelsSvcRc, pEncCtx->pMemAlign);
  }
}

码控模块结构体

  1. SRCTemporal结构体主要用于时域码率控制
typedef struct TagRCTemporal {
int32_t   iMinBitsTl;
int32_t   iMaxBitsTl;
int32_t   iTlayerWeight;
int32_t   iGopBitsDq;
//P frame level R-Q Model
int64_t   iLinearCmplx; // *INT_MULTIPLY
int32_t   iPFrameNum;
int64_t   iFrameCmplxMean;
int32_t   iMaxQp;
int32_t   iMinQp;
} SRCTemporal;
  1. SWelsSvcRc结构体主要用于帧级码率控制。
typedef struct TagWelsRc {
int32_t   iRcVaryPercentage;
int32_t   iRcVaryRatio;

int32_t   iInitialQp; //initial qp
int64_t   iBitRate; // Note: although the max bit rate is 240000*1200 which can be represented by int32, but there are many multipler of this iBitRate in the calculation of RC, so use int64 to avoid type conversion at all such places
int32_t   iPreviousBitrate;
int32_t   iPreviousGopSize;
double    fFrameRate;
int32_t   iBitsPerFrame;
int32_t   iMaxBitsPerFrame;
double    dPreviousFps;

// bits allocation and status
int32_t   iRemainingBits;
int32_t   iBitsPerMb;
int32_t   iTargetBits;
int32_t   iCurrentBitsLevel;//0:normal; 1:limited; 2:exceeded.

int32_t   iIdrNum;
int64_t   iIntraComplexity; //255*255(MaxMbSAD)*36864(MaxFS) make the highest bit of 32-bit integer 1
int32_t   iIntraMbCount;
int64_t   iIntraComplxMean;

int8_t    iTlOfFrames[VGOP_SIZE];
int32_t   iRemainingWeights;
int32_t   iFrameDqBits;

bool       bGomRC;
double*    pGomComplexity;
int32_t*   pGomForegroundBlockNum;
int32_t*   pCurrentFrameGomSad;
int32_t*   pGomCost;

int32_t   bEnableGomQp;
int32_t   iAverageFrameQp;
int32_t   iMinFrameQp;
int32_t   iMaxFrameQp;
int32_t   iNumberMbFrame;
int32_t   iNumberMbGom;
int32_t   iGomSize;

int32_t   iSkipFrameNum;
int32_t   iFrameCodedInVGop;
int32_t   iSkipFrameInVGop;
int32_t   iGopNumberInVGop;
int32_t   iGopIndexInVGop;

int32_t   iSkipQpValue;
int32_t   iQpRangeUpperInFrame;
int32_t   iQpRangeLowerInFrame;
int32_t   iMinQp;
int32_t   iMaxQp;
//int32_t   delta_adaptive_qp;
int32_t   iSkipBufferRatio;

int32_t   iQStep; // *INT_MULTIPLY
int32_t   iFrameDeltaQpUpper;
int32_t   iFrameDeltaQpLower;
int32_t   iLastCalculatedQScale;

//for skip frame and padding
int32_t   iBufferSizeSkip;
int64_t   iBufferFullnessSkip;
int64_t   iBufferMaxBRFullness[TIME_WINDOW_TOTAL];//0: EVEN_TIME_WINDOW; 1: ODD_TIME_WINDOW
int32_t   iPredFrameBit;
bool      bNeedShiftWindowCheck[TIME_WINDOW_TOTAL];
int32_t   iBufferSizePadding;
int32_t   iBufferFullnessPadding;
int32_t   iPaddingSize;
int32_t   iPaddingBitrateStat;
bool      bSkipFlag;
int32_t   iContinualSkipFrames;
SRCTemporal* pTemporalOverRc;

//for scc
int64_t     iAvgCost2Bits;
int64_t     iCost2BitsIntra;
int32_t    iBaseQp;
long long  uiLastTimeStamp;

//for statistics and online adjustments
int32_t   iActualBitRate; // TODO: to complete later
float     fLatestFrameRate; // TODO: to complete later
} SWelsSvcRc;
  1. SRCSlicing主要用于片级slice 的码率控制。
// slice level rc statistic info
typedef struct TagRCSlicing {
  int32_t   iComplexityIndexSlice;
  int32_t   iCalculatedQpSlice;
  int32_t   iStartMbSlice;
  int32_t   iEndMbSlice;
  int32_t   iTotalQpSlice;
  int32_t   iTotalMbSlice;
  int32_t   iTargetBitsSlice;
  int32_t   iBsPosSlice;
  int32_t   iFrameBitsSlice;
  int32_t   iGomBitsSlice;
  int32_t   iGomTargetBits;
  //int32_t   gom_coded_mb;
} SRCSlicing;

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Nvidia Isaac Sim 入门教程 2024(3)图形界面

Isaac Sim 基本使用 版权信息 Copyright 2023-2024 Herman YeAuromix. All rights reserved.This course and all of its associated content, including but not limited to text, images, videos, and any other materials, are protected by copyright law. The author …

Hadoop3:MapReduce中的Partition原理及自定义Partition

一、默认Partition分区配置 以WC案例来进行验证。 1、设置setNumReduceTasks 修改的代码 这行代码&#xff0c;确定了reduceTask的数量&#xff0c;也确定了分区逻辑 在mapper文件中&#xff0c;打上断点 计算分区的代码 这里会对每一个kv进行计算&#xff0c;然后&#…

【星环社区版TDH2024年度大事件】全新版本?全新组件?性能提升10倍?

TDH社区版家族迎来新成员 不知不觉社区版已经陪伴大家将近两年的时间了&#xff0c;在这两年里收获到了很多认可&#xff0c;同时也收获到了一些建议与意见&#xff0c;比如资源成本的问题。在去年我们发布了TDH社区开发版&#xff0c;仅需单台服务器即可一键安装部署Inceptor…

zip文件上传到linux服务器文件大小发生变化

在传一个文件到服务器的时候&#xff0c;第一次传完看见大小不一样&#xff08;服务器中du命令查看大小796596MB&#xff09;就重传了一下&#xff0c;还是大小不一样&#xff0c;就查了下。 查了下有以下原因&#xff1a; 文件系统的不同&#xff1a; 原因&#xff1a;不同的…

12.2 Go 编写测试代码

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

Spring之IoC(容器配置、Spring坐标导入、获取bean)

这里的话&#xff0c;因为博主学习时间有限&#xff0c;并没有实际去操作&#xff0c;只是学习和了解一个大概的流程。 目录 一、引言 1、管理什么&#xff1f;&#xff08;对象&#xff1a;Service、Dao ...&#xff09; 2、如何将被管理的对象告知 IoC 容器?&#xff08;用…

Linux内核编程(六)平台总线plantform驱动模型

本文目录 前述&#xff1a;为什么引入平台总线模型一、知识点1. 什么是平台总线模型2. 平台总线模型使用3. 平台总线是如何工作的4. 平台总线模型的优点 二、平台总线设备层1. 常用API&#xff08;1&#xff09; 注册一个平台设备&#xff08;2&#xff09; 注销一个平台设备&a…

2748. 美丽下标对的数目

题目 给定一个下标从 0 开始的整数数组 nums。如果下标对 (i, j) 满足 0 ≤ i < j < nums.length&#xff0c;且 nums[i] 的第一个数字与 nums[j] 的最后一个数字互质&#xff0c;那么认为 nums[i] 和 nums[j] 是一组美丽下标对。 对于两个整数 x 和 y&#xff0c;如果…

无忧易售新功能:集成图片库智能图片翻译,跨越语言障碍

在电商全球化的浪潮中&#xff0c;跨越语言的障碍&#xff0c;让产品图像说话&#xff0c;成为了商家致胜的关键。"无忧易售ERP"推出集成图片库与图片翻译功能的全新升级&#xff0c;为全球电商提供一站式解决方案&#xff0c;让商品跨越国界&#xff0c;沟通无界。 …

使用二进制安装安装docker

在一些情况下无法使用yum安装docker下面写了一个使用二进制安装docker的文档 官网下载地址https://download.docker.com/linux/static/stable/x86_64/ 可以按需求下载 wget https://download.docker.com/linux/static/stable/x86_64/docker-20.10.10.tgz 下载包 tar xf dcker…

计算机网络 —— 应用层(DHCP)

计算机网络 —— 应用层&#xff08;DHCP&#xff09; 什么是DHCPDHCP工作过程DHCP DISCOVERDHCP OFFERDHCP RQUESTDHCP ACK DHCP租约机制中继代理工作原理功能与优势 我们今天来计网的DHCP&#xff1a; 什么是DHCP DHCP&#xff08;Dynamic Host Configuration Protocol&…

Python11 使用爬虫实现图书250排行榜信息爬取

1.什么是网络爬虫 Python爬虫是使用Python编程语言编写的程序&#xff0c;它能自动从互联网上抓取数据。这类程序一般利用网络请求来访问网站&#xff0c;解析网站的HTML或其他格式的内容&#xff0c;提取出有用的数据&#xff0c;有时还会进行后续的数据处理或存储。 Python…

人工智能大模型之开源大语言模型汇总(国内外开源项目模型汇总)

开源大语言模型完整列表 Large Language Model (LLM) 即大规模语言模型&#xff0c;是一种基于深度学习的自然语言处理模型&#xff0c;它能够学习到自然语言的语法和语义&#xff0c;从而可以生成人类可读的文本。 所谓"语言模型"&#xff0c;就是只用来处理语言文…

如何制定数据治理策略?做好这7点就够了

在当今的商业环境中&#xff0c;数据已成为企业最宝贵的资产之一。随着大数据、云计算、物联网&#xff08;IoT&#xff09;和人工智能&#xff08;AI&#xff09;等技术的不断进步&#xff0c;企业积累的数据量呈指数级增长&#xff0c;这为企业提供了前所未有的商业机会&…

大语言模型的微调方法_大语言模型六种微调方法

01 引言 自2018年BERT发布以来&#xff0c;“预训练微调”成为语言模型的通用范式。以ChatGPT为代表的大语言模型针对不同任务构造Prompt来训练&#xff0c;本质上仍然是预训练与微调的使用范式。千亿规模的参数微调需要大量算力&#xff0c;即使提供了预训练的基座模型&…

正版 navicat 下载

1. 打开浏览器访问 navicat 官网 Navicat | 下载 Navicat Premium 14 天免费 Windows、macOS 和 Linux 的试用版 windows 用户选择这三项其中一个就可以 2. 下载 点击之后等个几秒钟就会开始下载了 3. 双击打开 下载好的 .exe 程序 进入安装程序 (不影响之前已经安装过的) 可…

数据结构试题 20-21

真需要就死记吧 二叉树遍历-先序(非递归)【图解代码】_哔哩哔哩_bilibili 解释一下步骤&#xff1a; 一个循环为&#xff1a; 1.取节点 2.放右子树 3.放左子树 每次循环&#xff0c;都要从栈里取出一个节点 先放右子树&#xff0c;再放左子树 那这道题就是&#xff0c;先放1&am…

山西青年杂志山西青年杂志社山西青年编辑部2024年第10期目录

本刊专稿 共融共创、校企共建BIM创新创业中心的探索与实践 黄强;马福贵;贾晓敏;苏艳贞;魏艳卿; 1-3 财务管理课程专创融合教学改革与实践 宋衍程; 4-7 数字化赋能国际贸易实务课程建设研究 吴珍彩; 8-11《山西青年》投稿&#xff1a;cn7kantougao163.com 青年教育研…

智慧学习实践系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;企业管理&#xff0c;任务管理&#xff0c;公告管理&#xff0c;菜单管理&#xff0c;用户管理&#xff0c;基础数据管理 企业账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;任务…

android 在线程中更新界面

在Android中&#xff0c;你不能直接从子线程中更新UI&#xff0c;因为这会导致应用崩溃。你需要使用Handler或runOnUiThread()来更新UI。 使用Handler 以下是如何使用Handler在子线程中更新UI的示例&#xff1a; 1. 创建Handler实例&#xff1a; import android.os.Bundle;…