FFmpeg 中的多线程解码

news2024/11/13 9:12:32

1.共享变量的互斥


互斥锁(mutex-lock)是一种信号量,用来防止两个线程在同一时刻访问相同的共享资源,它有锁定状态和非锁定状态。

在任意时刻,一个线程要想存取共享数据,线程必须首先获得mutex-lock,当此线程释放此共享数据的时候必须对mutex-lock解锁,在一个任意的时间内,只有一个线程能锁定互斥锁,通过函数pthread_mutex_lock上锁,通过函数pthread_mutex_unlock解锁。

2.同步条件变量


条件变量用来提供另一种线程同步的方法,其基于实际的变量值来实现线程的同步操作,设置了条件变量的情况下,线程就不需要通过不停的轮询来查询条件是否满足,也不需要不停的忙等,从而能够节省很多系统资源。

一个条件变量总是和一个mutex-lock对应,系统通过pthread_cond_await函数来阻塞调用的线程,一直到条件变量得到满足。

当这个线程阻塞的时候对应的mutex-lock会自动解锁,但当该线程运行的时候,其对应的mutex-lock会被加锁。

使用函数pthread_cond_signal来唤醒等待在条件变量的另一个线程,当用来唤醒多个处于阻塞状态线程时通过pthread_cond_broadcast函数来完成。

3.ffmpeg实现多线程方案


Thread List,线程列表,线程列表中的每一项都映射一个解码线程。

主线程会从线程列表中按照序号由小到大(循环)提取解码线程,并把解码任务提交到该解码线程。

同时主线程在提交完解码任务后也会从线程列表中按照序号由小到大(循环)提取解码线程,并尝试从该解码线程获取解码完成的帧。

M,主线程,主要目的有两个:

  • 向解码线程提交解码任务。FFmpeg中是以packet为单位进行解码任务的提交的,按照前一小节的描述,FFmpeg就是以frame为单位进行解码任务的提交的。

  • 从解码线程获取解码所得的帧并进行返回。不过在第一轮进行任务提交的时候是不会去获取帧,在第一轮任务提交完成后,此时所有解码线程都已经开始进行了解码作业,那么主线程就可以开始等待第一个线程解码完成,然后尝试去获得解码完成的帧。这里的“尝试”,是因为就像单线程解码时那样,并不一定是每次调用解码API都会返回一帧的。由于h264编码的视频中常常包含B帧,这会使得码流的解码顺序并非帧的播放顺序,但是解码API必须按照帧的播放顺序进行返回,因此在进行帧的返回时会进行相应的调整。接下来每次向一个线程提交一个解码任务后,都需要等待下一个线程空闲并尝试返回帧。

  • T,解码线程,接收解码任务并进行解码。解码线程是以frame为单位进行处理的。解码线程解码主线程所提交的packet,执行与单线程时一样的解码作业。

ffmpeg中的多线程解码主要分为片 Slice级别的多线程解码 和 帧Frame级别的多线程解码:

Slice级的解码效率比Frame级的解码效率要低,故,本文先考虑Frame级的多线程解码。

4.Frame级的多线程解码


通过查看ffmpeg源码,了解到Frame级的多线程解码流程大致如下:

其中右侧的frame_worker_thread为解码线程,在open解码器时就已经创建,随后阻塞在pthread_cond_wait(&p->input_cond, &p->mutex)函数。等待被主线程唤醒。

当主线程运行到ff_thread_decode_frame函数时,会调用submit_packet函数,这个函数的目的就是将packet包交给解码线程。

submit_packet函数会调用pthread_cond_signal(&p->input_cond)函数,这个函数就是为唤醒刚才阻塞的解码线程。

当主线程唤醒解码线程后,其pthread_cond_wait(&p->output_cond, &p->progress_mutex)函数会进入阻塞状态,等待解码线程唤醒。

  1. 如果Codec未实现update_thread_context()和线程安全的get_buffer(),则必须在解码完成后才能将状态转换为STATUS_SETUP_FINISHED,意味着下一个线程只能在当前线程解码完成后才能开始解码。当解码线程解码完成后,会用pthread_cond_signal(&p->output_cond)将主线程唤醒,其中会通过回调函数将解码线程解码出来的frame获取,从而输出。

\2. 如果Codec实现update_thread_context()和线程安全的get_buffer(),线程状态可以在解码开始之前转换为STATUS_SETUP_FINISHED,这样,主线程就能够被唤醒,就能够去读包进行下一个包的解码,因此下一个线程就可能与当前线程并行。

5.Slice级的多线程解码


ffmpeg的slice级并行只能在帧内并行。

因此,如果在某个视频在编码时,一帧图像分为多个slice进行编码的话,那么在使用ffmpeg解码时调用slice级并行解码就会得到不错的效果。

而在实际应用中,大多数h264编码的视频都是一帧只有一个slice,对于这种视频,就算采用了slice级并行,也只有一个线程在进行解码作业。

如果一帧,即一个packet分为几个slice时,会先把这一帧前面的slice加入队列,到最后一个slice时统一对这一帧的所有slice进行并行解码。其中涉及到的关键要素如下:

Slice Context List,slice的上下文是slice context(FFmpeg中的变量为slice_ctx),如果一帧中有多个slice,那么会把slice上下文组成一个列表。前面所说的入队列操作会对该列表进行填充以供后续解码使用。

M,主线程,如单线程一样的流程,从用户调用解码API一直执行到我们前面所说的入队列,到最后一个slice时会调用一个入口函数启动多线程解码操作。在调用入口函数后,主线程参与的多线程解码过程一共包含三个步骤:

  1. 通过发送启动消息激活其它正在等待的解码线程。

  1. 在启动多线程解码后,主线程也会一同作为其中一个线程进行slice的解码。

  1. 最后等待所有线程完成任务后返回。

T,解码线程,接收到主线程所发起的启动消息后,解码线程会到Slice Context List去提取其中一个slice context(原子操作),然后进行slice解码。

原文地址: https://blog.csdn.net/yihuanyih

★文末名片可以免费领取音视频开发学习资料,内容包括(FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,srs)以及音视频学习路线图等等。

见下方!↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

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

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

相关文章

一种全新的图像变换理论的实验(四)——研究目的替代DCT和小波

一、前言 2023年02月28日凌晨1点 以前我定义为这个算法是滤波算法,实则上应该算是一种新变换算法,比如傅里叶变换(FFT)、离散余弦变换(DCT),以及小波变换。所以就把所有的标题改变了一下。 本次…

MySQL的InnoDB 三种行锁,SQL 语句加了哪些锁?

InnoDB 三种行锁: Record Lock(记录锁):锁住某一行记录 Gap Lock(间隙锁):锁住一段左开右开的区间 Next-key Lock(临键锁):锁住一段左开右闭的区间 哪些语句…

前端面试题 —— HTML

目录 一、src 和 href 的区别 二、对 HTML 语义化的理解 三、DOCTYPE(⽂档类型) 的作⽤ 四、script 标签中 defer 和 async 的区别 五、常⽤的 meta 标签有哪些? 六、HTML5 有哪些更新 八、行内元素有哪些?块级元素有哪些? 空(void)元素…

【正点原子FPGA连载】第十九章FreeRtos Hello World实验 摘自【正点原子】DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南

1)实验平台:正点原子MPSoC开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id692450874670 3)全套实验源码手册视频下载地址: http://www.openedv.com/thread-340252-1-1.html 第十九章FreeRto…

项目调研丨以太坊再质押项目EigenLayer白皮书四大看点(内附完整版中文白皮书)

北京时间2月21日下午,被众多一线投研机构视为2023年以太坊最重要的创新,有可能开启以太坊新叙事方向的项目Eigenlayer终于披露了其第一版白皮书。EigenLayer是以太坊的再质押集,允许共识层ETH质押者选择验证构建在以太坊生态系统之上的新软件…

第七节 面向对象

面向对象 1.类和对象是什么? )类:是共同特征的描述(设计图);对象:是真实存在的具体实例。 2.如何设计类? public class 类名 { 1、成员变量(代表属性的,一般是名词) 2、成员方法(代表行为的,一般是动词) 3.如何创建对象? 类名对象名new 类名(); 4.拿到对象后怎么…

ubuntu 编译安装支持CUDA的OpenCV

安装须知 cuda支持 在安装完“ linux CUDAtoolkitcudnntensorrt 的安装”之后进行支持cuda的opencv安装 否则报错:CMake Error at modules/dnn/CMakeLists.txt:41 (message): DNN: CUDA backend requires CUDA Toolkit. Please resolve dependency or disable OPE…

Ubuntu 安装指定版本 Mysql,并设置远程连接(以安装mysql 5.5 为例)

目录 一、安装Mysql 1、卸载Mysql(可跳过) 2、安装mysql 软件源 3、安装mysql 5.5 4、验证测试 二、设置远程登录 1、允许使用root账号远程连接 2、Mysql 允许远程登录 一、安装Mysql 1、卸载Mysql(可跳过) 如果之前安装…

数据结构六大排序

1.插入排序 1.插入排序 思路: 从第一个元素开始认为是有序的,去一个元素tem从有序序列从后往前扫描,如果该元素大于tem,将该元素一刀下一位,循环步骤3知道找到有序序列中小于等于的元素将tem插入到该元素后&#xff0…

卡特兰数

文章目录1、简介1.1 何为卡特兰数1.2 卡特兰数的通项公式2、应用2.1 题目1:括号合法题目描述思路分析2.2 题目2:进出栈的方式2.2.1 题目描述2.2.2 思路分析2.3 题目3:合法的序列2.3.1 题目描述2.3.2 思路分析2.3.3 代码实现2.4 题目4&#xf…

分布式ID生成系统

目录背景常用分布式ID生成系统介绍UUIDSnowflake背景 在大多数复杂的分布式系统中,往往需要对大量的数据和消息进行唯一标识。而对分布式系统后台数据库的分库分表后需要有一个唯一的ID来表示一条数据或者是消息。那么我们分布式系统ID一般都有哪些需求呢&#xff1…

IP地址、主机名、域名解析(DNS)

1.什么是IP地址 每一台联网的电脑都会有一个地址,用于和其他计算机进行通讯 IP地址主要有两个版本:v4 v6 IPV4版本的地址格式名为:a.b.c.d,其中abcd表示0-225的数字,如192.168.88.10为一个标准地址 查看IP地址&#x…

Android 蓝牙开发——HCI log 分析(二十)

HCI log 是用来分析蓝牙设备之间的交互行为是否符合预期,是否符合蓝牙规范。对于蓝牙开发者来说,通过 HCI log 可以帮助我们更好地分析问题,理解蓝牙协议。 一、抓取HCI log 1、手机抓取HCI log 在开发者选项中打开启用蓝牙HCI信息收集日志开关,Android系统就开始自动地收…

计算机SCI论文选题和投稿需要注意什么? - 易智编译EaseEditing

科研创新与选题 科研创新是至关重要的,往往关系到论文是否顺利发表。 摆在我们面前的,往往是别人挑剩下的资料,似乎毫无写作价值,很多人便知难而退,干脆不写论文了。 其实,应该问问自已“我有什么&#xf…

Flask应用的基本组成部分、模板引擎Jinja2的使用、Flask-WTF、SQLAlchemy

目录标题1. Flask应用的基本组成部分1.1 路由(Routing)1.2 视图函数(View Function)1.3 请求(Request)1.4 响应(Response)2. 模板引擎Jinja2的使用2.1 入门案例2.2 条件判断2.3 循环…

Python采集m3u8格式做个小姐姐动态壁纸~

人生苦短,我用python 首先,我和大家一样喜欢看小姐姐~ 其次,看美丽的事物会让人更加有动力去… 我编不下去了哈哈哈,我就是爱看充满美感的人儿~ 更多python好看的:点击此处跳转文末名片获取 环境 Pythonpycharm 模块使用 第…

使用virtualenv和pip构建项目所需的独立Python环境

1、为什么需要独立的Python环境?在讲技术前,想先讲讲目的。为什么我们需要独立的Python环境?这里就借用virtualenv的文档来解释吧。virtualenv is a tool to create isolated Python environments.The basic problem being addressed is one …

51-Jenkins-Periodic Backup插件实现Jenkins备份

Periodic Backup插件实现Jenkins备份前言目录结构插件备份安装插件使用插件前言 本篇来学习下使用Periodic Backup插件实现Jenkins备份 目录结构 Jenkins的所有数据都是存放在文件中的,所以,Jenins备份其实就是备份Jenkins_HOME目录。 Jenkins_Home目…

taobao.user.buyer.get( 查询买家信息API )

¥开放平台基础API必须用户授权 查询买家信息API,只能买家类应用调用。 公共参数 请求地址: HTTP地址 http://gw.api.taobao.com/router/rest 公共请求参数: 公共响应参数: 请求参数 响应参数 点击获取key和secret 请求示例 TaobaoClient client new…

现在00后都是这么卷了吗?

现在的00后小年轻真的卷得过分了。前段时间我们公司来了个00年的,工作没两年,跳槽到我们公司起薪20K,都快接近我了。后来才知道人家是个卷王,从早干到晚就差搬张床到工位睡觉了。 最近和他聊了一次天,原来这位小老弟家…