我的问题
我使用AVFoundation每5秒捕获一次视频输出帧。当用户点击一个按钮时,输入摄像头应该从前面一个切换到后面一个,反之亦然。问题是,每当我将后置摄像头切换到前置摄像头时,它就会冻结(奇怪的是,它的工作方式相反 - 意思是前置摄像头到后置摄像头)!
我使用的代码
要在相机之间切换,我使用从Apple的AVCam sample code获取的完全代码,稍微更改一下变量名称(因此它会匹配我的代码):
- (BOOL)toggleCamera
{
BOOL success = NO;
if ([self cameraCount] > 1) {
NSError *error;
AVCaptureDeviceInput *newVideoInput;
AVCaptureDevicePosition position = [[self.videoInput device] position];
if (position == AVCaptureDevicePositionBack)
newVideoInput = [[AVCaptureDeviceInput alloc] initWithDevice:[self frontFacingCamera] error:&error];
else if (position == AVCaptureDevicePositionFront)
newVideoInput = [[AVCaptureDeviceInput alloc] initWithDevice:[self backFacingCamera] error:&error];
else
goto bail;
if (newVideoInput != nil) {
// Start configuring the session.
[[self captureSession] beginConfiguration];
// Remove the current video input device.
[[self captureSession] removeInput:[self videoInput]];
if ([[self captureSession] canAddInput:newVideoInput]) {
[[self captureSession] addInput:newVideoInput];
[self setVideoInput:newVideoInput];
}
else {
[[self captureSession] addInput:[self videoInput]];
}
[[self captureSession] commitConfiguration];
success = YES;
[newVideoInput release];
}
else if (error) {
NSLog(@"PICTURE TAKER: Failed to toggle cameras."
@"\nError: %@", error.localizedDescription);
}
}
bail:
return success;
}
再次设置AVCaptureSession
,我使用AVCam sample code中的完全相同代码,添加的输出略有变化(以满足我的需求) ):
- (BOOL) setupSession
{
BOOL success = NO;
// Set torch and flash mode to auto
if ([[self backFacingCamera] hasFlash]) {
if ([[self backFacingCamera] lockForConfiguration:nil]) {
if ([[self backFacingCamera] isFlashModeSupported:AVCaptureFlashModeAuto]) {
[[self backFacingCamera] setFlashMode:AVCaptureFlashModeAuto];
}
[[self backFacingCamera] unlockForConfiguration];
}
}
if ([[self backFacingCamera] hasTorch]) {
if ([[self backFacingCamera] lockForConfiguration:nil]) {
if ([[self backFacingCamera] isTorchModeSupported:AVCaptureTorchModeAuto]) {
[[self backFacingCamera] setTorchMode:AVCaptureTorchModeAuto];
}
[[self backFacingCamera] unlockForConfiguration];
}
}
// Init the device inputs
AVCaptureDeviceInput *newVideoInput = [[AVCaptureDeviceInput alloc] initWithDevice:[self frontFacingCamera] error:nil];
// Create a video output & configure it.
AVCaptureVideoDataOutput *newVideoDataOutput = [[AVCaptureVideoDataOutput alloc] init];
newVideoDataOutput.videoSettings = @{(NSString *)kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_32BGRA)};
// Set the output's delegate.
dispatch_queue_t queue = dispatch_queue_create("MyQueue", NULL);
[newVideoDataOutput setSampleBufferDelegate:self queue:queue];
dispatch_release(queue);
// Create session (use default AVCaptureSessionPresetHigh)
AVCaptureSession *newCaptureSession = [[AVCaptureSession alloc] init];
// Add inputs and output to the capture session
if ([newCaptureSession canAddInput:newVideoInput]) {
[newCaptureSession addInput:newVideoInput];
}
if ([newCaptureSession canAddOutput:newVideoDataOutput]) {
[newCaptureSession addOutput:newVideoDataOutput];
}
[self setVideoOutput:newVideoDataOutput];
[self setVideoInput:newVideoInput];
[self setCaptureSession:newCaptureSession];
[newVideoDataOutput release];
[newVideoInput release];
[newCaptureSession release];
// Get our view's layer.
CALayer *viewLayer = self.view.layer;
// Add the the session's preview layer.
AVCaptureVideoPreviewLayer *captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.captureSession];
captureVideoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
captureVideoPreviewLayer.frame = self.view.bounds;
[viewLayer insertSublayer:captureVideoPreviewLayer below:self.imageViewOverlay.layer];
[captureVideoPreviewLayer release];
success = YES;
return success;
}
* 重要提示:在调用输出代表后,相机会立即冻结。
任何人都可以帮我解决这个问题吗?似乎我几乎尝试了所有东西!
更新#1
根据要求,self指的是一个视图控制器,它提供会话的预览图层并管理与摄像头相关的所有内容。另外,我发布代码处理frontFacingCamera部分,这是(就像我到目前为止发布的所有代码一样)取自Apple的AVCam sample code:
// Find a camera with the specificed AVCaptureDevicePosition, returning nil if one is not found
- (AVCaptureDevice *) cameraWithPosition:(AVCaptureDevicePosition) position
{
NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
for (AVCaptureDevice *device in devices) {
if ([device position] == position) {
return device;
}
}
return nil;
}
// Find a front facing camera, returning nil if one is not found
- (AVCaptureDevice *) frontFacingCamera
{
return [self cameraWithPosition:AVCaptureDevicePositionFront];
}
答案 0 :(得分:6)
BOOL isUsingFrontFacingCamera;
- (BOOL) swapCameras
{
if ([self cameraCount] > 1) {
AVCaptureDevicePosition desiredPosition;
if (isUsingFrontFacingCamera) {
desiredPosition = AVCaptureDevicePositionBack;
} else {
desiredPosition = AVCaptureDevicePositionFront;
}
for (AVCaptureDevice *d in [AVCaptureDevice devicesWithMediaType: AVMediaTypeVideo]) {
if ([d position] == desiredPosition) {
[[self session] beginConfiguration];
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:d error:nil];
for (AVCaptureInput *oldInput in [[self session] inputs]) {
[[self session] removeInput:oldInput];
}
[[self session] addInput:input];
[[self session] commitConfiguration];
break;
}
}
isUsingFrontFacingCamera = !isUsingFrontFacingCamera;
return YES;
}
return NO;
}
来自here
的回答EDITED:来自Square Cam Apple示例代码。工作良好。测试也。 http://developer.apple.com/library/ios/#samplecode/SquareCam/Listings/SquareCam_SqareCamViewController_m.html
//使用前/后相机
- (IBAction)switchCameras:(id)sender
{
AVCaptureDevicePosition desiredPosition;
if (isUsingFrontFacingCamera)
desiredPosition = AVCaptureDevicePositionBack;
else
desiredPosition = AVCaptureDevicePositionFront;
for (AVCaptureDevice *d in [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]) {
if ([d position] == desiredPosition) {
[[previewLayer session] beginConfiguration];
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:d error:nil];
for (AVCaptureInput *oldInput in [[previewLayer session] inputs]) {
[[previewLayer session] removeInput:oldInput];
}
[[previewLayer session] addInput:input];
[[previewLayer session] commitConfiguration];
break;
}
}
isUsingFrontFacingCamera = !isUsingFrontFacingCamera;
}