AVPlayerItemVideoOutput

AVPlayerItemVideoOutput

这是我的第一个问题,所以请不要太认真。

我正在使用AVPlayer从网上播放视频。我使用附加到 AVPlayer 播放的 AVPlayerItem AVPlayerItemVideoOutput 输出当前帧。要检查新框架是否准备就绪,我调用 [AVPlayerItemVideoOutput hasNewPixelBufferForItemTime] ,然后使用OpenGL ES将其输出。如果我阅读mp4,一切都可以正常工作,但是如果我尝试阅读m3u8,则可以工作约1秒(〜30帧),但是在这段时间之后 [AVPlayerItemVideoOutput hasNewPixelBufferForItemTime] 仅开始返回FALSE,因此当前帧不是更新。

如果我在第一次出现此问题之前使用 [AVPlayer seekToTime] 查找当前帧,则一切正常。

在这里测试我使用的m3u8视频:

http://195.16.112.71/adaptive/3006a26a-9154-4b38-a327-4fa2a2381ae6.video/3006a26a-9154-4b38-a327-4fa2a2381ae6.m3u8

为了重现此问题,我修改了苹果的示例AVPlayerDemo,它是:https://yadi.sk/d/T2aVGoKnWmf5Z

主要变化在于,我调用了 [AVPlayerDemoPlaybackViewController更新] ,它调用了提到的 [AVPlayerItemVideoOutput hasNewPixelBufferForItemTime] 。此函数具有静态变量计数器,该变量存储已成功 [AVPlayerItemVideoOutput copyPixelBufferForItemTime] 调用的数量。

视频网址是在 [AVPlayerDemoPlaybackViewController setURL] 中设置的,它在功能的开头进行了硬编码。默认情况下,它的值指向m3u8视频,这会重现此问题,在这种情况下,带有该索引 [AVPlayerItemVideoOutput hasNewPixelBufferForItemTime]的帧之后计数器的平均值约为30,仅返回FALSE。

如果使用其他视频网址(请参见 [AVPlayerDemoPlaybackViewController setURL] 的开头-您可以取消注释另一个网址),则所有帧均已成功读取。

任何帮助将不胜感激!

最佳答案

代码打击无法解决我的问题,[AVPlayerItemVideoOutput hasNewPixelBufferForItemTime]仍然无法解决任何问题

if (failedCount > 100) {
    failedCount = 0;
    [_playerItem removeOutput:_output];
    [_playerItem addOutput:_output];
}

最后测试了我的代码一整天。我找到了解决方法。
#pragma mark - AVPlayerItemOutputPullDelegate
- (void)outputMediaDataWillChange:(AVPlayerItemOutput *)sender {
    if (![self.videoOutput hasNewPixelBufferForItemTime:CMTimeMake(1, 10)]) {
        [self configVideoOutput];
    }
    [self.displayLink setPaused:NO];
}

调用[AVPlayerItemVideoOutput hasNewPixelBufferForItemTime]时检查outputMediaDataWillChange:如果在0.1秒内没有新的像素缓冲区,请重新创建AVPlayerItemVideoOutput
[self configVideoOutput];中的代码只需重新创建一个新的AVPlayerItemVideoOutput即可替换当前的videoOutput属性。

为什么是0.1秒?

经过多次测试,我发现前1或2帧可能始终没有像素缓冲区。因此,最初的1/30s,2/30s(对于30fps的视频)可能没有帧和像素缓冲区。但是,如果在0.1秒后没有视频像素缓冲区,则视频输出可能会损坏或出现问题。因此,我们需要重新创建它。

10-05 18:53