Ffmpeg中的ffplay的使用和分析
1、默认的ffmpeg中没有编译fffplay(可能是因为ffplay引用了SDL库,而SDL库需要另外下载),config后,确认Makefile中指定的config.mak(在ffmpeg根目录下)中:CONFIG_FFPLAY=yes,如果不是需要重新./configure
2、下载SDL媒体库库,类似于QT,MW等图像引擎,这个SDL库是视频显示时用,编译时需要安装libsdl1.2-dev,命令为sudo apt-get install libsdl1.2-dev,如果安装失败,之前如果安装过sdl-devel包最好将其卸载。根据错误原因来解决。
3、make,结束后发现ffplay已经生成了
4、make install
目前在ubuntu12.04上播放视频,会出现问题,会报如下错,
t@ubuntu:/home/hfl/hflsamb/ffmpeg-1.2.4# ./ffplay abc.avi
ffplay version 1.2.4 Copyright (c) 2003-2013 the FFmpeg developers
built on Feb 6 2014 06:38:02 with gcc 4.6 (Ubuntu/Linaro 4.6.3-1ubuntu5)
configuration:
libavutil 52. 18.100 / 52. 18.100
libavcodec 54. 92.100 / 54. 92.100
libavformat 54. 63.104 / 54. 63.104
libavdevice 54. 3.103 / 54. 3.103
libavfilter 3. 42.103 / 3. 42.103
libswscale 2. 2.100 / 2. 2.100
libswresample 0. 17.102 / 0. 17.102
Input #0, avi, from 'abc.avi':= 0KB vq= 0KB sq= 0B f=0/0
Metadata:
encoder : Lavf55.22.103
Duration: 00:01:02.81, start: 0.000000, bitrate: 710 kb/s
Stream #0:0 nan A-V: 0.000 fd= 0 aq= 0KB vq= 0KB sq= 0B f=0/0: Video: mpeg4 (Simple Profile) (FMP4 / 0x34504D46), yuv420p, 720x540 [SAR 135:136 DAR 45:34], 25 tbr, 25 tbn, 25 tbc
Stream #0:1: Audio: mp3 (U[0][0][0] / 0x0055), 48000 Hz, stereo, s16p, 128 kb/s
X Error of failed request: BadAlloc (insufficient resources for operation)
Major opcode of failed request: 134 (XVideo)
Minor opcode of failed request: 19 ()
Serial number of failed request: 25
Current serial number in output stream: 26
google一下,很多人遇到同样的问题,是12.04版本的一个bug,有很多网友是通过修改/etc/X11/navia_cofnig文件的一个参数来完成,但我的系统没有这个文件,重新安装显卡驱动,繁琐。而以外在ubuntu9.10上没问题,所以目前开发的思路是:ubuntu12.04 开发,ubuntu9.10上测试验证(因为ubuntu9.10太老,很多source已经关闭,也懒得去更换源了)
Ffplay 除了可以播放文件,也可以播放网络。即file ,udp,http都支持
ffplay.exe http://192.168.1.108/myserver/ctl.mp3
ffplay.exe ctl.avi
ffplay基本框架分析:
1. 初始化化工作:注册解码器,编码器,demux.mux,网络等
avcodec_register_all();
#if CONFIG_AVDEVICE
avdevice_register_all();
#endif
#if CONFIG_AVFILTER
avfilter_register_all();
#endif
av_register_all();
avformat_network_init();
av_register_all();
包含编解码器资源,demux资源,拉流协议资源
这里注册了所有的文件格式和编解码器的库,所以它们将被自动的使用在被打开的合适格式的文件上。注意你只需要调用 av_register_all()一次,因此我们在主函数main()中来调用它。如果你喜欢,也可以只注册特定的格式和编解码器,但是通常你没有必要这样做。
注意av_register_all();包含 avcodec_register_all(); 所以在ffplay中注册avcodec_register_all();是多余的。不过没有关系,每次注册都要检测是否已经注册了,如果已经注册了,就不会第二次注册了
2. 解析命令行,打显示banner信息
show_banner(argc, argv, options);
parse_options(NULL, argc, argv, options,opt_input_file);
3. 初始化SDL(因为视频显示是基于SDL媒体框架,所以必须出示SDL)
SDL_Init()
4. 初始化化AVPacket;(改结构体描述音视频的属性信息,如pts,dts,pos,duration等)
av_init_packet(&flush_pkt);
5. 打开流对象,进行解码播放
stream_open(input_filename,file_iformat);
ffplay核心就在这个函数,这个函数创建了一个read_thread,线程完成了拉流(读文件),demux(解析,解复用),decoder(解码),display(显示)动作,即完成读文件模块(source filter),解复用模块(Demux filter),视/音频解码模块(Decode filter),颜色空间转换模块(Color Space converter filter),视频/音频播放模块(Renderfilter)三个模块的过程。
6. 事件处理event_loop(is);
event_loop(is);就是一个死循环,不断接受外部事件的动作,完成对播放的控制,如暂停,快进,快退,resume,窗口缩放等。这些事件来自于SDL从GUI中获取,触发源主要是鼠标和键盘的动作。
这样5,6动作就是实现了主线程完成播放控制,子线程完成解码播放的动作。主线程在循环中,由于某种外部事件触发,改变全局的播放控制变量,而子线程在每解码一帧前都要判断该控制变量,进而决定trick的动作或窗口的大小。
stream_open(input_filename, file_iformat)函数的简要分析:
1. 为VideoState分配内存
2. av_strlcpy(is->filename, filename,sizeof(is->filename));将文件名赋给VideoState
初始化VideoState其他成员。
3. 创建read_thread 线程
read_thread 的分析
avformat_open_input()完成各种协议拉流(读文件)动作
av_find_best_stream()找到因视频流,字幕流
stream_component_open()打开音视频流并音打开视频解码器并创建
video_thread(),subtitle_thread()进行解码
refresh_thread()开启屏幕视频显示刷新线程
av_read_frame()将音视频读取,解析并写入解码器