Locking iOS Camera Exposure Crashes - ios

I have the following code:
-(void) startCameraCapture {
// start capturing frames
// Create the AVCapture Session
session = [[AVCaptureSession alloc] init];
// create a preview layer to show the output from the camera
AVCaptureVideoPreviewLayer *previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:session];
// Specify that the video should be stretched to fill the layer’s bounds.
previewLayer.videoGravity = AVLayerVideoGravityResize;
//previewView.frame = CGRectMake(126.0, 164.0, 64.0, 75.0);
previewLayer.frame = previewView.frame;
[previewView.layer addSublayer:previewLayer];
// Get the default camera device
AVCaptureDevice* camera = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
// get the current settings
[appDelegate loadSettings];
[session startRunning];
}
Is there a way I can lock the exposure of a camera device to only allow the screen to adjust to a certain brightness?
Sorry if I am not asking this right.
Thank you.
EDIT:
I tried adding:
[camera setExposureModeCustomWithDuration:CMTimeMake(1,1) ISO:100 completionHandler:nil];
but that only results in the app crashing at that line.

According to Apple's doc:
An NSGenericException exception is thrown if this method is invoked without first obtaining exclusive access to the receiver using lockForConfiguration:.
So add this line in front:
[camera lockForConfiguration:nil];

Related

Is anything special required to use an AVCaptureVideoPreviewLayer in a multitasking app in iPadOS? [duplicate]

I have created a camera using AVCaptureSession. I have configured that for both Photo and Video recording modes.
Camera and App is running fine. Also I allowed background music play (If user play song using Music App in iPhone) while open camera or recording video. It is also working fine. (Attached image 2)
I allowed background Music play with the help of this code
AVAudioSession *session1 = [AVAudioSession sharedInstance];
[session1 setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionMixWithOthers|AVAudioSessionCategoryOptionDefaultToSpeaker|AVAudioSessionCategoryOptionAllowBluetooth error:nil];
[session1 setActive:YES error:nil];
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
Now if i receive a call, minimize phone call screen by tapping on Home button and open app and want to open camera screen to capture image / record video, It opens but freeze with a image (Attached image(1)).
Now my requirement is, i want to capture image / record video while on phone call. I looked for another apps, and Snapchat is doing same, and i am able to record video while i am on call.
please help me, how can i achieve this.
You need to use the AVCaptureSessionWasInterruptedNotification and AVCaptureSessionInterruptionEndedNotification callbacks and disconnect the audio capture while the session is interrupted:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(sessionWasInterrupted:) name:AVCaptureSessionWasInterruptedNotification object:self.session];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(sessionInterruptionEnded:) name:AVCaptureSessionInterruptionEndedNotification object:self.session];
// note that self.session is an AVCaptureSession
-
- (void)sessionWasInterrupted:(NSNotification *)notification {
NSLog(#"session was interrupted");
AVCaptureDevice *device = [[self audioInput] device];
if ([device hasMediaType:AVMediaTypeAudio]) {
[[self session] removeInput:[self audioInput]];
[self setAudioInput:nil];
}
}
- (void)sessionInterruptionEnded:(NSNotification *)notification {
NSLog(#"session interuption ended");
}
// note that [self audioInput] is a getter for an AVCaptureDeviceInput
This will allow the camera to continue running and allows it to capture stills / silent video
Now as for how to reconnect the audio after the call ends.. let me know if you figure it out, seemed impossible as of iOS 10: Callback when phone call ends? (to resume AVCaptureSession)

AVCaptureVideoPreviewLayer blinks when changing sessionPreset on a running AVCaptureSession

I'm running a session with AVCaptureSessionPresetMediumto process the frames, when I find what I need I want to capture a stills image with AVCaptureSessionPresetPhoto. I'm changing the sessionPreset with the code
dispatch_async(_captureSessionQueue, ^{
[_captureSession beginConfiguration];
if ([_captureSession canSetSessionPreset:AVCaptureSessionPresetPhoto])
{
_captureSession.sessionPreset = AVCaptureSessionPresetPhoto;
}
[_captureSession commitConfiguration];
});
When this code is called the screen(AVCaptureVideoPreviewLayer) "blinks".
I can't use highResolutionStillImageOutputEnabled because I need to support iOS 7 and devices lower than iPhone 6. Does any one have an idea why this blink happens?

Is it possible to auto-adjust the image brightness in iPhone?

I use iPhone camera to capture images in my iOS APP.
AVCaptureVideoDataOutputSampleBufferDelegate is used to get images from iPhone camera.
A part of the program is shown below.
AVCaptureDevice *videoDevice = [AVCamViewController deviceWithMediaType:AVMediaTypeVideo preferringPosition:AVCaptureDevicePositionBack];
AVCaptureDeviceInput *videoDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:videoDevice error:&error];
if (error)
{
NSLog(#"%#", error);
}
if ([session canAddInput:videoDeviceInput])
{
[session addInput:videoDeviceInput];
[self setVideoDeviceInput:videoDeviceInput];
dispatch_async(dispatch_get_main_queue(), ^{
// Why are we dispatching this to the main queue?
// Because AVCaptureVideoPreviewLayer is the backing layer for AVCamPreviewView and UIView can only be manipulated on main thread.
// Note: As an exception to the above rule, it is not necessary to serialize video orientation changes on the AVCaptureVideoPreviewLayer’s connection with other session manipulation.
//[self previewView] layer
[[(AVCaptureVideoPreviewLayer *)[[self previewView] layer] connection] setVideoOrientation:(AVCaptureVideoOrientation)[self interfaceOrientation]];
});
}
Sometimes, the environment is dark a bit. In the iPhone camera app, it can brighten the image by tapping the iPhone screen on the darker part. But I don't like such suer's involvement.
I check RGB intensity, once I realise the brightness is not enough, I like to brighten the image by adjusting the camera parameters (such as camera exposure, etc) in my program. Is it possible in iPhone programming?
Thanks
I haven't work on AVFoundation much but you can find more details here.
I hope this will be useful for you.

Unable to Set Session Preset While Capture Session Running in iOS 7

I have the following code that no longer works in iOS 7 for changing the sessionPreset of a capture session while it is still running (but not capturing video). This worked on iOS 6.x, but on 7 the video preview freezes.
I've tried removing begin/commit configuration, as well as locking the input device and unlocking after. I've also tried calling beginSession again after the commitConfiguration, but this causes the device to start capturing video.
Is this a bug or am I doing something wrong?
- (void)setVideoCaptureSessionPreset:(NSString *)videoCaptureSessionPreset
{
if (_captureSession.sessionPreset == videoCaptureSessionPreset) return;
if (![_captureSession canSetSessionPreset:videoCaptureSessionPreset])
{
TFLog(#"%s Device cannot set preset to: %#", __PRETTY_FUNCTION__, videoCaptureSessionPreset);
return;
}
[_captureSession beginConfiguration];
_captureSession.sessionPreset = videoCaptureSessionPreset;
[_captureSession commitConfiguration];
}
Edit: Not only does this cause the video preview to freeze, it causes the entire phone lock up (background no longer displayed on home screen, app cannot restart, and eventually the entire phone has to be hard-reset).
In iOS 7 and up, the solution is to use the new AVCaptureDevice activeFormat API and set the session preset to AVCaptureSessionPresetInputPriority. When you change the active format, you have to wrap your startRunning in the lockForConfiguration like so:
if ([_videoCaptureDevice lockForConfiguration:nil])
{
_videoCaptureDevice.activeFormat = format
[_captureSession startRunning];
[_videoCaptureDevice unlockForConfiguration];
}

iOS 7 UIImagePickerController Camera No Image

For some reason the first time I open the UIImagePickerController in camera mode on my app it comes up blank. I have to close and reopen that view to get the camera feed to start working. I'm using the standard code that works in iOS 6 perfectly for camera capture. From the sample below I'm firing the capturePhoto: method. Anyone else running into this jenkiness with the iOS 7 camera? I checked the Apple dev forums but its near impossible to find answers there.
- (IBAction)capturePhoto:(id)sender {
[self doImagePickerForType:UIImagePickerControllerSourceTypeCamera];
}
- (void)doImagePickerForType:(UIImagePickerControllerSourceType)type {
if (!_imagePicker) {
_imagePicker = [[UIImagePickerController alloc] init];
_imagePicker.mediaTypes = #[(NSString*)kUTTypeImage];
_imagePicker.delegate = self;
}
_imagePicker.sourceType = type;
[self presentViewController:_imagePicker animated:YES completion:nil];
}
I'm also using UIImagePickerController and ran into the same issue with a blank screen. I'd like to expand a little on what klaudz mentioned regarding iOS 7 authorization for the camera.
Reference:
https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVCaptureDevice_Class/Reference/Reference.html
"Recording audio always requires explicit permission from the user; recording video also requires user permission on devices sold in certain regions."
Here is some code fragments you can start with to check to see if you have permission for the camera and request it if your app hadn't previously requested it. If you are denied due to an earlier request, your app may need to put up a notice to the user to go into settings to manually enable access as klaudz pointed out.
iOS 7 example
NSString *mediaType = AVMediaTypeVideo; // Or AVMediaTypeAudio
AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:mediaType];
// This status is normally not visible—the AVCaptureDevice class methods for discovering devices do not return devices the user is restricted from accessing.
if(authStatus == AVAuthorizationStatusRestricted){
NSLog(#"Restricted");
}
// The user has explicitly denied permission for media capture.
else if(authStatus == AVAuthorizationStatusDenied){
NSLog(#"Denied");
}
// The user has explicitly granted permission for media capture, or explicit user permission is not necessary for the media type in question.
else if(authStatus == AVAuthorizationStatusAuthorized){
NSLog(#"Authorized");
}
// Explicit user permission is required for media capture, but the user has not yet granted or denied such permission.
else if(authStatus == AVAuthorizationStatusNotDetermined){
[AVCaptureDevice requestAccessForMediaType:mediaType completionHandler:^(BOOL granted) {
// Make sure we execute our code on the main thread so we can update the UI immediately.
//
// See documentation for ABAddressBookRequestAccessWithCompletion where it says
// "The completion handler is called on an arbitrary queue."
//
// Though there is no similar mention for requestAccessForMediaType, it appears it does
// the same thing.
//
dispatch_async(dispatch_get_main_queue(), ^{
if(granted){
// UI updates as needed
NSLog(#"Granted access to %#", mediaType);
}
else {
// UI updates as needed
NSLog(#"Not granted access to %#", mediaType);
}
});
}];
}
else {
NSLog(#"Unknown authorization status");
}
In iOS 7, an app could access the camera before getting authorize of the user.
When an app accesses the camera the first time, iOS show an alert view to ask user.
Users could also set the authorize in Settings--Privacy--Camera--[Your app's name].
The camera will stay in a black blank view if the switch is off.
If you call the camera by using AVCaptureDeviceInput, you can check like:
NSError *inputError = nil;
AVCaptureDeviceInput *captureInput =
[AVCaptureDeviceInput deviceInputWithDevice:inputDevice error:&inputError];
if (inputError &&
inputError.code == AVErrorApplicationIsNotAuthorizedToUseDevice)
{
// not authorized
}
If you call by using UIImagePickerController, I am still looking for a way to check whether got the authorize.
I tried these two methods:
[UIImagePickerController isSourceTypeAvailable:]
[UIImagePickerController isCameraDeviceAvailable:]
but they did't work that they all returned YES.
UPDATE
Thanks for Scott's expanding. [AVCaptureDevice authorizationStatusForMediaType:] is a better way to check.
AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
if (authStatus == AVAuthorizationStatusAuthorized) {
// successful
} else {
// failed, such as
// AVAuthorizationStatusNotDetermined
// AVAuthorizationStatusRestricted
// AVAuthorizationStatusNotDetermined
}
But remember to check the iOS version, because [AVCaptureDevice authorizationStatusForMediaType:] and AVAuthorizationStatus are available above iOS 7.
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
// code for AVCaptureDevice auth checking
}
I experienced the exact same problem, and tried every solution on the Internet with no luck. But finally I found out it was the background thread prevented the camera preview to show up. If you happen to have background thread running while trying to open the camera as I do, try to block the background thread and see what happens. Hope you can get around it.
I came across this control AQPhotoPicker. It's quite easy to use, and hopefully it will help you

Resources