在我们的iOS应用程序中,我们使用使用Metal(CIKernel/CIColorKernel包装器)的自定义过滤器。
假设我们有一个 4K 视频和一个具有 1080p 输出大小的自定义视频合成,它在视频缓冲区上应用了高级过滤器。
显然,我们不需要以原始大小过滤视频,这样做我们可能会终止应用程序并显示内存警告(真实故事)。
这是视频过滤管道:
获取 4K 缓冲区(如CIImage
) -->在CIImage
上应用过滤器 -->过滤器在CIImage
上应用CIKernel
Metal
过滤器函数-->
将过滤后的CIImage
返回到合成
我能想到的唯一两个应用调整大小的地方是在我们将其发送到过滤过程之前或在Metal
函数中。
public class VHSFilter: CIFilter {
public override var outputImage: CIImage? {
// InputImage size is 4K
guard let inputImage = self.inputImage else { return nil }
// Manipulate the image here
let roiCallback: CIKernelROICallback = { _, rect -> CGRect in
return inputImage.extent
}
// Or inside the Kernel Metal function
let outputImage = self.kernel.apply(extent: inputExtent,
roiCallback: roiCallback,
arguments: [inputImage])
return outputImage
}
}
我确定我不是第一个遇到这个问题的人
当传入的视频缓冲区太大(内存方面)而无法过滤,并且需要有效地即时调整大小时,该怎么办?之前没有重新编码视频?
正如Warrenm所说,你可以在处理之前使用CILanczosScaleTransform
滤波器对视频帧进行下采样。但是,这仍会导致 AVFoundation 以全分辨率分配缓冲区。
我假设您使用AVMutableVideoComposition
进行过滤?在这种情况下,您只需将合成的renderSize
设置为目标大小即可。从文档中:
视频合成应呈现的大小。
这将告诉 AVFoundation 在将帧交给过滤器管道之前(高效、快速)对帧进行重新采样。