62

ここでこのチュートリアルを使用します: http://www.musicalgeometry.com/?p=1297でカスタム オーバーレイと画像キャプチャを作成しましたAVCaptureSession

ユーザーが前面カメラと背面カメラを切り替えられるようにしようとしています。CaptureSessionManagerカメラを切り替えるための私のコードは次のとおりです。

- (void)addVideoInputFrontCamera:(BOOL)front {
    NSArray *devices = [AVCaptureDevice devices];
    AVCaptureDevice *frontCamera;
    AVCaptureDevice *backCamera;

    for (AVCaptureDevice *device in devices) {

        //NSLog(@"Device name: %@", [device localizedName]);

        if ([device hasMediaType:AVMediaTypeVideo]) {

            if ([device position] == AVCaptureDevicePositionBack) {
                //NSLog(@"Device position : back");
                backCamera = device;
            }
            else {
                //NSLog(@"Device position : front");
                frontCamera = device;
            }
        }
    }

    NSError *error = nil;

    if (front) {
        AVCaptureDeviceInput *frontFacingCameraDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:frontCamera error:&error];
        if (!error) {
            if ([[self captureSession] canAddInput:frontFacingCameraDeviceInput]) {
                [[self captureSession] addInput:frontFacingCameraDeviceInput];
            } else {
                NSLog(@"Couldn't add front facing video input");
            }
        }
    } else {
        AVCaptureDeviceInput *backFacingCameraDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:backCamera error:&error];
        if (!error) {
            if ([[self captureSession] canAddInput:backFacingCameraDeviceInput]) {
                [[self captureSession] addInput:backFacingCameraDeviceInput];
            } else {
                NSLog(@"Couldn't add back facing video input");
            }
        }
    }
}

今、私のカスタムオーバーレイコントローラーで、次のようにすべてを初期化しますviewDidLoad:

[self setCaptureManager:[[CaptureSessionManager alloc] init]];

[[self captureManager] addVideoInputFrontCamera:NO]; // set to YES for Front Camera, No for Back camera

[[self captureManager] addStillImageOutput];

[[self captureManager] addVideoPreviewLayer];
CGRect layerRect = [[[self view] layer] bounds];
[[[self captureManager] previewLayer] setBounds:layerRect];
[[[self captureManager] previewLayer] setPosition:CGPointMake(CGRectGetMidX(layerRect),CGRectGetMidY(layerRect))];
[[[self view] layer] addSublayer:[[self captureManager] previewLayer]];

[[_captureManager captureSession] startRunning];

カメラの切り替えボタンは、 というメソッドに接続されていますswitchCamera。私はこれを試しました:

- (void)switchCameraView:(id)sender {

    [[self captureManager] addVideoInputFrontCamera:YES]; // set to YES for Front Camera, No for Back camera

}

これを呼び出すと、NSLogからエラーが発生し、そのCaptureSessionManager理由がわかりません。でviewDidLoadを に設定するfontCameraYES、フロント カメラは表示されますが、バック カメラに切り替えることはできず、その逆も同様です。

適切に切り替える方法についてのアイデアはありますか?

4

6 に答える 6

103

最初に既存の AVCameraInput を AVCaptureSession から削除してから、新しい AVCameraInput を AVCaptureSession に追加する必要があります。以下は私にとって(ARCの下で)機能します:

-(IBAction)switchCameraTapped:(id)sender
{
    //Change camera source
    if(_captureSession)
    {
        //Indicate that some changes will be made to the session
        [_captureSession beginConfiguration];

        //Remove existing input
        AVCaptureInput* currentCameraInput = [_captureSession.inputs objectAtIndex:0];
        [_captureSession removeInput:currentCameraInput];

        //Get new input
        AVCaptureDevice *newCamera = nil;
        if(((AVCaptureDeviceInput*)currentCameraInput).device.position == AVCaptureDevicePositionBack)
        {
            newCamera = [self cameraWithPosition:AVCaptureDevicePositionFront];
        }
        else
        {
            newCamera = [self cameraWithPosition:AVCaptureDevicePositionBack];
        }

        //Add input to session
        NSError *err = nil;
        AVCaptureDeviceInput *newVideoInput = [[AVCaptureDeviceInput alloc] initWithDevice:newCamera error:&err];
        if(!newVideoInput || err)
        {
            NSLog(@"Error creating capture device input: %@", err.localizedDescription);
        }
        else
        {
            [_captureSession addInput:newVideoInput];
        }

        //Commit all the configuration changes at once
        [_captureSession commitConfiguration];
    }
}

// Find a camera with the specified 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;
}
于 2014-02-12T10:18:03.383 に答える
11

以前の回答に基づいて、いくつかの検証と1つの特定の変更を加えて独自のバージョンを作成しました.現在のカメラ入力はキャプチャセッションの入力の最初のオブジェクトではない可能性があるため、これを変更しました:

//Remove existing input
AVCaptureInput* currentCameraInput = [self.captureSession.inputs objectAtIndex:0];
[self.captureSession removeInput:currentCameraInput];

これに(すべてのビデオタイプ入力を削除します):

for (AVCaptureDeviceInput *input in self.captureSession.inputs) {
    if ([input.device hasMediaType:AVMediaTypeVideo]) {
        [self.captureSession removeInput:input];
        break;
    }
}

コード全体は次のとおりです。

if (!self.captureSession) return;

[self.captureSession beginConfiguration];

AVCaptureDeviceInput *currentCameraInput;

// Remove current (video) input
for (AVCaptureDeviceInput *input in self.captureSession.inputs) {
    if ([input.device hasMediaType:AVMediaTypeVideo]) {
        [self.captureSession removeInput:input];

        currentCameraInput = input;
        break;
    }
}

if (!currentCameraInput) return;

// Switch device position
AVCaptureDevicePosition captureDevicePosition = AVCaptureDevicePositionUnspecified;
if (currentCameraInput.device.position == AVCaptureDevicePositionBack) {
    captureDevicePosition = AVCaptureDevicePositionFront;
} else {
    captureDevicePosition = AVCaptureDevicePositionBack;
}

// Select new camera
AVCaptureDevice *newCamera;
NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];

for (AVCaptureDevice *captureDevice in devices) {
    if (captureDevice.position == captureDevicePosition) {
        newCamera = captureDevice;
    }
}

if (!newCamera) return;

// Add new camera input
NSError *error;
AVCaptureDeviceInput *newVideoInput = [[AVCaptureDeviceInput alloc] initWithDevice:newCamera error:&error];
if (!error && [self.captureSession canAddInput:newVideoInput]) {
    [self.captureSession addInput:newVideoInput];
}

[self.captureSession commitConfiguration];
于 2016-04-12T17:16:42.420 に答える