libaom 源码分析线程结构

一 libaom线程启动函数

void av1_create_workers(AV1_PRIMARY *ppi, int num_workers)

{

PrimaryMultiThreadInfo *const p_mt_info = &ppu->p_mt_info;

const AVxWorkerInterface *const = winterface = aom_get_worker_interface();

for (int i = 0; i < num_workers; ++i) {

AVxWorker* const worker = &p_mt_info->workers[i];

EncWorkerData *const thread_data = &p_mt_info->tile_thr_data[i];

winterface->init(worker);

worker->thread_nae = "aom enc worker";

thread_data->thread_id = i;

thread_data->start = i;

if (i > 0) {

if (!winterface->reset(worker))

aom_internal_error(&ppi->error, AOM_CODEC_ERROR, "Tile encoder thread creation failed");

}

}

winterface->sync(worker);

++p_mt_info->num_workers;

}

二 libaom线程调用栈

#0 in full_pixel_diamond()

#1 0x000000000058ee91 in av1_full_pixel_search ()

firstpass_inter_prediction->first_pass_motion_search

#2 0x000000000057d22c in av1_first_pass_row ()

#3 0x0000000000571124 in fp_enc_row_mt_worker_hook ()

#4 0x0000000000be5ef7 in execute ()

#5 0x00000000005788c8 in av1_fp_encode_tiles_row_mt ()

#6 0x000000000057ea03 in av1_first_pass ()

#7 0x00000000005625c0 in av1_encode ()

#8 0x0000000000c8036f in av1_encode_strategy ()

#9 0x00000000005636eb in av1_get_compressed_data ()

#10 0x00000000004ff0fb in encoder_encode ()

#11 0x00000000004bca0a in aom_codec_encode ()

#12 0x000000000040af05 in encode_frame.isra ()

#13 0x000000000040786c in main ()

三 libaom 线程调用关系

void av1_first_pass_row(AV1_COMP *cpi, ThreadData *td, TileDataEnc *tile_data, const int unit_row, const BLOCK_SIZE fp_block_size) ->

firstpass_inter_prediction(cpi, td, last_frame, golden_frame, unit_row, unit_col, recon_yoffset, recon_uvoffset, src_yoffset, fp_block_size, this_intra_error, raw_motion_err_counts, raw_motion_err_list, best_ref_mv, &best_ref_mv, &last_mv, mb_stats);

firstpass_intra_prediction()

线程入口函数

//定义一个静态整型函数用于多线程编码工作钩子

static int fp_enc_row_mt_worker_hook(void *arg1, void *unused)

{

//传入arg1转换EncWorkerData类型这个结构包含了线程数据

EncWorkerData *const thread_data = (EncWorkerData*)arg1;

//线程数据中获取编码器上下文结构

AV1_COMP* const cpi = thread_data->cpi;

//获取当前线程ID

int thread_id = thread_data->thread_id;

//获取编码器多线程信息

AV1EncRowMultiThreadInfo *const enc_row_mt = &cpi->mt_info.enc_row_mt;

//如果配置多线程获取多线程互斥

//获取线程数据中内部错误信息结构体

struct aom_internal_error_info* const error_info = &thread_data->error_info;

//获取宏块解码器上下文

MACROBLOCK* const xd = &thread_data->td->mb.e_mbd;

//设置宏块解码器上下文的错误信息

xd->error_info = error_info;

//设置错误恢复环境只有调用setjmp()函数中才有效

//如果setjmp() 返回非零表示发生了错误跳转

if (setjmp(error_info->jmp)) {

error_info->setjmp = 0;

pthread_mutext_lock(enc_ro_mt_mutex_);

//设置firstpass_mt_exittrue, 表示第一个通过多线程退出

enc_row_mt->firstpass_mt_exit = true;

//解锁互斥

pthread_mutex_unlock(enc_row_mt_mutex_);

set_firstpass_encode_done(cpi);

return 0;

}

//设置setjmp字段1表示jmp_buf有效

error_info->setjmp = 1;

//获取AV1公共结构体

AV1_COMMON *const cm = *cpi->common;

//获取当前线程对应tile ID

int cur_tile_id = enc_row_mt->thread_id_to_tile_id[thread_id];

//断言当前tile ID不是-1

assert(cur_tile_id != -1);

//获取固定大小

const BLOCK_SIZE fp_block_size = cpi->fp_block_size;

//获取单位高度

const int unit_height = mi_size_high[fp_block_size];

//初始化end of frame0

int end_of_frame = 0;

while (1) {

//初始化当前MI

int current_mi_row = -1;

//获取firstpass_mt_exit状态

bool firstpass_mt_exit = enc_row_mt->firstpass_mt_exit;

//如果firstpass_mt_exitfalse并且没有当前tile工作查询其他tile状态获取下一个工作

if (!firstpass_mt_exit && !get_next_job(&cpi->tile_data[cur_tile_id],
                                            &current_mi_row, unit_height)) {
      // 没有当前tile的工作,查询其他tile的状态并获取下一个工作。
      switch_tile_and_get_next_job(cm, cpi->tile_data, &cur_tile_id,
                                   &current_mi_row, &end_of_frame, 1,
                                   fp_block_size);
    }

//如果firstpass mt exittrue, 或者其他工人不需要进一步工作跳出循环

if (firstpass_mt_exit || ned_of_frame) break;

//获取当前tile数据

TileDataEnc *const this_tile = &cpi->tile_data[cur_tile_id]

// 获取行多线程同步信息。
    AV1EncRowMultiThreadSync *const row_mt_sync = &this_tile->row_mt_sync;
    // 获取线程数据。
    ThreadData *td = thread_data->td;

    // 断言current_mi_row不是-1,并且小于当前tile的MI行结束。
    assert(current_mi_row != -1 &&
           current_mi_row < this_tile->tile_info.mi_row_end);

    // 获取单位高度的对数。
    const int unit_height_log2 = mi_size_high_log2[fp_block_size];
    // 调用av1_first_pass_row函数进行第一通过编码。
    av1_first_pass_row(cpi, td, this_tile, current_mi_row >> unit_height_log2,
                       fp_block_size);
#if CONFIG_MULTITHREAD
    // 如果配置了多线程,锁定互斥锁。
    pthread_mutex_lock(enc_row_mt_mutex_);
#endif
    // 减少正在工作的线程数。
    row_mt_sync->num_threads_working--;
#if CONFIG_MULTITHREAD
    // 解锁互斥锁。
    pthread_mutex_unlock(enc_row_mt_mutex_);
#endif
  }
  // 重置setjmp字段为0。
  error_info->setjmp = 0;
  // 返回1表示成功。
  return 1;

}

}

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

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

相关文章

沁恒CH32V208GBU6外设PWM:注意分辨时钟使能函数RCC_APB2PeriphClockCmd;PWM模式1和模式2的区别;PWM动态开启和关闭

从事嵌入式单片机的工作算是符合我个人兴趣爱好的,当面对一个新的芯片我即想把芯片尽快搞懂完成项目赚钱,也想着能够把自己遇到的坑和注意事项记录下来,即方便自己后面查阅也可以分享给大家,这是一种冲动,但是这个或许并不是原厂希望的,尽管这样有可能会牺牲一些时间也有哪天原…

飞书企业消息实践

一、飞书自带的消息机器人限制 频控策略 - 服务端 API - 飞书开放平台 自定义机器人的频率控制和普通应用不同&#xff0c;为单租户单机器人 100 次/分钟&#xff0c;5 次/秒。建议发送消息尽量避开诸如 10:00、17:30 等整点及半点时间&#xff0c;否则可能出现因系统压力导致…

0107作业

思维导图 练习: 要求在堆区连续申请5个int的大小空间用于存储5名学生的成绩&#xff0c;分别完成空间的申请、成绩的录入、升序 排序、 成绩输出函数以及空间释放函数&#xff0c;并在主程序中完成测试 要求使用new和delete完成 #include <iostream>using namespace std…

以C++为基础快速了解C#

using System: - using 关键字用于在程序中包含 System 命名空间。 一个程序一般有多个 using 语句, 相当于C的 using namespace std; C# 是大小写敏感的。 所有的语句和表达式必须以分号&#xff08;;&#xff09;结尾。 程序的执行从 Main 方法开始。 与 Java 不同的是&#…

面试题:并发与并行的区别?

并发&#xff08;Concurrency&#xff09;和并行&#xff08;Parallelism&#xff09;是计算机科学中两个相关但不同的概念&#xff0c;它们都涉及到同时处理多个任务&#xff0c;但在实现方式和效果上有显著的区别。理解这两者的区别对于编写高效的多任务程序非常重要。 并发&…

面向对象分析和设计OOA/D,UML,GRASP

目录 什么是分析和设计&#xff1f; 什么是面向对象的分析和设计&#xff1f; 迭代开发 UML 用例图 交互图 基于职责驱动设计 GRASP 常见设计原则 什么是分析和设计&#xff1f; 分析&#xff0c;强调是对问题和需求的调查研究&#xff0c;不是解决方案。例如&#x…

MySQL使用navicat新增触发器

找到要新增触发器的表&#xff0c;然后点击设计&#xff0c;找到触发器标签。 根据实际需要&#xff0c;填写相关内容&#xff0c;操作完毕&#xff0c;点击保存按钮。 在右侧的预览界面&#xff0c;可以看到新生成的触发器脚本

Anthropic 的人工智能 Claude 表现优于 ChatGPT

在人工智能领域&#xff0c;竞争一直激烈&#xff0c;尤其是在自然语言处理&#xff08;NLP&#xff09;技术的发展中&#xff0c;多个公司都在争夺市场的主导地位。OpenAI的ChatGPT和Anthropic的Claude是目前最具影响力的两款对话型AI产品&#xff0c;它们都能够理解并生成自然…

《罪恶装备-奋战》官方中文学习版

《罪恶装备 -奋战-》是Arc System Works开发的格斗游戏《罪恶装备》系列的第二十五部作品 [1]&#xff0c;男主角索尔历时25年的故事就此画上句号&#xff0c;而罪恶装备的故事却并未结束。 《罪恶装备-奋战》官方中文版 https://pan.xunlei.com/s/VODWAm1Dv-ZWVvvmUMflgbbxA1…

期末概率论总结提纲(仅适用于本校,看文中说明)

文章目录 说明A选择题1.硬币2.两个事件的关系 与或非3.概率和为14.概率密度 均匀分布5.联合分布率求未知参数6.联合分布率求未知参数7.什么是统计量&#xff08;记忆即可&#xff09;8.矩估计量9.117页12题10.显著水平阿尔法&#xff08;背公式就完了&#xff09; 判断题11.事件…

流程图(四)利用python绘制漏斗图

流程图&#xff08;四&#xff09;利用python绘制漏斗图 漏斗图&#xff08;Funnel Chart&#xff09;简介 漏斗图经常用于展示生产经营各环节的关键数值变化&#xff0c;以较高的头部开始&#xff0c;较低的底部结束&#xff0c;可视化呈现各环节的转化效率与变动大小。一般重…

继承(5)

大家好&#xff0c;今天我们继续来学习继承的相关知识&#xff0c;来看看子类构造方法&#xff08;也叫做构造器&#xff09;是如何做的。 1.6 子类构造方法 父子父子,先有父再有子,即:子类对象构选时,需要先调用基类构造方法,然后执行子类的构造方法 ★此时虽然执行了父类的…

Vue框架主要用来做什么?Vue框架的好处和特性.

在快速发展的互联网时代&#xff0c;前端开发技术的变革日新月异&#xff0c;为开发者带来了前所未有的机遇与挑战。Vue.js&#xff0c;作为前端开发领域的一颗璀璨新星&#xff0c;以其轻量级、高效灵活的特性&#xff0c;赢得了广大开发者的青睐。本文将深入探讨Vue框架的主要…

搭建Hadoop分布式集群

软件和操作系统版本 Hadoop框架是采用Java语言编写&#xff0c;需要java环境&#xff08;jvm&#xff09; JDK版本&#xff1a;JDK8版本 &#xff0c;本次使用的是 Java: jdk-8u431-linux-x64.tar.gz Hadoop: hadoop-3.3.6.tar.gz 三台Linux虚拟节点: CentOS-7-x86_64-DVD-2…

电子应用设计方案87:智能AI收纳箱系统设计

智能 AI 收纳箱系统设计 一、引言 智能 AI 收纳箱系统旨在为用户提供更高效、便捷和智能的物品收纳与管理解决方案&#xff0c;通过融合人工智能技术和创新设计&#xff0c;提升用户的生活品质和物品整理效率。 二、系统概述 1. 系统目标 - 实现物品的自动分类和整理&#xf…

MySQL数据结构选择

系列文章目录 一、MySQL数据结构选择 二、MySQL性能优化explain关键字详解 三、MySQL索引优化 文章目录 系列文章目录前言一、索引1.1、什么是索引1.2、构建索引的过程1.3、索引的更新和维护1.4、索引的查询和管理1.5、InnoDB 和 MyISAM 的索引实现1.6、联合索引和最左前缀法则…

shell基础使用及vim的常用快捷键

一、shell简介 参考博文1 参考博文2——shell语法及应用 参考博文3——vi的使用 在linux中有很多类型的shell&#xff0c;不同的shell具备不同的功能&#xff0c;shell还决定了脚本中函数的语法&#xff0c;Linux中默认的shell是 / b in/ b a s h &#xff0c;流行的shell…

(leetcode算法题)76. 最小覆盖子串

以s "ADOBECODEBANC", t "ABC"为例&#xff0c;进行如下演示 对于上图的说明&#xff1a; 1. 上面八个状态是在从左往右滑动窗口时&#xff0c;每发现一个窗口满足以下条件就进行状态暂停 条件&#xff1a;s[l, r] 覆盖了 t 这个字符串 2. 只有出窗口之…

二、BIO、NIO编程与直接内存、零拷贝

一、网络通信 1、什么是socket&#xff1f; Socket 是应用层与 TCP/IP 协议族通信的中间软件抽象层&#xff0c;它是一组接口&#xff0c;一般由操作 系统提供。客户端连接上一个服务端&#xff0c;就会在客户端中产生一个 socket 接口实例&#xff0c;服务端每接受 一个客户端…

HDFS架构原理

一、HDFS架构整体概述 HDFS是Hadoop Distribute File System 的简称&#xff0c;意为&#xff1a;Hadoop分布式文件系统。HDFS是Hadoop核心组件之一&#xff0c;作为大数据生态圈最底层的分布式存储服务而存在。HDFS解决的问题就是大数据如何存储,它是横跨在多台计算机上的文件…