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转码步骤源码实现的一点点浅析的更多相关文章

  1. FFmpeg的HEVC解码器源码简单分析:解码器主干部分

    ===================================================== HEVC源码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpeg ...

  2. FFmpeg的HEVC解码器源码简单分析:解析器(Parser)部分

    ===================================================== HEVC源码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpeg ...

  3. FFmpeg的HEVC解码器源码简单分析:概述

    ===================================================== HEVC源码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpeg ...

  4. Flink源码分析 - 源码构建

    原文地址:https://mp.weixin.qq.com/s?__biz=MzU2Njg5Nzk0NQ==&mid=2247483692&idx=1&sn=18cddc1ee ...

  5. Elasticsearch源码分析 - 源码构建

    原文地址:https://mp.weixin.qq.com/s?__biz=MzU2Njg5Nzk0NQ==&mid=2247483694&idx=1&sn=bd03afe5a ...

  6. EventBus源码解析 源码阅读记录

    EventBus源码阅读记录 repo地址: greenrobot/EventBus EventBus的构造 双重加锁的单例. static volatile EventBus defaultInst ...

  7. ios源码-ios游戏源码-ios源码下载

    游戏源码   一款休闲类的音乐小游戏源码 该源码实现了一款休闲类的音乐小游戏源码,该游戏的源码很简单,而且游戏的玩法也很容易学会,只要我们点击视图中的grid,就可以 人气:2943运行环境:/Xco ...

  8. C#UDP(接收和发送源码)源码完整

    C#UDP(接收和发送源码)源码完整 最近做了一个UDP的服务接收和发送的东西.希望能对初学的朋友一点帮助. 源码如下: 一.逻辑--UdpServer.cs using System;using S ...

  9. 二维码zxing源码分析(五)精简代码

    由于工作的需要,我并不是需要二维码扫描的所有的功能,我只是需要扫一扫,并显示出来图片和url就行,于是我们就要精简代码了,源码已经分析完了,精简起来就方便多了,源码分析请看 二维码zxing源码分析( ...

随机推荐

  1. Python 爬取豆瓣电影Top250排行榜,爬虫初试

    from bs4 import BeautifulSoup import openpyxl import re import urllib.request import urllib.error # ...

  2. Proteus传感器+气体浓度检测的报警方式控制仿真

    Proteus传感器+气体浓度检测的报警方式控制仿真 目录 Proteus传感器+气体浓度检测的报警方式控制仿真 1 实验意义理解 2 主要实验器件 3 实验参考电路 4 实验中的问题思考 4.1 实 ...

  3. Ubuntu系统make menuconfig的依赖包ncurses安装

    Linux内核或者u-boot进行make menuconfig的时候,如果系统上没有安装ncurses,就会出现以下报错 *** Unable to find the ncurses librari ...

  4. Matlab中 awgn 函数输入参数带有‘measured’ 时snr的含义

    MATLAB中awgn 函数可以为输入信号x 添加一定大小的噪声. out = awgn(in,snr,'measured');  是一种常见的使用方法,意思是在添加噪声前先测量一下输入信号的功率,再 ...

  5. java 8 stream、lambda表达式对list操作分组、过滤、求和、最值、排序、去重

    1.分组 通过groupingBy分组指定字段 list.stream().collect(Collectors.groupingBy(User::getSex)); 2.过滤 通过filter方法过 ...

  6. ASP.NET Core Blazor 初探之 Blazor Server

    上周初步对Blazor WebAssembly进行了初步的探索(ASP.NET Core Blazor 初探之 Blazor WebAssembly).这次来看看Blazor Server该怎么玩. ...

  7. OPTICS聚类算法原理

    OPTICS聚类算法原理 基础 OPTICS聚类算法是基于密度的聚类算法,全称是Ordering points to identify the clustering structure,目标是将空间中 ...

  8. 「雕爷学编程」Arduino动手做(8)——湿度传感器模块

    37款传感器和模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的.鉴于本人手头积累了一些传感器与模块,依照实践出真知(动手试试)的理念,以学习和交流为目的,这里准备 ...

  9. Linux下分析bin文件的10种方法

    这世界有10种人,一种人懂二进制,另一种人不懂二进制. --鲁迅 大家好,我是良许. 二进制文件是我们几乎每天都需要打交道的文件类型,但很少人知道他们的工作原理.这里所讲的二进制文件,是指一些可执行文 ...

  10. CodeChef - TELEPORT

    题目链接:https://vjudge.net/problem/CodeChef-TELEPORT 题目大意: 有\(Q\)个指令,指令为:\(+\) \(x\) \(y\)(在二维平面内添加一个点, ...