openh264 自适应量化功能源码分析

openh264

  • OpenH264是一个开源的H.264/AVC视频编解码器,由Cisco公司发起并贡献了最初的代码基础。它提供了一个用于视频编码和解码的库,支持H.264视频压缩标准,广泛应用于视频会议、流媒体和视频存储等领域。
  • OpenH264是实现H.264编解码功能的一个很好的选择,特别是对于需要免费解决方案的场景。
  • OpenH264的一些关键特性:
  • 开源:OpenH264遵循BSD风格的开源许可证,允许任何人自由使用、修改和分发。

  • 跨平台:支持多种操作系统,包括Windows、Linux、Mac OS X等。

  • 高性能:提供了高效的编码和解码算法,能够处理高分辨率视频。

  • 硬件加速:支持多种硬件加速技术,如Intel Quick Sync Video、NVIDIA CUDA等。

  • 编码配置灵活:允许用户根据需要配置编码参数,如分辨率、帧率、比特率等。

  • 解码能力:除了编码功能外,OpenH264也提供了解码能力,能够解码H.264编码的视频流。

  • API接口:提供了一套API接口,方便开发者集成到自己的应用程序中。

  • 社区支持:作为一个开源项目,OpenH264得到了活跃的社区支持,不断有新的功能和改进被加入。

自适应量化功能源码文件位置

  • openh264/codec/processing/adaptivequantization/AdaptiveQuantization.cpp

自适应量化功能源码文件流程

在这里插入图片描述

  • 说明
    • 可以看到目前 openh264 选择关闭自适应量化算法,需要重构。
    • 实现自适应量化的核心功能就是 Process 函数。

自适应量化功能原理分析

  1. 功能:实现视频编码自适应量化处理,涉及到图像的运动和纹理分析,以及量化参数的动态调整等。
  2. 过程
  • 初始化一些变量,包括图像宽度、高度、宏块(MB)宽度和高度,以及总宏块数等。
  • 声明了一些用于存储运动纹理单元SMotionTextureUnit和SVAACalcResult(Variable Adaptive Analysis)计算结果的指针;其中通过VAACalcSadSsdBgd_c/VAACalcSadBgd_c函数计算
    SVAACalcResult结构体中变量。
  • 初始化了一些用于计算量化步长和量化参数的变量。
  • 获取源图像和参考图像的Y分量的指针以及它们的跨度(stride)。
  • 进入运动分析部分,计算宏块的运动残差方差和纹理方差。
  • 如果SVAACalcResult计算结果中的指针与传入的图像指针相同;
    • 则使用SVAACalcResult结果;
    • 对每个宏块,根据运动和纹理分析结果,计算运动指数iAverageMotionIndex和纹理指数iAverageTextureIndex,并累加到平均值中。
  • 否则,
    • 调用m_pfVar函数进行运动和纹理分析;
    • 对每个宏块,根据运动和纹理分析结果,计算运动指数iAverageMotionIndex和纹理指数iAverageTextureIndex,并累加到平均值中。
  • 计算平均运动指数和纹理指数,并进行一些条件判断和调整。
  • 双层 for 循环处理每个宏块;
    • 根据运动和纹理指数映射到量化参数(QP),计算iMotionTextureIndexToDeltaQp;
    • 根自适应量化模式(AQ_QUALITY_MODE或AQ_BITRATE_MODE),调整量化参数iMotionTextureIndexToDeltaQp。
  • 将计算出的量化参数映射存储到m_sAdaptiveQuantParam结构体中iAverMotionTextureIndexToDeltaQp。
  • 设置返回值为成功(RET_SUCCESS)。
  1. 相关源码
  • Process函数
EResult CAdaptiveQuantization::Process (int32_t iType, SPixMap* pSrcPixMap, SPixMap* pRefPixMap) {EResult eReturn = RET_INVALIDPARAM;int32_t iWidth     = pSrcPixMap->sRect.iRectWidth;int32_t iHeight    = pSrcPixMap->sRect.iRectHeight;int32_t iMbWidth  = iWidth  >> 4;int32_t iMbHeight = iHeight >> 4;int32_t iMbTotalNum    = iMbWidth * iMbHeight;SMotionTextureUnit* pMotionTexture = NULL;SVAACalcResult*     pVaaCalcResults = NULL;int32_t   iMotionTextureIndexToDeltaQp = 0;int32_t iAverMotionTextureIndexToDeltaQp = 0;  // double to uint32int64_t iAverageMotionIndex = 0;      // double to floatint64_t iAverageTextureIndex = 0;int64_t iQStep = 0;int64_t iLumaMotionDeltaQp = 0;int64_t iLumaTextureDeltaQp = 0;uint8_t* pRefFrameY = NULL, *pCurFrameY = NULL;int32_t iRefStride = 0, iCurStride = 0;uint8_t* pRefFrameTmp = NULL, *pCurFrameTmp = NULL;int32_t i = 0, j = 0;pRefFrameY = (uint8_t*)pRefPixMap->pPixel[0];pCurFrameY = (uint8_t*)pSrcPixMap->pPixel[0];iRefStride  = pRefPixMap->iStride[0];iCurStride  = pSrcPixMap->iStride[0];/// motion ////  motion MB residual varianceiAverageMotionIndex = 0;iAverageTextureIndex = 0;pMotionTexture = m_sAdaptiveQuantParam.pMotionTextureUnit;pVaaCalcResults = m_sAdaptiveQuantParam.pCalcResult;if (pVaaCalcResults->pRefY == pRefFrameY && pVaaCalcResults->pCurY == pCurFrameY) {int32_t iMbIndex = 0;int32_t iSumDiff, iSQDiff, uiSum, iSQSum;for (j = 0; j < iMbHeight; j ++) {pRefFrameTmp  = pRefFrameY;pCurFrameTmp  = pCurFrameY;for (i = 0; i < iMbWidth; i++) {iSumDiff =  pVaaCalcResults->pSad8x8[iMbIndex][0];iSumDiff += pVaaCalcResults->pSad8x8[iMbIndex][1];iSumDiff += pVaaCalcResults->pSad8x8[iMbIndex][2];iSumDiff += pVaaCalcResults->pSad8x8[iMbIndex][3];iSQDiff = pVaaCalcResults->pSsd16x16[iMbIndex];uiSum = pVaaCalcResults->pSum16x16[iMbIndex];iSQSum = pVaaCalcResults->pSumOfSquare16x16[iMbIndex];iSumDiff = iSumDiff >> 8;pMotionTexture->uiMotionIndex = (iSQDiff >> 8) - (iSumDiff * iSumDiff);uiSum = uiSum >> 8;pMotionTexture->uiTextureIndex = (iSQSum >> 8) - (uiSum * uiSum);iAverageMotionIndex += pMotionTexture->uiMotionIndex;iAverageTextureIndex += pMotionTexture->uiTextureIndex;pMotionTexture++;++iMbIndex;pRefFrameTmp += MB_WIDTH_LUMA;pCurFrameTmp += MB_WIDTH_LUMA;}pRefFrameY += (iRefStride) << 4;pCurFrameY += (iCurStride) << 4;}} else {for (j = 0; j < iMbHeight; j ++) {pRefFrameTmp  = pRefFrameY;pCurFrameTmp  = pCurFrameY;for (i = 0; i < iMbWidth; i++) {m_pfVar (pRefFrameTmp, iRefStride, pCurFrameTmp, iCurStride, pMotionTexture);iAverageMotionIndex += pMotionTexture->uiMotionIndex;iAverageTextureIndex += pMotionTexture->uiTextureIndex;pMotionTexture++;pRefFrameTmp += MB_WIDTH_LUMA;pCurFrameTmp += MB_WIDTH_LUMA;}pRefFrameY += (iRefStride) << 4;pCurFrameY += (iCurStride) << 4;}}iAverageMotionIndex = WELS_DIV_ROUND64 (iAverageMotionIndex * AQ_INT_MULTIPLY, iMbTotalNum);iAverageTextureIndex = WELS_DIV_ROUND64 (iAverageTextureIndex * AQ_INT_MULTIPLY, iMbTotalNum);if ((iAverageMotionIndex <= AQ_PESN) && (iAverageMotionIndex >= -AQ_PESN)) {iAverageMotionIndex = AQ_INT_MULTIPLY;}if ((iAverageTextureIndex <= AQ_PESN) && (iAverageTextureIndex >= -AQ_PESN)) {iAverageTextureIndex = AQ_INT_MULTIPLY;}//  motion mb residual map to QP//  texture mb original map to QPiAverMotionTextureIndexToDeltaQp = 0;iAverageMotionIndex = WELS_DIV_ROUND64 (AVERAGE_TIME_MOTION * iAverageMotionIndex, AQ_TIME_INT_MULTIPLY);if (m_sAdaptiveQuantParam.iAdaptiveQuantMode == AQ_QUALITY_MODE) {iAverageTextureIndex = WELS_DIV_ROUND64 (AVERAGE_TIME_TEXTURE_QUALITYMODE * iAverageTextureIndex, AQ_TIME_INT_MULTIPLY);} else {iAverageTextureIndex = WELS_DIV_ROUND64 (AVERAGE_TIME_TEXTURE_BITRATEMODE * iAverageTextureIndex, AQ_TIME_INT_MULTIPLY);}int64_t iAQ_EPSN = - ((int64_t)AQ_PESN * AQ_TIME_INT_MULTIPLY * AQ_QSTEP_INT_MULTIPLY / AQ_INT_MULTIPLY);pMotionTexture = m_sAdaptiveQuantParam.pMotionTextureUnit;for (j = 0; j < iMbHeight; j ++) {for (i = 0; i < iMbWidth; i++) {int64_t a = WELS_DIV_ROUND64 ((int64_t) (pMotionTexture->uiTextureIndex) * AQ_INT_MULTIPLY * AQ_TIME_INT_MULTIPLY,iAverageTextureIndex);iQStep = WELS_DIV_ROUND64 ((a - AQ_TIME_INT_MULTIPLY) * AQ_QSTEP_INT_MULTIPLY, (a + MODEL_ALPHA));iLumaTextureDeltaQp = MODEL_TIME * iQStep;// range +- 6iMotionTextureIndexToDeltaQp = ((int32_t) (iLumaTextureDeltaQp / (AQ_TIME_INT_MULTIPLY)));a = WELS_DIV_ROUND64 (((int64_t)pMotionTexture->uiMotionIndex) * AQ_INT_MULTIPLY * AQ_TIME_INT_MULTIPLY,iAverageMotionIndex);iQStep = WELS_DIV_ROUND64 ((a - AQ_TIME_INT_MULTIPLY) * AQ_QSTEP_INT_MULTIPLY, (a + MODEL_ALPHA));iLumaMotionDeltaQp = MODEL_TIME * iQStep;// range +- 6if ((m_sAdaptiveQuantParam.iAdaptiveQuantMode == AQ_QUALITY_MODE && iLumaMotionDeltaQp < iAQ_EPSN)|| (m_sAdaptiveQuantParam.iAdaptiveQuantMode == AQ_BITRATE_MODE)) {iMotionTextureIndexToDeltaQp += ((int32_t) (iLumaMotionDeltaQp / (AQ_TIME_INT_MULTIPLY)));}m_sAdaptiveQuantParam.pMotionTextureIndexToDeltaQp[j * iMbWidth + i] = (int8_t) (iMotionTextureIndexToDeltaQp /AQ_QSTEP_INT_MULTIPLY);iAverMotionTextureIndexToDeltaQp += iMotionTextureIndexToDeltaQp;pMotionTexture++;}}m_sAdaptiveQuantParam.iAverMotionTextureIndexToDeltaQp = iAverMotionTextureIndexToDeltaQp / iMbTotalNum;eReturn = RET_SUCCESS;return eReturn;
}
  • m_pfVar函数(指向SampleVariance16x16_c函数)
void SampleVariance16x16_c (uint8_t* pRefY, int32_t iRefStride, uint8_t* pSrcY, int32_t iSrcStride,SMotionTextureUnit* pMotionTexture) {uint32_t uiCurSquare = 0,  uiSquare = 0;uint16_t uiCurSum = 0,  uiSum = 0;for (int32_t y = 0; y < MB_WIDTH_LUMA; y++) {for (int32_t x = 0; x < MB_WIDTH_LUMA; x++) {uint32_t uiDiff = WELS_ABS (pRefY[x] - pSrcY[x]);uiSum += uiDiff;uiSquare += uiDiff * uiDiff;uiCurSum += pSrcY[x];uiCurSquare += pSrcY[x] * pSrcY[x];}pRefY += iRefStride;pSrcY += iSrcStride;}uiSum = uiSum >> 8;pMotionTexture->uiMotionIndex = (uiSquare >> 8) - (uiSum * uiSum);uiCurSum = uiCurSum >> 8;pMotionTexture->uiTextureIndex = (uiCurSquare >> 8) - (uiCurSum * uiCurSum);
}

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

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

相关文章

【鸿蒙】开发之页面跳转组件—实现页面跳转方法汇总!

①不同 Slice 间跳转&#xff0c;同一个 Ability 中&#xff0c;优点是方便&#xff0c;高效&#xff0c;缺点是业务逻辑复杂度受限。 button.setClickedListener(listener -> present(new SecondAbilitySlice(), new Intent()) );②使用 Intent 借助于 ElementName&#x…

javascript导入excel文件

导入文件用到一个 xlsx.core.js 的包。 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><script type"tex…

DSP28335模块配置模板系列——ADC配置模板

一、配置步骤 1.使能并配置高速时钟HSPCLK、ADC校验 EALLOW;SysCtrlRegs.PCLKCR0.bit.ADCENCLK 1; EDIS;EALLOW;SysCtrlRegs.HISPCP.all ADC_MODCLK; // HSPCLK SYSCLKOUT/(2*ADC_MODCLK)ADC_cal();EDIS; 这里ADC_MODCLK3&#xff0c;所以HSPCLK时钟为150/625Mhz 2.配…

《TCP/IP网络编程》(第十三章)多种I/O函数(2)

使用readv和writev函数可以提高数据通信的效率&#xff0c;它们的功能可以概括为**“对数据进行整合传输及发送”**。 即使用writev函数可以将分散在多个缓冲中的数据一并发送&#xff0c;使用readv函数可以由多个缓冲分别接受&#xff0c;所以适当使用他们可以减少I/O函数的调…

压力测试-性能指标-Jmeter使用-压力测试报告

文章目录 1.压测目的2.性能指标3.Jmeter3.1Jmeter使用3.1.1 运行Jmeter3.1.2 添加线程组3.1.3设置HTTP请求3.1.4 设置监视器 3.2 查看Jmeter压测结果3.2.1 查看结果树3.2.2 查看汇总报告3.2.3 查看聚合报告3.2.4 查看汇总图 1.压测目的 内存泄漏&#xff1a;OOM&#xff0c;重…

Hadoop3:MapReduce源码解读之Map阶段的CombineFileInputFormat切片机制(4)

Job那块的断点代码截图省略&#xff0c;直接进入切片逻辑 参考&#xff1a;Hadoop3&#xff1a;MapReduce源码解读之Map阶段的Job任务提交流程&#xff08;1&#xff09; 6、CombineFileInputFormat原理解析 类的继承关系 与TextInputFormat切片机制的区别 框架默认的TextI…

TPC-H建表语句(MySQL语法)

TPC-H测试集介绍 TPC-H&#xff08;Transaction Processing Performance Council, Standard Specification, Decision Support Benchmark, 简称TPC-H&#xff09;是一个非常权威数据库基准测试程序&#xff0c;由TPC组织制定。 TPC-H定义了一个包含8个表的模式&#xff08;Sc…

敏捷开发:拥抱变化,持续交付价值的艺术

目录 敏捷开发&#xff1a;拥抱变化&#xff0c;持续交付价值的艺术 引言 第一部分&#xff1a;敏捷开发是什么&#xff1f; a.定义&#xff1a;敏捷开发的基本概念和核心原则 b.历史&#xff1a;敏捷宣言的诞生和敏捷开发的历史背景 c.价值观&#xff1a;敏捷宣言的12条…

戴尔R720服务器(4)虚拟机性能测试

物理机环境 机型戴尔R720系统环境PVECPUE5-2660V2 2.2GHz 双路内存1333MHz 单通道内存1333MHz 双通道硬盘用6块转速1万的2.5寸盘组的RAID5&#xff0c;使用了H310mini阵列卡 ‍ 测试工具&#xff1a;Sysbench。一个跨平台的基准测试工具&#xff0c;用于评估系统性能&#xff…

[消息队列 Kafka] Kafka 架构组件及其特性(一)

工作中的消息队列用的是Kafka&#xff0c;一直没有系统的了解&#xff0c;这边集中整理一下。 目录 Kafka主要组件有十个部分。 1.Broker&#xff08;服务器&#xff09; 2.Record&#xff08;消息&#xff09; 3.Producer&#xff08;生产者&#xff09; 4.Consumer&…

Coolmuster Android助手评测:简化Android到电脑的联系人传输

产品概述 Coolmuster Android助手是一款旨在简化Android设备与计算机之间数据管理和传输过程的全面工具。它以用户友好的界面和全面的功能&#xff0c;成为寻求高效数据管理解决方案的Android用户的热门选择。 主要特点和功能Coolmuster Android助手拥有一系列使其成为管理Andr…

XR模拟的巨大飞跃,Varjo如何塑造战斗机飞行员培训的未来

随着虚拟现实技术的不断发展&#xff0c;拥有直通功能的XR技术被广泛应用于各种虚拟培训项目之中&#xff0c;能够完美混合虚拟与现实环境的XR技术能够最大限度的优化培训效果并有效减少仿真培训中的成本消耗。 技术总部位于加利福尼亚州南旧金山的Aechelon是集培训、模拟和娱乐…

盛夏之约,即将启程,2024中国北京消防展将于6月26举行

盛夏之约&#xff0c;即将启程&#xff0c;2024中国北京消防展将于6月26举行 盛夏之约&#xff0c;即将启程&#xff01;备受瞩目的2024中国&#xff08;北京&#xff09;消防技术与设备展览会将于6月26-28 日在北京.首钢会展中心盛大召开。作为消防安全和应急救援的年度盛会&…

转让北京海淀成立满1年拍卖公司许可证条件和流程

拍卖经营批准证书是拍卖企业经营所需的许可&#xff0c;是为了维护拍卖秩序&#xff0c;保护拍卖活动各方合法权益而颁发的合法凭证。其中个人物品&#xff0c;公司物品&#xff0c;或者国有资源的拍卖可通过普通拍卖资质进行拍卖。而文物古董拍卖类的需取得文物拍卖经营许可证…

Cortex系列详解

Cortex系列属于ARMv7架构(ARM公司在经典处理器ARM11以后的产品改用Cortex命名) 一、Cortex-A系列 “A”系列面向尖端的基于虚拟内存的操作系统和用户应用。 A 系列处理器适用于具有高计算要求、运行丰富操作系统以及提供交互媒体和图形体验的应用领域。 具体案例如:智能手…

course-nlp——6-rnn-english-numbers

本文参考自https://github.com/fastai/course-nlp。 使用 RNN 预测数字的英文单词版本 在上一课中&#xff0c;我们将 RNN 用作语言模型的一部分。今天&#xff0c;我们将深入了解 RNN 是什么以及它们如何工作。我们将使用尝试预测数字的英文单词版本的问题来实现这一点。 让…

K210视觉识别模块学习笔记4: (MaixHub)训练与使用自己的模型_识别字母

今日开始学习K210视觉识别模块: 模型训练与使用_识别字母 亚博智能的K210视觉识别模块...... 固件库: maixpy_v0.6.2_52_gb1a1c5c5d_minimum_with_ide_support.bin 文章提供测试代码讲解、完整代码贴出、测试效果图、测试工程下载 这里也算是正式开始进入到视觉识别的领域了…

【Python】教你彻底了解Python中的正则表达式

​​​​ 文章目录 一、正则表达式的基本概念1. 元字符2. 特殊序列 二、Python中正则表达式的使用方法1. 导入re模块2. 匹配&#xff08;match&#xff09;3. 搜索&#xff08;search&#xff09;4. 查找所有匹配&#xff08;findall&#xff09;5. 替换&#xff08;sub&#…

linux实验报告

实验一&#xff1a;Linux操作系统的安装与配置 实验目的&#xff1a; 1.掌握虚拟机技术&#xff1b; 2.掌握Linux的安装步骤&#xff1b; 3.掌握安装过程中的基本配置要求。 4.掌握正确启动Linux的方法&#xff1b; 5.掌握正确退出Linux的方法&#xff1b; 6.熟悉已安装…

在人工智能背景下,程序员要有什么职业素养,怎么改进

文章目录 1. 持续学习和适应能力原因改善方法 2. 跨学科知识原因改善方法 3. 高效的计算资源利用原因改善方法 4. 模型解释性和可控性原因改善方法 5. 数据隐私和安全意识原因改善方法 在AI大模型的背景下&#xff0c;程序员要有什么职业素养&#xff0c;怎么改进&#xff0c;才…