ffmpeg和ffserver配合使用可以实现实时的流媒体服务,这里实时的数据来自摄像头,如果考虑到应用程序和网络状况,这里客户端看到的画面还是会落后与摄像头本地获取的画面,最糟糕时甚至看不到画面(扯远了),这里我们关注的是ffmpeg和ffserver之间是如何配合工作的,了解了他们之间的关系,对个别问题也能有的放矢。
ffserver先于ffmpeg启动,它在启动的时候需要加参数-f指定其配置文件,配置文件里包含有向客户端传送的流的配置(如编码方式,帧率,采样率……),也有对feed1.ffm的配置,还有其他的一些配置。feed1.ffm是什么?这里可以理解为一个缓冲文件,下面会提到它是如何被用到,ffserver启动后,feed1.ffm就会被创建,这时如果你打开feed1.ffm看看,会发现feed1.ffm开始的部分已经写入了内容,你可以找到关键字ffm以及向客户端传送流的配置信息,在feed1.ffm做缓冲用的时候,这些信息是不会被覆盖掉的,就把它们理解为feed1.ffm文件的头吧。
ffserver启动后,ffmpeg启动,它启动时加的一个关键参数就是“http://ip:8090/feed1.ffm”,其中ip是运行ffserver主机的ip,如果ffmpeg和ffserver都在同一系统中运行的话,用localhost也行。ffmpeg启动后会与ffserver建立一个连接(短暂的连接),通过这第一次的连接,ffmpeg从ffserver那里获取了向客户端输出流的配置,并把这些配置作为自己编码输出的配置,然后ffmpeg断开了这次连接,再次与ffserver建立连接(长久的连接),利用这个连接ffmpeg会把编码后的数据发送给ffserver。如果你观察ffserver端的输出就会发现这段时间会出现两次HTTP的200,这就是两次连接的过程。
ffmpeg从摄像头获取数据后,按照输出流的编码方式编码,然后发送给ffserver,ffserver收到ffmpeg的数据后,如果网络上没有播放的请求,就把数据写入feed1.ffm中缓存,写入时把数据加上些头信息然后分块,每块4096B(每块也有结构),当feed1.ffm的大小到了ffserver.conf中规定的大小后,就会从文件开始(跳过头)写入,覆盖旧的数据。直到网络上有播放的请求,ffserver从feed1.ffm中读取数据,发送给客户端。
上面粗略的描述在实时流媒体服务时ffmpeg和ffserver的关系,这些看法都是在阅读较早FFmpeg代码(very old)时得出的,现在不知这个架构是否改变,兄弟我把砖扔出,希望大家用玉来砸。
我采用的是H.264的编码器,我阅读output_example后发现编码后的数据格式应该是绑定到AVpacket格式上,我想问一下,ffserver是对什么数据格式进行rtp打包的,是直接对编码后的缓存数据打包,还是对AVpacket数据进行rtp打包?
希望大哥能予以指点。
-
我理解你这里说的缓存数据是feed1.ffm中的数据,那么发出去的时候应该是从这里取数据的,可以这样理解,一帧解码后的数据被在缓冲的时候,被拆分成一块一块(4096)的存放在feed1.ffm中,在要发送的时候,就把这一块一块的数据拼装起来,还原为一帧解码后的数据,交由AVpacket->data指向,再看要以什么样的格式发给客户端,比如你这里说的RTP,再把数据按照RTP格式打包,发送给客户端。
-
乐: 我理解你这里说的缓存数据是feed1.ffm中的数据,那么发出去的时候应该是从这里取数据的,可以这样理解,一帧解码后的数据被在缓冲的时候,被拆分成一块一块(40看到你的回复太高兴了,非常感谢 我还是有点不明白,还得再麻烦一下
FFmpeg中的编码函数应该是
out_size = avcodec_encode_video(AVCodecContext *avctx, uint8_t *buf, int buf_size,const AVFrame *pict);
这时编码后的数据放在buf里,我想问一下这时buf里的数据是不是应该是由一个一个的NALUnit组成的?
如果是,我查看内存映像时发现只有最头的数据是0x000001,以后的就都是普通数据了,也就是说,我编码后的数据好像就只有一个NALUnit,但是我的输入数据pict是一帧图像(摄像头采集到的一帧图像)应该由许多NALUnit组成啊,我想问一下这是什么原因?是编码的参数没设置对吗?
因为我想对每一个NALUnit打包,如果是现在这种情况:每一个包是一帧数据,传输时也许会有很大的问题,麻烦您了! -
2009-03-02 17:02: 看到你的回复太高兴了,非常感谢我还是有点不明白,还得再麻烦一下抱歉,这个我也不太清楚,你可以请教下admin,或是到论坛或群里问问。
FFmpeg中的编码函数应该是
out_size = avcodec_encode_video(AVCodecContext *avctx -
2009-03-02 18:15: 抱歉,这个我也不太清楚,你可以请教下admin,或是到论坛或群里问问。恩,好的,还是非常感谢您
-
2009-03-05 21:11我想请问一下,FFmpeg有没有做接收端?
服务器端用FFserver+FFmpeg,那么接收端应该用什么接收呢?
除了VLC,我想问一下FFmpeg自己的接收端有类似FFserver的例程吗? -
2009-03-05 21:18呵呵,好像FFplay就是可以做客户端吗?
FFplay可以接收网络来的rtp包吗?然后自己解码调用SDL显示,是这样吗?
谢谢王李乐 -
2009-03-06 08:27宁: 呵呵,好像FFplay就是可以做客户端吗?ffplay要播放从ffserver来的RTSP/RTP流的话,可能要改代码了,不知道现在最新的ffplay能否直接播,就是类似ffplay rtsp://ip:5454/file这种形式,你可以试试。
FFplay可以接收网络来的rtp包吗?然后自己解码调用SDL显示,是这样吗?
谢谢
我原来试过ffmpeg编码后的数据直接通过RTP发给客户端,不经过ffserver,就是在服务端:
ffmpeg -参数 ... rtp://client_ip:client_port?localport=server_port
这样的形式,客户端用ffplay接收的时候类似于:
ffplay rtp://server_ip:server_port?localport=client_port -
2009-03-06 11:49恩,好的,明白了,谢谢大牛
-
2009-04-23 22:14你好!
我使用ffserver命令启动服务器
然后用ffmpeg -i bj.3gp -f flv http:localhost:8090/feed1.ffm
在RealPlayer和VLC上都可以正确显示页面
但却无法正常播放请问您知道怎么解决吗?
ffserver用的是源码自带的ffserver .conf 谢谢!~ -
2009-04-27 10:12: 你好!什么叫正常显示页面,无法正常播放?
我使用ffserver命令启动服务器
然后用ffmpeg -i bj.3gp -f flv http:localhost:8090/feed1.ffm
在RealPlayer和VLC上都可以正确显示页面
但却无法正常播放
客户端请求的URL是什么?
是否是3gp已经转换完但客户端的请求还未到? -
2009-04-29 09:51在realplay中 输入 http://192.168.0.190:8090/stat.html 可以显示
FFServer Status
Available Streams
Path Served
Conns
bytes Format Bit rate
kbits/s Video
kbits/s
Codec Audio
kbits/s
Codec Feed
test1.mpg 1 63 mpeg 96 64 mpeg1video 32 mp2 feed1.ffm
test.asf 3960 3094k asf_stream 320 256 msmpeg4 64 libmp3lame feed1.ffm
stat.html 2 2142 - - - -
index.html 0 0 - - - -
Feed feed1.ffm
Stream type kbits/s codec Parameters
0 audio 32 mp2 1 channel(s), 44100 Hz
1 video 64 mpeg1video 160x128, q=3-31, fps=3
2 audio 64 libmp3lame 1 channel(s), 22050 Hz
3 video 256 msmpeg4 352x240, q=3-31, fps=15
Connection Status
Number of connections: 1 / 1000
Bandwidth in use: 0k / 1000k
# File IP Proto State Target bits/sec Actual bits/sec Bytes transferred
1 stat.html 192.168.0.95 HTTP/1.1 HTTP_WAIT_REQUEST 0 0 0
--------------------------------------------------------------------------------
Generated at Wed Apr 29 09:41:07 2009
然而页面中的test1.mpg和test.asf都无法播放
甚至在播放栏点选的时候 迅雷自动启动 默认要下载test.asf和test1.mpg
而在VLC中输入192.168.0.190:8090/test.asf 或者192.168.0.190:8090/test1.mpg则一直显示连接状态 超时 则弹出 您的输入无法被打开。。。
3gp转换和客户端的打开顺序应该是如何的呢?我这里不管是先转换还是先打开客户端似乎都不能正确播放