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源码分析( ...
 
随机推荐
- 【T-SQL】基础——表别名
			
Som有时候我们需要为表设置别名,这样就可以方便的修改表. 如果在SSMS中,可以点击 Query-> SQL CMD mode --Set Alisa for the table:setvar ...
 - 在本地运行Kubernetes的3种主流方式
			
作者简介 Chris Tozzi,曾担任记者和Linux管理员.对开源技术.敏捷基础架构以及网络问题兴趣浓厚.目前担任高级内容编辑,并且是Fixate IO的DevOps分析师. 原文链接: http ...
 - 整理了最全的Python3数据类型转换方法,可以收藏当手册用
			
本文基于python3.8版本,总结了各种数据类型直接的转换规则和方法.算是比较全了,可以收藏当手册来查. 概述 数据类型转换,指的是通过某种方法,将一个数据由原来的类型转换为另外一个类型.比如,我们 ...
 - 基于Nettty打造自己的MVC服务器
			
最近开始折腾Netty,体验下NIO编程.既然学习了,就要做点东西出来,要不然不容易掌握学到的东西.在Netty的官方demo上都有各种case的sample,打造Http服务器的核心代码就是从Sam ...
 - Linux常用命令~新手必知
			
ifconfig查看本机IP ls 查看当前目录下所有文件及文件夹 ll 以详细方式显示所有文件与文件夹.(相当于 ls -l 命令) pwd 显示当前目录路径 cd /user ...
 - lvm 日常操作。
			
步骤: pvcreate /dev/sdb pvdisplay vgcreate volgroup /dev/sdb vgdisplay lvcreate -L2G volgroup lvdispla ...
 - 「雕爷学编程」Arduino动手做(28)——RGB全彩LED模块
			
37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的.鉴于本人手头积累了一些传感器和模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里 ...
 - webpack打包时修改package.json的版本号,并输出相关版本
			
可直接修改的方式 { plugins: [ function() { // 修改package.json中的版本号 this.plugin('done', function() { const pkg ...
 - 09 基于模块wsgiref版web框架
			
09 基于模块wsgiref版web框架 模块引入 真实开发中的python web程序,一般会分为两部分: 服务器程序:负责对socket服务器进行封装,并在请求到来时,对请求的各种数据 ...
 - Gym101630L Laminar Family
			
题目链接:https://cn.vjudge.net/problem/Gym-101630L 题目大意: 对于一个集合的集合,若其中任意两个集合 \(A\) 和 \(B\) 都满足下述三个条件之一:\ ...