FFmpeg + iOS +有损蜂窝连接

时间:2014-11-08 18:04:51

标签: ios ffmpeg video-streaming

我可以使用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()? (或改善重新连接时间的策略?)

1 个答案:

答案 0 :(得分:0)

我想您需要转移到自己对网络I / O的处理,并使用数据块提供avformat。