I'm trying to capture an IOSurface using both CVPixelBufferCreateWithIOSurface
and by reading pixels from IOSurfaceGetBaseAddressOfPlane
.
However, on newer devices (iPhone XS), I get an unknown pixel format &wq2
(again, using both IOSurfaceGetPixelFormat
and CVPixelBufferGetPixelFormatType
).
CVPixelFormatDescriptionCreateWithPixelFormatType
returns the following:
@"{\n BitsPerComponent = 10;\n ComponentRange = FullRange;\n ContainsAlpha = 1;\n ContainsGrayscale = 0;\n ContainsRGB = 1;\n ContainsYCbCr = 0;\n PixelFormat = 645346401;\n Planes = (\n {\n BitsPerBlock = 64;\n CompressionType = 2;\n TileHeight = 16;\n TileWidth = 16;\n }\n );\n}"
My code works perfectly on older devices (where it returns BGRA
as the pixel format), but breaks down on what I assume are newer devices. How can I unmarshal the pixels from this undocumented format.
I have a bad habit of answering my own questions.
To convert this IOSurface
to say an IOSurface
with a known pixel type, an IOAccelerator
should be used.
CFMutableDictionary dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);;
char pixelFormat[4] = {'A', 'R', 'G', 'B'};
CFDictionarySetValue(dict, kIOSurfaceBytesPerRow, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &bytesPerRow));
CFDictionarySetValue(dict, kIOSurfaceBytesPerElement, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &bytesPerElement));
CFDictionarySetValue(dict, kIOSurfaceWidth, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &width));
CFDictionarySetValue(dict, kIOSurfaceHeight, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &height));
CFDictionarySetValue(dict, kIOSurfacePixelFormat, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, pixelFormat));
CFDictionarySetValue(dict, kIOSurfaceAllocSize, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &bufferSize));
IOSurfaceRef surface = IOSurfaceCreate(dict);
auto const didCreateAccelerator = IOSurfaceAcceleratorCreate(kCFAllocatorDefault, 0, &accelerator);