AVPlayerItemVideoOutput.hasNewPixelBufferForItemTime无法正常工作

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

我使用AVPlayer从网上播放video。 我使用附加在AVPlayer播放的AVPlayerItem上的AVPlayerItemVideoOutput输出当前帧。 要检查新的帧是否准备就绪,我调用[AVPlayerItemVideoOutput hasNewPixelBufferForItemTime] ,然后使用OpenGL ES输出。 所有的作品完美的,如果我读mp4,但如果我尝试读m3u8,它的作品约1秒(约30帧),但在这段时间后[AVPlayerItemVideoOutput hasNewPixelBufferForItemTime]开始只返回FALSE,所以当前帧不更新。

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

testingm3u8video我在这里使用生命:

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] 。 这个函数有静态variables计数器 ,它存储了成功的[AVPlayerItemVideoOutput copyPixelBufferForItemTime]调用的数量。

Video Url在[AVPlayerDemoPlaybackViewController setURL]中设置 ,它在函数的开头被硬编码。 默认情况下,它的值指向m3u8video,这再现了问题,在这种情况下, 计数器的平均值大约为30,在具有该索引的帧之后[AVPlayerItemVideoOutput hasNewPixelBufferForItemTime]仅返回FALSE。

在使用其他videoUrl的情况下(见[AVPlayerDemoPlaybackViewController setURL]的开头 – 有一个可以取消注释的替代Url),所有的帧都被成功读取。

任何帮助将不胜感激!

代码打击没有解决我的问题,我还是从[AVPlayerItemVideoOutput hasNewPixelBufferForItemTime]

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

最后在testing我的代码一整天后。 我find了解决的办法

 #pragma mark - AVPlayerItemOutputPullDelegate - (void)outputMediaDataWillChange:(AVPlayerItemOutput *)sender { if (![self.videoOutput hasNewPixelBufferForItemTime:CMTimeMake(1, 10)]) { [self configVideoOutput]; } [self.displayLink setPaused:NO]; } 

调用outputMediaDataWillChange:时检查[AVPlayerItemVideoOutput hasNewPixelBufferForItemTime]如果在0.1s没有新的像素缓冲区,请重新创buildAVPlayerItemVideoOutput

[self configVideoOutput];代码[self configVideoOutput]; 只需重新创build一个新的AVPlayerItemVideoOutput来replace当前的videoOutput属性。

为什么0.1s?

我经过多次testing和实验,发现前1或2帧可能总是没有像素缓冲区。 所以第一个1 / 30s,2 / 30s(对于30fps的video)可能没有帧和像素缓冲器。 但是如果在0.1s之后没有video像素缓冲,video输出可能会破坏或者出现问题。 所以我们需要重新创build它。

我注意到AVPlayerItemVideoOutput在使用HLS多比特率播放列表时以某种方式“堵塞”。 当播放器改变为更高的比特率 – > TrackID的播放器项目video轨道改变 – >它将得到很less的像素缓冲区,但之后hasNewPixelBufferForItemTime将永远返回NO。

我花了几天的时间来解决这个问题。 不小心,我注意到,如果我去背景,然后回到前台 – >video将正常播放与更高的比特率。 这不是解决scheme。

最后我find了解决这个问题的办法。 我设置了失败的像素缓冲区计数器,100失败后,我从播放器中删除当前输出,并设置相同的实例。

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

我有一个非常好的解决scheme:确保你调用- (void)addOutput:(AVPlayerItemOutput *)output方法只有当你观察到你的AVPlayerItemstatusAVPlayerItemStatusReadyToPlay

参考: 看这个页面depinxi的答复