当前位置: 首页 > article >正文

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;

}

}


http://www.kler.cn/a/470777.html

相关文章:

  • java 转义 反斜杠 Unexpected internal error near index 1
  • 深度学习中多个损失怎么平衡?
  • “AI智慧语言训练系统:让语言学习变得更简单有趣
  • 统计字符【2】(PTA)C语言
  • 计算机网络:网络层知识点及习题(一)
  • kafka使用以及基于zookeeper集群搭建集群环境
  • uni-app 页面生命周期及组件生命周期汇总(Vue2、Vue3)
  • 特征点检测与匹配——MATLAB R2022b
  • 2025资源从哪里来!
  • vue3-dom-diff算法
  • Postman接口测试02|接口用例设计
  • 云原生周刊:K8s 生态系统的五大趋势预测
  • IDEA中Lombok不能使用,找不到get方法
  • 乾元通渠道商中标玉溪市自然灾害应急能力提升项目
  • 【C++面向对象——继承与派生】派生类的应用(头歌实践教学平台习题)【合集】
  • Flink-CDC 全面解析
  • 【pytorch-lightning】架构一览
  • 复杂园区网基本分支的构建
  • 工控主板ESM7000/6800E支持远程桌面控制
  • GolangWeb开发-好用的HTTP客户端httplib(beego)
  • 对智能手表进行逆向工程
  • 数据结构:二叉搜索树详解
  • 搭建SSL邮件服务器
  • 2024年最新外包干了10个月,技术退步明显,程序人生
  • 基于云效 Windows 构建环境和 Nuget 制品仓库进行 .Net 应用开发
  • 在 Windows 上安装 NodeJS