| Index: webrtc/sdk/objc/Framework/Classes/PeerConnection/RTCCameraVideoCapturer.m
|
| diff --git a/webrtc/sdk/objc/Framework/Classes/PeerConnection/RTCCameraVideoCapturer.m b/webrtc/sdk/objc/Framework/Classes/PeerConnection/RTCCameraVideoCapturer.m
|
| index a2290c2458405a1d39458f64eae820abfdc14bc9..fb2ce547b0a7700d55bc6d324242336e2bfb6d1c 100644
|
| --- a/webrtc/sdk/objc/Framework/Classes/PeerConnection/RTCCameraVideoCapturer.m
|
| +++ b/webrtc/sdk/objc/Framework/Classes/PeerConnection/RTCCameraVideoCapturer.m
|
| @@ -29,21 +29,26 @@ static inline BOOL IsMediaSubTypeSupported(FourCharCode mediaSubType) {
|
|
|
| @interface RTCCameraVideoCapturer ()<AVCaptureVideoDataOutputSampleBufferDelegate>
|
| @property(nonatomic, readonly) dispatch_queue_t frameQueue;
|
| +@property(assign) BOOL switchingCameras;
|
| @end
|
|
|
| @implementation RTCCameraVideoCapturer {
|
| AVCaptureVideoDataOutput *_videoDataOutput;
|
| AVCaptureSession *_captureSession;
|
| AVCaptureDevice *_currentDevice;
|
| - RTCVideoRotation _rotation;
|
| BOOL _hasRetriedOnFatalError;
|
| BOOL _isRunning;
|
| // Will the session be running once all asynchronous operations have been completed?
|
| BOOL _willBeRunning;
|
| + BOOL _switchingCameras;
|
| +#if TARGET_OS_IPHONE
|
| + UIDeviceOrientation _orientation;
|
| +#endif
|
| }
|
|
|
| @synthesize frameQueue = _frameQueue;
|
| @synthesize captureSession = _captureSession;
|
| +@synthesize switchingCameras = _switchingCameras;
|
|
|
| - (instancetype)initWithDelegate:(__weak id<RTCVideoCapturerDelegate>)delegate {
|
| if (self = [super initWithDelegate:delegate]) {
|
| @@ -55,7 +60,9 @@ static inline BOOL IsMediaSubTypeSupported(FourCharCode mediaSubType) {
|
| return nil;
|
| }
|
| NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
|
| + self.switchingCameras = NO;
|
| #if TARGET_OS_IPHONE
|
| + _orientation = UIDeviceOrientationPortrait;
|
| [center addObserver:self
|
| selector:@selector(deviceOrientationDidChange:)
|
| name:UIDeviceOrientationDidChangeNotification
|
| @@ -117,7 +124,7 @@ static inline BOOL IsMediaSubTypeSupported(FourCharCode mediaSubType) {
|
| - (void)startCaptureWithDevice:(AVCaptureDevice *)device
|
| format:(AVCaptureDeviceFormat *)format
|
| fps:(NSInteger)fps {
|
| - _willBeRunning = true;
|
| + _willBeRunning = YES;
|
| [RTCDispatcher
|
| dispatchAsyncOnType:RTCDispatcherTypeCaptureSession
|
| block:^{
|
| @@ -136,17 +143,19 @@ static inline BOOL IsMediaSubTypeSupported(FourCharCode mediaSubType) {
|
| return;
|
| }
|
|
|
| + self.switchingCameras = YES;
|
| [self reconfigureCaptureSessionInput];
|
| [self updateOrientation];
|
| [_captureSession startRunning];
|
| [self updateDeviceCaptureFormat:format fps:fps];
|
| [_currentDevice unlockForConfiguration];
|
| - _isRunning = true;
|
| + self.switchingCameras = NO;
|
| + _isRunning = YES;
|
| }];
|
| }
|
|
|
| - (void)stopCapture {
|
| - _willBeRunning = false;
|
| + _willBeRunning = NO;
|
| [RTCDispatcher
|
| dispatchAsyncOnType:RTCDispatcherTypeCaptureSession
|
| block:^{
|
| @@ -160,7 +169,7 @@ static inline BOOL IsMediaSubTypeSupported(FourCharCode mediaSubType) {
|
| #if TARGET_OS_IPHONE
|
| [[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
|
| #endif
|
| - _isRunning = false;
|
| + _isRunning = NO;
|
| }];
|
| }
|
|
|
| @@ -192,11 +201,68 @@ static inline BOOL IsMediaSubTypeSupported(FourCharCode mediaSubType) {
|
| return;
|
| }
|
|
|
| +#if TARGET_OS_IPHONE
|
| + // Default to portrait orientation on iPhone.
|
| + RTCVideoRotation rotation = RTCVideoRotation_90;
|
| + // Check here, which camera this frame is from, to avoid any race conditions.
|
| + AVCaptureDeviceInput *deviceInput =
|
| + (AVCaptureDeviceInput *)((AVCaptureInputPort *)connection.inputPorts.firstObject).input;
|
| + BOOL usingFrontCamera = deviceInput.device.position == AVCaptureDevicePositionFront;
|
| + if (self.switchingCameras) {
|
| + // Check the image's EXIF for the actual camera the image came from only when switching
|
| + // cameras as the image may still be from the old camera.
|
| + CFDictionaryRef attachments = CMCopyDictionaryOfAttachments(
|
| + kCFAllocatorDefault, sampleBuffer, kCMAttachmentMode_ShouldPropagate);
|
| + if (attachments) {
|
| + int size = CFDictionaryGetCount(attachments);
|
| + if (size > 0) {
|
| + CFDictionaryRef cfExifDictVal = NULL;
|
| + if (CFDictionaryGetValueIfPresent(
|
| + attachments, (const void *)CFSTR("{Exif}"), (const void **)&cfExifDictVal)) {
|
| + CFStringRef cfLensModelStrVal;
|
| + if (CFDictionaryGetValueIfPresent(cfExifDictVal,
|
| + (const void *)CFSTR("LensModel"),
|
| + (const void **)&cfLensModelStrVal)) {
|
| + if ([(__bridge NSString *)cfLensModelStrVal containsString:@"front"]) {
|
| + usingFrontCamera = YES;
|
| + } else if ([(__bridge NSString *)cfLensModelStrVal containsString:@"back"]) {
|
| + usingFrontCamera = NO;
|
| + }
|
| + }
|
| + }
|
| + }
|
| + CFRelease(attachments);
|
| + }
|
| + }
|
| + switch (_orientation) {
|
| + case UIDeviceOrientationPortrait:
|
| + rotation = RTCVideoRotation_90;
|
| + break;
|
| + case UIDeviceOrientationPortraitUpsideDown:
|
| + rotation = RTCVideoRotation_270;
|
| + break;
|
| + case UIDeviceOrientationLandscapeLeft:
|
| + rotation = usingFrontCamera ? RTCVideoRotation_180 : RTCVideoRotation_0;
|
| + break;
|
| + case UIDeviceOrientationLandscapeRight:
|
| + rotation = usingFrontCamera ? RTCVideoRotation_0 : RTCVideoRotation_180;
|
| + break;
|
| + case UIDeviceOrientationFaceUp:
|
| + case UIDeviceOrientationFaceDown:
|
| + case UIDeviceOrientationUnknown:
|
| + // Ignore.
|
| + break;
|
| + }
|
| +#else
|
| + // No rotation on Mac.
|
| + RTCVideoRotation rotation = RTCVideoRotation_0;
|
| +#endif
|
| +
|
| RTCCVPixelBuffer *rtcPixelBuffer = [[RTCCVPixelBuffer alloc] initWithPixelBuffer:pixelBuffer];
|
| int64_t timeStampNs = CMTimeGetSeconds(CMSampleBufferGetPresentationTimeStamp(sampleBuffer)) *
|
| - kNanosecondsPerSecond;
|
| + kNanosecondsPerSecond;
|
| RTCVideoFrame *videoFrame = [[RTCVideoFrame alloc] initWithBuffer:rtcPixelBuffer
|
| - rotation:_rotation
|
| + rotation:rotation
|
| timeStampNs:timeStampNs];
|
| [self.delegate capturer:self didCaptureVideoFrame:videoFrame];
|
| }
|
| @@ -399,26 +465,7 @@ static inline BOOL IsMediaSubTypeSupported(FourCharCode mediaSubType) {
|
| NSAssert([RTCDispatcher isOnQueueForType:RTCDispatcherTypeCaptureSession],
|
| @"updateOrientation must be called on the capture queue.");
|
| #if TARGET_OS_IPHONE
|
| - BOOL usingFrontCamera = _currentDevice.position == AVCaptureDevicePositionFront;
|
| - switch ([UIDevice currentDevice].orientation) {
|
| - case UIDeviceOrientationPortrait:
|
| - _rotation = RTCVideoRotation_90;
|
| - break;
|
| - case UIDeviceOrientationPortraitUpsideDown:
|
| - _rotation = RTCVideoRotation_270;
|
| - break;
|
| - case UIDeviceOrientationLandscapeLeft:
|
| - _rotation = usingFrontCamera ? RTCVideoRotation_180 : RTCVideoRotation_0;
|
| - break;
|
| - case UIDeviceOrientationLandscapeRight:
|
| - _rotation = usingFrontCamera ? RTCVideoRotation_0 : RTCVideoRotation_180;
|
| - break;
|
| - case UIDeviceOrientationFaceUp:
|
| - case UIDeviceOrientationFaceDown:
|
| - case UIDeviceOrientationUnknown:
|
| - // Ignore.
|
| - break;
|
| - }
|
| + _orientation = [UIDevice currentDevice].orientation;
|
| #endif
|
| }
|
|
|
|
|