这是我的第一个问题,所以不要太严厉。
我正在使用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),所有帧都已成功读取。
任何帮助将不胜感激!
代码打击并没有解决我的问题,我仍然没有得到任何东西 [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秒之后没有视频像素缓冲,则视频输出可能会破坏或出现问题。所以我们需要重新创建它。
代码打击并没有解决我的问题,我仍然没有得到任何东西 [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秒之后没有视频像素缓冲,则视频输出可能会破坏或出现问题。所以我们需要重新创建它。