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

Pal*_*ltr 11 iphone video ios avplayer

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

我正在使用AVPlayer从网上播放视频.I输出使用当前帧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
Run Code Online (Sandbox Code Playgroud)

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

主要的变化在于我调用[AVPlayerDemoPlaybackViewController update]调用提到的[AVPlayerItemVideoOutput hasNewPixelBufferForItemTime].此函数具有静态变量计数器,用于存储成功[AVPlayerItemVideoOutput copyPixelBufferForItemTime]调用的数量.

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

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

任何帮助将不胜感激!

noa*_*ark 5

代码打击并没有解决我的问题,我仍然没有得到任何东西 [AVPlayerItemVideoOutput hasNewPixelBufferForItemTime]

if (failedCount > 100) {
    failedCount = 0;
    [_playerItem removeOutput:_output];
    [_playerItem addOutput:_output];
}
Run Code Online (Sandbox Code Playgroud)

最后在我的代码测试了一整天之后.我找到了解决问题的方法.

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

检查[AVPlayerItemVideoOutput hasNewPixelBufferForItemTime]何时outputMediaDataWillChange:被叫.如果没有0.1s的新像素缓冲区,则重新创建AVPlayerItemVideoOutput.

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

为什么0.1秒?

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


小智 2

我注意到,在使用 HLS 多比特率播放列表时,AVPlayerItemVideoOutput 会以某种方式“卡住”。当播放器更改为更高的比特率时 -> 播放器视频轨道的 trackid 更改 -> 它将获得很少的像素缓冲区,但之后 hasNewPixelBufferForItemTime 将始终返回 NO。

我已经花了好几天的时间来解决这个问题。我无意中注意到,如果我进入后台,然后返回前台 -> 视频将以更高的比特率正常播放。这不是解决方案。

最后我找到了解决这个问题的方法。我为失败的像素缓冲区设置了计数器,在 100 次失败后,我从玩家项目中删除当前输出并设置回相同的实例。

if (failedCount > 100)
    {
        failedCount = 0;
        [_playerItem removeOutput:_output];
        [_playerItem addOutput:_output];
    }
Run Code Online (Sandbox Code Playgroud)