Search code examples
iosswiftcameraavfoundationavcapturedevice

Set AVCaptureDevice format range


I am able to query and find formats for slo-mo at 240FPS. There are two, with 420v and 420f each, at Full HD (correct me if I'm wrong that they only differ in the pixel value range). I was wondering if I could distinguish them at runtime.

print(format.formatDescription.mediaSubType) // this prints "420v" and "420f" each

This does not work, however:

    // always false
if format.formatDescription.mediaSubType == .init(string: "420f") {
    // ...
}

A workaround I have been adapting is to rely on the for-loop to always find v first then f for my device, but I am not sure if this is guaranteed for all devices.


Here are some of discovered slow motion formats on this iPad: (other slo-mo formats are for 1280x720 dimension, etc.)

<AVCaptureDeviceFormat: 0x280b58ec0 'vide'/'420v' 1920x1080, { 2-240 fps}, fov:64.717, binned, supports vis, max zoom:67.50 (upscales @1.00), AF System:1, ISO:18.0-720.0, SS:0.000016-0.500000> <CMVideoFormatDescription 0x2807d95c0 [0x1ff615860]> {
    mediaType:'vide' 
    mediaSubType:'420v' 
    mediaSpecific: {
        codecType: '420v'       dimensions: 1920 x 1080 
    } 
    extensions: {(null)}
}
<AVCaptureDeviceFormat: 0x280b58eb0 'vide'/'420f' 1920x1080, { 2-240 fps}, fov:64.717, binned, supports vis, max zoom:67.50 (upscales @1.00), AF System:1, ISO:18.0-720.0, SS:0.000016-0.500000, supports wide color> <CMVideoFormatDescription 0x280731770 [0x1ff615860]> {
    mediaType:'vide' 
    mediaSubType:'420f' 
    mediaSpecific: {
        codecType: '420f'       dimensions: 1920 x 1080 
    } 
    extensions: {(null)}
}

Solution

  • There are already some pixel type constants defined on MediaSubType, like CMFormatDescription.MediaSubType.pixelFormat_422YpCbCr8_yuvs, but sadly no 4:2:0 variants.

    You can symbolically check for 420f and 420v with

    format.formatDescription.mediaSubType == .init(rawValue: kCVPixelFormatType_420YpCbCr8BiPlanarFullRange)
    

    and

    format.formatDescription.mediaSubType == .init(rawValue: kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange)
    

    The strange thing is your .init(string:"420f") works for me.