Khaled Barazi
Khaled Barazi

Reputation: 8741

Getting actual NSString of AvCaptureVideoDataOutput availableVideoCVPixelFormatTypes

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

Upvotes: 11

Views: 3946

Answers (5)

Arkader
Arkader

Reputation: 138

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

Upvotes: 1

RAllen
RAllen

Reputation: 1523

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.

Upvotes: 1

Bill22
Bill22

Reputation: 51

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.

Upvotes: 5

Cameron Lowell Palmer
Cameron Lowell Palmer

Reputation: 22245

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);

Upvotes: 5

Khaled Barazi
Khaled Barazi

Reputation: 8741

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

Upvotes: 10

Related Questions