| Index: webrtc/modules/video_capture/ios/rtc_video_capture_ios_objc.mm
|
| diff --git a/webrtc/modules/video_capture/ios/rtc_video_capture_ios_objc.mm b/webrtc/modules/video_capture/ios/rtc_video_capture_ios_objc.mm
|
| deleted file mode 100644
|
| index e36c83bad9485517b69f9acea5ab5fde74ba3b0e..0000000000000000000000000000000000000000
|
| --- a/webrtc/modules/video_capture/ios/rtc_video_capture_ios_objc.mm
|
| +++ /dev/null
|
| @@ -1,423 +0,0 @@
|
| -/*
|
| - * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
| - *
|
| - * Use of this source code is governed by a BSD-style license
|
| - * that can be found in the LICENSE file in the root of the source
|
| - * tree. An additional intellectual property rights grant can be found
|
| - * in the file PATENTS. All contributing project authors may
|
| - * be found in the AUTHORS file in the root of the source tree.
|
| - */
|
| -
|
| -#if !defined(__has_feature) || !__has_feature(objc_arc)
|
| -#error "This file requires ARC support."
|
| -#endif
|
| -
|
| -#import <UIKit/UIKit.h>
|
| -
|
| -#import "webrtc/modules/video_capture/ios/device_info_ios_objc.h"
|
| -#import "webrtc/modules/video_capture/ios/rtc_video_capture_ios_objc.h"
|
| -
|
| -#include "webrtc/system_wrappers/include/trace.h"
|
| -
|
| -using namespace webrtc;
|
| -using namespace webrtc::videocapturemodule;
|
| -
|
| -@interface RTCVideoCaptureIosObjC (hidden)
|
| -- (int)changeCaptureInputWithName:(NSString*)captureDeviceName;
|
| -@end
|
| -
|
| -@implementation RTCVideoCaptureIosObjC {
|
| - webrtc::videocapturemodule::VideoCaptureIos* _owner;
|
| - webrtc::VideoCaptureCapability _capability;
|
| - AVCaptureSession* _captureSession;
|
| - int _captureId;
|
| - BOOL _orientationHasChanged;
|
| - AVCaptureConnection* _connection;
|
| - BOOL _captureChanging; // Guarded by _captureChangingCondition.
|
| - NSCondition* _captureChangingCondition;
|
| -}
|
| -
|
| -@synthesize frameRotation = _framRotation;
|
| -
|
| -- (id)initWithOwner:(VideoCaptureIos*)owner captureId:(int)captureId {
|
| - if (self == [super init]) {
|
| - _owner = owner;
|
| - _captureId = captureId;
|
| - _captureSession = [[AVCaptureSession alloc] init];
|
| -#if defined(__IPHONE_7_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_7_0
|
| - NSString* version = [[UIDevice currentDevice] systemVersion];
|
| - if ([version integerValue] >= 7) {
|
| - _captureSession.usesApplicationAudioSession = NO;
|
| - }
|
| -#endif
|
| - _captureChanging = NO;
|
| - _captureChangingCondition = [[NSCondition alloc] init];
|
| -
|
| - if (!_captureSession || !_captureChangingCondition) {
|
| - return nil;
|
| - }
|
| -
|
| - // create and configure a new output (using callbacks)
|
| - AVCaptureVideoDataOutput* captureOutput =
|
| - [[AVCaptureVideoDataOutput alloc] init];
|
| - NSString* key = (NSString*)kCVPixelBufferPixelFormatTypeKey;
|
| -
|
| - NSNumber* val = [NSNumber
|
| - numberWithUnsignedInt:kCVPixelFormatType_420YpCbCr8BiPlanarFullRange];
|
| - NSDictionary* videoSettings =
|
| - [NSDictionary dictionaryWithObject:val forKey:key];
|
| - captureOutput.videoSettings = videoSettings;
|
| -
|
| - // add new output
|
| - if ([_captureSession canAddOutput:captureOutput]) {
|
| - [_captureSession addOutput:captureOutput];
|
| - } else {
|
| - WEBRTC_TRACE(kTraceError,
|
| - kTraceVideoCapture,
|
| - _captureId,
|
| - "%s:%s:%d Could not add output to AVCaptureSession ",
|
| - __FILE__,
|
| - __FUNCTION__,
|
| - __LINE__);
|
| - }
|
| -
|
| - [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
|
| -
|
| - NSNotificationCenter* notify = [NSNotificationCenter defaultCenter];
|
| - [notify addObserver:self
|
| - selector:@selector(onVideoError:)
|
| - name:AVCaptureSessionRuntimeErrorNotification
|
| - object:_captureSession];
|
| - [notify addObserver:self
|
| - selector:@selector(deviceOrientationDidChange:)
|
| - name:UIDeviceOrientationDidChangeNotification
|
| - object:nil];
|
| - }
|
| -
|
| - return self;
|
| -}
|
| -
|
| -- (void)directOutputToSelf {
|
| - [[self currentOutput]
|
| - setSampleBufferDelegate:self
|
| - queue:dispatch_get_global_queue(
|
| - DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)];
|
| -}
|
| -
|
| -- (void)directOutputToNil {
|
| - [[self currentOutput] setSampleBufferDelegate:nil queue:NULL];
|
| -}
|
| -
|
| -- (void)deviceOrientationDidChange:(NSNotification*)notification {
|
| - _orientationHasChanged = YES;
|
| - [self setRelativeVideoOrientation];
|
| -}
|
| -
|
| -- (void)dealloc {
|
| - [[NSNotificationCenter defaultCenter] removeObserver:self];
|
| -}
|
| -
|
| -- (BOOL)setCaptureDeviceByUniqueId:(NSString*)uniqueId {
|
| - [self waitForCaptureChangeToFinish];
|
| - // check to see if the camera is already set
|
| - if (_captureSession) {
|
| - NSArray* currentInputs = [NSArray arrayWithArray:[_captureSession inputs]];
|
| - if ([currentInputs count] > 0) {
|
| - AVCaptureDeviceInput* currentInput = [currentInputs objectAtIndex:0];
|
| - if ([uniqueId isEqualToString:[currentInput.device localizedName]]) {
|
| - return YES;
|
| - }
|
| - }
|
| - }
|
| -
|
| - return [self changeCaptureInputByUniqueId:uniqueId];
|
| -}
|
| -
|
| -- (BOOL)startCaptureWithCapability:(const VideoCaptureCapability&)capability {
|
| - [self waitForCaptureChangeToFinish];
|
| - if (!_captureSession) {
|
| - return NO;
|
| - }
|
| -
|
| - // check limits of the resolution
|
| - if (capability.maxFPS < 0 || capability.maxFPS > 60) {
|
| - return NO;
|
| - }
|
| -
|
| - if ([_captureSession canSetSessionPreset:AVCaptureSessionPreset1920x1080]) {
|
| - if (capability.width > 1920 || capability.height > 1080) {
|
| - return NO;
|
| - }
|
| - } else if ([_captureSession
|
| - canSetSessionPreset:AVCaptureSessionPreset1280x720]) {
|
| - if (capability.width > 1280 || capability.height > 720) {
|
| - return NO;
|
| - }
|
| - } else if ([_captureSession
|
| - canSetSessionPreset:AVCaptureSessionPreset640x480]) {
|
| - if (capability.width > 640 || capability.height > 480) {
|
| - return NO;
|
| - }
|
| - } else if ([_captureSession
|
| - canSetSessionPreset:AVCaptureSessionPreset352x288]) {
|
| - if (capability.width > 352 || capability.height > 288) {
|
| - return NO;
|
| - }
|
| - } else if (capability.width < 0 || capability.height < 0) {
|
| - return NO;
|
| - }
|
| -
|
| - _capability = capability;
|
| -
|
| - AVCaptureVideoDataOutput* currentOutput = [self currentOutput];
|
| - if (!currentOutput)
|
| - return NO;
|
| -
|
| - [self directOutputToSelf];
|
| -
|
| - _orientationHasChanged = NO;
|
| - _captureChanging = YES;
|
| - dispatch_async(
|
| - dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
|
| - ^(void) { [self startCaptureInBackgroundWithOutput:currentOutput]; });
|
| - return YES;
|
| -}
|
| -
|
| -- (AVCaptureVideoDataOutput*)currentOutput {
|
| - return [[_captureSession outputs] firstObject];
|
| -}
|
| -
|
| -- (void)startCaptureInBackgroundWithOutput:
|
| - (AVCaptureVideoDataOutput*)currentOutput {
|
| - NSString* captureQuality =
|
| - [NSString stringWithString:AVCaptureSessionPresetLow];
|
| - if (_capability.width >= 1920 || _capability.height >= 1080) {
|
| - captureQuality =
|
| - [NSString stringWithString:AVCaptureSessionPreset1920x1080];
|
| - } else if (_capability.width >= 1280 || _capability.height >= 720) {
|
| - captureQuality = [NSString stringWithString:AVCaptureSessionPreset1280x720];
|
| - } else if (_capability.width >= 640 || _capability.height >= 480) {
|
| - captureQuality = [NSString stringWithString:AVCaptureSessionPreset640x480];
|
| - } else if (_capability.width >= 352 || _capability.height >= 288) {
|
| - captureQuality = [NSString stringWithString:AVCaptureSessionPreset352x288];
|
| - }
|
| -
|
| - // begin configuration for the AVCaptureSession
|
| - [_captureSession beginConfiguration];
|
| -
|
| - // picture resolution
|
| - [_captureSession setSessionPreset:captureQuality];
|
| -
|
| - // take care of capture framerate now
|
| - NSArray* sessionInputs = _captureSession.inputs;
|
| - AVCaptureDeviceInput* deviceInput = [sessionInputs count] > 0 ?
|
| - sessionInputs[0] : nil;
|
| - AVCaptureDevice* inputDevice = deviceInput.device;
|
| - if (inputDevice) {
|
| - AVCaptureDeviceFormat* activeFormat = inputDevice.activeFormat;
|
| - NSArray* supportedRanges = activeFormat.videoSupportedFrameRateRanges;
|
| - AVFrameRateRange* targetRange = [supportedRanges count] > 0 ?
|
| - supportedRanges[0] : nil;
|
| - // Find the largest supported framerate less than capability maxFPS.
|
| - for (AVFrameRateRange* range in supportedRanges) {
|
| - if (range.maxFrameRate <= _capability.maxFPS &&
|
| - targetRange.maxFrameRate <= range.maxFrameRate) {
|
| - targetRange = range;
|
| - }
|
| - }
|
| - if (targetRange && [inputDevice lockForConfiguration:NULL]) {
|
| - inputDevice.activeVideoMinFrameDuration = targetRange.minFrameDuration;
|
| - inputDevice.activeVideoMaxFrameDuration = targetRange.minFrameDuration;
|
| - [inputDevice unlockForConfiguration];
|
| - }
|
| - }
|
| -
|
| - _connection = [currentOutput connectionWithMediaType:AVMediaTypeVideo];
|
| - [self setRelativeVideoOrientation];
|
| -
|
| - // finished configuring, commit settings to AVCaptureSession.
|
| - [_captureSession commitConfiguration];
|
| -
|
| - [_captureSession startRunning];
|
| - [self signalCaptureChangeEnd];
|
| -}
|
| -
|
| -- (void)setRelativeVideoOrientation {
|
| - if (!_connection.supportsVideoOrientation) {
|
| - return;
|
| - }
|
| -
|
| - switch ([UIDevice currentDevice].orientation) {
|
| - case UIDeviceOrientationPortrait:
|
| - _connection.videoOrientation =
|
| - AVCaptureVideoOrientationPortrait;
|
| - break;
|
| - case UIDeviceOrientationPortraitUpsideDown:
|
| - _connection.videoOrientation =
|
| - AVCaptureVideoOrientationPortraitUpsideDown;
|
| - break;
|
| - case UIDeviceOrientationLandscapeLeft:
|
| - _connection.videoOrientation =
|
| - AVCaptureVideoOrientationLandscapeRight;
|
| - break;
|
| - case UIDeviceOrientationLandscapeRight:
|
| - _connection.videoOrientation =
|
| - AVCaptureVideoOrientationLandscapeLeft;
|
| - break;
|
| - case UIDeviceOrientationFaceUp:
|
| - case UIDeviceOrientationFaceDown:
|
| - case UIDeviceOrientationUnknown:
|
| - if (!_orientationHasChanged) {
|
| - _connection.videoOrientation =
|
| - AVCaptureVideoOrientationPortrait;
|
| - }
|
| - break;
|
| - }
|
| -}
|
| -
|
| -- (void)onVideoError:(NSNotification*)notification {
|
| - NSLog(@"onVideoError: %@", notification);
|
| - // TODO(sjlee): make the specific error handling with this notification.
|
| - WEBRTC_TRACE(kTraceError,
|
| - kTraceVideoCapture,
|
| - _captureId,
|
| - "%s:%s:%d [AVCaptureSession startRunning] error.",
|
| - __FILE__,
|
| - __FUNCTION__,
|
| - __LINE__);
|
| -}
|
| -
|
| -- (BOOL)stopCapture {
|
| - [[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
|
| - _orientationHasChanged = NO;
|
| - [self waitForCaptureChangeToFinish];
|
| - [self directOutputToNil];
|
| -
|
| - if (!_captureSession) {
|
| - return NO;
|
| - }
|
| -
|
| - _captureChanging = YES;
|
| - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
|
| - ^(void) { [self stopCaptureInBackground]; });
|
| - return YES;
|
| -}
|
| -
|
| -- (void)stopCaptureInBackground {
|
| - [_captureSession stopRunning];
|
| - [self signalCaptureChangeEnd];
|
| -}
|
| -
|
| -- (BOOL)changeCaptureInputByUniqueId:(NSString*)uniqueId {
|
| - [self waitForCaptureChangeToFinish];
|
| - NSArray* currentInputs = [_captureSession inputs];
|
| - // remove current input
|
| - if ([currentInputs count] > 0) {
|
| - AVCaptureInput* currentInput =
|
| - (AVCaptureInput*)[currentInputs objectAtIndex:0];
|
| -
|
| - [_captureSession removeInput:currentInput];
|
| - }
|
| -
|
| - // Look for input device with the name requested (as our input param)
|
| - // get list of available capture devices
|
| - int captureDeviceCount = [DeviceInfoIosObjC captureDeviceCount];
|
| - if (captureDeviceCount <= 0) {
|
| - return NO;
|
| - }
|
| -
|
| - AVCaptureDevice* captureDevice =
|
| - [DeviceInfoIosObjC captureDeviceForUniqueId:uniqueId];
|
| -
|
| - if (!captureDevice) {
|
| - return NO;
|
| - }
|
| -
|
| - // now create capture session input out of AVCaptureDevice
|
| - NSError* deviceError = nil;
|
| - AVCaptureDeviceInput* newCaptureInput =
|
| - [AVCaptureDeviceInput deviceInputWithDevice:captureDevice
|
| - error:&deviceError];
|
| -
|
| - if (!newCaptureInput) {
|
| - const char* errorMessage = [[deviceError localizedDescription] UTF8String];
|
| -
|
| - WEBRTC_TRACE(kTraceError,
|
| - kTraceVideoCapture,
|
| - _captureId,
|
| - "%s:%s:%d deviceInputWithDevice error:%s",
|
| - __FILE__,
|
| - __FUNCTION__,
|
| - __LINE__,
|
| - errorMessage);
|
| -
|
| - return NO;
|
| - }
|
| -
|
| - // try to add our new capture device to the capture session
|
| - [_captureSession beginConfiguration];
|
| -
|
| - BOOL addedCaptureInput = NO;
|
| - if ([_captureSession canAddInput:newCaptureInput]) {
|
| - [_captureSession addInput:newCaptureInput];
|
| - addedCaptureInput = YES;
|
| - } else {
|
| - addedCaptureInput = NO;
|
| - }
|
| -
|
| - [_captureSession commitConfiguration];
|
| -
|
| - return addedCaptureInput;
|
| -}
|
| -
|
| -- (void)captureOutput:(AVCaptureOutput*)captureOutput
|
| - didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
|
| - fromConnection:(AVCaptureConnection*)connection {
|
| - const int kFlags = 0;
|
| - CVImageBufferRef videoFrame = CMSampleBufferGetImageBuffer(sampleBuffer);
|
| -
|
| - if (CVPixelBufferLockBaseAddress(videoFrame, kFlags) != kCVReturnSuccess) {
|
| - return;
|
| - }
|
| -
|
| - const int kYPlaneIndex = 0;
|
| - const int kUVPlaneIndex = 1;
|
| -
|
| - uint8_t* baseAddress =
|
| - (uint8_t*)CVPixelBufferGetBaseAddressOfPlane(videoFrame, kYPlaneIndex);
|
| - size_t yPlaneBytesPerRow =
|
| - CVPixelBufferGetBytesPerRowOfPlane(videoFrame, kYPlaneIndex);
|
| - size_t yPlaneHeight = CVPixelBufferGetHeightOfPlane(videoFrame, kYPlaneIndex);
|
| - size_t uvPlaneBytesPerRow =
|
| - CVPixelBufferGetBytesPerRowOfPlane(videoFrame, kUVPlaneIndex);
|
| - size_t uvPlaneHeight =
|
| - CVPixelBufferGetHeightOfPlane(videoFrame, kUVPlaneIndex);
|
| - size_t frameSize =
|
| - yPlaneBytesPerRow * yPlaneHeight + uvPlaneBytesPerRow * uvPlaneHeight;
|
| -
|
| - VideoCaptureCapability tempCaptureCapability;
|
| - tempCaptureCapability.width = CVPixelBufferGetWidth(videoFrame);
|
| - tempCaptureCapability.height = CVPixelBufferGetHeight(videoFrame);
|
| - tempCaptureCapability.maxFPS = _capability.maxFPS;
|
| - tempCaptureCapability.rawType = kVideoNV12;
|
| -
|
| - _owner->IncomingFrame(baseAddress, frameSize, tempCaptureCapability, 0);
|
| -
|
| - CVPixelBufferUnlockBaseAddress(videoFrame, kFlags);
|
| -}
|
| -
|
| -- (void)signalCaptureChangeEnd {
|
| - [_captureChangingCondition lock];
|
| - _captureChanging = NO;
|
| - [_captureChangingCondition signal];
|
| - [_captureChangingCondition unlock];
|
| -}
|
| -
|
| -- (void)waitForCaptureChangeToFinish {
|
| - [_captureChangingCondition lock];
|
| - while (_captureChanging) {
|
| - [_captureChangingCondition wait];
|
| - }
|
| - [_captureChangingCondition unlock];
|
| -}
|
| -@end
|
|
|