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 ?
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With