热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

开发笔记:ffmpeg转码步骤源码实现的一点点浅析

本文由编程笔记#小编为大家整理,主要介绍了ffmpeg转码步骤源码实现的一点点浅析相关的知识,希望对你有一定的参考价值。
本文由编程笔记#小编为大家整理,主要介绍了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);
}
}
}


















推荐阅读
  • 海马s5近光灯能否直接更换为H7?
    本文主要介绍了海马s5车型的近光灯是否可以直接更换为H7灯泡,并提供了完整的教程下载地址。此外,还详细讲解了DSP功能函数中的数据拷贝、数据填充和浮点数转换为定点数的相关内容。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • Android工程师面试准备及设计模式使用场景
    本文介绍了Android工程师面试准备的经验,包括面试流程和重点准备内容。同时,还介绍了建造者模式的使用场景,以及在Android开发中的具体应用。 ... [详细]
  • 如何使用Python从工程图图像中提取底部的方法?
    本文介绍了使用Python从工程图图像中提取底部的方法。首先将输入图片转换为灰度图像,并进行高斯模糊和阈值处理。然后通过填充潜在的轮廓以及使用轮廓逼近和矩形核进行过滤,去除非矩形轮廓。最后通过查找轮廓并使用轮廓近似、宽高比和轮廓区域进行过滤,隔离所需的底部轮廓,并使用Numpy切片提取底部模板部分。 ... [详细]
  • 本文讨论了如何使用GStreamer来删除H264格式视频文件中的中间部分,而不需要进行重编码。作者提出了使用gst_element_seek(...)函数来实现这个目标的思路,并提到遇到了一个解决不了的BUG。文章还列举了8个解决方案,希望能够得到更好的思路。 ... [详细]
  • SpringMVC接收请求参数的方式总结
    本文总结了在SpringMVC开发中处理控制器参数的各种方式,包括处理使用@RequestParam注解的参数、MultipartFile类型参数和Simple类型参数的RequestParamMethodArgumentResolver,处理@RequestBody注解的参数的RequestResponseBodyMethodProcessor,以及PathVariableMapMethodArgumentResol等子类。 ... [详细]
  • 本文介绍了Python语言程序设计中文件和数据格式化的操作,包括使用np.savetext保存文本文件,对文本文件和二进制文件进行统一的操作步骤,以及使用Numpy模块进行数据可视化编程的指南。同时还提供了一些关于Python的测试题。 ... [详细]
  • Python使用Pillow包生成验证码图片的方法
    本文介绍了使用Python中的Pillow包生成验证码图片的方法。通过随机生成数字和符号,并添加干扰象素,生成一幅验证码图片。需要配置好Python环境,并安装Pillow库。代码实现包括导入Pillow包和随机模块,定义随机生成字母、数字和字体颜色的函数。 ... [详细]
  • 用Vue实现的Demo商品管理效果图及实现代码
    本文介绍了一个使用Vue实现的Demo商品管理的效果图及实现代码。 ... [详细]
  • 大数据Hadoop生态(20)MapReduce框架原理OutputFormat的开发笔记
    本文介绍了大数据Hadoop生态(20)MapReduce框架原理OutputFormat的开发笔记,包括outputFormat接口实现类、自定义outputFormat步骤和案例。案例中将包含nty的日志输出到nty.log文件,其他日志输出到other.log文件。同时提供了一些相关网址供参考。 ... [详细]
  • Spring Batch中多线程配置及实现例子
    本文介绍了在Spring Batch中开启多线程的配置方法,包括设置线程数目和使用线程池。通过一个示例演示了如何实现多线程从数据库读取数据并输出。同时提到了在多线程情况下需要考虑Reader的线程安全问题,并提供了解决方法。 ... [详细]
  • 本文介绍了DataTables插件的官方网站以及其基本特点和使用方法,包括分页处理、数据过滤、数据排序、数据类型检测、列宽度自动适应、CSS定制样式、隐藏列等功能。同时还介绍了其易用性、可扩展性和灵活性,以及国际化和动态创建表格的功能。此外,还提供了参数初始化和延迟加载的示例代码。 ... [详细]
  • SQL Server 内存中OLTP内部机制概述(一)
    内存中OLTP(项目名为“Hekaton”)是一个新的完全集成到SQLServer中的数据库引擎组件。它专为访问内存常驻数据的OLTP工作负荷而进行优化。内存中OLTP有助于OLT ... [详细]
  • 本文介绍了在PostgreSQL中批量导入数据时的优化方法。包括使用unlogged表、删除重建索引、删除重建外键、禁用触发器、使用COPY方法、批量插入等。同时还提到了一些参数优化的注意事项,如设置effective_cache_size、shared_buffer等,并强调了在导入大量数据后使用analyze命令重新收集统计信息的重要性。 ... [详细]
  • 流数据流和IO流的使用及应用
    本文介绍了流数据流和IO流的基本概念和用法,包括输入流、输出流、字节流、字符流、缓冲区等。同时还介绍了异常处理和常用的流类,如FileReader、FileWriter、FileInputStream、FileOutputStream、OutputStreamWriter、InputStreamReader、BufferedReader、BufferedWriter等。此外,还介绍了系统流和标准流的使用。 ... [详细]
author-avatar
股海一游6888
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有