openh264 帧内预测编码原理:WelsMdIntraChroma 函数

news2024/11/28 1:29:40

帧内色度预测编码

  • 帧内预测的目的是利用图像中相邻像素的亮度和色度值之间的接近性来进行压缩。在H.264中,帧内预测包括亮度和色度的预测。色度预测模式通常是基于亮度预测模式来确定的,因为色度分量通常具有更高的空间冗余度。色度预测模式的选择可以基于亮度预测模式,并且可能包括DC模式、垂直模式、水平模式等。
  • 在OpenH264中,帧内色度预测编码的过程涉及到几个核心函数,如 WelsMdIntraChroma 函数,它负责色度像素块的帧内模式决策。色度的预测模式与亮度16x16块的预测模式相似,有7种模式可供选择。在编码过程中,会根据可用的参考像素和预测模式列表来选择最佳模式,以最小化编码成本。

函数介绍

  1. 函数说明:类似 I16x16决策过程,色度的预测模式跟 I16x16 块一样,具体可以参考:openh264 帧内预测编码过程源码分析。
  2. 函数功能:针对色度像素块的帧内模式决策
  3. 函数原型
int32_t WelsMdIntraChroma (SWelsFuncPtrList* pFunc, SDqLayer* pCurDqLayer, SMbCache* pMbCache, int32_t iLambda)
  1. 函数参数
  • pFunc: 指向函数指针列表的指针,包含用于编码的各种函数。
  • pCurDqLayer: 指向当前解码层的指针。
  • pMbCache: 指向宏块缓存的指针,包含编码过程中使用的缓存数据。
  • iLambda: 一个用于调整成本计算的权重值。

函数关系图

在这里插入图片描述

函数原理

  1. 内部实现详细过程
  • 局部变量初始化;
  • 根据宏块的领域宏块情况计算得出iOffset;
  • iAvailCount 和 kpAvailMode 用于获取当前宏块可用的帧内预测模式数量和预测模式列表;
  • 如果iAvailCount大于 3,且提供 pfIntra16x16Combined3函数,
    • 调用pfIntra16x16Combined3函数计算出最佳代价iBestCost和色度最佳模式iBestMode;
    • 基于当前预测模式iCurMode调用pfGetChromaPred函数分别预测两个色度 Cb、Cr的预测块;
    • 调用pfMdCost函数计算两个色度的代价相加,并加上iLambda * 4,作为当前模式下的代价iCurCost;
    • 如果 iCurCost 小于 iBestCost,
      • 则更新最佳模式iBestMode和最佳代价iBestCost;
    • 否则,
      • 基于最佳模式iBestMode,重新调用pfGetChromaPred函数分别预测两个色度的预测块;
    • 累加iLambda到最佳代价iBestCost;
  • 否则,
    • for 循环每个模式,
      • 基于当前预测模式iCurMode调用pfGetChromaPred函数分别预测两个色度 Cb、Cr的预测块;
      • 调用pfMdCost函数计算两个色度的代价相加,并加上加上量化参数 iLambda 与当前模式编号的编码长度(使用 BsSizeUE 函数和 g_kiMapModeI16x16 数组计算)的乘积,作为当前模式下的代价iCurCost;
      • 如果 iCurCost 小于 iBestCost,
        • 则更新最佳模式iBestMode和最佳代价iBestCost;
  • 返回最佳代价iBestCost。
  1. 函数原理流程图
    在这里插入图片描述

源码


int32_t WelsMdIntraChroma (SWelsFuncPtrList* pFunc, SDqLayer* pCurDqLayer, SMbCache* pMbCache, int32_t iLambda) {
  const int8_t* kpAvailMode;
  int32_t iAvailCount = 0;
  int32_t iChmaIdx = 0;
  uint8_t* pPredIntraChma[2]    = {pMbCache->pMemPredChroma, pMbCache->pMemPredChroma + 128};
  uint8_t* pDstChma             = pPredIntraChma[0];
  uint8_t* pEncCb               = pMbCache->SPicData.pEncMb[1];
  uint8_t* pEncCr               = pMbCache->SPicData.pEncMb[2];
  uint8_t* pDecCb               = pMbCache->SPicData.pCsMb[1];//pMbCache->SPicData.pDecMb[1];
  uint8_t* pDecCr               = pMbCache->SPicData.pCsMb[2];//pMbCache->SPicData.pDecMb[2];
  const int32_t kiLineSizeEnc   = pCurDqLayer->iEncStride[1];
  const int32_t kiLineSizeDec   = pCurDqLayer->iCsStride[1];//pMbCache->SPicData.i_stride_dec[1];

  int32_t i, iCurMode, iCurCost, iBestMode, iBestCost = INT_MAX;

  int32_t iOffset = pMbCache->uiNeighborIntra & 0x07;
  iAvailCount = g_kiIntraChromaAvailMode[iOffset][4];
  kpAvailMode = g_kiIntraChromaAvailMode[iOffset];
  if (iAvailCount > 3 && pFunc->sSampleDealingFuncs.pfIntra8x8Combined3) {
    iBestCost = pFunc->sSampleDealingFuncs.pfIntra8x8Combined3 (pDecCb, kiLineSizeDec, pEncCb, kiLineSizeEnc, &iBestMode,
                iLambda, pDstChma, pDecCr, pEncCr);
    iCurMode = kpAvailMode[3];
    pFunc->pfGetChromaPred[iCurMode] (pDstChma, pDecCb, kiLineSizeDec); //Cb
    pFunc->pfGetChromaPred[iCurMode] (pDstChma + 64, pDecCr, kiLineSizeDec); //Cr

    iCurCost = pFunc->sSampleDealingFuncs.pfMdCost[BLOCK_8x8] (pDstChma, 8, pEncCb, kiLineSizeEnc) +
               pFunc->sSampleDealingFuncs.pfMdCost[BLOCK_8x8] (pDstChma + 64, 8, pEncCr, kiLineSizeEnc) +
               iLambda * 4;
    if (iCurCost < iBestCost) {
      iBestMode = iCurMode;
      iBestCost = iCurCost;
    } else {
      pFunc->pfGetChromaPred[iBestMode] (pDstChma, pDecCb, kiLineSizeDec); //Cb
      pFunc->pfGetChromaPred[iBestMode] (pDstChma + 64, pDecCr, kiLineSizeDec); //Cr
    }
    iBestCost += iLambda;
    iChmaIdx = 1;
  } else {
    iBestMode = kpAvailMode[0];
    for (i = 0; i < iAvailCount; ++ i) {
      iCurMode = kpAvailMode[i];

      assert (iCurMode >= 0 && iCurMode < 7);

      // pDstCb = &pMbCache->mem_pred_intra_cb[iCurMode<<6];
      // pDstCr = &pMbCache->mem_pred_intra_cr[iCurMode<<6];
      pFunc->pfGetChromaPred[iCurMode] (pDstChma, pDecCb, kiLineSizeDec); //Cb
      iCurCost = pFunc->sSampleDealingFuncs.pfMdCost[BLOCK_8x8] (pDstChma, 8, pEncCb, kiLineSizeEnc);

      pFunc->pfGetChromaPred[iCurMode] (pDstChma + 64, pDecCr, kiLineSizeDec); //Cr
      iCurCost += pFunc->sSampleDealingFuncs.pfMdCost[BLOCK_8x8] (pDstChma + 64, 8, pEncCr, kiLineSizeEnc) +
                  iLambda * BsSizeUE (g_kiMapModeIntraChroma[iCurMode]);
      if (iCurCost < iBestCost) {
        iBestMode = iCurMode;
        iBestCost = iCurCost;
        iChmaIdx = iChmaIdx ^ 0x01;
        pDstChma = pPredIntraChma[iChmaIdx];
      }
    }
  }

  pMbCache->pBestPredIntraChroma = pPredIntraChma[iChmaIdx ^ 0x01];
  pMbCache->uiChmaI8x8Mode = iBestMode;
  return iBestCost;
}

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

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

相关文章

汽车级TPSI2140QDWQRQ1隔离式固态继电器,TMUX6136PWR、TMUX1109PWR、TMUX1133PWR模拟开关与多路复用器(参数)

1、TPSI2140-Q1 是一款隔离式固态继电器&#xff0c;专为高电压汽车和工业应用而设计。 TPSI2140-Q1 与 TI 具有高可靠性的电容隔离技术和内部背对背 MOSFET 整合在一起&#xff0c;形成了一款完全集成式解决方案&#xff0c;无需次级侧电源。 该器件的初级侧仅由 9mA 的输入电…

Blender帧动画

时间线窗口Timeline用于定义帧动画 -视图&#xff1a;方法&#xff0c;平移&#xff0c;框显全部 -帧范围&#xff1a;可以调整动画共多少帧 -当前帧&#xff1a;可以拖动或手工指定 默认每秒24帧 定义一个帧动画类似unity的Timeline&#xff0c;只需定义关键帧&#xff0c…

java学习 项目篇 一

学习地址&#xff1a;https://www.bilibili.com/video/BV1TP411v7v6?p6&spm_id_frompageDriver&vd_sourcea6f7db332f104aff6fadf5b3542e5875 后端环境搭建 Entity 实体&#xff0c;通常和数据库的表对应DTO 数据传输对象&#xff0c;用于程序中各层之间传递数据 (前端…

如何使用Keil打开GD32 FPU及使用ARM DSP库

GD32目前支持ARM Cortex-M和RISC-V两种内核系列芯片&#xff0c;其中Cortex-M内核已经支持的有M3、M4、M23、M33、M7&#xff0c;这里面除了M3和M23以外&#xff0c;其他的都带FPU单元。我们知道&#xff0c;FPU在浮点运算速度上有很大的提升&#xff0c;并且只有带FPU才可以使…

服务器权限管理

我们linux服务器上有严格的权限等级&#xff0c;如果权限过高导致误操作会增加服务器的风险。所以对于了解linux系统中的各种权限及要给用户&#xff0c;服务等分配合理的权限十分重要。&#xff08;权限越大&#xff0c;责任越大&#xff09; 1.基本权限 U--user用户,G-group…

板凳------56.Linux/Unix 系统编程手册(下) -- SOCKET 介绍

56.1.概述 socket 是一种IPC方法&#xff0c;允许位于同一主机或使用网络连接起来的不同主机上的应用程序之间交换数据。 UNIX 允许位于同一主机系统上的应用程序之间通信 Internet domain IPv4 and IPV6 // socket 通信方式 1.各个应用程序创建一个socket&#xff0c;socket是…

GraogGNSSLib学习

GraogGNSSLib学习 程序编译环境版本项目编译结果问题 程序编译 GraphGNSSLib 环境版本 程序开源是在ubuntu16.04-kinetic环境跑通的&#xff0c;但是我的环境是UBUNTU20.04&#xff0c;所以&#xff0c;先进行了ROS的安装&#xff0c;因为我的系统是ubuntu20.04所以&#xf…

软考中级|软件设计师-知识点整理

目录 计算机网络概论 计算机系统基础知识 中央处理单元 数据表示 校验码 计算机体系结构 计算机体系结构的发展 存储系统 输入/输出技术 安全性、可靠性与系统性能评测基础知识 加密技术和认证技术 计算机可靠性 程序设计语言基础知识 程序设计语言概述 程序设计…

Python自动化办公(二) —— 查看文件夹中的PDF文件数量

Python自动化办公&#xff08;二&#xff09; —— 查看文件夹中的PDF文件数量 在日常办公中&#xff0c;我们经常需要统计某个文件夹中的PDF文件数量。手动操作不仅费时费力&#xff0c;而且容易出错。幸运的是&#xff0c;使用Python可以轻松实现这个过程。本文将介绍如何使用…

南通国际高中有哪些?南通惠立学校高中部校长见面日重磅来袭

惠灵顿&#xff08;中国&#xff09;自2011年成立以来&#xff0c;一直坚持深耕国际与双语教育&#xff0c;拥有丰厚的办学经验。依托于集团化的深厚经验南通惠立学校于2024-2025学年开设9-11年级&#xff0c;这所南通国际高中为高中学生搭建一个集卓越升学成果、强大师资、纯正…

码住!详解时序数据库不同分类与性能对比

加速发展中的时序数据库&#xff0c;基于不同架构&#xff0c;最流行的类别是&#xff1f; 作为管理工业场景时序数据的新兴数据库品类&#xff0c;时序数据库凭借着对海量时序数据的高效存储、高可扩展性、时序分析计算等特性&#xff0c;一跃成为物联网时代工业领域颇受欢迎的…

解决Maven依赖引入不成功的问题

解决Maven依赖引入不成功的问题 确认IntelliJ IDEA中Maven的设置是否正确。 file --> settings --> maven 清除无效的jar&#xff0c;进入本地仓库清除或利用bat工具 以下是bat工具内容&#xff0c;运行即可。【把仓库地址换成你自己的地址进行无效jar包清除】 echo o…

C++:STL容器-->set

使用set容器时需要导入头文件&#xff1a;#include <set> set和multiset区别&#xff1a; set不允许容器中有重复的元素 multiset允许容器中有重复的元素 1. 构造函数 set<T> st; set s(const &st); void printSet(set<int>& s) {for (set<int>…

laravel版本≥ 8.1

laravel10 php ≥ 8.1 且 ≤ 8.3&#xff1f; 8.1 < php < 8.3PHP版本要求在 8.1 到 8.3 之间&#xff0c;包括这两个版本。具体来说&#xff1a;"≥ 8.1" 表示 PHP 的版本至少是 8.1&#xff0c;也就是说 8.1 及以上的版本都可以。 "≤ 8.3" 表示 P…

MBD_入门篇_21_SimulinkSignalAttributes

21.SignalAttributes 21.1 概述 Signal Attributes&#xff0c;信号属性&#xff0c;信号特性。 21.2 回顾常用模块 21.2.1 DataTypeConversion 数据类型转换模块&#xff0c;可以对信号的数据类型进行强制转换。无符号数据与有符号数据相加&#xff0c;我们可以将无符号数据转…

VS2022 使用C++访问 mariadb 数据库

首先,下载 MariaDB Connector/C++ 库 MariaDB Products & Tools Downloads | MariaDB 第二步,安装后 第三步,写代码 #include <iostream> #include <cstring> #include <memory> #include <windows.h>#include <mariadb/conncpp.hpp>…

echarts学习:通过图例事件实现选中后控制多条折线的显隐

1.问题描述 我在工作中遇到了这样一个需求&#xff1a;我们都知道点击echarts折线图的图例&#xff0c;是可以控制折线的显隐的。我现在希望点击某一个图例可以改变多条折线的显隐。 例如在下面这张图中&#xff0c;我将“xxx水位”和“yyy水位”分为一组&#xff1b;将“xxx…

基于vue的游戏网站设计与实现-计算机毕业设计源码02473

摘要 随着计算机科学技术日渐成熟&#xff0c;人们已经深刻认识到了计算机功能的强大&#xff0c;计算机已经进入到了人类社会发展的各个领域&#xff0c;并且发挥着十分重要的作用。通过管理系统在电脑上的应用&#xff0c;人们能更好的管理信息&#xff0c;储存数据。为了能够…

Linux 终端窗口设置为透明

Linux 终端窗口设置为透明 打开终端 右键鼠标 选择Profile Preferences 点击Background 选择 Transparent background 拖动滑条调整透明度 完成。

SQL编程基础常见题型练习

SQL编程基础常见题型练习 1. 基础查询1.1. 基础查询1.2. 简单处理查询结果 2. 条件查询2.1. 基础排序2.2. 基础操作符2.3. 高级操作符 3. 高级查询3.1. 计算函数3.2. 分组查询 4. 多表查询4.1. 子查询4.2. 链接查询4.3. 组合查询 5. 必会的常用函数5.1. 条件函数5.2. 日期函数 …