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

Side by Side Diff: talk/app/webrtc/objc/avfoundationvideocapturer.mm

Issue 1416303003: Handle iOS devices with no rear-facing camera (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Changes based on feedback Created 4 years, 9 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 * libjingle 2 * libjingle
3 * Copyright 2015 Google Inc. 3 * Copyright 2015 Google Inc.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7 * 7 *
8 * 1. Redistributions of source code must retain the above copyright notice, 8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer. 9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice, 10 * 2. Redistributions in binary form must reproduce the above copyright notice,
(...skipping 16 matching lines...) Expand all
27 27
28 #include "talk/app/webrtc/objc/avfoundationvideocapturer.h" 28 #include "talk/app/webrtc/objc/avfoundationvideocapturer.h"
29 29
30 #include "webrtc/base/bind.h" 30 #include "webrtc/base/bind.h"
31 31
32 #import <AVFoundation/AVFoundation.h> 32 #import <AVFoundation/AVFoundation.h>
33 #import <Foundation/Foundation.h> 33 #import <Foundation/Foundation.h>
34 #import <UIKit/UIKit.h> 34 #import <UIKit/UIKit.h>
35 35
36 #import "webrtc/base/objc/RTCDispatcher.h" 36 #import "webrtc/base/objc/RTCDispatcher.h"
37 #import "webrtc/base/objc/RTCLogging.h"
37 38
38 // TODO(tkchin): support other formats. 39 // TODO(tkchin): support other formats.
39 static NSString* const kDefaultPreset = AVCaptureSessionPreset640x480; 40 static NSString* const kDefaultPreset = AVCaptureSessionPreset640x480;
40 static cricket::VideoFormat const kDefaultFormat = 41 static cricket::VideoFormat const kDefaultFormat =
41 cricket::VideoFormat(640, 42 cricket::VideoFormat(640,
42 480, 43 480,
43 cricket::VideoFormat::FpsToInterval(30), 44 cricket::VideoFormat::FpsToInterval(30),
44 cricket::FOURCC_NV12); 45 cricket::FOURCC_NV12);
45 46
46 // This class used to capture frames using AVFoundation APIs on iOS. It is meant 47 // This class used to capture frames using AVFoundation APIs on iOS. It is meant
47 // to be owned by an instance of AVFoundationVideoCapturer. The reason for this 48 // to be owned by an instance of AVFoundationVideoCapturer. The reason for this
48 // because other webrtc objects own cricket::VideoCapturer, which is not 49 // because other webrtc objects own cricket::VideoCapturer, which is not
49 // ref counted. To prevent bad behavior we do not expose this class directly. 50 // ref counted. To prevent bad behavior we do not expose this class directly.
50 @interface RTCAVFoundationVideoCapturerInternal : NSObject 51 @interface RTCAVFoundationVideoCapturerInternal : NSObject
51 <AVCaptureVideoDataOutputSampleBufferDelegate> 52 <AVCaptureVideoDataOutputSampleBufferDelegate>
52 53
53 @property(nonatomic, readonly) AVCaptureSession* captureSession; 54 @property(nonatomic, readonly) AVCaptureSession* captureSession;
54 @property(nonatomic, readonly) BOOL isRunning; 55 @property(nonatomic, readonly) BOOL isRunning;
56 @property(nonatomic, readonly) BOOL canUseBackCamera;
55 @property(nonatomic, assign) BOOL useBackCamera; // Defaults to NO. 57 @property(nonatomic, assign) BOOL useBackCamera; // Defaults to NO.
56 58
57 // We keep a pointer back to AVFoundationVideoCapturer to make callbacks on it 59 // We keep a pointer back to AVFoundationVideoCapturer to make callbacks on it
58 // when we receive frames. This is safe because this object should be owned by 60 // when we receive frames. This is safe because this object should be owned by
59 // it. 61 // it.
60 - (instancetype)initWithCapturer:(webrtc::AVFoundationVideoCapturer*)capturer; 62 - (instancetype)initWithCapturer:(webrtc::AVFoundationVideoCapturer*)capturer;
61 - (void)startCaptureAsync; 63 - (void)startCaptureAsync;
62 - (void)stopCaptureAsync; 64 - (void)stopCaptureAsync;
63 65
64 @end 66 @end
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 } 100 }
99 return self; 101 return self;
100 } 102 }
101 103
102 - (void)dealloc { 104 - (void)dealloc {
103 [self stopCaptureAsync]; 105 [self stopCaptureAsync];
104 [[NSNotificationCenter defaultCenter] removeObserver:self]; 106 [[NSNotificationCenter defaultCenter] removeObserver:self];
105 _capturer = nullptr; 107 _capturer = nullptr;
106 } 108 }
107 109
110 - (BOOL)canUseBackCamera {
111 return _backDeviceInput != nil;
112 }
113
108 - (void)setUseBackCamera:(BOOL)useBackCamera { 114 - (void)setUseBackCamera:(BOOL)useBackCamera {
109 if (_useBackCamera == useBackCamera) { 115 if (_useBackCamera == useBackCamera) {
110 return; 116 return;
111 } 117 }
118 if (!self.canUseBackCamera) {
119 RTCLog(@"No rear-facing camera exists or it cannot be used;"
120 "not switching.");
121 return;
122 }
112 _useBackCamera = useBackCamera; 123 _useBackCamera = useBackCamera;
113 [self updateSessionInput]; 124 [self updateSessionInput];
114 } 125 }
115 126
116 - (void)startCaptureAsync { 127 - (void)startCaptureAsync {
117 if (_isRunning) { 128 if (_isRunning) {
118 return; 129 return;
119 } 130 }
120 _orientationHasChanged = NO; 131 _orientationHasChanged = NO;
121 [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; 132 [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
196 AVCaptureDevice* backCaptureDevice = nil; 207 AVCaptureDevice* backCaptureDevice = nil;
197 for (AVCaptureDevice* captureDevice in 208 for (AVCaptureDevice* captureDevice in
198 [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]) { 209 [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]) {
199 if (captureDevice.position == AVCaptureDevicePositionBack) { 210 if (captureDevice.position == AVCaptureDevicePositionBack) {
200 backCaptureDevice = captureDevice; 211 backCaptureDevice = captureDevice;
201 } 212 }
202 if (captureDevice.position == AVCaptureDevicePositionFront) { 213 if (captureDevice.position == AVCaptureDevicePositionFront) {
203 frontCaptureDevice = captureDevice; 214 frontCaptureDevice = captureDevice;
204 } 215 }
205 } 216 }
206 if (!frontCaptureDevice || !backCaptureDevice) { 217 if (!frontCaptureDevice) {
207 NSLog(@"Failed to get capture devices."); 218 RTCLog(@"Failed to get front capture device.");
208 return NO; 219 return NO;
209 } 220 }
221 if (!backCaptureDevice) {
222 RTCLog(@"Failed to get back capture device");
223 // Don't return NO here because devices exist (16GB 5th generation iPod
224 // Touch) that don't have a rear-facing camera.
225 }
210 226
211 // Set up the session inputs. 227 // Set up the session inputs.
212 NSError* error = nil; 228 NSError* error = nil;
213 _frontDeviceInput = 229 _frontDeviceInput =
214 [AVCaptureDeviceInput deviceInputWithDevice:frontCaptureDevice 230 [AVCaptureDeviceInput deviceInputWithDevice:frontCaptureDevice
215 error:&error]; 231 error:&error];
216 if (!_frontDeviceInput) { 232 if (!_frontDeviceInput) {
217 NSLog(@"Failed to get capture device input: %@", 233 NSLog(@"Failed to get capture device input: %@",
218 error.localizedDescription); 234 error.localizedDescription);
219 return NO; 235 return NO;
220 } 236 }
221 _backDeviceInput = 237 if (backCaptureDevice) {
222 [AVCaptureDeviceInput deviceInputWithDevice:backCaptureDevice 238 error = nil;
223 error:&error]; 239 _backDeviceInput =
224 if (!_backDeviceInput) { 240 [AVCaptureDeviceInput deviceInputWithDevice:backCaptureDevice
225 NSLog(@"Failed to get capture device input: %@", 241 error:&error];
226 error.localizedDescription); 242 if (error) {
227 return NO; 243 RTCLog(@"Failed to get capture device input: %@",
244 error.localizedDescription);
245 _backDeviceInput = nil;
246 }
228 } 247 }
229 248
230 // Add the inputs. 249 // Add the inputs.
231 if (![_captureSession canAddInput:_frontDeviceInput] || 250 if (![_captureSession canAddInput:_frontDeviceInput] ||
232 ![_captureSession canAddInput:_backDeviceInput]) { 251 (_backDeviceInput && ![_captureSession canAddInput:_backDeviceInput])) {
233 NSLog(@"Session does not support capture inputs."); 252 NSLog(@"Session does not support capture inputs.");
234 return NO; 253 return NO;
235 } 254 }
236 [self updateSessionInput]; 255 [self updateSessionInput];
237 256
238 return YES; 257 return YES;
239 } 258 }
240 259
241 - (void)deviceOrientationDidChange:(NSNotification*)notification { 260 - (void)deviceOrientationDidChange:(NSNotification*)notification {
242 _orientationHasChanged = YES; 261 _orientationHasChanged = YES;
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
346 } 365 }
347 366
348 bool AVFoundationVideoCapturer::IsRunning() { 367 bool AVFoundationVideoCapturer::IsRunning() {
349 return _capturer.isRunning; 368 return _capturer.isRunning;
350 } 369 }
351 370
352 AVCaptureSession* AVFoundationVideoCapturer::GetCaptureSession() { 371 AVCaptureSession* AVFoundationVideoCapturer::GetCaptureSession() {
353 return _capturer.captureSession; 372 return _capturer.captureSession;
354 } 373 }
355 374
375 bool AVFoundationVideoCapturer::CanUseBackCamera() const {
376 return _capturer.canUseBackCamera;
377 }
378
356 void AVFoundationVideoCapturer::SetUseBackCamera(bool useBackCamera) { 379 void AVFoundationVideoCapturer::SetUseBackCamera(bool useBackCamera) {
357 _capturer.useBackCamera = useBackCamera; 380 _capturer.useBackCamera = useBackCamera;
358 } 381 }
359 382
360 bool AVFoundationVideoCapturer::GetUseBackCamera() const { 383 bool AVFoundationVideoCapturer::GetUseBackCamera() const {
361 return _capturer.useBackCamera; 384 return _capturer.useBackCamera;
362 } 385 }
363 386
364 void AVFoundationVideoCapturer::CaptureSampleBuffer( 387 void AVFoundationVideoCapturer::CaptureSampleBuffer(
365 CMSampleBufferRef sampleBuffer) { 388 CMSampleBufferRef sampleBuffer) {
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
428 451
429 void AVFoundationVideoCapturer::SignalFrameCapturedOnStartThread( 452 void AVFoundationVideoCapturer::SignalFrameCapturedOnStartThread(
430 const cricket::CapturedFrame* frame) { 453 const cricket::CapturedFrame* frame) {
431 RTC_DCHECK(_startThread->IsCurrent()); 454 RTC_DCHECK(_startThread->IsCurrent());
432 // This will call a superclass method that will perform the frame conversion 455 // This will call a superclass method that will perform the frame conversion
433 // to I420. 456 // to I420.
434 SignalFrameCaptured(this, frame); 457 SignalFrameCaptured(this, frame);
435 } 458 }
436 459
437 } // namespace webrtc 460 } // namespace webrtc
OLDNEW
« no previous file with comments | « talk/app/webrtc/objc/avfoundationvideocapturer.h ('k') | talk/app/webrtc/objc/public/RTCAVFoundationVideoSource.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698