Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(293)

Side by Side Diff: webrtc/modules/video_capture/objc/rtc_video_capture_objc.mm

Issue 2375273004: Reland of Unify the macOS and iOS capturer implementations (Closed)
Patch Set: fix gyp build Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #if !defined(__has_feature) || !__has_feature(objc_arc) 11 #if !defined(__has_feature) || !__has_feature(objc_arc)
12 #error "This file requires ARC support." 12 #error "This file requires ARC support."
13 #endif 13 #endif
14 14
15 #import <AVFoundation/AVFoundation.h>
16 #ifdef WEBRTC_IOS
15 #import <UIKit/UIKit.h> 17 #import <UIKit/UIKit.h>
18 #endif
16 19
17 #import "webrtc/modules/video_capture/ios/device_info_ios_objc.h" 20 #import "webrtc/modules/video_capture/objc/device_info_objc.h"
18 #import "webrtc/modules/video_capture/ios/rtc_video_capture_ios_objc.h" 21 #import "webrtc/modules/video_capture/objc/rtc_video_capture_objc.h"
19 22
20 #include "webrtc/system_wrappers/include/trace.h" 23 #include "webrtc/system_wrappers/include/trace.h"
21 24
22 using namespace webrtc; 25 using namespace webrtc;
23 using namespace webrtc::videocapturemodule; 26 using namespace webrtc::videocapturemodule;
24 27
25 @interface RTCVideoCaptureIosObjC (hidden) 28 @interface RTCVideoCaptureIosObjC (hidden)
26 - (int)changeCaptureInputWithName:(NSString*)captureDeviceName; 29 - (int)changeCaptureInputWithName:(NSString*)captureDeviceName;
27 @end 30 @end
28 31
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
65 NSNumber* val = [NSNumber 68 NSNumber* val = [NSNumber
66 numberWithUnsignedInt:kCVPixelFormatType_420YpCbCr8BiPlanarFullRange]; 69 numberWithUnsignedInt:kCVPixelFormatType_420YpCbCr8BiPlanarFullRange];
67 NSDictionary* videoSettings = 70 NSDictionary* videoSettings =
68 [NSDictionary dictionaryWithObject:val forKey:key]; 71 [NSDictionary dictionaryWithObject:val forKey:key];
69 captureOutput.videoSettings = videoSettings; 72 captureOutput.videoSettings = videoSettings;
70 73
71 // add new output 74 // add new output
72 if ([_captureSession canAddOutput:captureOutput]) { 75 if ([_captureSession canAddOutput:captureOutput]) {
73 [_captureSession addOutput:captureOutput]; 76 [_captureSession addOutput:captureOutput];
74 } else { 77 } else {
75 WEBRTC_TRACE(kTraceError, 78 WEBRTC_TRACE(kTraceError, kTraceVideoCapture, _captureId,
76 kTraceVideoCapture,
77 _captureId,
78 "%s:%s:%d Could not add output to AVCaptureSession ", 79 "%s:%s:%d Could not add output to AVCaptureSession ",
79 __FILE__, 80 __FILE__, __FUNCTION__, __LINE__);
80 __FUNCTION__,
81 __LINE__);
82 } 81 }
83 82
83 #ifdef WEBRTC_IOS
84 [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; 84 [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
85 85
86 NSNotificationCenter* notify = [NSNotificationCenter defaultCenter]; 86 NSNotificationCenter* notify = [NSNotificationCenter defaultCenter];
87 [notify addObserver:self 87 [notify addObserver:self
88 selector:@selector(onVideoError:) 88 selector:@selector(onVideoError:)
89 name:AVCaptureSessionRuntimeErrorNotification 89 name:AVCaptureSessionRuntimeErrorNotification
90 object:_captureSession]; 90 object:_captureSession];
91 [notify addObserver:self 91 [notify addObserver:self
92 selector:@selector(deviceOrientationDidChange:) 92 selector:@selector(deviceOrientationDidChange:)
93 name:UIDeviceOrientationDidChangeNotification 93 name:UIDeviceOrientationDidChangeNotification
94 object:nil]; 94 object:nil];
95 #endif
95 } 96 }
96 97
97 return self; 98 return self;
98 } 99 }
99 100
100 - (void)directOutputToSelf { 101 - (void)directOutputToSelf {
101 [[self currentOutput] 102 [[self currentOutput]
102 setSampleBufferDelegate:self 103 setSampleBufferDelegate:self
103 queue:dispatch_get_global_queue( 104 queue:dispatch_get_global_queue(
104 DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)]; 105 DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)];
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
137 [self waitForCaptureChangeToFinish]; 138 [self waitForCaptureChangeToFinish];
138 if (!_captureSession) { 139 if (!_captureSession) {
139 return NO; 140 return NO;
140 } 141 }
141 142
142 // check limits of the resolution 143 // check limits of the resolution
143 if (capability.maxFPS < 0 || capability.maxFPS > 60) { 144 if (capability.maxFPS < 0 || capability.maxFPS > 60) {
144 return NO; 145 return NO;
145 } 146 }
146 147
147 if ([_captureSession canSetSessionPreset:AVCaptureSessionPreset1920x1080]) { 148 if ([_captureSession canSetSessionPreset:AVCaptureSessionPreset1280x720]) {
148 if (capability.width > 1920 || capability.height > 1080) {
149 return NO;
150 }
151 } else if ([_captureSession
152 canSetSessionPreset:AVCaptureSessionPreset1280x720]) {
153 if (capability.width > 1280 || capability.height > 720) { 149 if (capability.width > 1280 || capability.height > 720) {
154 return NO; 150 return NO;
155 } 151 }
156 } else if ([_captureSession 152 } else if ([_captureSession
157 canSetSessionPreset:AVCaptureSessionPreset640x480]) { 153 canSetSessionPreset:AVCaptureSessionPreset640x480]) {
158 if (capability.width > 640 || capability.height > 480) { 154 if (capability.width > 640 || capability.height > 480) {
159 return NO; 155 return NO;
160 } 156 }
161 } else if ([_captureSession 157 } else if ([_captureSession
162 canSetSessionPreset:AVCaptureSessionPreset352x288]) { 158 canSetSessionPreset:AVCaptureSessionPreset352x288]) {
163 if (capability.width > 352 || capability.height > 288) { 159 if (capability.width > 352 || capability.height > 288) {
164 return NO; 160 return NO;
165 } 161 }
166 } else if (capability.width < 0 || capability.height < 0) { 162 } else if (capability.width < 0 || capability.height < 0) {
167 return NO; 163 return NO;
168 } 164 }
169 165
170 _capability = capability; 166 _capability = capability;
171 167
172 AVCaptureVideoDataOutput* currentOutput = [self currentOutput]; 168 AVCaptureVideoDataOutput* currentOutput = [self currentOutput];
173 if (!currentOutput) 169 if (!currentOutput)
174 return NO; 170 return NO;
175 171
176 [self directOutputToSelf]; 172 [self directOutputToSelf];
177 173
178 _orientationHasChanged = NO; 174 _orientationHasChanged = NO;
179 _captureChanging = YES; 175 _captureChanging = YES;
180 dispatch_async( 176 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
181 dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), 177 ^{
182 ^(void) { [self startCaptureInBackgroundWithOutput:currentOutput]; }); 178 [self startCaptureInBackgroundWithOutput:currentOutput];
179 });
183 return YES; 180 return YES;
184 } 181 }
185 182
186 - (AVCaptureVideoDataOutput*)currentOutput { 183 - (AVCaptureVideoDataOutput*)currentOutput {
187 return [[_captureSession outputs] firstObject]; 184 return [[_captureSession outputs] firstObject];
188 } 185 }
189 186
190 - (void)startCaptureInBackgroundWithOutput: 187 - (void)startCaptureInBackgroundWithOutput:
191 (AVCaptureVideoDataOutput*)currentOutput { 188 (AVCaptureVideoDataOutput*)currentOutput {
192 NSString* captureQuality = 189 NSString* captureQuality =
193 [NSString stringWithString:AVCaptureSessionPresetLow]; 190 [NSString stringWithString:AVCaptureSessionPresetLow];
194 if (_capability.width >= 1920 || _capability.height >= 1080) { 191 if (_capability.width >= 1280 || _capability.height >= 720) {
195 captureQuality =
196 [NSString stringWithString:AVCaptureSessionPreset1920x1080];
197 } else if (_capability.width >= 1280 || _capability.height >= 720) {
198 captureQuality = [NSString stringWithString:AVCaptureSessionPreset1280x720]; 192 captureQuality = [NSString stringWithString:AVCaptureSessionPreset1280x720];
199 } else if (_capability.width >= 640 || _capability.height >= 480) { 193 } else if (_capability.width >= 640 || _capability.height >= 480) {
200 captureQuality = [NSString stringWithString:AVCaptureSessionPreset640x480]; 194 captureQuality = [NSString stringWithString:AVCaptureSessionPreset640x480];
201 } else if (_capability.width >= 352 || _capability.height >= 288) { 195 } else if (_capability.width >= 352 || _capability.height >= 288) {
202 captureQuality = [NSString stringWithString:AVCaptureSessionPreset352x288]; 196 captureQuality = [NSString stringWithString:AVCaptureSessionPreset352x288];
203 } 197 }
204 198
205 // begin configuration for the AVCaptureSession 199 // begin configuration for the AVCaptureSession
206 [_captureSession beginConfiguration]; 200 [_captureSession beginConfiguration];
207 201
208 // picture resolution 202 // picture resolution
209 [_captureSession setSessionPreset:captureQuality]; 203 [_captureSession setSessionPreset:captureQuality];
210 204
211 // take care of capture framerate now
212 NSArray* sessionInputs = _captureSession.inputs;
213 AVCaptureDeviceInput* deviceInput = [sessionInputs count] > 0 ?
214 sessionInputs[0] : nil;
215 AVCaptureDevice* inputDevice = deviceInput.device;
216 if (inputDevice) {
217 AVCaptureDeviceFormat* activeFormat = inputDevice.activeFormat;
218 NSArray* supportedRanges = activeFormat.videoSupportedFrameRateRanges;
219 AVFrameRateRange* targetRange = [supportedRanges count] > 0 ?
220 supportedRanges[0] : nil;
221 // Find the largest supported framerate less than capability maxFPS.
222 for (AVFrameRateRange* range in supportedRanges) {
223 if (range.maxFrameRate <= _capability.maxFPS &&
224 targetRange.maxFrameRate <= range.maxFrameRate) {
225 targetRange = range;
226 }
227 }
228 if (targetRange && [inputDevice lockForConfiguration:NULL]) {
229 inputDevice.activeVideoMinFrameDuration = targetRange.minFrameDuration;
230 inputDevice.activeVideoMaxFrameDuration = targetRange.minFrameDuration;
231 [inputDevice unlockForConfiguration];
232 }
233 }
234
235 _connection = [currentOutput connectionWithMediaType:AVMediaTypeVideo]; 205 _connection = [currentOutput connectionWithMediaType:AVMediaTypeVideo];
236 [self setRelativeVideoOrientation]; 206 [self setRelativeVideoOrientation];
237 207
238 // finished configuring, commit settings to AVCaptureSession. 208 // finished configuring, commit settings to AVCaptureSession.
239 [_captureSession commitConfiguration]; 209 [_captureSession commitConfiguration];
240 210
241 [_captureSession startRunning]; 211 [_captureSession startRunning];
242 [self signalCaptureChangeEnd]; 212 [self signalCaptureChangeEnd];
243 } 213 }
244 214
245 - (void)setRelativeVideoOrientation { 215 - (void)setRelativeVideoOrientation {
246 if (!_connection.supportsVideoOrientation) { 216 if (!_connection.supportsVideoOrientation) {
247 return; 217 return;
248 } 218 }
249 219 #ifndef WEBRTC_IOS
220 _connection.videoOrientation = AVCaptureVideoOrientationLandscapeRight;
221 return;
222 #else
250 switch ([UIDevice currentDevice].orientation) { 223 switch ([UIDevice currentDevice].orientation) {
251 case UIDeviceOrientationPortrait: 224 case UIDeviceOrientationPortrait:
252 _connection.videoOrientation = 225 _connection.videoOrientation = AVCaptureVideoOrientationPortrait;
253 AVCaptureVideoOrientationPortrait;
254 break; 226 break;
255 case UIDeviceOrientationPortraitUpsideDown: 227 case UIDeviceOrientationPortraitUpsideDown:
256 _connection.videoOrientation = 228 _connection.videoOrientation =
257 AVCaptureVideoOrientationPortraitUpsideDown; 229 AVCaptureVideoOrientationPortraitUpsideDown;
258 break; 230 break;
259 case UIDeviceOrientationLandscapeLeft: 231 case UIDeviceOrientationLandscapeLeft:
260 _connection.videoOrientation = 232 _connection.videoOrientation = AVCaptureVideoOrientationLandscapeRight;
261 AVCaptureVideoOrientationLandscapeRight;
262 break; 233 break;
263 case UIDeviceOrientationLandscapeRight: 234 case UIDeviceOrientationLandscapeRight:
264 _connection.videoOrientation = 235 _connection.videoOrientation = AVCaptureVideoOrientationLandscapeLeft;
265 AVCaptureVideoOrientationLandscapeLeft;
266 break; 236 break;
267 case UIDeviceOrientationFaceUp: 237 case UIDeviceOrientationFaceUp:
268 case UIDeviceOrientationFaceDown: 238 case UIDeviceOrientationFaceDown:
269 case UIDeviceOrientationUnknown: 239 case UIDeviceOrientationUnknown:
270 if (!_orientationHasChanged) { 240 if (!_orientationHasChanged) {
271 _connection.videoOrientation = 241 _connection.videoOrientation = AVCaptureVideoOrientationPortrait;
272 AVCaptureVideoOrientationPortrait;
273 } 242 }
274 break; 243 break;
275 } 244 }
245 #endif
276 } 246 }
277 247
278 - (void)onVideoError:(NSNotification*)notification { 248 - (void)onVideoError:(NSNotification*)notification {
279 NSLog(@"onVideoError: %@", notification); 249 NSLog(@"onVideoError: %@", notification);
280 // TODO(sjlee): make the specific error handling with this notification. 250 // TODO(sjlee): make the specific error handling with this notification.
281 WEBRTC_TRACE(kTraceError, 251 WEBRTC_TRACE(kTraceError, kTraceVideoCapture, _captureId,
282 kTraceVideoCapture, 252 "%s:%s:%d [AVCaptureSession startRunning] error.", __FILE__,
283 _captureId, 253 __FUNCTION__, __LINE__);
284 "%s:%s:%d [AVCaptureSession startRunning] error.",
285 __FILE__,
286 __FUNCTION__,
287 __LINE__);
288 } 254 }
289 255
290 - (BOOL)stopCapture { 256 - (BOOL)stopCapture {
257 #ifdef WEBRTC_IOS
291 [[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications]; 258 [[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
259 #endif
292 _orientationHasChanged = NO; 260 _orientationHasChanged = NO;
293 [self waitForCaptureChangeToFinish]; 261 [self waitForCaptureChangeToFinish];
294 [self directOutputToNil]; 262 [self directOutputToNil];
295 263
296 if (!_captureSession) { 264 if (!_captureSession) {
297 return NO; 265 return NO;
298 } 266 }
299 267
300 _captureChanging = YES; 268 _captureChanging = YES;
301 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), 269 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
302 ^(void) { [self stopCaptureInBackground]; }); 270 ^(void) {
271 [self stopCaptureInBackground];
272 });
303 return YES; 273 return YES;
304 } 274 }
305 275
306 - (void)stopCaptureInBackground { 276 - (void)stopCaptureInBackground {
307 [_captureSession stopRunning]; 277 [_captureSession stopRunning];
308 [self signalCaptureChangeEnd]; 278 [self signalCaptureChangeEnd];
309 } 279 }
310 280
311 - (BOOL)changeCaptureInputByUniqueId:(NSString*)uniqueId { 281 - (BOOL)changeCaptureInputByUniqueId:(NSString*)uniqueId {
312 [self waitForCaptureChangeToFinish]; 282 [self waitForCaptureChangeToFinish];
(...skipping 22 matching lines...) Expand all
335 305
336 // now create capture session input out of AVCaptureDevice 306 // now create capture session input out of AVCaptureDevice
337 NSError* deviceError = nil; 307 NSError* deviceError = nil;
338 AVCaptureDeviceInput* newCaptureInput = 308 AVCaptureDeviceInput* newCaptureInput =
339 [AVCaptureDeviceInput deviceInputWithDevice:captureDevice 309 [AVCaptureDeviceInput deviceInputWithDevice:captureDevice
340 error:&deviceError]; 310 error:&deviceError];
341 311
342 if (!newCaptureInput) { 312 if (!newCaptureInput) {
343 const char* errorMessage = [[deviceError localizedDescription] UTF8String]; 313 const char* errorMessage = [[deviceError localizedDescription] UTF8String];
344 314
345 WEBRTC_TRACE(kTraceError, 315 WEBRTC_TRACE(kTraceError, kTraceVideoCapture, _captureId,
346 kTraceVideoCapture, 316 "%s:%s:%d deviceInputWithDevice error:%s", __FILE__,
347 _captureId, 317 __FUNCTION__, __LINE__, errorMessage);
348 "%s:%s:%d deviceInputWithDevice error:%s",
349 __FILE__,
350 __FUNCTION__,
351 __LINE__,
352 errorMessage);
353 318
354 return NO; 319 return NO;
355 } 320 }
356 321
357 // try to add our new capture device to the capture session 322 // try to add our new capture device to the capture session
358 [_captureSession beginConfiguration]; 323 [_captureSession beginConfiguration];
359 324
360 BOOL addedCaptureInput = NO; 325 BOOL addedCaptureInput = NO;
361 if ([_captureSession canAddInput:newCaptureInput]) { 326 if ([_captureSession canAddInput:newCaptureInput]) {
362 [_captureSession addInput:newCaptureInput]; 327 [_captureSession addInput:newCaptureInput];
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
414 } 379 }
415 380
416 - (void)waitForCaptureChangeToFinish { 381 - (void)waitForCaptureChangeToFinish {
417 [_captureChangingCondition lock]; 382 [_captureChangingCondition lock];
418 while (_captureChanging) { 383 while (_captureChanging) {
419 [_captureChangingCondition wait]; 384 [_captureChangingCondition wait];
420 } 385 }
421 [_captureChangingCondition unlock]; 386 [_captureChangingCondition unlock];
422 } 387 }
423 @end 388 @end
OLDNEW
« no previous file with comments | « webrtc/modules/video_capture/objc/rtc_video_capture_objc.h ('k') | webrtc/modules/video_capture/objc/video_capture.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698