video_capture(iOS): move stopCapture to background thread

Also suspend frame delivery on stopCapture() to avoid pause+onVideoError
during hangup.

BUG=3162
R=noahric@google.com

Review URL: https://webrtc-codereview.appspot.com/11389004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@5863 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
fischman@webrtc.org 2014-04-08 21:06:52 +00:00
parent 2a03498825
commit 984e4fbaaa
2 changed files with 52 additions and 26 deletions

View File

@ -32,8 +32,8 @@ using namespace webrtc::videocapturemodule;
AVCaptureSession* _captureSession; AVCaptureSession* _captureSession;
int _captureId; int _captureId;
AVCaptureConnection* _connection; AVCaptureConnection* _connection;
BOOL _captureStarting; // Guarded by _captureStartingCondition. BOOL _captureChanging; // Guarded by _captureChangingCondition.
NSCondition* _captureStartingCondition; NSCondition* _captureChangingCondition;
} }
@synthesize frameRotation = _framRotation; @synthesize frameRotation = _framRotation;
@ -43,18 +43,16 @@ using namespace webrtc::videocapturemodule;
_owner = owner; _owner = owner;
_captureId = captureId; _captureId = captureId;
_captureSession = [[AVCaptureSession alloc] init]; _captureSession = [[AVCaptureSession alloc] init];
_captureStarting = NO; _captureChanging = NO;
_captureStartingCondition = [[NSCondition alloc] init]; _captureChangingCondition = [[NSCondition alloc] init];
if (!_captureSession || !_captureStartingCondition) { if (!_captureSession || !_captureChangingCondition) {
return nil; return nil;
} }
// create and configure a new output (using callbacks) // create and configure a new output (using callbacks)
AVCaptureVideoDataOutput* captureOutput = AVCaptureVideoDataOutput* captureOutput =
[[AVCaptureVideoDataOutput alloc] init]; [[AVCaptureVideoDataOutput alloc] init];
[captureOutput setSampleBufferDelegate:self
queue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)];
NSString* key = (NSString*)kCVPixelBufferPixelFormatTypeKey; NSString* key = (NSString*)kCVPixelBufferPixelFormatTypeKey;
NSNumber* val = [NSNumber NSNumber* val = [NSNumber
@ -90,6 +88,17 @@ using namespace webrtc::videocapturemodule;
return self; 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)statusBarOrientationDidChange:(NSNotification*)notification { - (void)statusBarOrientationDidChange:(NSNotification*)notification {
[self setRelativeVideoOrientation]; [self setRelativeVideoOrientation];
} }
@ -99,6 +108,7 @@ using namespace webrtc::videocapturemodule;
} }
- (BOOL)setCaptureDeviceByUniqueId:(NSString*)uniqueId { - (BOOL)setCaptureDeviceByUniqueId:(NSString*)uniqueId {
[self waitForCaptureChangeToFinish];
// check to see if the camera is already set // check to see if the camera is already set
if (_captureSession) { if (_captureSession) {
NSArray* currentInputs = [NSArray arrayWithArray:[_captureSession inputs]]; NSArray* currentInputs = [NSArray arrayWithArray:[_captureSession inputs]];
@ -114,6 +124,7 @@ using namespace webrtc::videocapturemodule;
} }
- (BOOL)startCaptureWithCapability:(const VideoCaptureCapability&)capability { - (BOOL)startCaptureWithCapability:(const VideoCaptureCapability&)capability {
[self waitForCaptureChangeToFinish];
if (!_captureSession) { if (!_captureSession) {
return NO; return NO;
} }
@ -148,20 +159,23 @@ using namespace webrtc::videocapturemodule;
_capability = capability; _capability = capability;
NSArray* currentOutputs = [_captureSession outputs]; AVCaptureVideoDataOutput* currentOutput = [self currentOutput];
if ([currentOutputs count] == 0) { if (!currentOutput)
return NO; return NO;
}
AVCaptureVideoDataOutput* currentOutput = [self directOutputToSelf];
(AVCaptureVideoDataOutput*)[currentOutputs objectAtIndex:0];
_captureChanging = YES;
dispatch_async( dispatch_async(
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
^(void) { [self startCaptureInBackgroundWithOutput:currentOutput]; }); ^(void) { [self startCaptureInBackgroundWithOutput:currentOutput]; });
return YES; return YES;
} }
- (AVCaptureVideoDataOutput*)currentOutput {
return [[_captureSession outputs] firstObject];
}
- (void)startCaptureInBackgroundWithOutput: - (void)startCaptureInBackgroundWithOutput:
(AVCaptureVideoDataOutput*)currentOutput { (AVCaptureVideoDataOutput*)currentOutput {
NSString* captureQuality = NSString* captureQuality =
@ -195,11 +209,7 @@ using namespace webrtc::videocapturemodule;
[_captureSession commitConfiguration]; [_captureSession commitConfiguration];
[_captureSession startRunning]; [_captureSession startRunning];
[self signalCaptureChangeEnd];
[_captureStartingCondition lock];
_captureStarting = NO;
[_captureStartingCondition signal];
[_captureStartingCondition unlock];
} }
- (void)setRelativeVideoOrientation { - (void)setRelativeVideoOrientation {
@ -235,17 +245,26 @@ using namespace webrtc::videocapturemodule;
} }
- (BOOL)stopCapture { - (BOOL)stopCapture {
[self waitForCaptureStartToFinish]; [self waitForCaptureChangeToFinish];
[self directOutputToNil];
if (!_captureSession) { if (!_captureSession) {
return NO; return NO;
} }
[_captureSession stopRunning]; _captureChanging = YES;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
^(void) { [self stopCaptureInBackground]; });
return YES; return YES;
} }
- (void)stopCaptureInBackground {
[_captureSession stopRunning];
[self signalCaptureChangeEnd];
}
- (BOOL)changeCaptureInputByUniqueId:(NSString*)uniqueId { - (BOOL)changeCaptureInputByUniqueId:(NSString*)uniqueId {
[self waitForCaptureChangeToFinish];
NSArray* currentInputs = [_captureSession inputs]; NSArray* currentInputs = [_captureSession inputs];
// remove current input // remove current input
if ([currentInputs count] > 0) { if ([currentInputs count] > 0) {
@ -341,11 +360,18 @@ using namespace webrtc::videocapturemodule;
CVPixelBufferUnlockBaseAddress(videoFrame, kFlags); CVPixelBufferUnlockBaseAddress(videoFrame, kFlags);
} }
- (void)waitForCaptureStartToFinish { - (void)signalCaptureChangeEnd {
[_captureStartingCondition lock]; [_captureChangingCondition lock];
while (_captureStarting) { _captureChanging = NO;
[_captureStartingCondition wait]; [_captureChangingCondition signal];
[_captureChangingCondition unlock];
}
- (void)waitForCaptureChangeToFinish {
[_captureChangingCondition lock];
while (_captureChanging) {
[_captureChangingCondition wait];
} }
[_captureStartingCondition unlock]; [_captureChangingCondition unlock];
} }
@end @end

View File

@ -34,7 +34,7 @@ VideoCaptureIos::VideoCaptureIos(const int32_t capture_id)
} }
VideoCaptureIos::~VideoCaptureIos() { VideoCaptureIos::~VideoCaptureIos() {
if (capture_device_) { if (is_capturing_) {
[capture_device_ stopCapture]; [capture_device_ stopCapture];
} }
} }