我想使用最少的资源以60fps的速度捕获视频,因为我需要每帧最多使用16-20ms,并且大部分时间将被帧上的繁重计算所占用。

我当前正在使用预设的AVCaptureSessionPreset1280x720,但是我想以640x480进行计算,否则设备将无法跟上。这就是问题所在:根据Apple让开发人员执行的操作,我无法直接以640x480 @ 60fps捕获,而我当前的调整大小非常慢。

我正在使用带有Metal内核着色器调整图像大小的图像,但是以下两行中花费了98%的时间(在Instruments中可见):

[_inputTexture replaceRegion:region mipmapLevel:0 withBytes:inputImage.data bytesPerRow:inputImage.channels() * inputImage.cols];
...
[_outputTexture getBytes:outputImage.data bytesPerRow:inputImage.channels() * outputImage.cols fromRegion:outputRegion mipmapLevel:0];

基本上在内存加载/存储指令中。从理论上讲,这部分使我感到困惑,因为内存在iPhone上的CPU和GPU之间共享。

您认为金属代码应该更快吗?我还使用Metal进行了视频演示,并且不费吹灰之力(在GPU上约为1ms,而调整大小则需要约20ms)。

有没有更快的方法来调整图像大小?您对Image I / O的体验如何?

更新:

当我将工作组的大小增加到22x22x1时,图像调整大小的性能从GPU的20毫秒提高到了8毫秒。仍然不是我想要的,但是更好。

更新2:

我切换到CoreGraphics,它运行速度足够快。参见this post

最佳答案

我认为您已经从Capture session 创建了UIImage,然后必须将其转换为Metal纹理(MTLTexture)。但是你不应该这样做。这是一个如何从CaptureOutput委托获取MTLTexture的示例:

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {
CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
CVPixelBufferLockBaseAddress(pixelBuffer, 0);
id<MTLTexture> inTexture = nil;
size_t width = CVPixelBufferGetWidth(pixelBuffer);
size_t height = CVPixelBufferGetHeight(pixelBuffer);

MTLPixelFormat pixelFormat = MTLPixelFormatBGRA8Unorm;

CVMetalTextureRef metalTextureRef = NULL;
CVReturn status = CVMetalTextureCacheCreateTextureFromImage(NULL, _textureCache, pixelBuffer, NULL, pixelFormat, width, height, 0, &metalTextureRef);
if(status == kCVReturnSuccess) {
    inTexture = CVMetalTextureGetTexture(metalTextureRef);
    CFRelease(metalTextureRef);
}
CVPixelBufferUnlockBaseAddress(pixelBuffer,0);
}

关于ios - 640x480 @ 60fps的快速视频捕获,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29016732/

10-08 20:59