2015-04-23 43 views
1

我正在实现裁剪视频帧的自定义视频合成器。目前我使用Core Graphics来执行此操作:如何使用Metal API或Accelerate Framework绘制裁剪的位图?

-(void)renderImage:(CGImageRef)image inBuffer:(CVPixelBufferRef)destination { 
    CGRect cropRect = // some rect ... 
    CGImageRef currentRectImage = CGImageCreateWithImageInRect(photoFullImage, cropRect); 

    size_t width = CVPixelBufferGetWidth(destination); 
    size_t height = CVPixelBufferGetHeight(destination); 

    CGContextRef context = CGBitmapContextCreate(CVPixelBufferGetBaseAddress(destination),  // data 
              width, 
              height, 
              8,            // bpp 
              CVPixelBufferGetBytesPerRow(destination), 
              CGImageGetColorSpace(backImage), 
              CGImageGetBitmapInfo(backImage)); 

    CGRect frame = CGRectMake(0, 0, width, height); 
    CGContextDrawImage(context, frame, currentRectImage); 
    CGContextRelease(context); 
} 

如何使用金属API执行此操作?它应该更快,对吗? 使用Accelerate Framework(vImage具体)怎么样?这会更简单吗?

回答

3

好的,我不知道这对你有用,但仍然。 看看下面的代码:

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection 
{ 
    CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 

    id<MTLTexture> textureY = nil; 

    { 
    size_t width = CVPixelBufferGetWidth(pixelBuffer); 
    size_t height = CVPixelBufferGetHeight(pixelBuffer); 

    MTLPixelFormat pixelFormat = MTLPixelFormatBGRA8Unorm; 

    CVMetalTextureRef texture = NULL; 
    CVReturn status = CVMetalTextureCacheCreateTextureFromImage(NULL, _textureCache, pixelBuffer, NULL, pixelFormat, width, height, 0, &texture); 
    if(status == kCVReturnSuccess) 
    { 
     textureY = CVMetalTextureGetTexture(texture); 
     if (self.delegate){ 
     [self.delegate textureUpdated:textureY]; 
     } 
     CFRelease(texture); 
    } 
    } 
} 

我使用此代码CVPixelBufferRef转换成MTLTexture。之后,你可能需要创建blitCommandEncoder和使用它的

func copyFromTexture(sourceTexture: MTLTexture, sourceSlice: Int, sourceLevel: Int, sourceOrigin: MTLOrigin, sourceSize: MTLSize, toTexture destinationTexture: MTLTexture, destinationSlice: Int, destinationLevel: Int, destinationOrigin: MTLOrigin) 

在里面,你可以选择裁剪矩形,并把它复制到一些其他的质感。

下一步是将生成的MTLTextures转换回CVPixelBufferRefs,然后制作一个视频,遗憾的是我不知道该怎么做。

真的很想听听你想出了什么。干杯。

+0

你可以很容易地从CVMetalTextureRef到CGImageRef,然后到CVPixelBufferRef,但是如果你需要实时性能,我在同一个pickle中(试图找出如何获得CVPixelBufferRef) –

2

由于它使用裸指针和未封装的数据,只需将指针移动到图像的左上角以指向新的左上角并相应地减小高度和宽度,vImage就会“裁剪”事物。您现在有一个vImage_Buffer,它指向图像中间的区域。当然,您仍然需要将内容作为文件再次导出,或者将其复制到注定要绘制到屏幕上的内容中。请参阅vImageCreateCGImageFromBuffer()。

CG可以CGImageCreateWithImageInRect()

金属会做到这一点无论是作为一个简单的计算拷贝内核,一个MTLBlitCommandEncoder块传送,或3D渲染贴图的应用程序与相应的三角形的集合坐标偏移做到这一点本身。