libaom 源码分析:帧间运动矢量预测
AV1 帧间运动矢量预测原理
- 运动矢量可以被相邻块预测,这些相邻块可以是空域相邻块,或位于参考帧中的时域相邻块;通过检查所有这些块,将确定一组运动矢量预测器,并用于编码运动矢量信息。
空域运动矢量预测
- 两组空域相邻块可以被利用寻找空域 MV 预测器,第一组包括当前块的直接上方和左侧的邻近空间邻居,第二组包括靠近但不是直接相邻于当前块的外部空间邻居。
- 对于每组空间邻近块,首先从左到右检查顶行,然后从上到下检查左列。对于相邻空间邻近块,在检查完左列邻近块之后,还会额外检查右上角的块。对于非相邻空间邻近块,首先检查位于(-1,-1)位置的左上角块,然后以与相邻邻近块相似的方式检查顶行和左列。首先检查相邻邻近块,其次检查下一子节将描述的时间运动矢量预测器,之后检查非相邻空间邻近块。
- 对于使用一对参考帧的复合预测,不使用非相邻空间邻近块来推导运动矢量预测器。
时域运动矢量预测
-
除了空域相邻块,MV 预测器还可以使用参考图像的同位块来推导出运动矢量(MV)预测器,即所谓的时间MV预测器。
-
过程:
-
存储参考帧的MV:首先,将参考帧的MV与各自的参考帧索引一起存储。
-
为当前帧的每个8×8块生成时间MV预测器:对于当前帧的每个8×8块,识别并存储穿过该块的参考帧的MV,并与参考帧索引一起存放在时间MV缓冲区中。
-
示例:如下图所示的例子中,参考帧1(R1;图右侧)的MV,即MVref,从R1指向R1的参考帧(图左侧)。在此过程中,它穿过了当前帧的8×8块。MVref被存储在与这个8×8块相关联的时间MV缓冲区中。
-
运动投影过程:在推导时间MV预测器的过程中,参考帧按预定义的顺序进行扫描:LAST_FRAME、BWDREF_FRAME、ALTREF2_FRAME、ALTREF_FRAME和LAST2_FRAME。按扫描顺序,较晚的参考帧的MV会替换之前识别的MV。
-
最终时间MV预测器的确定:给定预定义的块坐标,识别并投影存储在时间MV缓冲区中的相关MV,以派生出指向当前块到其参考帧的时间MV预测器,例如上图中的MV0。
-
时间MV预测器的预定义块位置:如下图所示,展示了派生16×16块时间MV预测器的预定义块位置。最多检查七个块以找到有效的时间MV预测器。在检查最近的空间MV预测器之后,但在检查非相邻空间MV预测器之前,会检查时间MV预测器。
-
-
MV预测器的派生:在派生MV预测器时,将所有空间和时间MV候选项汇集在一起,每个预测器被分配一个在扫描空间和时间邻近块期间确定的权重。基于相关权重,对候选项进行排序和排名,并识别出多达四个候选项,将它们添加到MV预测器列表中。这个MV预测器列表也被称为动态参考列表(DRL),如下一子节所述,它在动态MV预测模式中进一步使用。
动态运动矢量预测
-
运动向量(MVs)的预测可以通过以下方式完成:
- 空间邻近块:在当前帧内,利用空间上邻近的编码块来预测MV。
- 时间邻近块:在参考帧内,利用时间上邻近的块来预测MV。
- MV预测器集合:通过检查所有这些块,最多可以确定四个MV预测器。
-
单参考帧间预测的MV预测模式:
- NEARESTMV:始终使用MV预测器列表中索引为0的条目。它适用于那些运动变化不大的场景,选择最接近当前编码块的运动向量作为预测。
- NEARMV:使用索引为1、2或3的条目之一,信号化一个三元DRL(直接参考列表)索引来指示使用哪个条目作为MV预测器。
- NEWMV:使用索引为0、1或2的条目之一,信号化一个三元DRL索引来指示使用哪个条目作为MV预测器,并信号化相对于MV预测器的MV差分(MVD)。
- GLOBALMV:使用基于帧级全局运动参数的MV作为MV预测器。它适用于全局运动补偿的场景,其中整个帧或大部分区域都遵循相同的运动。
-
复合帧间预测的MV预测模式:
-
NEAREST_NEARESTMV:始终使用列表中索引为0的MV对。
-
NEAR_NEARMV:使用由三元DRL索引信号化的索引为1、2或3的MV对。
-
NEAREST_NEWMV:始终使用列表中索引为0的MV对作为MV预测器,并为第二个MV信号化一个MVD。
-
NEW_NEARESTMV:始终使用列表中索引为0的MV对作为MV预测器,并为第一个MV信号化一个MVD。
-
NEAR_NEWMV:使用由三元DRL索引信号化的索引为1、2或3的MV对作为MV预测器,并为第二个MV信号化一个MVD。
-
NEW_NEARMV:使用由三元DRL索引信号化的索引为1、2或3的MV对作为MV预测器,并为第一个MV信号化一个MVD。
-
NEW_NEWMV:使用由三元DRL索引信号化的索引为0、1或2的MV对作为MV预测器,并为两个MV都信号化MVD。
-
GLOBAL_GLOBALMV:基于每个参考帧的帧级全局运动参数使用MV。
-
除了NEARESTMV和NEAREST_NEARESTMV模式外,在所有情况下,都需要信号化DRL索引来指定用作MV预测器的确切MV或MV对。然而,DRL索引的范围在参考列表中可以根据MV预测模式是[0, 1, 2]或[1, 2, 3]。
-
libaom 相关源码分析
-
函数关系:
-
av1_find_mv_refs 函数:
- 获取宏块位置:从 xd 结构中获取当前宏块的行(mi_row)和列(mi_col)。
- 初始化全局运动矢量:gm_mv 数组用于存储全局运动矢量,它将被初始化为零。
- 处理内部帧:如果参考帧是内部帧(INTRA_FRAME),则将全局运动矢量设置为零,并将 global_mvs 对应的元素标记为无效。
- 计算全局运动矢量:如果参考帧不是内部帧,根据参考帧的类型(单参考帧或复合参考帧),计算全局运动矢量。这些矢量是通过 gm_get_motion_vector 函数计算的,该函数考虑了是否允许高精密运动矢量和是否强制整数运动矢量。
- 设置参考运动矢量列表:调用 setup_ref_mv_list 函数,传入上述参数,以设置参考运动矢量列表。这个列表将用于后续的运动矢量预测和编码过程。
void av1_find_mv_refs(const AV1_COMMON *cm, const MACROBLOCKD *xd,MB_MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,uint8_t ref_mv_count[MODE_CTX_REF_FRAMES],CANDIDATE_MV ref_mv_stack[][MAX_REF_MV_STACK_SIZE],uint16_t ref_mv_weight[][MAX_REF_MV_STACK_SIZE],int_mv mv_ref_list[][MAX_MV_REF_CANDIDATES],int_mv *global_mvs, int16_t *mode_context) {const int mi_row = xd->mi_row;const int mi_col = xd->mi_col;int_mv gm_mv[2];if (ref_frame == INTRA_FRAME) {gm_mv[0].as_int = gm_mv[1].as_int = 0;if (global_mvs != NULL) {global_mvs[ref_frame].as_int = INVALID_MV;}} else {const BLOCK_SIZE bsize = mi->bsize;const int allow_high_precision_mv = cm->features.allow_high_precision_mv;const int force_integer_mv = cm->features.cur_frame_force_integer_mv;if (ref_frame < REF_FRAMES) {gm_mv[0] = gm_get_motion_vector(&cm->global_motion[ref_frame],allow_high_precision_mv, bsize, mi_col,mi_row, force_integer_mv);gm_mv[1].as_int = 0;if (global_mvs != NULL) global_mvs[ref_frame] = gm_mv[0];} else {MV_REFERENCE_FRAME rf[2];av1_set_ref_frame(rf, ref_frame);gm_mv[0] = gm_get_motion_vector(&cm->global_motion[rf[0]],allow_high_precision_mv, bsize, mi_col,mi_row, force_integer_mv);gm_mv[1] = gm_get_motion_vector(&cm->global_motion[rf[1]],allow_high_precision_mv, bsize, mi_col,mi_row, force_integer_mv);}}setup_ref_mv_list(cm, xd, ref_frame, &ref_mv_count[ref_frame],ref_mv_stack[ref_frame], ref_mv_weight[ref_frame],mv_ref_list ? mv_ref_list[ref_frame] : NULL, gm_mv, mi_row,mi_col, mode_context);
}
- setup_ref_mv_list 函数
- 扫描第一行上方模式信息:scan_row_mbmi 函数被调用来扫描当前宏块正上方的行(row_offset = -1)的模式信息;
- 扫描第一列左边模式信息:scan_col_mbmi 函数被调用来扫描当前宏块左方的列(col_offset = -1)的模式信息;
- 检查上右边界:如果宏块有右上角块(has_tr 为真),则调用 scan_blk_mbmi 函数来扫描右上角块的模式信息;
- 获取时域参考 mv 信息:调用add_tpl_ref_mv函数获取时域参考 mv 信息;
- 扫描第二外层区域,检查左上角块:scan_blk_mbmi 函数检查左上角块;
- for 循环两次外层行列:分别调用scan_row_mbmi、scan_col_mbmi函数扫描外层的行、列信息;
- 根据nearest_match 更新模式上下文mode_context,这个上下文信息将用于后续的编码决策,包括选择最佳的运动矢量预测模式。通过这种方式,编码器可以更智能地选择运动矢量,从而提高编码效率和视频质量;
- 排序参考帧候选,分配最近 mv 和近 mv;
- 处理复合参考帧:通过调用 process_compound_ref_mv_candidate 函数,处理行和列偏移量内的宏块,以收集复合参考 MV 候选。
- 处理单参考帧:通过调用 process_single_ref_mv_candidate 函数,处理行和列偏移量内的宏块,以收集单一参考 MV 候选。
static AOM_INLINE void setup_ref_mv_list(const AV1_COMMON *cm, const MACROBLOCKD *xd, MV_REFERENCE_FRAME ref_frame,uint8_t *const refmv_count,CANDIDATE_MV ref_mv_stack[MAX_REF_MV_STACK_SIZE],uint16_t ref_mv_weight[MAX_REF_MV_STACK_SIZE],int_mv mv_ref_list[MAX_MV_REF_CANDIDATES], int_mv *gm_mv_candidates,int mi_row, int mi_col, int16_t *mode_context) {const int bs = AOMMAX(xd->width, xd->height);const int has_tr = has_top_right(cm, xd, mi_row, mi_col, bs);MV_REFERENCE_FRAME rf[2];const TileInfo *const tile = &xd->tile;int max_row_offset = 0, max_col_offset = 0;const int row_adj = (xd->height < mi_size_high[BLOCK_8X8]) && (mi_row & 0x01);const int col_adj = (xd->width < mi_size_wide[BLOCK_8X8]) && (mi_col & 0x01);int processed_rows = 0;int processed_cols = 0;av1_set_ref_frame(rf, ref_frame);mode_context[ref_frame] = 0;*refmv_count = 0;// Find valid maximum row/col offset.if (xd->up_available) {max_row_offset = -(MVREF_ROW_COLS << 1) + row_adj;if (xd->height < mi_size_high[BLOCK_8X8])max_row_offset = -(2 << 1) + row_adj;max_row_offset = find_valid_row_offset(tile, mi_row, max_row_offset);}if (xd->left_available) {max_col_offset = -(MVREF_ROW_COLS << 1) + col_adj;if (xd->width < mi_size_wide[BLOCK_8X8])max_col_offset = -(2 << 1) + col_adj;max_col_offset = find_valid_col_offset(tile, mi_col, max_col_offset);}uint8_t col_match_count = 0;uint8_t row_match_count = 0;uint8_t newmv_count = 0;// Scan the first above row mode info. row_offset = -1;if (abs(max_row_offset) >= 1)scan_row_mbmi(cm, xd, mi_col, rf, -1, ref_mv_stack, ref_mv_weight,refmv_count, &row_match_count, &newmv_count, gm_mv_candidates,max_row_offset, &processed_rows);// Scan the first left column mode info. col_offset = -1;if (abs(max_col_offset) >= 1)scan_col_mbmi(cm, xd, mi_row, rf, -1, ref_mv_stack, ref_mv_weight,refmv_count, &col_match_count, &newmv_count, gm_mv_candidates,max_col_offset, &processed_cols);// Check top-right boundaryif (has_tr)scan_blk_mbmi(cm, xd, mi_row, mi_col, rf, -1, xd->width, ref_mv_stack,ref_mv_weight, &row_match_count, &newmv_count,gm_mv_candidates, refmv_count);const uint8_t nearest_match = (row_match_count > 0) + (col_match_count > 0);const uint8_t nearest_refmv_count = *refmv_count;// TODO(yunqing): for comp_search, do it for all 3 cases.for (int idx = 0; idx < nearest_refmv_count; ++idx)ref_mv_weight[idx] += REF_CAT_LEVEL;if (cm->features.allow_ref_frame_mvs) {int is_available = 0;const int voffset =</
相关文章:

libaom 源码分析:帧间运动矢量预测
AV1 帧间运动矢量预测原理 运动矢量可以被相邻块预测,这些相邻块可以是空域相邻块,或位于参考帧中的时域相邻块;通过检查所有这些块,将确定一组运动矢量预测器,并用于编码运动矢量信息。空域运动矢量预测 两组空域相邻块可以被利用寻找空域 MV 预测器,第一组包括当前块的…...

Android TextView自动换行文本显示不全解决
某些情况下,TextView自动换行后,会出现每行结尾处显示不全的问题, 如图: 常见解决方案: 设置TextView的“ellipsize”属性为“end” 实测无效!将TextView外部的Layout改为RelativeLayout 实测无效&…...

【LeetCode】【算法】394. 字符串解码
LeetCode 394. 字符串解码 题目描述 给定一个经过编码的字符串,返回它解码后的字符串。 编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。 你可以认为输入字符串总是有效的;输入字…...

最新整理:Selenium自动化测试面试题
1.selenium中如何判断元素是否存在? find_elements查找到的元素个数为0,find_element报错意味着元素不存在 2.如何判断元素是否出现? 判断元素是否出现,存在两种情况,一种是该元素压根就没有,自然不会出现;另外一种是有这样的…...

外包干了2年,快要废了。。。
先说一下自己的情况,普通本科,在外包干了2年多的功能测试,这几年因为大环境不好,我整个人心惊胆战的,怕自己卷铺盖走人了,我感觉自己不能够在这样蹉跎下去了,长时间呆在一个舒适的环境真的会让一…...

乐尚代驾十订单支付seata、rabbitmq异步消息、redisson延迟队列
账单信息 司机结束代驾之后,生成账单(包含账单信息和分账信息)司机发送账单给乘客乘客获取账单之后,进行支付 获取账单信息 order_bill表记录的账单信息,我们直接获取即可 Operation(summary "根据订单id获取…...

HCIP--3实验- 链路聚合,VLAN间通讯,Super VLAN,MSTP,VRRPip配置,静态路由,环回,缺省,空接口,NAT
学习目标: 链路聚合VLAN间通讯Super VLANMSTPVRRPip配置,静态路由,环回,缺省,空接口NAT 学习内容: 实验拓扑实验需求实验需求分析实验配置内容 (每一个设备的每一步操作)实验结果验证 1.实验拓扑 搭建 …...

Apple提出MM1.5:多模态大型语言模型微调的方法、分析和见解_mm1.5 模型下载
摘要 我们介绍了 MM1.5,一个新的多模态大型语言模型 (MLLM) 家族,旨在增强在富文本图像理解、视觉参照和定位以及多图像推理方面的能力。 在 MM1 架构的基础上,MM1.5 采用以数据为中心的模型训练方法,系统地探索了整个模型训练生…...

【毫米波雷达(三)】汽车控制器启动流程——BootLoader
汽车控制器启动流程——BootLoader 一、什么是Bootloader(BT)?二、FBL、PBL、SBL、ESS的区别三、MCU的 A/B分区的实现 一、什么是Bootloader(BT)? BT就是一段程序,一段引导程序。它包含了启动代码、中断、主程序等。 雷达启动需要由BT跳转到…...

AI 搜索来势汹汹,互联网将被颠覆还是进化?
最近,美国新闻集团起诉了知名 AI 搜索引擎 Perplexity AI。也许你会想,这不就是又一起“AI 惹官司”吗?其实,这次情况不太一样,甚至可能会改变我们未来上网的方式! 争议的焦点是什么?是未来的 …...

《二分查找算法:在有序数组中搜索目标值》
目录 一、问题分析 二、二分查找算法原理 三、代码实现 给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target,我们要写一个函数来搜索 nums 中的 target,如果目标值存在就返回它的下标,否则返回 -1。 …...

【万字总结】数据结构常考应用大题做法画法详解_树_哈希表_图_排序大总结
文章目录 1.树相关应用大题1.1 已知二叉树的中序序列和前序or中序,画出二叉树1.2 二叉树的遍历、树的遍历、森林的遍历总结1.3二叉树与森林之间的转换1.3.1 已知树的先序序列和中序序列,画出森林 1.4 二叉树的线索化1.5 二叉排序树1.5.1 二叉排序树的删除…...

Docker + Jenkins + gitee 实现CICD环境搭建
目录 前言 关于Jenkins 安装Jenkins docker中运行Jenkins注意事项 通过容器中的Jenkins,把服务打包到docker进行部署 启动Jenkins 创建第一个任务 前言 CI/CD(持续集成和持续交付/持续部署),它可以实现自动化的构建、测试和部署…...

rabbitMq怎么保证消息不丢失?消费者没有接收到消息怎么处理
在使用RabbitMQ时,保证消息不丢失以及处理消费者未接收到消息的情况可以通过以下几个方法: 1. 确保消息的持久化 队列持久化:在声明队列时将其设置为持久化(durabletrue),这样RabbitMQ在重启后也会保留队…...

商务数据分析在提升客户体验方面的作用体现在哪些环节
在当今竞争激烈的商业环境中,客户体验已成为企业成功的关键因素。商务数据分析犹如一把神奇的钥匙,在提升客户体验的征程中发挥着至关重要的作用,贯穿于多个环节。 一、客户需求分析:洞察客户内心的窗口 客户需求分析是商务数据…...

cooladmin使用整理
1、后端关键字自动生成没有代码段提示,原因是拉取的项目代码中没有.vscode文件夹,复制一套至项目src同级即可 2、前端快速创建,在Entity完成后就去快速创建中选数据结构,这时没有对应的内容,数据结构是和controller层a…...

CentOS 7 更换软件仓库
CentOS 7 于2024年6月30日停止维护,官方仓库已经没有软件了,想要继续使用 ,需要更换软件仓库,这里更换到阿里云的软件仓库 https://developer.aliyun.com/mirror/ 查看目前可用的软件数量 yum repolist 更换软件仓库:…...

现代Web开发:React Hooks深入解析
💓 博客主页:瑕疵的CSDN主页 📝 Gitee主页:瑕疵的gitee主页 ⏩ 文章专栏:《热点资讯》 现代Web开发:React Hooks深入解析 现代Web开发:React Hooks深入解析 现代Web开发:React Hook…...

HarmonyOS使用arkTS拉起指定第三方应用程序
HarmonyOS使用arkTS拉起指定第三方应用程序 前言代码及说明bundleName获取abilityName获取 前言 本篇只说采用startAbility方式拉起第三方应用,需要用到两个必备的参数bundleName,abilityName,本篇就介绍如何获取参数… 代码及说明 bundle…...

flex安装学习笔记
https://zhuanlan.zhihu.com/p/2783726096 3.下载 Flux 模型 FLUX.1 [dev] :官方版本满配版,最低显存要求 24G;FLUX.1 [dev] fp8:大佬优化 [dev] 后版本,建议选择此版本,最低 12G 显存可跑;FLU…...

09-结构化搜索、搜索的相关性算分
term 查询执行精确值匹配,要求文档中的字段值与指定的词项完全相等。对于日期字段等精确值字段,通常使用 term 查询可以快速有效地匹配文档。match 查询执行全文搜索,会对输入的文本进行分析,生成查询词项,并试图找到与…...

手机屏幕上进行OCR识别方案
在手机屏幕上进行OCR识别,可以通过一些主流方案实现高效、准确的文本识别。以下是几种常见方案: 1. 使用 Tesseract OCR 原理:Tesseract 是一个开源的 OCR 引擎,支持多种语言。可以通过一些优化提升其对手机屏幕文本的识别效果。…...

遗传算法与深度学习实战(22)——使用Numpy构建神经网络
遗传算法与深度学习实战(22)——使用Numpy构建神经网络 0. 前言1. 神经网络基础1.1 简单神经网络的架构1.2 神经网络的训练 2. 使用 Numpy 构建神经网络2.1 网络架构2.2 实现神经网络 小结系列链接 0. 前言 我们已经学习了如何使用进化算法来优化深度学…...

react->Antd->Table调整checkbox默认样式
checkbox默认不展示,hover此行时,出现checkbox,选中后不消失: hover前,设置透明边框; hover时,checkbox出现 选中后 代码块: .ant-checkbox {.ant-checkbox-inner {border: transparent;}}.ant…...

一种ESB的设计
系统架构 ESB包括: ESB总控服务、业务应用集群、业务消息WEB服务、业务消息日志服务、运维管理平台、业务设计器。如下图所示 ESB总控服务 ESB总控服务承载了各项业务的运维和管理。主要包括: 业务流程的管理ESB内部不同模块间的通讯ESB系统设置和管理…...

上位机常用通信方式
1. 串口通信:RS232(设备和PC之间,最常用,短距离)、RS485(工业现场总线,长距离,多点通信) 2. 以太网通信:TCP/IP协议 3. CAN总线通信 4. Modbus协议࿱…...

Vue3中使用LogicFlow实现简单流程图
实现结果 实现功能: 拖拽创建节点自定义节点/边自定义快捷键人员选择弹窗右侧动态配置组件配置项获取/回显必填项验证 自定义节点与拖拽创建节点 拖拽节点面板node-panel.vue <template><div class"node-panel"><divv-for"(item, k…...

《重学Java设计模式》之 工厂方法模式
《重学Java设计模式》之 建造者模式 《重学Java设计模式》之 原型模式 《重学Java设计模式》之 单例模式 模拟发奖多种商品 工程结构 奖品发放接口 package com.yys.mes.design.factory.store;public interface ICommodity {/*** Author Sherry* Date 14:20 2024/11/6**/voi…...

【大数据学习 | kafka】kafka的数据存储结构
以上是kafka的数据的存储方式。 这些数据可以在服务器集群上对应的文件夹中查看到。 [hexuanhadoop106 __consumer_offsets-0]$ ll 总用量 8 -rw-rw-r--. 1 hexuan hexuan 10485760 10月 28 22:21 00000000000000000000.index -rw-rw-r--. 1 hexuan hexuan 0 10月 28 …...

知识竞赛答题系统,线上答题小程序链接怎么做?
随着智能手机的普及,越来越多的单位开始在线上开展知识竞赛。这种形式的知识竞赛不仅易于操作,而且参与度更高。那么线上知识竞赛答题系统怎么做呢?自己可以做吗?答案是可以的!借助微信答题系统制作平台风传吧…...