22@interface TestAVFoundationRange : NSObject
23@property(nonatomic) CMTime minFrameDuration;
24@property(nonatomic) CMTime maxFrameDuration;
26@implementation TestAVFoundationRange
29static unsigned liveFormats = 0;
31@interface TestAVFoundationFormat : NSObject
32@property(nonatomic) CMVideoFormatDescriptionRef formatDescription;
33@property(nonatomic, copy) NSArray *videoSupportedFrameRateRanges;
35@implementation TestAVFoundationFormat
46 if (_formatDescription)
47 CFRelease(_formatDescription);
48 [_videoSupportedFrameRateRanges release];
53static TestAVFoundationRange *test_range(CMTime duration)
55 TestAVFoundationRange *range = [[[TestAVFoundationRange alloc] init] autorelease];
56 range.minFrameDuration = duration;
57 range.maxFrameDuration = duration;
61static AVCaptureDeviceFormat *test_format(
int width,
int height, NSArray *ranges)
63 TestAVFoundationFormat *format = [[[TestAVFoundationFormat alloc] init] autorelease];
64 CMVideoFormatDescriptionRef description = NULL;
65 if (CMVideoFormatDescriptionCreate(NULL, kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange, width,
66 height, NULL, &description) != noErr)
68 format.formatDescription = description;
69 format.videoSupportedFrameRateRanges = ranges;
70 return (AVCaptureDeviceFormat *)format;
73static BOOL test_modes(
void)
77 AVCaptureDeviceFormat *original = nil;
78 const CMTime native30 = CMTimeMake(1000000, 30000030);
79 const CMTime native15 = CMTimeMake(1000000, 15000015);
80 const CMTime unusual30 = CMTimeMake(33333333, 1000000000);
81 const CMTime nearby30 = CMTimeMake(1000000, 30000060);
86 NSArray *rates = @[test_range(native30), test_range(native15)];
87 original = test_format(640, 480, rates);
88 AVCaptureDeviceFormat *duplicate = test_format(640, 480, rates);
89 AVCaptureDeviceFormat *unusual = test_format(854, 480, @[test_range(unusual30)]);
90 AVCaptureDeviceFormat *nearby = test_format(640, 480, @[test_range(nearby30)]);
91 AVCaptureDeviceFormat *odd = test_format(641, 480, rates);
92 AVCaptureDeviceFormat *oversized = test_format(3840, 2160, rates);
93 if (!original || !duplicate || !unusual || !nearby || !odd || !oversized)
95 NSMutableArray *formats =
96 [NSMutableArray arrayWithArray:@[original, duplicate, unusual, nearby, odd, oversized]];
100 count = [modes copyMediaTypes:types capacity:ARRAYSIZE(types)];
102 [formats removeObjectAtIndex:0];
103 [(TestAVFoundationFormat *)original setVideoSupportedFrameRateRanges:@[]];
106 if ((count != 4) || (liveFormats != 3) || (types[0].Width != 640) || (types[0].Height != 480) ||
107 (types[0].FrameRateNumerator != 3000003) || (types[0].FrameRateDenominator != 100000) ||
108 (types[1].FrameRateDenominator != 200000) || (types[2].Width != 854) ||
109 (types[2].FrameRateNumerator != 1000000000) ||
110 (types[2].FrameRateDenominator != 33333333) || (types[3].FrameRateNumerator != 1500003) ||
111 (types[3].FrameRateDenominator != 50000))
113 fprintf(stderr,
"Native mode enumeration, deduplication or retention failed\n");
116 const CMTime durations[] = { native30, native15, unusual30, nearby30 };
117 for (
size_t i = 0; i < count; i++)
119 CMTime actual = kCMTimeInvalid;
120 AVCaptureDeviceFormat *format = [modes formatForMediaType:&types[i] frameDuration:&actual];
121 if (!format || ((i < 2) && (format != original)) || (actual.value != durations[i].value) ||
122 (actual.timescale != durations[i].timescale) || (actual.flags != durations[i].flags) ||
123 (actual.epoch != durations[i].epoch))
125 fprintf(stderr,
"Cached native format/duration changed for mode %zu\n", i);
131 if (([modes copyMediaTypes:again capacity:ARRAYSIZE(again)] != count) ||
132 (memcmp(types, again, count * sizeof(types[0])) != 0) ||
133 ([modes copyMediaTypes:again capacity:0] != 0) ||
134 ([modes copyMediaTypes:again capacity:1] != 1) ||
135 (memcmp(types, again, sizeof(types[0])) != 0))
137 fprintf(stderr,
"Advertised mode snapshot changed\n");
141 CMTime duration = kCMTimeInvalid;
142 request.Flags = CAM_MEDIA_TYPE_DESCRIPTION_FLAG_DecodingRequired;
143 if ([modes formatForMediaType:&request frameDuration:&duration] != original)
145 fprintf(stderr,
"Shared encoder flags changed native mode lookup\n");
149 for (
size_t i = 0; i < 5; i++)
155 request.FrameRateNumerator = 30;
156 request.FrameRateDenominator = 1;
165 request.PixelAspectRatioNumerator = 2;
168 request.Format = CAM_MEDIA_FORMAT_H264;
171 if ([modes formatForMediaType:&request frameDuration:&duration] ||
172 CMTIME_IS_VALID(duration))
174 fprintf(stderr,
"Unadvertised mode accepted in case %zu\n", i);
181 if (liveFormats != 0)
183 fprintf(stderr,
"Cached native formats were not released\n");
189int main(
int argc,
char *argv[])
195 return test_modes() ? 0 : -1;