我可以用FFmpeg在iOS上播放RTMP音频+视频实时流。当一切都建立在一个稳定的WiFi连接上时,效果非常好。
当我切换到蜂窝连接(高信号强度和LTE/4G)时,av_read_frame()
会间歇性地阻塞一段不可接受的时间。据我所知,这并不是因为蜂窝数据连接刚刚中断,因为我可以立即重新连接并开始下载更多的数据包。在某些情况下,在它返回下一帧之前,我记录了30+秒的挂起时间。当下一帧最终到达时,我的实时视频流将永久延迟av_read_frame()
阻塞的时间量。
如果函数返回的时间超过1秒,我尝试使用AVIOInterruptCB
中断回调中止av_read_frame()
。代码如下所示:
- (void)readPackets {
// Make sure FFmpeg calls our interrupt periodically
_context->interrupt_callback.callback = interrupt_cb;
_context->interrupt_callback.opaque = self;
dispatch_async(_readPacketQueue, ^(void) {
int err;
while(true) {
_readFrameTimeStamp = [[NSDate date] timeIntervalSince1970];
err = av_read_frame(_context, &packet);
_readFrameTimeStamp = 0;
if(err) {
// Error - Reconnect the entire stream from scratch, taking 5-10 seconds
// And we know when av_read_frame() was aborted
// because its error code is -1414092869 ("EXIT")
}
else {
// Play this audio or video packet
}
}
});
}
/**
* Interrupt
* @return 1 to abort the current operation
*/
static int interrupt_cb(void *decoder) {
if(decoder) {
if(_readFrameTimeStamp != 0) {
if([[NSDate date] timeIntervalSince1970] - _readFrameTimeStamp > 1) {
// Abort av_read_frame(), it's taking longer than 1 second
return 1;
}
}
}
}
这肯定会在1秒后中止av_read_frame()
,但不幸的是,在我这样做之后,以后调用av_read_frame()
的尝试会导致EIO
错误(-5),这表明连接已被切断。
结果,我不得不完全重新连接查看器,这需要5-10秒。(avformat_open_input()
需要大约3-4秒,然后再次查找流信息需要大约2-3秒,然后开始读取帧)。
完全重新连接的5-10秒延迟比等待av_read_frame()
解锁超过10秒要好得多,也比实时流被大量延迟要好得多。但这比能够立即重试av_read_frame()要糟糕得多。
从手机用户的角度来看,他们的视频间歇性地锁定了5-10秒,而我们从头开始在后台重新连接流,这不是一个好的用户体验。
有什么策略可以更好地管理有损蜂窝连接上的av_read_frame()?(或改善重新连接时间的策略?)
发布于 2014-11-09 17:43:51
我认为您需要转移到自己的网络I/O处理上,并为avformat提供数据块。
https://stackoverflow.com/questions/26820331
复制相似问题