ffmpeg转码步骤源码实现的一点点浅析
ffmpeg转码实现的一点点浅析
ffmpeg转码过程对解码的处理封装在process_input()中(process_input()->decode_video()->decode()->avcodec_send_packet()),转码过程中ffmpeg会通过avformat库一包一包的读取avpacket经过avcodec_send_packet()往内部解码器送原始音视频压缩包、这里也提一下,我们都知道
avpacket 和 avframe 是ffmpeg的通用帧封装 ,
avpacket是压缩帧,avframe是原始图像帧,
在解码端,avpacket会送到解码器,产出avframe
在编码端,avframe会送进编码器,产出avpacket
在滤镜端,avframe 入,avframe 出

4.2.1ffmpeg内部做了并行解码,简图要如下:

avcodec->internal内部维系了一个环形线程列表,默认工作线程数量为nb_cpu + 1 个,主线程通过avcodec_send_pkt()—>...->submit_packet()通过条件变量提交一个任务给一个空闲的工作线程,空闲线程收到通知后调用对应的解码器回调函数code->decode()开始解码,同时此线程的状态机会切换到工作状态(假定为灰色格子)
next_decoded总是指向下一个空闲线程,
next_finnished总是指向第一个工作线程,这样解码器帧出来的顺序即帧送进解码器的顺序,
next_finnished指向的工作线程解码完成后,会存储在avcodec->internal->buffer_frame中,avcodec_receive_frame()中会判断它是否有数据有则取走,没有则走一遍内部调用取帧,internal一般都是ffmpeg内部结构,不建议开发人员访问.

关于ffmpeg的多线程编解码分为 frame级和slice级 两类, 当然应该不是所有的编解码器都支持.
我在测试过程中发现 ffmpeg n4.2.1的版本 解码 h264 默认是打开了帧级多线程解码的, 类 -threads 0 -thread_type frame -i xxx.mp4
ffmpeg -y -threads 0 -thread_type frame -i xxx.mp4 -f null -an -
同时扫了一下x264编码部分,实现方式和解码形同,但测试过程中却发现-threads x -thread_type frame 即x264帧级多线程编码并不支持, 而是转成了x264内部的多线程编码参数,可见是因编解码器而异.

另外ffmpeg transcode_step 中,即便不加filter也会毕走了一个null filter,
add_buffersrc会将avframe添加进内部filter graph link链的一个fifo队列中、
buffsersink_get会从自己buffsink的link fifo里面取已经产出的frame,如果还没有,则会激活跑一遍filter graph的滤镜链图再来取.
简化如下,未经调试,实际也许有区别.

static int get_frame_internal(AVFilterContext *ctx, AVFrame *frame, int flags, int samples)
{
BufferSinkContext *buf = ctx->priv;
AVFilterLink *inlink = ctx->inputs[0];
int status, ret;
AVFrame *cur_frame;
int64_t pts;
if (buf->peeked_frame)
return return_or_keep_frame(buf, frame, buf->peeked_frame, flags);
while (1) {
ret = samples ? ff_inlink_consume_samples(inlink, samples, samples, &cur_frame) :
ff_inlink_consume_frame(inlink, &cur_frame);
if (ret < 0) {
return ret;
} else if (ret) {
/* TODO return the frame instead of copying it */
return return_or_keep_frame(buf, frame, cur_frame, flags);
} else if (ff_inlink_acknowledge_status(inlink, &status, &pts)) {
return status;
} else if ((flags & AV_BUFFERSINK_FLAG_NO_REQUEST)) {
return AVERROR(EAGAIN);
} else if (inlink->frame_wanted_out) {
ret = ff_filter_graph_run_once(ctx->graph);
if (ret < 0)
return ret;
} else {
ff_inlink_request_frame(inlink);
}
}
}
ffmpeg转码步骤源码实现的一点点浅析的更多相关文章
- FFmpeg的HEVC解码器源码简单分析:解码器主干部分
===================================================== HEVC源码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpeg ...
- FFmpeg的HEVC解码器源码简单分析:解析器(Parser)部分
===================================================== HEVC源码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpeg ...
- FFmpeg的HEVC解码器源码简单分析:概述
===================================================== HEVC源码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpeg ...
- Flink源码分析 - 源码构建
原文地址:https://mp.weixin.qq.com/s?__biz=MzU2Njg5Nzk0NQ==&mid=2247483692&idx=1&sn=18cddc1ee ...
- Elasticsearch源码分析 - 源码构建
原文地址:https://mp.weixin.qq.com/s?__biz=MzU2Njg5Nzk0NQ==&mid=2247483694&idx=1&sn=bd03afe5a ...
- EventBus源码解析 源码阅读记录
EventBus源码阅读记录 repo地址: greenrobot/EventBus EventBus的构造 双重加锁的单例. static volatile EventBus defaultInst ...
- ios源码-ios游戏源码-ios源码下载
游戏源码 一款休闲类的音乐小游戏源码 该源码实现了一款休闲类的音乐小游戏源码,该游戏的源码很简单,而且游戏的玩法也很容易学会,只要我们点击视图中的grid,就可以 人气:2943运行环境:/Xco ...
- C#UDP(接收和发送源码)源码完整
C#UDP(接收和发送源码)源码完整 最近做了一个UDP的服务接收和发送的东西.希望能对初学的朋友一点帮助. 源码如下: 一.逻辑--UdpServer.cs using System;using S ...
- 二维码zxing源码分析(五)精简代码
由于工作的需要,我并不是需要二维码扫描的所有的功能,我只是需要扫一扫,并显示出来图片和url就行,于是我们就要精简代码了,源码已经分析完了,精简起来就方便多了,源码分析请看 二维码zxing源码分析( ...
随机推荐
- Python 爬取豆瓣电影Top250排行榜,爬虫初试
from bs4 import BeautifulSoup import openpyxl import re import urllib.request import urllib.error # ...
- Proteus传感器+气体浓度检测的报警方式控制仿真
Proteus传感器+气体浓度检测的报警方式控制仿真 目录 Proteus传感器+气体浓度检测的报警方式控制仿真 1 实验意义理解 2 主要实验器件 3 实验参考电路 4 实验中的问题思考 4.1 实 ...
- Ubuntu系统make menuconfig的依赖包ncurses安装
Linux内核或者u-boot进行make menuconfig的时候,如果系统上没有安装ncurses,就会出现以下报错 *** Unable to find the ncurses librari ...
- Matlab中 awgn 函数输入参数带有‘measured’ 时snr的含义
MATLAB中awgn 函数可以为输入信号x 添加一定大小的噪声. out = awgn(in,snr,'measured'); 是一种常见的使用方法,意思是在添加噪声前先测量一下输入信号的功率,再 ...
- java 8 stream、lambda表达式对list操作分组、过滤、求和、最值、排序、去重
1.分组 通过groupingBy分组指定字段 list.stream().collect(Collectors.groupingBy(User::getSex)); 2.过滤 通过filter方法过 ...
- ASP.NET Core Blazor 初探之 Blazor Server
上周初步对Blazor WebAssembly进行了初步的探索(ASP.NET Core Blazor 初探之 Blazor WebAssembly).这次来看看Blazor Server该怎么玩. ...
- OPTICS聚类算法原理
OPTICS聚类算法原理 基础 OPTICS聚类算法是基于密度的聚类算法,全称是Ordering points to identify the clustering structure,目标是将空间中 ...
- 「雕爷学编程」Arduino动手做(8)——湿度传感器模块
37款传感器和模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的.鉴于本人手头积累了一些传感器与模块,依照实践出真知(动手试试)的理念,以学习和交流为目的,这里准备 ...
- Linux下分析bin文件的10种方法
这世界有10种人,一种人懂二进制,另一种人不懂二进制. --鲁迅 大家好,我是良许. 二进制文件是我们几乎每天都需要打交道的文件类型,但很少人知道他们的工作原理.这里所讲的二进制文件,是指一些可执行文 ...
- CodeChef - TELEPORT
题目链接:https://vjudge.net/problem/CodeChef-TELEPORT 题目大意: 有\(Q\)个指令,指令为:\(+\) \(x\) \(y\)(在二维平面内添加一个点, ...