以640x480 @ 60fps快速捕获视频

时间:2015-03-12 17:44:28

标签: ios video-capture metal

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

我目前正在使用预设AVCaptureSessionPreset1280x720,但我想在640x480进行计算,否则设备将无法跟上。这里开始出现问题:我不能直接捕获640x480 @ 60fps,根据Apple允许开发人员做的事情而且我目前的调整速度非常慢。

我正在使用金属内核着色器调整图像大小,但98%的时间(在乐器中看到)花在这两行中:

[_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的20ms提高到8ms。仍然不是我想要的,但更好。

更新2:

我切换到CoreGraphics并且它足够快。请参阅this post

1 个答案:

答案 0 :(得分:0)

我认为你已经从Capture会话创建了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);
}