FFplay的一些接口函数
来源:互联网 发布:外交趣事 知乎 编辑:程序博客网 时间:2024/05/19 12:28
muxer/demuxer和encoder/decoder在FFmpeg中的实现代码里,有许多相同的地方,而二者最大的差别是muxer和demuxer分别是不同的结
构AVOutputFormat与AVInputFormat,而encoder和decoder都是用的AVCodec结构。这个需要认识清楚。
1.// Open video file
我们通过第一个参数来获得文件名。这个函数读取文件的头部并且把信息保存到我们给的AVFormatContext结构体中。
最后三个参数用来指定特殊的文件格式,缓冲大小和格式参数,但如果把它们设置为空NULL或者0,libavformat将自
动检测这些参数。
call:
1.av_probe_input_format
av_probe_input_format->av_probe_input_format2: 探测文件或流格式找到合适的解复用器,会循环一个一个从注册下去的 AVInputFormat list中获取
AVInputFormat *fmt1->read_probe [avi_probe,flv_probe,mp3_probe...]:会判断文件头的字节和对应的av format是否对应
av_match_ext:会判断输入的文件后缀名和AVInputFormat 的extensions比较,当然这边不准,一般是>read_probe 没有判断出才尝试此依据。
比如:avi_read_probe会将文件的头几个字节和 'R', 'I', 'F', 'F', 'A', 'V', 'I', ' '比较
flv_read_probe会将文件的头几个字节和 'f', 'l', 'v'比较
MP3_read_probe相对负责,但也是匹配文件的头的buf
总之通过probe获取 av foramat是比较准的。
当然如果probe无法判断出的话通过av_match_ext匹配文件名后缀来判断:
比如
当前文件名为xxx.mp3会匹配AVInputFormat MP3的extensions值"mp2,mp3,m2a"
当前文件名为xxx.avi会匹配AVInputFormat avi的extensions值为空,所以无法通过extensions匹配
当前文件名为xxx.flv会匹配AVInputFormat avi的extensions值"mp2,mp3,m2a"
注:AVInputFormat 操作的都是原始的文件数据
如果是网络流数据会调用流媒体相关接口:
2.url_fopen:会先调用url_open,如果是文件当然是用标准的file接口,其他的会匹配是http(如http://www.baidu.com),udp等,匹配出对应的URLProtocol等。
获取到URLProtocol后会调用URLProtocol xxx 中相关的接口open,seek等,其中URLProtocoxxl xxx是对应的IO 类型如file,http,udp等
获取到URLProtocol后将其赋给ByteIOContext。
3.ff_probe_input_buffer:探测流媒体传的是什么流媒体类型,需要什么解码资源准备等,由于流媒体数据是从网络中获取的,所以数据是一点一点获取到一个buf中的,做法有很多,ffmpeg采取的是
先获取2k数据然后probe探测(调用av_probe_input_format2),如果还没有探测出,再翻一倍4k数据probe,,,,翻倍loop 直到获取到一个AVInputFormat,如果到一个最大buf(1<<20)还探测不出来
就认为失败,找不到AVInputFormat。
以上1,2,3主要是探测出对应的AVInputFormat 和ByteIOContext,AVInputFormat其和对应的媒体类型已经相关了,如mp3,flv,avi,rm等都有自己对应的AVInputFormat。ByteIOContext也找到了,
如file,http,udp等 ,其中AVInputFormat最终的IO操作还是要用到ByteIOContext中的成员接口。
4.av_open_input_stream:已经探测出了stream 需要对应的解码器等信息后,需要构建一个AVFormatContext:此Context主要要明确有:
ByteIOContext:IO层面获取原始文件数据相关数据和接口
AVInputFormat:解复用相关,具体到了媒体文件的类型了
最后因为已经知道调用AVInputFormat->read_header(...),每个AVInputFormat 在调用read_header会新建AVStream,同时将对应的AVCodecContext codec获取到
然后赋值到AVStream,如果有多个类型会建多个AVStream。比如flv中有音频视频,则会建两个AVStream,并将每个stream对应codec_type,codec_id赋值到codec,当然因为是AVStream嘛,相
关的pts,nb_frames(avstream 数量)等都需要获取或赋值。
可能有些媒体类型没法在read_header中获取具体的codec_id,可能会到read_packet中才能知道具体的codec_id,但大体逻辑是如此。
note: AVStream->id不清楚有什么特殊的地方,大部分看到是id为0是视频,为1为音频,不知道其他值代表什么意思,后续请教大侠。
总结.
av_open_input_file
主要获取
AVInputFormat *iformat; ---->>>>mp3,flv,avi,...
ByteIOContext *pb;----->>>>>file,http,tcp,udp,rtp,md5等
AVStream **streams;----->>>>>pts,nbstream,AVCodecContext *codec----->>>>codec_type,codec_id
2.
av_find_stream_info:
call:
av_parser_init:暂时不知道av parser干嘛的
avcodec_find_decoder:之前av_open_input_file 只是获取了AVStream->AVCodecContext,通过AVCodecContext 的codec-id可以获取AVCodec *codec;
avcodec_open:获取到了AVCodec *codec可以调用其相关接口了,设置完善相应的codec参数,最后调用codec->init,主要也是做些相关的编解码准备。
每个CODEC_ID_xxx,都需要有一套AVCodec:PCM_S16LE,MP3,png,H263P,MPEG2VIDEO等
loop :////循环读数据填满codec,avstream,avpacket等的信息
av_read_frame_internal(ic, &pkt1);///获取1 frame的数据,如果这frame一般avpacket获取不全要多获取几次。
av_read_packet:第一次的话至少先要获取1 个packet。
av_parser_parse2:ffmpeg解码都需要一帧一帧完整地传给解码器,要么自己查找真传给解码器,要么调用av_parser_parse2查找,
注意2点:1.调用av_parser_parse2拿到一个完整帧对应的packet数据,因为帧数据可能比较大,一个packet承载不下需要多个packet。
2.拿到的是帧对应的数据,原始数据,并未解码的数据,可能是一个packet也可能是多个packet拼接重构的起来的数据,但并不是frame格式的数据。
compute_pkt_fields
ff_reduce_index
av_add_index_entry
add_to_pktbuf(&ic->packet_buffer, &pkt1, &ic->packet_buffer_end);
...完善codec等的信息
3.
av_read_frame:
call:
loop:av_read_frame_internal(。。。)->av_parser_parse2,直到拿到一个完整frame对应的数据包。
4.
avcodec_decode_video:
拿到了一个完整的frame数据包,将其解码为avframe格式数据,至此完成解码流程。
- FFplay的一些接口函数
- freetds的一些函数接口
- ffplay相关函数
- 使用egypt+graphviz分析ffplay的函数调用关系图
- 使用egypt+graphviz分析ffplay的函数调用关系图
- FFPLAY的原理
- FFPLAY的原理 .
- FFPLAY的原理
- [ffmpeg]FFPLAY的原理
- ffplay的使用
- 直播--FFPLAY 的原理
- 简化ffplay的分析
- ffplay的大致流程
- ffplay中stream_component_open()函数分析
- ip地址校验API接口函数的一些感触
- Qt中计算坐标的一些简单函数接口
- Qt中计算坐标的一些简单函数接口
- ffplay
- 关于远程linux 客户端 打开elipse
- 开发日志:使用JavaScript添加/修改/删除Table表单
- 解决Linux下Python安装版本问题
- python中文注释及输出出错
- php中的正则表达式的逆向引用
- FFplay的一些接口函数
- hbase开发,hbase表操作及其java api实现
- RSA私钥DER编码
- tomcat如何配置环境变量
- 【二叉树7】递归计算二叉树中节点数目
- What and where are the stack and heap?
- To_小涛_topic
- hdu4709求三角形面积
- PHP函数set_magic_quotes_runtime