openh264 Pskip 模式决策过程源码分析

skip模式

视频编码中的 “skip” 模式是一种优化技术,用于提高编码效率,减少不必要的编码工作。当编码器确定某个宏块(Macroblock,
MB)在当前帧和参考帧之间没有显著的运动或变化时,可以采用skip模式。以下是skip模式的一些关键点:

  1. 宏块未变化:在视频序列中,许多宏块在连续的帧之间可能看起来相同或非常相似。如果编码器检测到这种情况,它可以决定不对这些宏块进行编码。

  2. 运动向量(Motion Vector, MV):编码器会计算当前宏块和参考帧中相应宏块之间的运动向量。如果运动向量为零或非常小,表明宏块没有显著运动,可以考虑使用skip模式。

  3. 编码效率:使用skip模式可以减少编码器需要处理的数据量,从而提高编码效率。由于不需要对这些宏块进行变换、量化和编码,编码器可以将资源集中在那些确实发生变化的宏块上。

  4. P-skip和B-skip

    • P-skip:在P帧(预测帧)中,如果宏块与前一帧中的对应宏块相同或非常相似,可以使用P-skip模式。
    • B-skip:在B帧(双向预测帧)中,如果宏块与前后两个参考帧中的对应宏块相同或非常相似,可以使用B-skip模式。
  5. 条件判断:编码器通常会根据一些条件来判断是否使用skip模式,例如宏块的运动向量、编码成本、宏块类型等。

  6. 预测和更新:在决定使用skip模式之前,编码器可能需要进行一些预测和成本计算。如果预测的成本低于实际编码的成本,编码器可能会选择skip模式。此外,编码器还需要更新相关的状态和缓存信息,以确保解码器能够正确地重建视频帧。

  7. 编码器复杂性:虽然skip模式可以提高编码效率,但它也可能增加编码器的复杂性,因为编码器需要准确地判断何时使用skip模式。

  8. 编码标准:不同的视频编码标准(如H.264/AVC, H.265/HEVC, VP9等)可能有不同的skip模式实现和优化策略。

总的来说,skip模式是一种有效的视频编码技术,可以在保持视频质量的同时减少编码工作量和提高编码速度。

openh264 中 Pskip 决策过程分析

Pskip 判断逻辑的函数关系图

在这里插入图片描述

  • 说明:可以看到Pskip 决策的核心函数是WelsMdInterJudgePskipWelsMdInterDecidedPskip两个函数。

Pskip 判断的逻辑原理

在这里插入图片描述

skip 类型判断的核心函数

  1. WelsMdInterJudgePskip函数
  • 功能:判断当前宏块是否应该尝试使用P-skip模式进行编码。
  • 原理
    • 函数的返回值bRet初始化为true;
    • 如果参考帧是P-slice类型,并且宏块缓存中的参考宏块类型是P-skip或背景类型,或者bTrySkip为true,则进入判断逻辑;
      • 调用PredictSadSkip函数来预测P-skip宏块的SAD成本;
      • 调用WelsMdPSkipEnc函数尝试P-skip编码。如果成功,则bRet保持true;如果失败,则设置为false;
      • return 返回值 bRet;
    • return 返回 false;
  • 源码
//
//  try the ordinary Pskip
//
bool WelsMdInterJudgePskip (sWelsEncCtx* pEncCtx, SWelsMD* pWelsMd, SSlice* pSlice, SMB* pCurMb, SMbCache* pMbCache,bool bTrySkip) {bool bRet = true;if (((pEncCtx->pRefPic->iPictureType == P_SLICE) && (pMbCache->uiRefMbType == MB_TYPE_SKIP|| pMbCache->uiRefMbType == MB_TYPE_BACKGROUND)) ||bTrySkip) {PredictSadSkip (pMbCache->sMvComponents.iRefIndexCache, pMbCache->bMbTypeSkip, pMbCache->iSadCostSkip, 0,& (pWelsMd->iSadPredSkip));bRet = WelsMdPSkipEnc (pEncCtx, pWelsMd, pCurMb, pMbCache) ? true : false;return bRet;}return false;
}
  1. WelsMdInterDecidedPskip函数
  • 功能:将一个宏块标记为P-skip,并执行与此相关的编码操作。
  • 原理
    • 从编码上下文中获取当前解码层(Decoding Queue Layer)的指针;
    • 将当前宏块的类型设置为 MB_TYPE_SKIP,表明这是一个P-skip宏块;
    • 调用 WelsRecPskip 函数来记录P-skip宏块;
    • 调用 WelsMdInterUpdatePskip 函数来更新P-skip宏块的编码信息。
  • 源码
//
//  Pskip mb encode
//
void WelsMdInterDecidedPskip (sWelsEncCtx* pEncCtx, SSlice* pSlice, SMB* pCurMb, SMbCache* pMbCache) {SDqLayer* pCurDqLayer = pEncCtx->pCurDqLayer;pCurMb->uiMbType = MB_TYPE_SKIP;WelsRecPskip (pCurDqLayer, pEncCtx->pFuncList, pCurMb, pMbCache);WelsMdInterUpdatePskip (pCurDqLayer, pSlice, pCurMb, pMbCache);
}
  1. WelsMdInterDoubleCheckPskip函数
  • 功能:在特定条件下检查并可能更新宏块的类型为P-skip。
  • 原理
    • 检查当前宏块的类型是否为16x16模式,并且宏块的CBP(Coded Block Pattern)是否为0。如果都满足,表示宏块没有被编码,可能是由于没有显著变化;
      • 检查当前宏块的参考帧索引是否为0,这可能表示宏块使用的是帧内预测;
        • 初始化一个运动向量结构体sMvp;
        • 调用PredSkipMv函数预测跳过的宏块的运动向量,并将结果存储在sMvp中;
        • 比较预测的运动向量和当前宏块的运动向量是否相同;
          • 如果运动向量相同,将宏块类型设置为P-skip;
      • 根据当前宏块的运动向量是否为0,设置一个标志bCollocatedPredFlag,表示是否使用了同位置的预测。
  • 源码
//
//  doublecheck if current MBTYPE is Pskip
//
void WelsMdInterDoubleCheckPskip (SMB* pCurMb, SMbCache* pMbCache) {if (MB_TYPE_16x16 == pCurMb->uiMbType && 0 == pCurMb->uiCbp) {if (0 == pCurMb->pRefIndex[0]) {SMVUnitXY sMvp = { 0 };PredSkipMv (pMbCache, &sMvp);if (LD32 (&sMvp) == LD32 (&pCurMb->sMv[0])) {pCurMb->uiMbType = MB_TYPE_SKIP;}}pMbCache->bCollocatedPredFlag = (LD32 (&pCurMb->sMv[0]) == 0);}
}

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

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

相关文章

C#部分方法有什么用处?和传统方法有什么区别?什么时候用合适?

在C#中,部分类(partial class)和部分方法(partial method)是两个不同的概念,但它们经常一起使用,特别是在代码生成和框架设计中。下面我将分别解释这两个概念,并讨论它们的用处、与传…

汽车IVI中控开发入门及进阶(二十七):车载摄像头vehicle camera

前言: 在车载IVI、智能座舱系统中,有一个重要的应用场景就是视频。视频应用又可分为三种,一种是直接解码U盘、SD卡里面的视频文件进行播放,一种是手机投屏,就是把手机投屏软件已视频方式投屏到显示屏上显示,另外一种就是对视频采集设备(主要就是摄像头Camera)的视频源…

leetcode144. 二叉树的前序遍历

一、题目描述: 给你二叉树的根节点 root ,返回它节点值的 前序 遍历。 二、输入输出实例: 示例 1: 输入:root [1,null,2,3] 输出:[1,2,3]示例 2: 输入:root [] 输出:[]…

ubuntu查看当前系统版本

要查看当前的Ubuntu系统版本,可以使用以下几种方法: 方法一:使用 lsb_release 命令 这是最常用的方法,适用于大多数Debian系发行版,包括Ubuntu。 lsb_release -a这将显示类似以下的输出: No LSB module…

移动app必须进行安全测试吗?包括哪些测试内容?

移动App已经成为我们日常生活中不可或缺的一部分,无论是社交娱乐还是工作学习,我们都离不开这些精心设计的应用程序。然而,随着移动App的广泛普及和使用,其安全性问题也逐渐浮出水面。为了确保用户数据的安全和减少潜在的风险&…

IOS全平台去开屏广告方案,真实有效

笔者最近被苹果平台上的APP开屏广告搞得心烦意乱,十分想念安卓的李跳跳,逐在B站搜索方法,看到评论说圈x可以去开屏广告。 但经一番搜索,发现圈x要求很高且貌似小火箭的规则生态更好。接下来是最经济的最有效的解决方案&#xff1a…

数智化浪潮下的零售品牌商品计划革新

在数字化和智能化交织的时代背景下,零售品牌的商品计划正在经历一场前所未有的革新。这场革新不仅改变了商品计划的方式和流程,更重塑了零售品牌的竞争格局和市场地位。 一、数智化:零售品牌的新引擎 在快速变化的市场环境中,零…

旧电视盒子的玩法与思路

旧的电视盒子,和电视主板,只要是安卓的,都不用丟。 留着有大用。 第一种玩法:也是我刚完盒子接触到的,就是刷游戏机,一般这种是把游戏系统刷到tf卡或者优盘上面,不妨碍你的盒子看电视&#xf…

序列到序列模型中的注意力机制

目录 一、说明 二、编码器解码器架构中的问题:需要注意 2.1 编码器方面的问题: 2.2 解码器方面的问题: 三、什么是注意力机制? 3.1 计算 ci 值: 3.2 ci 的广义表示: 四、Bahdanau 注意 : 4.1. 兼…

Centos/Ubuntu等Linux系统下增加扩展4个串口以上配置操作

linux(Ubuntu、centos等)标准发行版系统默认是最多识别到4个COM串口设备,超过4个设备的串口则无法识别使用,想要载入使用则需要手动修改下grub配置文件,手动指定即可!可以参考如下步骤,有出入的地方大家可以…

yt-dlp:强大的跨平台视频下载器

一、引言 在当今数字时代,视频已成为我们获取信息和娱乐的重要途径。然而,由于版权和网络限制,我们常常无法直接在本地保存我们喜爱的视频。幸运的是,有一个名为yt-dlp的命令行程序,它可以帮助我们从YouTube.com和其他…

Tomcat 概述与部署1

一、Tomcat服务器简介 Tomcat 是 Java 语言开发的,Tomcat 服务器是一个免费的开放源代码的 Web 应用服务器,是 Apache 软件基金会的 Jakarta 项目中的一个核心项目,由 Apache、Sun 和其他一些公司及个人共同开发而成。 Tomcat 属于轻量级应…

【问题记录】解压文件出现:Cannot create symbolic link : 客户端没有所需的特权。

用7zip解压文件时候出现了如下错误: Cannot create symbolic link : 客户端没有所需的特权。 : C:\Users\86150\Downloads\mmpose_v1.0\mmpose.mim\tools Cannot create symbolic link : 客户端没有所需的特权。 : C:\Users\86150\Downloads\mmpose_v1.0\mmpose.mi…

自动化测试岗位的标准化求职指南(0到1)

简介: 自动化测试是软件开发过程中的关键环节,对于企业来说,招聘一名合适的自动化测试工程师非常重要。本文将从零开始,为想要从事自动化测试工作的求职者提供一份详细且规范的求职指南,帮助他们在自动化测试领域找到…

爱,需要学习--如何进入到一段亲密关系

[页面 7]: 亲密关系的经营, 是自我发展的延伸, 只不过和自我发展 相比, 亲密关系的经营有自己的逻辑, 它围绕着两个核心展 开。 [页面 7]: 一个核心是“关系”。“关系”不是你的事,也不是我的事,而 是发生…

猫头虎 分享已解决Bug || `Uncaught ReferenceError: x is not defined`✨

猫头虎 分享已解决Bug || Uncaught ReferenceError: x is not defined🚀✨ 摘要 ✨💡 大家好,我是猫头虎,一名全栈软件工程师,同时也是一位科技自媒体博主。今天我要和大家分享一些前端开发过程中常见的Bug以及详细的…

Java | Leetcode Java题解之第147题对链表进行插入排序

题目: 题解: class Solution {public ListNode insertionSortList(ListNode head) {if (head null) {return head;}ListNode dummyHead new ListNode(0);dummyHead.next head;ListNode lastSorted head, curr head.next;while (curr ! null) {if (…

LeetCode 14. 最长公共前缀

LeetCode 14. 最长公共前缀 编写一个函数来查找字符串数组中的最长公共前缀。 如果不存在公共前缀,返回空字符串 “”。 示例 1: 输入:strs [“flower”,“flow”,“flight”] 输出:“fl” 示例 2: 输入:s…

配置OSPF认证(华为)

#交换设备 配置OSPF认证-基于华为路由器 OSPF(开放最短路径优先)是一种内部网关协议(IGP),用于在单一自治系统(AS)内决策路由。OSPF认证功能是路由器中的一项安全措施,它的主要用途…

JavaFX密码字段

PasswordField用于密码输入。用户键入的字符通过显示回显字符串被隐藏。 创建密码字段 以下代码使用来自PasswordField类的默认构造函数创建一个密码字段,然后为密码字段设置提示消息文本。 提示消息在字段中显示为灰色文本,并为用户提供该字段是什么的…