如何在AVVideoComposition的applicationCIFiltersWithHandler中触发重绘过滤器?

时间:2016-02-04 18:08:00

标签: ios swift avplayer cifilter avvideocomposition

我使用Swift在视图的AVPlayerLayer中显示来自AVPlayer的内容。关联的AVPlayerItem有一个videoComposition,稍微简化的代码版本(无需错误检查等)如下所示:

playerItem.videoComposition = AVVideoComposition(asset: someAsset, applyingCIFiltersWithHandler: {
                [unowned self] (request: AVAsynchronousCIImageFilteringRequest) in

    let paramDict = << set up parameter dictionary based on class vars >>

    // filter the image
    let filter = self.ciFilterWithParamDict(paramDict) {
    filter.setValue(request.sourceImage, forKey: kCIInputImageKey)
    if let filteredImage = filter.outputImage {
        request.finishWithImage(filteredImage, context: nil)
    }
})

当AVPlayer正在播放或寻找时,这一切都按预期工作。如果创建并加载了新的videoComposition,则会正确呈现AVPlayerLayer。

然而,我还没有找到一种方法来触发&#34;触发&#34;当我更改了一些用于计算过滤器参数的值时,AVPlayer / AVPlayerItem / AVVideoComposition重新渲染。如果我更改值然后播放或搜索,则会正确呈现,但仅限于我玩或寻找。是否无法触发渲染&#34;到位&#34;?

4 个答案:

答案 0 :(得分:3)

我使用hack来完全替换avPlayerItem以强制刷新。但如果有一种方法可以触发avPlayerItem直接重新渲染,那就更好了。

// If the video is paused, force the player to re-render the frame.
if (self.avPlayer.currentItem.asset && self.avPlayer.rate == 0) {
    CMTime currentTime = self.avPlayerItem.currentTime;

    [self.avPlayer replaceCurrentItemWithPlayerItem:nil];
    [self.avPlayer replaceCurrentItemWithPlayerItem:self.avPlayerItem];
    [self.avPlayerItem seekToTime:currentTime toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];
}

答案 1 :(得分:3)

我知道这样做的最好方法是在暂停的AVPlayer上编辑CIFilter输入时,为AVPlayerItem创建一个新的AVVideoComposition实例。根据我的经验,它比将播放器项目交换回播放器更快更干净。您可能认为创建新的视频合成很慢,但实际上您所做的只是重新定义该特定帧的渲染路径,这几乎与使您的更改影响的Core Image缓存部分无效一样高效。 / p>

此处的关键是播放器项目的视频合成必须以某种方式无效以触发重绘。简单地改变核心图像过滤器的输入参数几乎没有办法(我知道)使视频合成无效,这是问题的根源。

通过为AVPlayerItem创建AVMutableVideoComposition实例并在某些方面(通过更改指令,animationTool,frameDuration之类的内容)在暂停时进行编辑,可以提高效率。

答案 2 :(得分:0)

这个可能对你有帮助。

let currentTime = self.player.current()
self.player.play()
self.player.pause()
self.player.seek(to: currentTime, toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero)

答案 3 :(得分:0)

沿this answer行,但不必创建一个全新的AVVideoComposition并将其设置为播放器的videoComposition,而是可以通过简单地强制刷新当前帧将videoComposition设置为nil,然后立即返回到现有的videoComposition实例。

只要您想强制刷新当前帧,就会得到以下简单的解决方法:

let videoComposition = player.currentItem?.videoComposition
player.currentItem?.videoComposition = nil
player.currentItem?.videoComposition = videoComposition