ffserver 目前支持rtsp/rtp, http/flv 网络播放, 不过还没有发现支持hls的案例。下面的目的是扩展ffserver功能以支持http live streaming。
====
ffserver -f stream.conf &
ffplay http://localhost:8090/test1.mpg & #可以多个
ffmpeg -i INPUT http://localhost:8090/mpg.ffm &
fg
#如果ffplay还没有显示,就再次ffmpeg feed一下。
摄像头+rtp:播放先于录制,大概有1秒延迟; 支持File。
ffplay rtsp://localhost:5454/test1-rtsp.mpg
摄像头+swf:没有延迟,开头部分快同步;只支持ffv1+mp3编码的File。
ffplay http://localhost:8090/test.flv -window_title new -v 0
关键代码
====
http_server 主循环:
跟据http_ctx构造poll_table
poll();
设置当前时间cur_time
对于所有http_ctx:
if(handle_connection() < 0)close_connection();
如果有请求来(即server_fd有可读事件):
new_connection()accept,并加入到http_ctx链表头。
handle_connection()处理:
recv,http_parse_request-->http_start_receive_data打开feed_filename
http_receive_data-->recv并写入feed_fd文件
http_send_data-->http_prepare_data
如果发生网络错误(比如客户端断开),状态不一致等,则返回-1
http_prepare_data-->
av_read_frame from Feed or File
av_write_frame to Stream.Format
close_connection-->
从http_ctx中取消,close socket, 关闭输入输出流。
stat.html统一处理为http reply, 包括
错误,重定向等网页内容(HTTPSTATE_SEND_HEADER)。
扩展
====
支持hls.
ffmpeg -f v4l2 -i /dev/video0 -vcodec mpeg2video \
-f hls -hls_wrap 5 -hls_list_size 5 out.m3u8
这里设置hls_wrap目的是不要生成太多的ts片段。out.m3u8在实时变化:
1,2,3,4,0-->3,4,0,1,2-->4,0,1,2,3;
ffplay out.m3u8也可连续播放;说明hls格式处理了这种把ts分段当成循环缓冲的机制,
o ffplay 需要实时检测文件的变化?
* 不是ffplay做的,在hls.c:read_data里面每个间隔时间都会reload 这个m3u8文件。
ffmpeg转码结束时m3u8文件里面结尾增加"#EXT-X-ENDLIST"
ffmpeg -f v4l2 -i /dev/video0 -vcodec mpeg1video -f hls http://localhost:8090/hls.ffm
[POST] "/hls.ffm HTTP/1.1" 200 5132288
New connection: POST /hls0.ts
File '/hls0.ts' not found
[POST] "/hls0.ts HTTP/1.1" 404 147
刷新网页的打印:
New connection: GET /stat.html #客户端发起
[GET] "/stat.html HTTP/1.1" 200 3965 #服务器响应
猜想ffmpeg打算向服务器上传hls0.ts, hls1.ts, ..., hlsN.ts, hls.m3u8。
没有-f hls参数,确认了
ffmpeg写入了/tmp/hls.ffm,格式为mpeg1video;
ffplay http://localhost:8090/test.hls一直卡住;
ffserver 在它所在目录下写了文件0.ts, 1.ts, 2.ts, ...每写一个就报错
Error writing frame to output for stream。
理解为:-f强制格式,与ffm后缀无关; ffplay虽然连接,但是没有数据;
ffserver调hlsenc做格式转换:ffm-->hls。
把若干ts文件塞到ffm,取的时候再拆分出来一个个文件?
如何扩展Feed-Stream机制?
hls说它其实只需要一个文件服务器!文件是客户端主动要的。
对于实时应用比如摄像头来说,设置hls_wrap=5还算流畅,只是有几秒钟的延迟。
对于离线hls封装一个已经下载的视频文件, 如果codec=copy的话,转码很快就完了,
只能看到一小段。当然前面的摄像头也不是严格“实时的”,现在问题变为:
TODO:如何控制ffmpeg转码速度?
问题
====
o 多个相同的ffplay实例,是共享同一个feed吗?
* 是的。同一个Feed,可以有多个读,多个写。
http连接是tcp,点对点的。对带宽的影响?
o 同一摄像头,ffplay播放滞后。
优化选项关? ffm太大? 修改VideoBufferSize只会导致
[mpeg @ 0x2ad0290]buffer underflow st=0 bufi=130 size=380
o 相同的ffplay实例先后启动,播放的内容vcd不同步,
但是摄像头是同步的,为什么?
* date=12:34:56 --
buffer=seconds --
stream_pos = av_gettime() - prebuffer * (int64_t)1000000;
av_seek_frame(c->fmt_in, -1, stream_pos, 0);
对于File, 新来的就应该从头开始。
o 带宽
* 从stat.html来看,Bandwidth in use是单个实例的。
o mulicast
ffplay http://localhost:8090/test1-sdp.sdp
setsockopt(IP_ADD_MEMBERSHIP): No such device