【转】ffserver和ffmpeg配合完成的实时流媒体服务

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)时得出的,现在不知这个架构是否改变,兄弟我把砖扔出,希望大家用玉来砸。

 

 

 

 

 

 

 

2009-03-01 19:36
非常感谢大虾精辟的分析。小弟最近正在看FFserver的源代码,看的有点头大,有问题想请教一下。
我采用的是H.264的编码器,我阅读output_example后发现编码后的数据格式应该是绑定到AVpacket格式上,我想问一下,ffserver是对什么数据格式进行rtp打包的,是直接对编码后的缓存数据打包,还是对AVpacket数据进行rtp打包?
希望大哥能予以指点。
  • 2009-03-02 13:38
    我理解你这里说的缓存数据是feed1.ffm中的数据,那么发出去的时候应该是从这里取数据的,可以这样理解,一帧解码后的数据被在缓冲的时候,被拆分成一块一块(4096)的存放在feed1.ffm中,在要发送的时候,就把这一块一块的数据拼装起来,还原为一帧解码后的数据,交由AVpacket->data指向,再看要以什么样的格式发给客户端,比如你这里说的RTP,再把数据按照RTP格式打包,发送给客户端。
  • 李海宁
    2009-03-02 16:25
    : 我理解你这里说的缓存数据是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
    : 看到你的回复太高兴了,非常感谢我还是有点不明白,还得再麻烦一下
    FFmpeg中的编码函数应该是
    out_size = avcodec_encode_video(AVCodecContext *avctx
    抱歉,这个我也不太清楚,你可以请教下admin,或是到论坛或群里问问。
  • 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可以接收网络来的rtp包吗?然后自己解码调用SDL显示,是这样吗?
    谢谢
    ffplay要播放从ffserver来的RTSP/RTP流的话,可能要改代码了,不知道现在最新的ffplay能否直接播,就是类似ffplay rtsp://ip:5454/file这种形式,你可以试试。
    我原来试过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转换和客户端的打开顺序应该是如何的呢?我这里不管是先转换还是先打开客户端似乎都不能正确播放

  •  
        

    <script type="text/javascript"></script>

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值