OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright 2016 The WebRTC project authors. All Rights Reserved. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license | |
5 * that can be found in the LICENSE file in the root of the source | |
6 * tree. An additional intellectual property rights grant can be found | |
7 * in the file PATENTS. All contributing project authors may | |
8 * be found in the AUTHORS file in the root of the source tree. | |
9 */ | |
10 | |
11 #import <Foundation/Foundation.h> | |
12 #import <OCMock/OCMock.h> | |
13 #include "avfoundationformatmapper.h" | |
14 #include "webrtc/base/gunit.h" | |
15 | |
16 static NSString * const kMediaSubtypeKey = @"subtype"; | |
17 static NSString * const kMinFrameRateKey = @"min_framerate"; | |
18 static NSString * const kMaxFrameRateKey = @"max_framerate"; | |
19 | |
20 // Widht and height don't play any role so lets use predefined values troughout | |
magjed_webrtc
2016/11/24 13:42:59
nit: Spelling: Width and throughout
daniela-webrtc
2016/11/25 08:58:15
Done.
| |
21 // the tests. | |
22 static const int kFormatWidth = 789; | |
23 static const int kFormatHeight = 987; | |
24 | |
25 // Hardcoded framrate to be used troughout the tests. | |
magjed_webrtc
2016/11/24 13:42:59
nit: spelling: throughout
daniela-webrtc
2016/11/25 08:58:15
Done.
| |
26 static const int kFramerate = 30; | |
27 | |
28 namespace webrtc { | |
29 NSArray<AVCaptureDeviceFormat*>* GetEligibleDeviceFormats( | |
magjed_webrtc
2016/11/24 13:42:59
Are you testing some implementation helper functio
daniela-webrtc
2016/11/25 08:58:15
Yes it's an implementation helper function. I want
magjed_webrtc
2016/11/28 12:21:23
I see. I'm sorry, but you have to stick to testing
| |
30 const AVCaptureDevice* device, | |
31 int supportedFps); | |
32 AVCaptureDeviceFormat* GetDeviceFormatForVideoFormat( | |
33 const AVCaptureDevice* device, | |
34 const cricket::VideoFormat& videoFormat); | |
35 } | |
36 | |
37 // Mock class for AVCaptureDeviceFormat. | |
38 // Custom implementation needed because OCMock cannot handle the | |
39 // CMVideoDescriptionRef mocking. | |
40 @interface AVCaptureDeviceFormatMock : NSObject { | |
41 CMVideoFormatDescriptionRef _format; | |
42 OCMockObject *_rangeMock; | |
43 } | |
44 | |
45 // The dictionaries are in the following format. | |
46 // @{@"subtype":@(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange), | |
47 // @"min_framerate":@0, | |
48 // @"max_framerate":@30} | |
49 | |
50 - (instancetype)initWithDictionary:(NSDictionary *)mockDataDictionary; | |
51 @end | |
52 | |
53 @implementation AVCaptureDeviceFormatMock | |
54 | |
55 - (instancetype)initWithDictionary:(NSDictionary *)mockDataDictionary { | |
56 if (self = [super init]) { | |
57 NSNumber *subtype = [mockDataDictionary objectForKey:kMediaSubtypeKey]; | |
58 NSNumber *minFramerate = [mockDataDictionary objectForKey:kMinFrameRateKey]; | |
59 NSNumber *maxFramerate = [mockDataDictionary objectForKey:kMaxFrameRateKey]; | |
60 | |
61 | |
62 CMVideoFormatDescriptionCreate(nil, subtype.intValue, kFormatWidth, | |
63 kFormatHeight, nil, &_format); | |
64 // We can use OCMock for the range. | |
65 _rangeMock = [OCMockObject mockForClass:[AVFrameRateRange class]]; | |
66 [[[_rangeMock stub] andReturnValue:@(minFramerate.floatValue)] minFrameRate] ; | |
67 [[[_rangeMock stub] andReturnValue:@(maxFramerate.floatValue)] maxFrameRate] ; | |
68 } | |
69 | |
70 return self; | |
71 } | |
72 | |
73 - (void)dealloc { | |
74 if (_rangeMock != nil) { | |
75 [_rangeMock dealloc]; | |
76 _rangeMock = nil; | |
77 } | |
78 if (_format != nil) { | |
79 CFRelease(_format); | |
80 _format = nil; | |
81 } | |
82 [super dealloc]; | |
83 } | |
84 | |
85 // Redefinition of AVCaptureDevice methods we want to mock. | |
86 - (CMVideoFormatDescriptionRef)formatDescription { | |
87 return _format; | |
88 } | |
89 | |
90 - (NSArray *)videoSupportedFrameRateRanges { | |
91 return @[_rangeMock]; | |
92 } | |
93 | |
94 @end | |
95 | |
96 class AVFormatMapperTest : public ::testing::Test { | |
97 protected: | |
98 void testEligibleWithValidFormats() { | |
99 // given | |
100 id mockDevice = [OCMockObject mockForClass:[AVCaptureDevice class]]; | |
101 | |
102 // Valid media subtype, valid framerate | |
103 AVCaptureDeviceFormatMock* mockOne = | |
104 [[AVCaptureDeviceFormatMock alloc] initWithDictionary:@{ | |
105 kMediaSubtypeKey : @(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange), | |
106 kMinFrameRateKey : @(0), | |
107 kMaxFrameRateKey : @(20) | |
108 }]; | |
109 // Valid media subtype, valid framerate | |
110 AVCaptureDeviceFormatMock* mockTwo = | |
111 [[AVCaptureDeviceFormatMock alloc] initWithDictionary:@{ | |
112 kMediaSubtypeKey : @(kCVPixelFormatType_420YpCbCr8PlanarFullRange), | |
113 kMinFrameRateKey : @(0), | |
114 kMaxFrameRateKey : @(20) | |
115 }]; | |
116 [[[mockDevice stub] andReturn:@[ mockOne, mockTwo ]] formats]; | |
117 | |
118 // when | |
119 NSArray* result = webrtc::GetEligibleDeviceFormats(mockDevice, kFramerate); | |
120 | |
121 // then | |
122 EXPECT_TRUE(result.count == 2); | |
123 } | |
124 | |
125 void testEligibleWithInvalidFramerateFormats() { | |
126 // given | |
127 id mockDevice = [OCMockObject mockForClass:[AVCaptureDevice class]]; | |
128 | |
129 // Valid media subtype, invalid framerate | |
130 AVCaptureDeviceFormatMock* mockOne = | |
131 [[AVCaptureDeviceFormatMock alloc] initWithDictionary:@{ | |
132 kMediaSubtypeKey : @(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange), | |
133 kMinFrameRateKey : @(0), | |
134 kMaxFrameRateKey : @(35) | |
135 }]; | |
136 | |
137 // Valid media subtype, valid framerate | |
138 AVCaptureDeviceFormatMock* mockTwo = | |
139 [[AVCaptureDeviceFormatMock alloc] initWithDictionary:@{ | |
140 kMediaSubtypeKey : @(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange), | |
141 kMinFrameRateKey : @(0), | |
142 kMaxFrameRateKey : @(30) | |
143 }]; | |
144 | |
145 [[[mockDevice stub] andReturn:@[ mockOne, mockTwo ]] formats]; | |
146 | |
147 // when | |
148 NSArray* result = webrtc::GetEligibleDeviceFormats(mockDevice, kFramerate); | |
149 | |
150 // then | |
151 EXPECT_TRUE(result.count == 1); | |
152 EXPECT_TRUE([result[0] isEqual:mockTwo]); | |
153 } | |
154 | |
155 void testEligibleWithInvalidFormats() { | |
156 // given | |
157 id mockDevice = [OCMockObject mockForClass:[AVCaptureDevice class]]; | |
158 | |
159 // Invalid media subtype, valid framerate | |
160 AVCaptureDeviceFormatMock* mockOne = | |
161 [[AVCaptureDeviceFormatMock alloc] initWithDictionary:@{ | |
162 kMediaSubtypeKey : @(kCVPixelFormatType_420YpCbCr8Planar), | |
163 kMinFrameRateKey : @(0), | |
164 kMaxFrameRateKey : @(20) | |
165 }]; | |
166 | |
167 // Valid media subtype, valid framerate | |
168 AVCaptureDeviceFormatMock* mockTwo = | |
169 [[AVCaptureDeviceFormatMock alloc] initWithDictionary:@{ | |
170 kMediaSubtypeKey : @(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange), | |
171 kMinFrameRateKey : @(0), | |
172 kMaxFrameRateKey : @(20) | |
173 }]; | |
174 | |
175 [[[mockDevice stub] andReturn:@[ mockOne, mockTwo ]] formats]; | |
176 | |
177 // when | |
178 NSArray* result = webrtc::GetEligibleDeviceFormats(mockDevice, kFramerate); | |
179 | |
180 // then | |
181 EXPECT_TRUE(result.count == 1); | |
182 EXPECT_TRUE([result[0] isEqual:mockTwo]); | |
183 } | |
184 | |
185 void testSuportedCricketFormats() { | |
186 // given | |
187 id mockDevice = [OCMockObject mockForClass:[AVCaptureDevice class]]; | |
188 | |
189 // valid media subtype, valid framerate | |
190 AVCaptureDeviceFormatMock* mockOne = | |
191 [[AVCaptureDeviceFormatMock alloc] initWithDictionary:@{ | |
192 kMediaSubtypeKey : @(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange), | |
193 kMinFrameRateKey : @(0), | |
194 kMaxFrameRateKey : @(20) | |
195 }]; | |
196 | |
197 [[[mockDevice stub] andReturn:@[ mockOne ]] formats]; | |
198 | |
199 cricket::VideoFormat expectedFormat = cricket::VideoFormat( | |
200 kFormatWidth, kFormatHeight, | |
201 cricket::VideoFormat::FpsToInterval(kFramerate), cricket::FOURCC_NV12); | |
202 | |
203 // when | |
204 std::set<cricket::VideoFormat> result = | |
205 webrtc::GetSupportedVideoFormatsForDevice(mockDevice); | |
206 | |
207 // then | |
208 EXPECT_EQ(result.size(), 1); | |
209 | |
210 // make sure the set has the expected format | |
211 auto it = result.find(expectedFormat); | |
212 EXPECT_TRUE(it != result.end()); | |
213 } | |
214 | |
215 void testAVFormatForCricketFormat() { | |
216 // given | |
217 id mockDevice = [OCMockObject mockForClass:[AVCaptureDevice class]]; | |
218 | |
219 // valid media subtype, valid framerate | |
220 AVCaptureDeviceFormatMock* mockOne = | |
221 [[AVCaptureDeviceFormatMock alloc] initWithDictionary:@{ | |
222 kMediaSubtypeKey : @(kCVPixelFormatType_420YpCbCr8PlanarFullRange), | |
223 kMinFrameRateKey : @(0), | |
224 kMaxFrameRateKey : @(20) | |
225 }]; | |
226 | |
227 // valid media subtype, valid framerate. | |
228 // This media subtype should be the preffered one. | |
229 AVCaptureDeviceFormatMock* mockTwo = | |
230 [[AVCaptureDeviceFormatMock alloc] initWithDictionary:@{ | |
231 kMediaSubtypeKey : @(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange), | |
232 kMinFrameRateKey : @(0), | |
233 kMaxFrameRateKey : @(20) | |
234 }]; | |
235 | |
236 [[[mockDevice stub] andReturn:@[ mockOne, mockTwo ]] formats]; | |
237 | |
238 cricket::VideoFormat inputFormat = cricket::VideoFormat( | |
239 kFormatWidth, kFormatHeight, | |
240 cricket::VideoFormat::FpsToInterval(kFramerate), cricket::FOURCC_NV12); | |
241 | |
242 // when | |
243 id resultFormat = | |
244 webrtc::GetDeviceFormatForVideoFormat(mockDevice, inputFormat); | |
245 | |
246 // then | |
247 EXPECT_TRUE([resultFormat isEqual:mockTwo]); | |
248 } | |
249 | |
250 void testSetFormatWhenDeviceCannotLock() { | |
251 // given | |
252 id mockDevice = [OCMockObject mockForClass:[AVCaptureDevice class]]; | |
253 [[[mockDevice stub] andReturnValue:@(NO)] | |
254 lockForConfiguration:[OCMArg setTo:nil]]; | |
255 | |
256 [[[mockDevice stub] andReturn:@[]] formats]; | |
257 | |
258 // when | |
259 bool resultFormat = webrtc::SetFormatForCaptureDevice( | |
260 mockDevice, nil, cricket::VideoFormat()); | |
261 | |
262 // then | |
263 EXPECT_FALSE(resultFormat); | |
264 } | |
265 | |
266 void testSetFormatWhenFormatIsIncompatible() { | |
267 // given | |
268 id mockDevice = [OCMockObject mockForClass:[AVCaptureDevice class]]; | |
269 [[[mockDevice stub] andReturn:@[]] formats]; | |
270 [[[mockDevice stub] andReturnValue:@(YES)] | |
271 lockForConfiguration:[OCMArg setTo:nil]]; | |
272 | |
273 NSException* exception = | |
274 [NSException exceptionWithName:@"Test exception" | |
275 reason:@"Raised from unit tests" | |
276 userInfo:nil]; | |
277 [[[mockDevice stub] andThrow:exception] setActiveFormat:[OCMArg any]]; | |
278 [[mockDevice expect] unlockForConfiguration]; | |
279 | |
280 // when | |
281 bool resultFormat = webrtc::SetFormatForCaptureDevice( | |
282 mockDevice, nil, cricket::VideoFormat()); | |
283 | |
284 // then | |
285 EXPECT_FALSE(resultFormat); | |
286 [mockDevice verify]; | |
287 } | |
288 }; | |
289 | |
290 TEST_F(AVFormatMapperTest, EligibleFormatsPerDeviceWithValidFormats) { | |
291 testEligibleWithValidFormats(); | |
292 } | |
293 | |
294 TEST_F(AVFormatMapperTest, | |
295 EligibleFormatsPerDeviceWithInvalidFramerateFormats) { | |
296 testEligibleWithInvalidFramerateFormats(); | |
297 } | |
298 | |
299 TEST_F(AVFormatMapperTest, EligibleFormatsPerDeviceWithInvalidFormats) { | |
300 testEligibleWithInvalidFormats(); | |
301 } | |
302 | |
303 TEST_F(AVFormatMapperTest, SuportedCricketFormats) { | |
304 testSuportedCricketFormats(); | |
305 } | |
306 | |
307 TEST_F(AVFormatMapperTest, AVFormatForCricketFormat) { | |
308 testAVFormatForCricketFormat(); | |
309 } | |
310 | |
311 TEST_F(AVFormatMapperTest, SetFormatWhenDeviceCannotLock) { | |
312 testSetFormatWhenDeviceCannotLock(); | |
313 } | |
314 | |
315 TEST_F(AVFormatMapperTest, SetFormatWhenFormatIsIncompatible) { | |
316 testSetFormatWhenFormatIsIncompatible(); | |
317 } | |
OLD | NEW |