问题 [iOS] AVPlayerItemVideoOutput.hasNewPixelBufferForItemTime无法正常工作


这是我的第一个问题,所以不要太严厉。

我正在使用AVPlayer从网上播放视频。我使用输出当前帧 AVPlayerItemVideoOutput 附在 AVPlayerItem 由...发挥 AVPlayer。为了检查新帧是否准备好,我打电话 [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

为了重现这个问题,我修改了Apple的AVPlayerDemo示例,这里是: https://yadi.sk/d/T2aVGoKnWmf5Z

主要的变化在于我打电话 [AVPlayerDemoPlaybackViewController更新] 哪个电话提到了 [AVPlayerItemVideoOutput hasNewPixelBufferForItemTime]。这个函数有静态变量 计数器 它存储了成功的数量 [AVPlayerItemVideoOutput copyPixelBufferForItemTime] 调用。

视频网址已设置 [AVPlayerDemoPlaybackViewController setURL],它在函数的开头是硬编码的。默认情况下,它的值指向m3u8视频,它会再现问题,在这种情况下是平均值 计数器 在具有该指数的框架之后约为30 [AVPlayerItemVideoOutput hasNewPixelBufferForItemTime] 仅返回FALSE。

在使用其他视频网址的情况下(参见开头) [AVPlayerDemoPlaybackViewController setURL]  - 您可以取消注释另一个Url),所有帧都已成功读取。

任何帮助将不胜感激!


11341
now


起源



答案:


代码打击并没有解决我的问题,我仍然没有得到任何东西 [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: 调用。 重新创建你的 AVPlayerItemVideoOutput 如果没有0.1s的新像素缓冲区。

代码 [self configVideoOutput]; 只是重新创建一个新的 AVPlayerItemVideoOutput 替换当前 videoOutput 属性。

为什么0.1秒?

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


5
2017-11-22 09:23



这对我有用。删除并向AVPlayerItem添加新输出似乎可以解决问题。 - Kazzin
这也为我修好了。非常感谢,在我找到这篇文章之前花了一段时间来对抗这个。 - crgt
我还必须在添加它之前重新创建输出以使我的工作。 - kleezy
我和swift以及iOS 9一起工作 - embinder
我希望我能给你不止一次投票。这个解决方案对我也有用。谢啦! - Eugene Alexeev


答案:


代码打击并没有解决我的问题,我仍然没有得到任何东西 [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: 调用。 重新创建你的 AVPlayerItemVideoOutput 如果没有0.1s的新像素缓冲区。

代码 [self configVideoOutput]; 只是重新创建一个新的 AVPlayerItemVideoOutput 替换当前 videoOutput 属性。

为什么0.1秒?

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


5
2017-11-22 09:23



这对我有用。删除并向AVPlayerItem添加新输出似乎可以解决问题。 - Kazzin
这也为我修好了。非常感谢,在我找到这篇文章之前花了一段时间来对抗这个。 - crgt
我还必须在添加它之前重新创建输出以使我的工作。 - kleezy
我和swift以及iOS 9一起工作 - embinder
我希望我能给你不止一次投票。这个解决方案对我也有用。谢啦! - Eugene Alexeev


确保这一点 AVPlayerItem.status 等于 AVPlayerItemStatusReadyToPlay 在打电话之前 - (void)addOutput:(AVPlayerItemOutput *)output 方法 AVPlayerItem

参考:看看depinxi在这个页面上的