Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CVMetalTextureCacheCreateTextureFromImage always return null

I'm trying to render I420 (YCbCr planner) via MetalKit

most of examples are using the CMSampleBuffer which from Camera,

but my goal is using a given I420 bytes.

I do something like this:

let data = NSMutableData(contentsOfURL: NSBundle.mainBundle().URLForResource("yuv_640_360", withExtension: "yuv")!)

// Cache for Y

CVMetalTextureCacheCreate(kCFAllocatorDefault, nil, self.device!, nil, &videoTextureCache)

var pixelBuffer: CVPixelBuffer?

CVPixelBufferCreateWithBytes(kCFAllocatorDefault, Int(size.width), Int(size.height), kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange, data.mutableBytes, Int(size.width), nil, nil, [
    "kCVPixelBufferMetalCompatibilityKey": true,
    "kCVPixelBufferOpenGLCompatibilityKey": true,
    "kCVPixelBufferIOSurfacePropertiesKey": []
    ]
    , &pixelBuffer)

// Y texture

var yTextureRef : Unmanaged<CVMetalTexture>?

let yWidth = CVPixelBufferGetWidthOfPlane(pixelBuffer, 0)

let yHeight = CVPixelBufferGetHeightOfPlane(pixelBuffer, 0)

let result = CVMetalTextureCacheCreateTextureFromImage(kCFAllocatorDefault, (videoTextureCache?.takeUnretainedValue())!, pixelBuffer, nil, MTLPixelFormat.R8Unorm, yWidth, yHeight, 0, &yTextureRef);

basically the code is almost same as other examples but I create my own CVPixelBuffer by myself.

I got no error when I creating CVPixelBuffer and CVMetalTexture,

but it always return null for yTexture.

How do I create the right CVPixelBuffer and use it to render ?

like image 734
PatrickSCLin Avatar asked Jun 30 '16 10:06

PatrickSCLin


1 Answers

problem solved.

iosurface is important, I found iosurface always be null if you create CVPixelBuffer by CVPixelBufferCreateWithBytes or CVPixelBufferCreateWithPlanarBytes.

once you use a CVPixelBuffer which's iosurface is null, then MetalTexture always be null.

should do something like this:

let result = CVPixelBufferCreate(kCFAllocatorDefault, width, height, kCVPixelFormatType_420YpCbCr8Planar, [
    String(kCVPixelBufferIOSurfacePropertiesKey): [
        "IOSurfaceOpenGLESFBOCompatibility": true,
        "IOSurfaceOpenGLESTextureCompatibility": true,
        "IOSurfaceCoreAnimationCompatibility": true,
        ]
    ], &self.pixelBuffer)

CVPixelBufferLockBaseAddress(self.pixelBuffer!, 0)

for index in 0...2 {

    memcpy(CVPixelBufferGetBaseAddressOfPlane(self.pixelBuffer!, index), planesAddress[index], planesWidth[index] * planesHeight[index])

}

CVPixelBufferUnlockBaseAddress(self.pixelBuffer!, 0)
like image 72
PatrickSCLin Avatar answered Sep 29 '22 11:09

PatrickSCLin