I am working on a project for macOS where I am taking an AVCaptureSession's CVPixelBuffer and I need to convert it into a MTLTexture for rendering. On macOS the pixel format is 2vuy, there does not seem to be a clear format conversion while converting to a metal texture. I have been able to convert it to a texture but the color space seems to be off as it is rendering distorted colors with a double image.
I believe 2vuy is a single pane color space and I have tried to account for that, but I am unaware of what is off.
I have attached The CVPixelBuffer and The distorted MTLTexture along with a laundry list of errors.
On iOS my conversions are fine, it is only the macOS 2vuy pixel format that seems to have issues.
My code for the conversion is also attached.
If there are any suggestions or guidance on how to properly convert a 2vuy CVPixelBuffer to a MTLTexture I would greatly appreciate it.
Many Thanks
Thanks for the focused sample, there are a couple of things to note here:
-
You are receiving '2vuy' pixel buffers from AVCapture. This Core Video pixel format maps to MTLPixelFormat.bgrg422, not MTLPixelFormat.gbgr422.
-
Your kernel is written to handle subsample, but because you are using one of the "422" pixel formats, Metal takes care of this for you automatically! From MTLPixelFormat.h: "There is no implicit colorspace conversion from YUV to RGB, the shader will receive (Cr, Y, Cb, 1)."
So, what should your kernel look like instead? Something like this:
// When using .bgrg422, shader receives (Cr (x), Y (y), Cb (z), 1)
float y = yuvTexture.read(gid).y; // Y <-> y
float cb = yuvTexture.read(gid).z; // Cb <-> z
float cr = yuvTexture.read(gid).x; // Cr <-> x
// YCbCr to RGB conversion matrix taken from the ARKit (Metal) template project.
const float4x4 ycbcrToRGBTransform = float4x4(
float4(+1.0000f, +1.0000f, +1.0000f, +0.0000f),
float4(+0.0000f, -0.3441f, +1.7720f, +0.0000f),
float4(+1.4020f, -0.7141f, +0.0000f, +0.0000f),
float4(-0.7010f, +0.5291f, -0.8860f, +1.0000f)
);
float4 rgba = ycbcrToRGBTransform * float4(y, cb, cr, 1.0);
// Write the RGB values to the output texture
rgbTexture.write(rgba, gid);
That should get you unblocked :)
-- Greg