FFmpeg 源码学习(一):avformat_open_input 源码分析
一、源码方法参数分析
下面是avformat_open_input的方法及参数:
/** * Open an input stream and read the header. The codecs are not opened. * The stream must be closed with avformat_close_input(). * * @param ps Pointer to user-supplied AVFormatContext (allocated by avformat_alloc_context). * May be a pointer to NULL, in which case an AVFormatContext is allocated by this * function and written into ps. * Note that a user-supplied AVFormatContext will be freed on failure. * @param url URL of the stream to open. * @param fmt If non-NULL, this parameter forces a specific input format. * Otherwise the format is autodetected. * @param options A dictionary filled with AVFormatContext and demuxer-private options. * On return this parameter will be destroyed and replaced with a dict containing * options that were not found. May be NULL. * * @return 0 on success, a negative AVERROR on failure. * * @note If you want to use custom IO, preallocate the format context and set its pb field. */
int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputFormat *fmt, AVDictionary **options)
这里我们提供的是英文的参数注释,主要是翻译不好,对此方法的理解也没有什么帮助。下面针对此方法的这几个参数进行一下说明:
- AVFormatContext **ps : 参数ps包含一切媒体相关的上下文结构,有它就有了一切,本函数如果打开媒体成功,会返回一个AVFormatContext的实例。此参数可以为avformat_alloc_context创建的,也可以是NULL。
- 参数filename是媒体文件名或URL.
- 参数fmt是要打开的媒体格式的操作结构,因为是读,所以是inputFormat.此处可以传入一个调用者定义的inputFormat,对应命令行中的 -f xxx段,如果指定了它,在打开文件中就不会探测文件的实际格式了,以它为准了.
- 参数options是对某种格式的一些操作,是为了在命令行中可以对不同的格式传入,特殊的操作参数而建的, 可以无视。
二、方法的作用及流程
1. 输入输出结构体AVIOContext的初始化;
2. 输入数据的协议(例如RTMP,或者File)的识别(通过一套评分机制)
判断文件名的后缀
读取文件头的数据进行比对;
3. 使用获得最高分的文件协议对应的URLProtocol,通过函数指针的方式,与FFMPEG连接,剩下的就是调用该URLProtocol的函数进行open,read等操作。
下图用来了解一下和avformat_open_input有关系的函数调用流程图:
可见最终都调用了URLProtocol结构体中的函数指针。
下面是URLProtocol结构,可以看出来URLProtocol是一大堆函数指针的集合(avio.h文件)
typedef struct URLProtocol {const char *name;int (*url_open)(URLContext *h, const char *url, int flags);int (*url_read)(URLContext *h, unsigned char *buf, int size);int (*url_write)(URLContext *h, const unsigned char *buf, int size);int64_t (*url_seek)(URLContext *h, int64_t pos, int whence);int (*url_close)(URLContext *h);struct URLProtocol *next;int (*url_read_pause)(URLContext *h, int pause);int64_t (*url_read_seek)(URLContext *h, int stream_index,int64_t timestamp, int flags);int (*url_get_file_handle)(URLContext *h);int priv_data_size;const AVClass *priv_data_class;int flags;int (*url_check)(URLContext *h, int mask); } URLProtocol;
URLProtocol功能就是完成各种输入协议的读写等操作
但输入协议种类繁多,它是怎样做到“大一统”的呢?
原来,每个具体的输入协议都有自己对应的URLProtocol。
比如file协议(FFMPEG把文件也当做一种特殊的协议)(*file.c文件)
URLProtocol ff_pipe_protocol = {.name = "pipe",.url_open = pipe_open,.url_read = file_read,.url_write = file_write,.url_get_file_handle = file_get_handle,.url_check = file_check, };
或者rtmp协议(此处使用了librtmp)(librtmp.c文件)
URLProtocol ff_rtmp_protocol = {.name = "rtmp",.url_open = rtmp_open,.url_read = rtmp_read,.url_write = rtmp_write,.url_close = rtmp_close,.url_read_pause = rtmp_read_pause,.url_read_seek = rtmp_read_seek,.url_get_file_handle = rtmp_get_file_handle,.priv_data_size = sizeof(RTMP),.flags = URL_PROTOCOL_FLAG_NETWORK, };
可见它们把各自的函数指针都赋值给了URLProtocol结构体的函数指针
因此avformat_open_input只需调用url_open,url_read这些函数就可以完成各种具体输入协议的open,read等操作了
三、方法的使用技巧
合理的使用 avformat_open_input 方法能够加快视频的首屏播放。
首先我们知道avformat_open_input
这个函数的作用是打开文件的链接,如果是网络连接,还会发起网络请求,并一直等待网络数据的返回,然后读取视频流的数据。
那如何加快首屏播放呢?
我们可以利用方法中的第三个参数——AVInputFormat。AVInputFormat的结构体比较复杂,主要是封装媒体数据封装类型的结构体,比如flv, mpegts, mp4等,在这里可以传入空(或者0),如果为空(或者0),那么FFmpeg就会自行去检测获取。
当然如果我们知道文件的类型,先用av_find_input_format("flv")初始化出对应的结构体,这里我们用的是flv,先初始化好这个结构体,就能够节约时间加快首屏播放了。
FFmpeg 源码学习(一):avformat_open_input 源码分析相关推荐
- mybatis源码学习篇之——执行流程分析
前言 在正式学习mybatis框架源码之前,需要先弄懂几个问题?myabtis框架是什么?为什么需要mybatis框架?使用mybatis框架带来的好处是什么? 回答这几个问题之前,我们先来看一下,之 ...
- 【Android 源码学习】SharedPreferences 源码学习
第一章:SharedPreferences 源码学习 文章目录 第一章:SharedPreferences 源码学习 Android SharedPreferences的缺陷 MMKV.Jetpack ...
- spring源码学习之整合Mybatis原理分析
本文主要解析spring是如何与mybatis进行整合,整合的过程中需要哪些组件的支持.以前面提到过的配置例子<spring源码学习之aop事物标签解析> 整合的过程中需要使用以下这个依赖 ...
- mybatis源码学习1--学习源码的目的
在开始分析mybatis源码之前,需要定一个目标,也就是我们不是为了读源码而去读,一定是带着问题去读,在读的时候去寻找到答案,然后再读码的同时整理总结,学习一些高级的编码方式和技巧. 首先我们知道my ...
- Golang源码学习(二)----Go源码学习基础
### 本文源码版本为 GO 1.17.8 Windows/amd64: ### 可能参与对比的版本:GO 1.16.2 Linux/amd64一.Golang的编译器究竟是如何工作的? (学习源码有 ...
- Spark源码学习之IDEA源码阅读环境搭建
软件准备 (1)Java 1.8 (2)Scala 2.11.12(需要在IDEA中安装) (3)Maven 3.8.2(需要在IDEA中配置) (4)Git 2.33 以上软件需要安装好,并进行环境 ...
- spark源码学习(十)--- blockManager分析
blockManager主要原理: blockmanager位于org.apache.spark.storage中,包含四个重要的组件:DiskStore,MemoryStore,Blocktrans ...
- nimble源码学习——广播流程源码分析1
广播流程源码分析1 在controller层有多种状态:广播.空闲.连接等等,这次分析的是广播这个状态或者叫 做角色.在前面controller层循环的分析中,可以明确controller层也有eve ...
- Spring源码学习---------(最简单易懂的源码学习笔记)
- Java多线程之JUC包:Semaphore源码学习笔记
若有不正之处请多多谅解,并欢迎批评指正. 请尊重作者劳动成果,转载请标明原文链接: http://www.cnblogs.com/go2sea/p/5625536.html Semaphore是JUC ...
最新文章
- 电磁信号检测 | 本是同根生,相煎何太急
- mysql yn 字段类型_mysql常用数据类型
- HDU 2852 KiKi's K-Number 主席树
- 【蓝桥杯】基础练习 十六进制转八进制(Java实现)
- Tomcat集群快速入门2
- PCL:全程详解 VS2010+PCL配置
- 移动IM开发那些事:技术选型和常见问题
- python项目之站长素材爬取
- 基于权重的节点驱逐 - Oracle RAC 12.2 新特性
- powershell提取html字段,使用PowerShell或VBS从HTML文件中提取表
- 编写一个文件目录常用操作的类
- 计算机维修与销售探讨,《计算机维修与维护》面向市场教学的探讨.pdf
- VS2013 安装配置 C++ boost 库
- 常见类 --Object
- 轻量级日志收集转发 | fluent-bit外部插件详解(三)
- 维汉语音翻译android,维汉语音翻译助手
- 《数据结构导论》之树
- java手机号码加密_用户名-手机号加密特殊处理
- 联想小新锁屏壁纸怎么换_如何设置联想小新电脑锁屏时间
- html 菜单栏横向排列,响应式可弹出横向导航栏
热门文章
- php唯一性查询,ThinkPHP5.0数据更新验证唯一性怎么验证。
- 炫酷的元素周期表html,HTML5 经典化学元素周期表
- java ui调试_如何使用 IBM i System Debugger 调试 Java 程序
- 关于去中心化身份的一点思考
- c语言socket原理,Socket底层原理
- java中间缓存变量机制_Java中间缓存变量机制
- java 监控执行时间_java-监测方法运行时间 | 学步园
- Android平滑图片加载和缓存库Glide使用详解
- 360浏览器极速模式_【小技巧】解除浏览器主页以及,锁定主页~
- SpringBoot自动装载