图解FFMPEG打开媒体的函数avformat_open_input&avformat_find_stream_info
来源:互联网 发布:4412linux内核移植步骤 编辑:程序博客网 时间:2024/04/27 21:47
参考: http://jiya.io/archives.html
http://blog.csdn.net/woshinia/article/category/1270366
http://my.oschina.net/mavericsoung/blog/139265 ffmpeg中MPEG2 TS 流解码的流程分析
1 int avformat_open_input(AVFormatContext **ps, const char *filename,
AVInputFormat *fmt, AVDictionary **options)
2 接口功能
- 创建AVFormatContext结构并填充其中的关键字段
- 打开一个指定URI,初始化输入模块。
- 解析多媒体文件或流的头信息,为每个流创建AVStream结构。
3 流程分析
如果s为空,则调用avformat_alloc_context方法为AVFormatContext结构体(以下简称s)分配内存,并使用默认值设置,具体的默认设置是av_format_context_class。
注:AVFormatContext这个结构体描述了一个媒体文件或媒体流的构成和基本信息。如果传入的AVInputFormat类型形参fmt不为空,即判断输入格式是否在调用该方法之前已经探明,
如果是则直接设置s的iformat成员为该指针。如果不是则需要在后续步骤中分析输入格式。AVDictionary相关设置暂不分析。
调用init_input,初始化输入。
4.1 判断s的pb成员是否为空,pb成员是AVIOContext类型的,AVIOContext是用于IO操作的结构体,其内部还包含缓冲区。
这里可以这么理解,如果该指针不为空,说明可以直接通过该指针进一步调用IO方法,而如果该指针为空,对于一个流输入来说,说明尚未建立网络层连接,则无法进行IO操作。
4.2 如果pb成员不为空,那么判断iformat成员是否为空,不为空则调用av_probe_input_buffer去分析输入格式,不为空该方法调用返回。
4.3 如果pb成员为空,通过avio_open2去建立连接,并设置pb的读写方法指针。
URLProtocol ff_librtmp_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(LibRTMPContext), .priv_data_class = &librtmp_class, .flags = URL_PROTOCOL_FLAG_NETWORK,};
4.4 如果iformat成员为空,调用av_probe_input_buffer方法去初始化iformat,流程如下:
4.4.1 通过avio_read进一步调用pb的read方法从网络层读取数据。
例如:接收一个RTMP协议的输入,read方法实际指向rtmp_read,读取第一帧数据到pb的buffer中。仔细看librtmp中RTMP_Read接口,它会判断是否是第一帧,如果是第一帧数据,会向返回的数据中添加一个flv头。
4.4.2 根据读到数据探测输入的格式。具体的猜测方法是这样的,通过av_iformat_next接口不断获取已注册的fmt结构体指针,如果该fmt存在read_probe方法,则调用该方法,分析文件格式。
例如:判断flv格式的方法是flv_probe,它就是比对前三个字节。
4.4.3 判断得到文件格式后,s的iformat成员就不会空了,例如flv:
AVInputFormat ff_flv_demuxer = { .name = "flv", .long_name = NULL_IF_CONFIG_SMALL("FLV (Flash Video)"), .priv_data_size = sizeof(FLVContext), .read_probe = flv_probe, .read_header = flv_read_header, .read_packet = flv_read_packet, .read_seek = flv_read_seek, .read_close = flv_read_close, .extensions = "flv", .priv_class = &class,};
设置duration和start_time。
根据需要,为iformat成员的priv_data分配内存。
读入一些数据分析该输入是否包含ID3(MP3相关)的头信息。
如果不包含ID3数据,并不会改变pb->buffer的buf_ptr指针,即数据开始指针。如果read_header方法指针不为空,则调用该方法,具体以flv_read_header方法分析:
8.1 根据flv格式,跳过前4个字节,读取8 bit的流信息位。
8.2 如果存在视频,则创建视频流。即s的streams指针。并设置codec_type,设置pts info。音频类似。
8.3 最后移动缓冲区指针,相当于跳过了flv的前13(9+4)个字节。ID3内容处理。
queue_attached_pictures尚未弄懂。
4 avformat_open_input流程图
5 avformat_find_stream_info流程图
6 TSContext
7. parse_packet()的作用:
util.c中 parse_packet() -> av_parser_parse2() -> AVCodecParserContext::parser->parser_parse 会把一个PES(包含多帧),分解成一帧一帧;
第一帧会使用PES包头中的DTS/PTS, 第二帧的DTS/PTS会通过compute_pkt_fields()函数,在第一帧DTS/PTS的基础上面,加duration。
数据流:
TS => PES => ES => PES => decode
parse_packet() 组帧 解码
8. packet_buffer 和 raw_packet_buffer 区别
packet_buffer 和 raw_packet_buffer都是AVFormatContext 结构成员
raw_packet_buffer :主要是直接从demuxer读出的包,它会包含格式信息,这个信息,对探测文件格式非常重要, 所以探测文件格式时,探测数据是直接从raw_packet_buffer 取得.
这个包是先于parser和decoder,只有当文件格式探测到后,才不需要使用这个缓冲,但它的缓冲数据需要,转移到packet_buffer上
packet_buffer:这里的packet是通过av_read_frame ,将av_read_packet的packet最终parser成一帧,然后放到packet_buffer中,也就是说packet_buffer是一帧帧的ES数据,它并没有format的信息,这个packet已经有pts,等信息
- 图解FFMPEG打开媒体的函数avformat_open_input&avformat_find_stream_info
- 图解FFMPEG打开媒体的函数avformat_open_input
- 图解FFMPEG打开媒体的函数avformat_open_input
- 图解FFMPEG打开媒体的函数avformat_open_input
- 图解FFMPEG打开媒体的函数avformat_open_input
- 图解FFMPEG打开媒体的函数avformat_open_input
- 图解FFMPEG打开媒体的函数avformat_open_input
- 图解FFMPEG打开媒体的函数avformat_open_input
- 图解FFMPEG打开媒体的函数avformat_open_input
- 图解FFMPEG打开媒体的函数avformat_open_input
- [雷神]图解FFMPEG打开媒体的函数avformat_open_input
- FFMPEG源码分析:avformat_open_input()(媒体打开函数)
- FFMPEG源码分析:avformat_open_input()(媒体打开函数)
- FFmpeg avformat_open_input函数打开acc,h264失败的错误问题
- FFmpeg图解:avformat_open_input()
- ffmpeg源码简析(七)解码-avformat_open_input,avformat_find_stream_info()
- FFMPEG函数之avformat_open_input
- FFmpeg函数简单分析:avformat_find_stream_info()
- 理解“统一编址与独立编址、I/O端口与I/O内存”
- Ansible学习之配置(3)
- java基础---线程二
- Python标准库14 数据库 (sqlite3)
- Concurrency, Goroutines and GOMAXPROCS
- 图解FFMPEG打开媒体的函数avformat_open_input&avformat_find_stream_info
- 1059. Prime Factors (25)
- Ansible学习之playbook(4)
- Appium 官网范例的地址
- 乘法
- JavaBean,List,Map转成json格式
- 软件测试工程师的“三十六变”
- C#初步总结
- Vagrant简介