av_interleaved_write_frame 网络不好的情况下返回较慢
用libvlc做直播推流引擎
在网络较差的情况下,需要关闭直播,并且重新开播。
这个过程中,推流引擎重启,需要的是快速响应。
实际上测试结果发现,经常会发生引擎关闭接口卡住。
后来跟踪代码,定位到s_rtmp_send_thread() 中
其中一句:
ret = av_interleaved_write_frame(formatContext, pkt);
这个方法在网络较好的情况下,一般是几个毫秒就返回发送成功。
然后在网络较差的情况下,会一直卡在这里,没有返回。。。
跟踪ffmpeg代码,这个方法的实现在mux.c
libavformat/mux.c
av_interleaved_write_frame()
write_packet() 真正写数据
ret = s->oformat->write_packet(s, pkt);
write_packet 这里就是一个定义在avformat.h中的指针,指向flv_write_packet()
经一步跟踪代码,发现关于网络读写的超时控制,定义在url.h中
typedef struct URLContext { ...... int64_t rw_timeout; /**< maximum time to wait for (network) read/write ...... } URLContext;
于是在初始化的地方,设置这个参数:
libavformat/avio.c --->
url_alloc_for_protocol() return之前添加如下语句
// 网络读写超时 控制在 800ms
if (0 == uc->rw_timeout || uc->rw_timeout > 800000) uc->rw_timeout = 800000;
回到项目中,在av_interleaved_write_frame两端输出时间,发现现在这个接口在网络不好的情况下,基本控制在1s以内。然后并不是精确的时间控制。貌似ffmpeg本身都不能严格控制到毫秒级别。
为了确保这个返回一定得到响应,同时在libavformat/mux.c
av_interleaved_write_frame()中修改下面的代码:
for(;;)
这个没有控制的for循环,改为
int mOutTimes = 128; int nn; for(nn=0;nn<mOutTimes;nn++)
这里的128是个经验值。