我可以使用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()? (或改善重新连接时间的策略?)
答案 0 :(得分:0)
我想您需要转移到自己对网络I / O的处理,并使用数据块提供avformat。