用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是個經驗值。