19#include "capture_policy.h"
20#include "frame_rate.h"
22@interface FreeRDPCameraAVFoundationMode : NSObject
24@property(nonatomic, retain) AVCaptureDeviceFormat *format;
25@property(nonatomic) CMTime frameDuration;
28@implementation FreeRDPCameraAVFoundationMode
41 return [NSString stringWithFormat:@"%u:%u:%u:%u:%u:%u:%u", type->Format, type->Width,
42 type->Height, type->FrameRateNumerator,
43 type->FrameRateDenominator, type->PixelAspectRatioNumerator,
44 type->PixelAspectRatioDenominator];
50 NSArray<FreeRDPCameraAVFoundationMode *> *_entries;
51 NSDictionary<NSString *, FreeRDPCameraAVFoundationMode *> *_lookup;
54- (instancetype)initWithFormats:(NSArray<AVCaptureDeviceFormat *> *)formats
59 NSMutableArray<FreeRDPCameraAVFoundationMode *> *entries = [NSMutableArray array];
60 NSMutableDictionary<NSString *, FreeRDPCameraAVFoundationMode *> *lookup =
61 [NSMutableDictionary dictionary];
62 for (AVCaptureDeviceFormat *format in formats)
64 const CMVideoDimensions size =
65 CMVideoFormatDescriptionGetDimensions(format.formatDescription);
66 if ((size.width < CAM_AVFOUNDATION_MIN_WIDTH) ||
67 (size.height < CAM_AVFOUNDATION_MIN_HEIGHT) ||
68 (size.width > CAM_AVFOUNDATION_MAX_WIDTH) ||
69 (size.height > CAM_AVFOUNDATION_MAX_HEIGHT) || (size.width % 2) || (size.height % 2))
71 const UINT32 rates[] = CAM_AVFOUNDATION_FRAME_RATES;
72 for (
size_t r = 0; r < ARRAYSIZE(rates); r++)
74 CMTime duration = kCMTimeInvalid;
75 for (AVFrameRateRange *range in format.videoSupportedFrameRateRanges)
77 if (cam_avfoundation_frame_duration(rates[r], 1, range.minFrameDuration,
78 range.maxFrameDuration, &duration))
82 CAM_MEDIA_FORMAT_NV12, (UINT32)size.width, (UINT32)size.height, 0, 0, 1, 1, 0
84 if (!cam_avfoundation_frame_rate(duration, &type.FrameRateNumerator,
85 &type.FrameRateDenominator))
87 NSString *key = cam_avfoundation_mode_key(&type);
88 if (lookup[key] || (entries.count >= ECAM_MAX_MEDIA_TYPE_DESCRIPTORS))
90 FreeRDPCameraAVFoundationMode *entry = [[FreeRDPCameraAVFoundationMode alloc] init];
96 entry.mediaType = type;
97 entry.format = format;
99 entry.frameDuration = duration;
100 [entries addObject:entry];
105 _entries = [entries copy];
106 _lookup = [lookup copy];
107 if (!_entries || !_lookup)
117 WINPR_ASSERT(mediaTypes);
119 for (FreeRDPCameraAVFoundationMode *entry in _entries)
121 if (count >= capacity)
123 mediaTypes[count++] = entry.mediaType;
129 frameDuration:(CMTime *)frameDuration
131 WINPR_ASSERT(frameDuration);
132 FreeRDPCameraAVFoundationMode *entry = _lookup[cam_avfoundation_mode_key(mediaType)];
133 *frameDuration = entry ? entry.frameDuration : kCMTimeInvalid;