AVCaptureDevice can't capture back camera - ios

I'm trying to use the back camera off my iphone with AVCaptureDevice. I tried both AVCaptureDevicePositionBack and AVCaptureDevicePositionFront but it still uses the FrontCamera no matter what.
This is my code:
- (void)setupCamera
{
_captureDevice = nil;
NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
for (AVCaptureDevice *device in devices)
{
if (device.position == AVCaptureDevicePositionBack)
{
_captureDevice = device;
break;
}
}
}
- (void)turnCameraOn
{
NSError *error;
_session = [[AVCaptureSession alloc] init];
[_session beginConfiguration];
[_session setSessionPreset:AVCaptureSessionPresetMedium];
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:_captureDevice error:&error];
if (input == nil)
NSLog(#"%#", error);
[_session addInput:input];
AVCaptureVideoDataOutput *output = [[AVCaptureVideoDataOutput alloc] init];
[output setSampleBufferDelegate:self queue:dispatch_queue_create("myQueue", NULL)];
output.videoSettings = #{(id)kCVPixelBufferPixelFormatTypeKey:#(kCVPixelFormatType_32BGRA)};
output.alwaysDiscardsLateVideoFrames = YES;
[_session addOutput:output];
[_session commitConfiguration];
[_session startRunning];
}
- (void)turnCameraOff
{
[_session stopRunning];
_session = nil;
}

Use the following code:
AVCaptureDevicePosition desiredPosition;
if (isUsingFrontFacingCamera)
desiredPosition = AVCaptureDevicePositionBack;
else
desiredPosition = AVCaptureDevicePositionFront;
for (AVCaptureDevice *d in [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]) {
if ([d position] == desiredPosition) {
[[captureVideoPreviewLayer session] beginConfiguration];
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:d error:nil];
for (AVCaptureInput *oldInput in [[captureVideoPreviewLayer session] inputs]) {
[[captureVideoPreviewLayer session] removeInput:oldInput];
}
[[captureVideoPreviewLayer session] addInput:input];
[[captureVideoPreviewLayer session] commitConfiguration];
break;
}
}

Related

custom camera view switch camera front back

i am using custom camera view for my app. but when i am changing my view its not responding well i can't able to see my view whatever changes its stop showing live view if i am not changing then its working just fine ,i don`t know i try alot were i am doing mistake or missing something. my code is
-(void)abdbcam
{
session=[[AVCaptureSession alloc]init];
[session setSessionPreset:AVCaptureSessionPresetPhoto];
/* AVCaptureDevice *inputDevice=[AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
NSError *error;
AVCaptureDeviceInput *deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:inputDevice error:&error];
if([session canAddInput:deviceInput])
{
[session addInput:deviceInput];
}*/
NSArray *devices = [AVCaptureDevice devices];
AVCaptureDevice *frontcamera;
AVCaptureDevice *backcamera;
for (AVCaptureDevice *device in devices)
{
NSLog(#"Device Nmae %#",[device localizedName]);
if ([device hasMediaType:AVMediaTypeVideo])
{
if ([device position] == AVCaptureDevicePositionBack)
{
NSLog(#"device position: bAck");
backcamera = device;
}
else
{
NSLog(#"device position : front");
frontcamera = device;
}
}
}
if (!FrontCamera)
{
NSError *error = nil;
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:backcamera error:&error];
if (!input)
{
NSLog(#"error: trying to open camera: %#", error);
}
[session addInput:input];
}
if (FrontCamera) {
NSError *error = nil;
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:frontcamera error:&error];
if (!input) {
NSLog(#"error: trying to open camera: %#", error);
}
[session addInput:input];
}
AVCaptureVideoPreviewLayer *previewLayer=[[AVCaptureVideoPreviewLayer alloc]initWithSession:session];
[previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
CALayer *rootLayer = [[self view]layer];
[rootLayer setMasksToBounds:YES];
CGRect frame=self.camerarole.frame;
[previewLayer setFrame:frame];
[rootLayer insertSublayer:previewLayer atIndex:0];
stillImageOutput=[[AVCaptureStillImageOutput alloc]init];
NSDictionary *outputSetting=[[NSDictionary alloc]initWithObjectsAndKeys:AVVideoCodecJPEG,AVVideoCodecKey, nil];
[stillImageOutput setOutputSettings:outputSetting];
[session addOutput:stillImageOutput];
[session startRunning];
}
// now my segment controller code is
- (IBAction)switchcamera:(id)sender {
if (cameraswitch.selectedSegmentIndex == 0) {
FrontCamera = YES;
[self abdbcam];
}
if (cameraswitch.selectedSegmentIndex == 1) {
[self abdbcam];
}
please have a look and suggest me if i am doing any mistake
So I've already implemented custom camera switch. Check this code below:
isUsingFrontFacingCamera is a bool flag, too detect which camera are you using at the moment
- (void) switchCam{
if (![self cameraIsRunning])
return;
AVCaptureDevicePosition desiredPosition;
if (isUsingFrontFacingCamera)
desiredPosition = AVCaptureDevicePositionBack;
else
desiredPosition = AVCaptureDevicePositionFront;
for (AVCaptureDevice *d in [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]) {
if ([d position] == desiredPosition) {
[[captureVideoPreviewLayer session] beginConfiguration];
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:d error:nil];
for (AVCaptureInput *oldInput in [[captureVideoPreviewLayer session] inputs]) {
[[captureVideoPreviewLayer session] removeInput:oldInput];
}
[[captureVideoPreviewLayer session] addInput:input];
[[captureVideoPreviewLayer session] commitConfiguration];
break;
}
}
isUsingFrontFacingCamera = !isUsingFrontFacingCamera;
}
This code worked for while i am working. i am posting this because it will be helpful for anyone.
NSArray *inputs = session.inputs;
for ( AVCaptureDeviceInput *input in inputs ) {
AVCaptureDevice *device = input.device;
if ( [device hasMediaType:AVMediaTypeVideo] ) {
AVCaptureDevicePosition position = device.position;
AVCaptureDevice *newCamera = nil;
AVCaptureDeviceInput *newInput = nil;
if (position == AVCaptureDevicePositionFront)
newCamera = [self cameraWithPosition:AVCaptureDevicePositionBack];
else
newCamera = [self cameraWithPosition:AVCaptureDevicePositionFront];
newInput = [AVCaptureDeviceInput deviceInputWithDevice:newCamera error:nil];
// beginConfiguration ensures that pending changes are not applied immediately
[session beginConfiguration];
[session removeInput:input];
[session addInput:newInput];
// Changes take effect once the outermost commitConfiguration is invoked.
[session commitConfiguration];
break;
}
}
- (AVCaptureDevice *)cameraWithPosition:(AVCaptureDevicePosition)position
{
NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
for ( AVCaptureDevice *device in devices )
if ( device.position == position )
return device;
return nil;
}

AVCaptureSession doesn't read PDF417 with front camera but works with the back

I'm trying to do an AVCaptureSession on the front camera to read a PDF417 barcode, but it refuses to read the same barcodes on the front camera that it will read no problem on the back. Is there a setting I'm missing or does it have to do with the front camera appearing "mirrored?"
I tried the same thing with a QR code and it works no problem on both the front and back cameras.
_session = [[AVCaptureSession alloc] init];
NSArray *videoDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
for( AVCaptureDevice *device in videoDevices )
{
if( device.position == AVCaptureDevicePositionFront )
{
_device = device;
break;
}
}
// couldn't find one on the front, so just get the default video device.
if( ! _device)
{
_device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
}
// _device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
NSError *error = nil;
if( _device.isAutoFocusRangeRestrictionSupported )
{
if( [_device lockForConfiguration:&error] )
{
[_device setAutoFocusRangeRestriction:AVCaptureAutoFocusRangeRestrictionNear];
[_device unlockForConfiguration];
}
}
_input = [AVCaptureDeviceInput deviceInputWithDevice:_device error:&error];
if (_input) {
[_session addInput:_input];
} else {
NSLog(#"Error: %#", error);
}
_output = [[AVCaptureMetadataOutput alloc] init];
[_output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
[_session addOutput:_output];
// _output.metadataObjectTypes = [_output availableMetadataObjectTypes];
_output.metadataObjectTypes = #[AVMetadataObjectTypePDF417Code ];
_prevLayer = [AVCaptureVideoPreviewLayer layerWithSession:_session];
_prevLayer.frame = self.view.bounds;
_prevLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
[self updatePreviewLayerForOrientation:[[UIApplication sharedApplication] statusBarOrientation] ];
[self.view.layer addSublayer:_prevLayer];
[_session startRunning];

Get BLACK photo when capture with AVFoundation

I make a Photo Capture and Video Record customise view (2 features in one view).
Init view:
_session = [[AVCaptureSession alloc] init];
_session.sessionPreset = AVCaptureSessionPreset640x480;
_captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:_session];
_captureVideoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
_captureVideoPreviewLayer.frame = _previewView.layer.bounds; // parent of layer
[_previewView.layer addSublayer:_captureVideoPreviewLayer];
AVCaptureDevice *videoDevice = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo][0];
if ([videoDevice isFlashAvailable] && videoDevice.flashActive && [videoDevice lockForConfiguration:nil]) {
videoDevice.flashMode = AVCaptureFlashModeOff;
[videoDevice unlockForConfiguration];
}
NSError * error = nil;
AVCaptureDeviceInput * input = [AVCaptureDeviceInput deviceInputWithDevice:videoDevice error:&error];
if (!input) {
if (_delegate && [_delegate respondsToSelector:#selector(customCameraViewDidLoadFailed)]) {
[_delegate customCameraViewDidLoadFailed];
}
}
if ([_session canAddInput:input]) {
[_session addInput:input];
}
AVCaptureDevice *audioDevice = [[AVCaptureDevice devicesWithMediaType:AVMediaTypeAudio] firstObject];
AVCaptureDeviceInput *audioDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:audioDevice error:&error];
if (!audioDeviceInput) {
if (_delegate && [_delegate respondsToSelector:#selector(customCameraViewDidLoadFailed)]) {
[_delegate customCameraViewDidLoadFailed];
}
}
if ([_session canAddInput:audioDeviceInput]) {
[_session addInput:audioDeviceInput];
}
_stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
NSDictionary * outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys:AVVideoCodecJPEG, AVVideoCodecKey, nil];
[_stillImageOutput setOutputSettings:outputSettings];
if ([_session canAddOutput:_stillImageOutput]) {
[_session addOutput:_stillImageOutput];
}
_movieFileOutput = [[AVCaptureMovieFileOutput alloc] init];
if ([_session canAddOutput:_movieFileOutput])
{
[_session addOutput:_movieFileOutput];
AVCaptureConnection *connection = [_movieFileOutput connectionWithMediaType:AVMediaTypeVideo];
if ([connection isVideoStabilizationSupported]) {
[connection setEnablesVideoStabilizationWhenAvailable:YES];
}
}
[_session startRunning];
In Capture method:
_session.sessionPreset = AVCaptureSessionPreset640x480;
_isCapturing = YES;
AVCaptureConnection *videoConnection = nil;
for (AVCaptureConnection *connection in _stillImageOutput.connections)
{
for (AVCaptureInputPort *port in [connection inputPorts])
{
if ([[port mediaType] isEqual:AVMediaTypeVideo] )
{
videoConnection = connection;
break;
}
}
if (videoConnection) {
break;
}
}
[_loadingView startAnimating];
[_stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler: ^(CMSampleBufferRef imageSampleBuffer, NSError *error)
{
NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer];
UIImage * capturedImage = [[UIImage alloc]initWithData:imageData scale:1];
_isCapturing = NO;
imageData = nil;
[_loadingView stopAnimating];
if (_delegate && [_delegate respondsToSelector:#selector(customCameraView:didFinishCaptureImage:)]) {
[_delegate customCameraView:self didFinishCaptureImage:capturedImage];
}
}];
I'm facing a problem that, the first photo/video when I capture, it's always BLACK photo, video.
Can you help me to solve this problem.
Thanks a lot!

Rotating AV video preview area on iPad

I'd like to use the video preview layer on the iPhone and the iPad, but on the iPad it doesn't rotate and it has the wrong height.
Here is the code I have:
- (void)capture
{
AVCaptureSession *session = [[AVCaptureSession alloc] init];
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
NSError *error = nil;
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device
error:&error];
if (!input)
{
NSLog(#"Error: %#", error);
return;
}
[session addInput:input];
//Turn on point autofocus for middle of view
[device lockForConfiguration:&error];
CGPoint point = CGPointMake(0.5,0.5);
[device setFocusPointOfInterest:point];
[device setFocusMode:AVCaptureFocusModeContinuousAutoFocus];
[device unlockForConfiguration];
//Add the metadata output device
AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc] init];
[output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
[session addOutput:output];
NSLog(#"%lu",output.availableMetadataObjectTypes.count);
for (NSString *s in output.availableMetadataObjectTypes)
NSLog(#"%#",s);
//You should check here to see if the session supports these types, if they aren't support you'll get an exception
output.metadataObjectTypes = #[AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeUPCECode, AVMetadataObjectTypeQRCode];
output.rectOfInterest = self.livevideo.bounds;
AVCaptureVideoPreviewLayer *newCaptureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
newCaptureVideoPreviewLayer.frame = self.view.layer.bounds;
newCaptureVideoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
[self.livevideo.layer insertSublayer:newCaptureVideoPreviewLayer above:self.livevideo.layer];
[session startRunning];
}
And:
- (void)captureFront
{
AVCaptureSession *session = [[AVCaptureSession alloc] init];
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
NSError *error = nil;
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device
error:&error];
if (!input)
{
NSLog(#"Error: %#", error);
return;
}
[session addInput:input];
//Turn on point autofocus for middle of view
[device lockForConfiguration:&error];
CGPoint point = CGPointMake(0.5,0.5);
[device setFocusPointOfInterest:point];
[device setFocusMode:AVCaptureFocusModeContinuousAutoFocus];
[device unlockForConfiguration];
//Add the metadata output device
AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc] init];
[output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
[session addOutput:output];
NSLog(#"%lu",output.availableMetadataObjectTypes.count);
for (NSString *s in output.availableMetadataObjectTypes)
NSLog(#"%#",s);
//You should check here to see if the session supports these types, if they aren't support you'll get an exception
output.metadataObjectTypes = #[AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeUPCECode, AVMetadataObjectTypeQRCode];
output.rectOfInterest = self.livevideo.bounds;
AVCaptureVideoPreviewLayer *newCaptureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
newCaptureVideoPreviewLayer.frame = self.view.layer.bounds;
newCaptureVideoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
[session startRunning];
}
Image

Video Saving in the wrong orientation AVCaptureSession

I'm trying to record a video (without displaying the camera) and save it. But the video being saved is not saving in the right orientation. I've tried forcing the UIViewController to be a certain orientation but that didn't help. All videos are being recorded in portrait. My code is below:
session = [[AVCaptureSession alloc] init];
[session beginConfiguration];
session.sessionPreset = AVCaptureSessionPresetHigh;
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
for (AVCaptureDevice *cam in [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo])
{
if (cam.position == AVCaptureDevicePositionFront)
device = cam;
}
NSError *error = nil;
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
if (!input) {
// Handle the error appropriately.
NSLog(#"ERROR: trying to open camera: %#", error);
}
AVCaptureDevice *audioDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
AVCaptureDeviceInput * audioInput = [AVCaptureDeviceInput deviceInputWithDevice:audioDevice error:nil];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectoryPath = [paths objectAtIndex:0];
NSString *outputpathofmovie = [[documentsDirectoryPath stringByAppendingPathComponent:#"RecordedVideo"] stringByAppendingString:#".mp4"];
outputURL = [[NSURL alloc] initFileURLWithPath:outputpathofmovie];
[self deleteTempVideos];
[session addInput:input];
[session addInput:audioInput];
[session commitConfiguration];
[session startRunning];
movieFileOutput = [[AVCaptureMovieFileOutput alloc] init];
NSLog(#"%#", movieFileOutput.connections);
AVCaptureConnection *videoConnection = nil;
for ( AVCaptureConnection *connection in [movieFileOutput connections] )
{
NSLog(#"%#", connection);
for ( AVCaptureInputPort *port in [connection inputPorts] )
{
NSLog(#"%#", port);
if ( [[port mediaType] isEqual:AVMediaTypeVideo] )
{
videoConnection = connection;
}
}
}
if([videoConnection isVideoOrientationSupported]) // **Here it is, its always false**
{
[videoConnection setVideoOrientation:[[UIDevice currentDevice] orientation]];
}
NSLog(#"%#", videoConnection);
[session addOutput:movieFileOutput];
[movieFileOutput startRecordingToOutputFileURL:outputURL recordingDelegate:self];
It turns out you have to add the connections' orientation to the AVCaptureMovieFileOutput after it is added to the session.
session = [[AVCaptureSession alloc] init];
[session beginConfiguration];
session.sessionPreset = AVCaptureSessionPresetHigh;
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
for (AVCaptureDevice *cam in [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo])
{
if (cam.position == AVCaptureDevicePositionFront)
device = cam;
}
NSError *error = nil;
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
if (!input) {
// Handle the error appropriately.
NSLog(#"ERROR: trying to open camera: %#", error);
}
AVCaptureDevice *audioDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
AVCaptureDeviceInput * audioInput = [AVCaptureDeviceInput deviceInputWithDevice:audioDevice error:nil];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectoryPath = [paths objectAtIndex:0];
NSString *outputpathofmovie = [[documentsDirectoryPath stringByAppendingPathComponent:#"RecordedVideo"] stringByAppendingString:#".mp4"];
outputURL = [[NSURL alloc] initFileURLWithPath:outputpathofmovie];
[self deleteTempVideos];
[session addInput:input];
[session addInput:audioInput];
[session commitConfiguration];
[session startRunning];
movieFileOutput = [[AVCaptureMovieFileOutput alloc] init];
[session addOutput:movieFileOutput];
AVCaptureConnection *videoConnection = nil;
for ( AVCaptureConnection *connection in [movieFileOutput connections] )
{
NSLog(#"%#", connection);
for ( AVCaptureInputPort *port in [connection inputPorts] )
{
NSLog(#"%#", port);
if ( [[port mediaType] isEqual:AVMediaTypeVideo] )
{
videoConnection = connection;
}
}
}
if([videoConnection isVideoOrientationSupported]) // **Here it is, its always false**
{
[videoConnection setVideoOrientation:[[UIDevice currentDevice] orientation]];
}
[movieFileOutput startRecordingToOutputFileURL:outputURL recordingDelegate:self];
**
Try changing its orientation just before starting recording.
**
if let videoConnection = fileOutput.connection(with: .video) {
let newOrientation: AVCaptureVideoOrientation
switch UIDevice.current.orientation {
case .portrait:
newOrientation = .portrait
case .portraitUpsideDown:
newOrientation = .portraitUpsideDown
case .landscapeLeft:
newOrientation = .landscapeRight
case .landscapeRight:
newOrientation = .landscapeLeft
default :
newOrientation = .portrait
}
videoConnection.videoOrientation = newOrientation
self.fileOutput.startRecording(to: URL(fileURLWithPath: filePath), recordingDelegate: self)
}
where,
var fileOutput : AVCaptureMovieFileOutput!
Try something like this:
#import <AVFoundation/AVFoundation.h>
AVCaptureConnection *captureConnection = <#A capture connection#>;
if ([captureConnection isVideoOrientationSupported])
{
AVCaptureVideoOrientation orientation = AVCaptureVideoOrientationLandscapeLeft;
[captureConnection setVideoOrientation:orientation];
}
http://developer.apple.com/library/ios/#qa/qa1744/_index.html#//apple_ref/doc/uid/DTS40011134
Thank you Destiny Dawn, incase anyone is looking for the code for Xamarin ios:
AVCaptureConnection videoConnection = null;
foreach(AVCaptureConnection connection in _videoOutput.Connections)
{
foreach ( AVCaptureInputPort port in connection.InputPorts)
{
if (port.MediaType == AVMediaType.Video)
{
videoConnection = connection;
break;
}
}
}
if (videoConnection != null) {
if (videoConnection.SupportsVideoOrientation) {
videoConnection.VideoOrientation = AVCaptureVideoOrientation.LandscapeRight;
}
}

Resources