2015-04-23 63 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渲染貼圖的應用程序與相應的三角形的集合座標偏移做到這一點本身。