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

ffmpeg源码分析open_output_file

推荐一个零声学院免费公开课程,个人觉得老师讲得不错,分享给大家:Linux,Nginx,ZeroMQÿ

推荐一个零声学院免费公开课程,个人觉得老师讲得不错,分享给大家:Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK等技术内容,立即学习


本系列 以 ffmpeg4.2 源码为准,下载地址:链接:百度网盘 提取码:g3k8

ffmpeg 源码分析系列以一条简单的命令开始,ffmpeg -i a.mp4 b.flv,分析其内部逻辑。

a.mp4下载链接:百度网盘,提取码:nl0s 。


本文章主要分析 open_output_file() 的内部逻辑。

简单转码命令 的 open_output_file() 流程图如下,一些参数赋值的内容没有画出来,只有主干。

理解 open_output_file(),必须先了解 2个新的数据结构,OutputFile,OutputStream,请先看源码自行阅读这两个结构体的声明。跑完 open_output_file() 之后形成的数据关系图如下,跟上一章的输入非常类似。

下面再贴一个 open_output_file() 的代码图,因为 open_output_file() 里面的逻辑分支比较多,在 ffmpeg -i a.mp4 b.flv 下并不会跑进去某些 if 条件,所以代码图为了简洁,会删减一些if,有一些参数赋值也会删掉。

接下来会逐行代码分析 open_output_file() 的内部逻辑。

  1. 图片1873~1894 行,申明一个 OutputFile 结构 ,丢进去全局变量数组 outpur_files[],然后把 OptionsContext 的一些值赋值给 of
  2. 图片1914~2083 行,这个代码块是比较重要的,首先根据算法,选出输入流里最好的 video 流 idx,然后调用 new_video_stream(o, oc, idx) 来创建输出流。new_video_stream() 函数比较复杂,这里简单介绍,下一段再仔细分析。 audio流类似 video流,也是根据算法选出最好 idx,然后调 new_audio_stream(o, oc, idx);
  3. 图片2090~2132 行,这部分代码主要对命令行参数做些检测,检测哪些option 没有用到,命令行写错了,给提示。不是主要逻辑。
  4. 图片2133~2213 行,这部分代码就是遍历输出流,然后调 init_simple_filtergraph(ist, ost) 初始化Filter,这块比较重要,要细看。
  5. 后面的代码都不重要,都是一些检测,参数赋值,处理metadata,处理chapter,后面的代码最重要的是调了 avio_open2() 打开输出文件

如此看来,open_output_file() 的内部逻辑就变得极其简单了,创建 OutputFile,用OptionsContext来赋值,调new_video_stream() ,new_audio_stream() 创建输出流,最后初始化 filter,然后avio_open2()打开输出文件。


上面有两个函数没有仔细介绍 new_video_stream() new_audio_stream() ,接下来仔细分析。

new_video_stream()的逻辑相对简单。如下面的流程图所示,new_video_stream() 里面有个 new_output_stream(),

new_output_stream() 主要创建 stream,编码器context,然后做一些初始化。

new_output_stream() 是一个公共函数,音频流,数据流,字幕流都用了它,所以 ffmpeg 把他分出来。video_stream 的一些初始化会在调用 new_output_stream() 后执行。

比较注意的一点是,new_video_stream() 跟 new_output_stream() 里面用了大量的 MATCH_PER_STREAM_OPT(),把 OptionsContex 的参数提取出来,赋值给 stream参数,或者赋值给编码器参数。所以一定要理解 MATCH_PER_STREAM_OPT() 的实现。

new_audio_stream()跟 new_video_stream() 类似,只是 new_audio_stream() 调了 new_output_stream() ,对音频流或编码器的某些参数赋值。


最后还有一个重要函数没有分析,init_simple_filtergraph(),即使是简单的转码命令,ffmpeg 为了通用性,也是会创建 filter 的,只不过是 null filter 跟 anull filter。空的视频流 filter,空的音频流filter

init_simple_filtergraph() 的逻辑比较简单,只是看 init_simple_filtergraph() ,不太容易看出filter的整体逻辑跟关系结构,需要后面分析 transcode()转码函数 ,ifilter_send_frame() 调用了 configure_filtergraph() 才能形成完整的关系结构体。这里尽量简单介绍,有个印象。

init_simple_filtergraph() 跑完之后形成的关系结构如下。

如图所示,有一个全局变量数组 filtergraphs[],一个 FilterGraph 里有一个InputFilter 跟一个 OutputFilter 。InputFilter 跟 OutputFilter 又各自有输入跟输出流,所以代码跑到这里,已经确定把输入输出流关联在一起了。

只要在输入流读数据,然后往输入流关联的输出流丢数据就完成转码了。其实之前 OutputStream 里面有个 source_index 成员本身已经关联了输入流,还要把 输入输出流 关联到 filter ,然后丢进去 FilterGraph 是因为 输入输出流虽然关联了,但他们的filter 还没关联起来。

FilterGraph::InputFilter 跟 FilterGraph::OutputFilter 在 init_simple_filtergraph() 里面也还没开始关联,关联之后就可以 发送 frame 到 buffersrc ,从 buffersink 出口读frame,不了解filter的,请先自己了解filter的基本用法。

关联 FilterGraph::InputFilter 跟 FilterGraph::OutputFilter 是在后面的 configure_filtergraph() 里完成的。

至此,open_output_file() 内部逻辑已经分析完毕


©版权所属:知识星球:弦外之音,QQ:2338195090。

由于笔者的水平有限, 加之编写的同时还要参与开发工作,文中难免会出现一些错误或者不准确的地方,恳请读者批评指正。如果读者有任何宝贵意见,可以加我微信 Loken1。


推荐阅读
  • 小王详解:内部网络中最易理解的NAT原理剖析,挑战你的认知极限
    小王详解:内部网络中最易理解的NAT原理剖析,挑战你的认知极限 ... [详细]
  • 三角测量计算三维坐标的代码_双目三维重建——层次化重建思考
    双目三维重建——层次化重建思考FesianXu2020.7.22atANTFINANCIALintern前言本文是笔者阅读[1]第10章内容的笔记,本文从宏观的角度阐 ... [详细]
  • 网站访问全流程解析
    本文详细介绍了从用户在浏览器中输入一个域名(如www.yy.com)到页面完全展示的整个过程,包括DNS解析、TCP连接、请求响应等多个步骤。 ... [详细]
  • 每日前端实战:148# 视频教程展示纯 CSS 实现按钮两侧滑入装饰元素的悬停效果
    通过点击页面右侧的“预览”按钮,您可以直接在当前页面查看效果,或点击链接进入全屏预览模式。该视频教程展示了如何使用纯 CSS 实现按钮两侧滑入装饰元素的悬停效果。视频内容具有互动性,观众可以实时调整代码并观察变化。访问以下链接体验完整效果:https://codepen.io/comehope/pen/yRyOZr。 ... [详细]
  • 深入解读张鑫旭文章,探索全新CSS属性
    近日,我仔细研读了张鑫旭关于知乎上十个热门问题的文章(http://www.zhangxinxu.com/wordpress/2017/06/ten-questions-about-css/)。这篇文章不仅详细解答了这些常见问题,还深入探讨了一些全新的CSS属性,为前端开发者提供了宝贵的见解和实用技巧。通过张鑫旭的专业解析,读者可以更好地理解和应用这些新特性,提升网页设计和开发的效率与质量。 ... [详细]
  • 本文详细介绍了 jQuery 的入门知识与实战应用,首先讲解了如何引入 jQuery 库及入口函数的使用方法,为初学者提供了清晰的操作指南。此外,还深入探讨了 jQuery 在实际项目中的多种应用场景,包括 DOM 操作、事件处理和 AJAX 请求等,帮助读者全面掌握 jQuery 的核心功能与技巧。 ... [详细]
  • 深入解析Spring Boot启动过程中Netty异步架构的工作原理与应用
    深入解析Spring Boot启动过程中Netty异步架构的工作原理与应用 ... [详细]
  • javascript分页类支持页码格式
    前端时间因为项目需要,要对一个产品下所有的附属图片进行分页显示,没考虑ajax一张张请求,所以干脆一次性全部把图片out,然 ... [详细]
  • 本文深入探讨了NoSQL数据库的四大主要类型:键值对存储、文档存储、列式存储和图数据库。NoSQL(Not Only SQL)是指一系列非关系型数据库系统,它们不依赖于固定模式的数据存储方式,能够灵活处理大规模、高并发的数据需求。键值对存储适用于简单的数据结构;文档存储支持复杂的数据对象;列式存储优化了大数据量的读写性能;而图数据库则擅长处理复杂的关系网络。每种类型的NoSQL数据库都有其独特的优势和应用场景,本文将详细分析它们的特点及应用实例。 ... [详细]
  • 本指南介绍了 `requests` 库的基本使用方法,详细解释了其七个主要函数。其中,`requests.request()` 是构建请求的基础方法,支持其他高级功能的实现。此外,我们还重点介绍了如何使用 `requests.get()` 方法来获取 HTML 网页内容,这是进行网页数据抓取和解析的重要步骤。通过这些基础方法,读者可以轻松上手并掌握网页数据抓取的核心技巧。 ... [详细]
  • HTML 页面中调用 JavaScript 函数生成随机数值并自动展示
    在HTML页面中,通过调用JavaScript函数生成随机数值,并将其自动展示在页面上。具体实现包括构建HTML页面结构,定义JavaScript函数以生成随机数,以及在页面加载时自动调用该函数并将结果呈现给用户。 ... [详细]
  • MongoDB高可用架构:深入解析Replica Set机制
    MongoDB的高可用架构主要依赖于其Replica Set机制。Replica Set通过多个mongod节点的协同工作,实现了数据的冗余存储和故障自动切换,确保了系统的高可用性和数据的一致性。本文将深入解析Replica Set的工作原理及其在实际应用中的配置和优化方法,帮助读者更好地理解和实施MongoDB的高可用架构。 ... [详细]
  • 掌握PHP框架开发与应用的核心知识点:构建高效PHP框架所需的技术与能力综述
    掌握PHP框架开发与应用的核心知识点对于构建高效PHP框架至关重要。本文综述了开发PHP框架所需的关键技术和能力,包括但不限于对PHP语言的深入理解、设计模式的应用、数据库操作、安全性措施以及性能优化等方面。对于初学者而言,熟悉主流框架如Laravel、Symfony等的实际应用场景,有助于更好地理解和掌握自定义框架开发的精髓。 ... [详细]
  • 成功实现Asp.Net MVC3网站与MongoDB数据库的高效集成
    我们成功地构建了一个基于Asp.NET MVC3框架的网站,并实现了与MongoDB数据库的高效集成。此次更新不仅完善了基本的创建和显示功能,还全面实现了数据的增删改查操作。在创建功能方面,我们修复了之前代码中的错误,确保每个属性都能正确生成。此外,我们还对数据模型进行了优化,以提高系统的性能和稳定性。 ... [详细]
  • 修复一个 Bug 竟耗时两天?真的有那么复杂吗?
    修复一个 Bug 竟然耗费了两天时间?这背后究竟隐藏着怎样的复杂性?本文将深入探讨这个看似简单的 Bug 为何会如此棘手,从代码层面剖析问题根源,并分享解决过程中遇到的技术挑战和心得。 ... [详细]
author-avatar
农大军乐团_697
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有