Getting actual NSString of AvCaptureVideoDataOutput availableVideoCVPixelFormatTypes

3.7k Views Asked by At

I am trying to find the accepted formats on an AVFoundation output:

self.theOutput=[[AVCaptureVideoDataOutput alloc]init];
    if ([self.theSession canAddOutput:self.theOutput])
        [self.theSession addOutput:self.theOutput]; 

I am then inserting a breakpoint right after and:

po [self.theOutput availableVideoCVPixelFormatTypes]

and I get this:

(NSArray *) $5 = 0x2087ad00 <__NSArrayM 0x2087ad00>(
875704438,
875704422,
1111970369
)

How do I get the string values of these format types?

Thanks

5

There are 5 best solutions below

2
On BEST ANSWER

On an iPhone5 running iOS6, here are the AVCaptureVideoDataOuput availableVideoCVPixelFormatTypes:

kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange

kCVPixelFormatType_420YpCbCr8BiPlanarFullRange

kCVPixelFormatType_32BGRA

Credit where credit is due, I found a way to get the value supported here. https://gist.github.com/2327666

0
On

I've written this Swift extension that you can add to your project

extension FourCharCode {
   func convertToString() -> String {
        let number: UInt32 = self
        let ostype = number.bigEndian // Assuming big-endian byte order
        let bytes = withUnsafeBytes(of: ostype) {
            Array($0)
        }
        let ostypeString = String(bytes: bytes, encoding: .ascii)
        return ostypeString ?? "error converting FourCharCode to String"
   }
}

Then call it this way

for pixel in videoOutput.availableVideoPixelFormatTypes {                
    print("\(pixel) = ", pixel.convertToString())
}

This will print

2016686642 =  x422
2016686640 =  x420
645428786 =  &xv2
762869298 =  -xv2
645428784 =  &xv0
762869296 =  -xv0

Then you can check the apple documentation do get the matching pixelFormat: https://developer.apple.com/documentation/technotes/tn3121-selecting-a-pixel-format-for-an-avcapturevideodataoutput

enter image description here

ps: I'm using an iPhone 13Pro with iOS 16.2, and an active format compatile with ProRes

0
On

You can convert values returned by availableVideoCVPixelFormatTypes like so:

NSArray *supportedPixelFormats = [videoDeviceOutput availableVideoCVPixelFormatTypes];
char buffer[5] = {0};
for (NSNumber *pixelFormat in supportedPixelFormats){
    *(int *)&buffer[0] = CFSwapInt32HostToBig([pixelFormat intValue]);
    NSLog(@"FORMAT: %s", buffer);
}

and the output will be

FORMAT: 420v
FORMAT: 420f
FORMAT: BGRA

These values correspond to enum values described in CVPixelBuffer.h of CoreVideo:

kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange = '420v'
kCVPixelFormatType_420YpCbCr8BiPlanarFullRange  = '420f',
kCVPixelFormatType_32BGRA         = 'BGRA',

Explanation of the code: The constant value '420v' is stored in memory as 4 bytes. At the same time, int is also 4 bytes, which allows us to convert '420v' into bytes and back into int.

The following line is writing a value as an int into buffer of chars to later read it as string.

*(int *)&buffer[0] = CFSwapInt32HostToBig([pixelFormat intValue]);

The only problem is that normally Objective-C would save an int value as little endian and this would produce 'v024' instead of '420v'. Hence, we need to use CFSwapInt32HostToBig to convert an enum value into big endian before saving it to the buffer.

Hope this helps.

0
On

A category version for debugging

As a category on NSNumber

#import <CoreVideo/CoreVideo.h> 

@implementation NSNumber (CVPixelFormatType)

- (NSString *)descriptivePixelFormat
{
    return @{
             @(kCVPixelFormatType_1Monochrome): @"kCVPixelFormatType_1Monochrome",
             @(kCVPixelFormatType_2Indexed): @"kCVPixelFormatType_2Indexed",
             @(kCVPixelFormatType_4Indexed): @"kCVPixelFormatType_4Indexed",
             @(kCVPixelFormatType_8Indexed): @"kCVPixelFormatType_8Indexed",
             @(kCVPixelFormatType_1IndexedGray_WhiteIsZero): @"kCVPixelFormatType_1IndexedGray_WhiteIsZero",
             @(kCVPixelFormatType_2IndexedGray_WhiteIsZero): @"kCVPixelFormatType_2IndexedGray_WhiteIsZero",
             @(kCVPixelFormatType_4IndexedGray_WhiteIsZero): @"kCVPixelFormatType_4IndexedGray_WhiteIsZero",
             @(kCVPixelFormatType_8IndexedGray_WhiteIsZero): @"kCVPixelFormatType_8IndexedGray_WhiteIsZero",
             @(kCVPixelFormatType_16BE555): @"kCVPixelFormatType_16BE555",
             @(kCVPixelFormatType_16LE555): @"kCVPixelFormatType_16LE555",
             @(kCVPixelFormatType_16LE5551): @"kCVPixelFormatType_16LE5551",
             @(kCVPixelFormatType_16BE565): @"kCVPixelFormatType_16BE565",
             @(kCVPixelFormatType_16LE565): @"kCVPixelFormatType_16LE565",
             @(kCVPixelFormatType_24RGB): @"kCVPixelFormatType_24RGB",
             @(kCVPixelFormatType_24BGR): @"kCVPixelFormatType_24BGR",
             @(kCVPixelFormatType_32ARGB): @"kCVPixelFormatType_32ARGB",
             @(kCVPixelFormatType_32BGRA): @"kCVPixelFormatType_32BGRA",
             @(kCVPixelFormatType_32ABGR): @"kCVPixelFormatType_32ABGR",
             @(kCVPixelFormatType_32RGBA): @"kCVPixelFormatType_32RGBA",
             @(kCVPixelFormatType_64ARGB): @"kCVPixelFormatType_64ARGB",
             @(kCVPixelFormatType_48RGB): @"kCVPixelFormatType_48RGB",
             @(kCVPixelFormatType_32AlphaGray): @"kCVPixelFormatType_32AlphaGray",
             @(kCVPixelFormatType_16Gray): @"kCVPixelFormatType_16Gray",
             @(kCVPixelFormatType_422YpCbCr8): @"kCVPixelFormatType_422YpCbCr8",
             @(kCVPixelFormatType_4444YpCbCrA8): @"kCVPixelFormatType_4444YpCbCrA8",
             @(kCVPixelFormatType_4444YpCbCrA8R): @"kCVPixelFormatType_4444YpCbCrA8R",
             @(kCVPixelFormatType_444YpCbCr8): @"kCVPixelFormatType_444YpCbCr8",
             @(kCVPixelFormatType_422YpCbCr16): @"kCVPixelFormatType_422YpCbCr16",
             @(kCVPixelFormatType_422YpCbCr10): @"kCVPixelFormatType_422YpCbCr10",
             @(kCVPixelFormatType_444YpCbCr10): @"kCVPixelFormatType_444YpCbCr10",
             @(kCVPixelFormatType_420YpCbCr8Planar): @"kCVPixelFormatType_420YpCbCr8Planar",
             @(kCVPixelFormatType_420YpCbCr8PlanarFullRange): @"kCVPixelFormatType_420YpCbCr8PlanarFullRange",
             @(kCVPixelFormatType_422YpCbCr_4A_8BiPlanar): @"kCVPixelFormatType_422YpCbCr_4A_8BiPlanar",
             @(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange): @"kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange",
             @(kCVPixelFormatType_420YpCbCr8BiPlanarFullRange): @"kCVPixelFormatType_420YpCbCr8BiPlanarFullRange",
             @(kCVPixelFormatType_422YpCbCr8_yuvs): @"kCVPixelFormatType_422YpCbCr8_yuvs",
             @(kCVPixelFormatType_422YpCbCr8FullRange): @"kCVPixelFormatType_422YpCbCr8FullRange"
             }[self];
}

@end

Diagnostic output example

NSMutableArray *mutablePixelFormatTypes = [NSMutableArray array];
[captureOutput.availableVideoCVPixelFormatTypes enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    [mutablePixelFormatTypes addObject:[obj descriptivePixelFormat]];
}];
NSString *pixelFormats = [mutablePixelFormatTypes componentsJoinedByString:@",\n"];
NSLog(@"Available pixel formats:\n%@\n", pixelFormats);
0
On

When you call availableVideoCVPixelFormatTypes you get the decimal representation of all of the pixel format type labels. If you convert those to hex you can match some of them to labels listed on Apple's Documentation. For the rest you have to convert the hex value you got into ASCII characters to finally match the label.

For example:

(Decimal) ------> (Hex) ---> (ASCII)

875704438 -> 34323076 -> 420v

875704422 -> 34323066 -> 420f

1111970369 -> 42475241 -> BGRA

I found this site "ASCII to Hex" to be useful.