2

使用 aCIFilter和 anAVVideoComposition时,如何在AVAsynchronousCIImageFilteringRequest回调中访问当前帧号?

我能做的最好的就是估计当时的帧数:

^(AVAsynchronousCIImageFilteringRequest * _Nonnull request) {
    double seconds = CMTimeGetSeconds(request.compositionTime);
    double fps = [[_avAsset tracksWithMediaType:AVMediaTypeVideo] firstObject].nominalFrameRate;
    int frame = round(seconds * fps);

    // (Calculate filter parameters based on frame number)
}

但这对我来说还不够准确。有没有办法访问帧号?

4

2 回答 2

3

关键是在frameDuration上设置AVMutableVideoComposition以匹配底层的AVAssetTrack。如果你这样做,那么 的值compositionTime将是的偶数倍,minFrameDuration并且不会有任何舍入问题。

AVMutableVideoComposition *vidComp =
    [AVMutableVideoComposition videoCompositionWithAsset:self.avAsset
                            applyingCIFiltersWithHandler:
        ^(AVAsynchronousCIImageFilteringRequest * _Nonnull request) {
            CMTime frame = self.avAssetTrack.minFrameDuration;
            int frameNum = (request.compositionTime.value * frame.timescale) /
                           (request.compositionTime.timescale * frame.value);

            // (Calculate filter parameters based on frame number)
        }];

vidComp.frameDuration = self.avAssetTrack.minFrameDuration;

以我的 ~60 fps MP4 电影为例avAssetTrack.minFrameDuration = (1001/60000),但vidComp.frameDuration = (1501/90000)在我更新它之前。这导致回调中“compositionTime”的缓慢漂移,从而导致偶尔出现重复帧。

于 2016-06-22T01:22:34.247 回答
0

怎么样(一个hacky)

__block int frameNum = 0;

AVMutableVideoComposition *vidComp = 
    [AVMutableVideoComposition videoCompositionWithAsset:self.avAsset
        applyingCIFiltersWithHandler:^(AVAsynchronousCIImageFilteringRequest * request) {

        // (Calculate filter parameters based on frame number)

        frameNum++;
    }];

?

这里有两个假设:

  1. 您的处理程序的调用顺序与框架相同
  2. 您的处理程序一次不会被多个线程调用

我不知道这些是否是安全的假设。

ps 帧速率通常是可变的,因此最小、最大和帧持续时间可能会产生误导。

UPDATE from the AVCompositionquestion旨在用于AVPlayer违反假设1的可搜索播放。

于 2016-06-22T13:51:38.920 回答