I am developing a simple app in which i need to make my camera flash mode to be on continuously not only when capturing image. And the mode of operation should be camera not video recording. Is it possible ? If so than how. Please help me with some code
You can use the below method to toggle camera flash on and off.
- (void)toggleFlashlight
{
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
if (device.torchMode == AVCaptureTorchModeOff)
{
// Create an AV session
AVCaptureSession *session = [[AVCaptureSession alloc] init];
// Create device input and add to current session
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error: nil];
[session addInput:input];
// Create video output and add to current session
AVCaptureVideoDataOutput *output = [[AVCaptureVideoDataOutput alloc] init];
[session addOutput:output];
// Start session configuration
[session beginConfiguration];
[device lockForConfiguration:nil];
// Set torch to on
[device setTorchMode:AVCaptureTorchModeOn];
[device unlockForConfiguration];
[session commitConfiguration];
// Start the session
[session startRunning];
// Keep the session around
[self setAVSession:session];
[output release];
}
else
{
[AVSession stopRunning];
[AVSession release],
AVSession = nil;
}
}
You can also use the following method along with the display of camera,
- (void) toggleFlashlight {
// check if flashlight available
Class captureDeviceClass = NSClassFromString(#"AVCaptureDevice");
if (captureDeviceClass != nil) {
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
if ([device hasTorch] && [device hasFlash]){
[device lockForConfiguration:nil];
if (device.torchMode == AVCaptureTorchModeOff)
{
[device setTorchMode:AVCaptureTorchModeOn];
[device setFlashMode:AVCaptureFlashModeOn];
}
else
{
[device setTorchMode:AVCaptureTorchModeOff];
[device setFlashMode:AVCaptureFlashModeOff];
}
[device unlockForConfiguration];
}
}
}
Source
Use this for Swift 4
func toggleFlash() {
guard let device = AVCaptureDevice.default(for: AVMediaType.video)
else {return}
if device.hasTorch {
do {
try device.lockForConfiguration()
if device.torchMode == AVCaptureDevice.TorchMode.on {
device.torchMode = AVCaptureDevice.TorchMode.off
//AVCaptureDevice.TorchModeAVCaptureDevice.TorchMode.off
} else {
do {
try device.setTorchModeOn(level: 1.0)
} catch {
print(error)
}
}
device.unlockForConfiguration()
} catch {
print(error)
}
}
}
Related
I'm having problem with recording video+audio on ios7;
I have created the application on ios6.1.3 and everything worked perfect until I have updated my iphone to ios7.
I use AVCaptureSession and connect input devices(microphone and camera);
Please see my code below, this is how I setup devices:
- (void)setupSessionWithPreset:(NSString *)preset withCaptureDevice:(AVCaptureDevicePosition)cd withTorchMode:(AVCaptureTorchMode)tm withError:(NSError **)error
{
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
[audioSession setActive:YES error:nil];
// NSLog(#"sessionError :%#", sessionError);
self.movieFileOutput = [[AVCaptureMovieFileOutput alloc] init];
[self startNotificationObservers];
if(setupComplete)
{
*error = [NSError errorWithDomain:#"Setup session already complete." code:102 userInfo:nil];
return;
}
setupComplete = YES;
AVCaptureDevice *captureDevice = [self cameraWithPosition:cd];
if ([captureDevice hasTorch])
{
if ([captureDevice lockForConfiguration:nil])
{
if ([captureDevice isTorchModeSupported:tm])
{
[captureDevice setTorchMode:AVCaptureTorchModeOff];
}
[captureDevice unlockForConfiguration];
}
}
self.captureSession = [[AVCaptureSession alloc] init];
self.captureSession.sessionPreset = preset;
NSError *errorVI = nil;
self.videoInput = [[AVCaptureDeviceInput alloc] initWithDevice:captureDevice error:&errorVI];
NSLog(#"Video Input :%#", errorVI);
if([self.captureSession canAddInput:self.videoInput])
{
[self.captureSession addInput:self.videoInput];
}
else
{
*error = [NSError errorWithDomain:#"Error setting video input." code:101 userInfo:nil];
return;
}
NSError *errorAI = nil;
self.audioInput = [[AVCaptureDeviceInput alloc] initWithDevice:[self audioDevice] error:&errorAI];
if([self.captureSession canAddInput:self.audioInput])
{
[self.captureSession addInput:self.audioInput];
}
else
{
*error = [NSError errorWithDomain:#"Settings->Privacy->Microphone->VideoFrames(On)" code:500 userInfo:nil];
return;
}
if([self.captureSession canAddOutput:self.movieFileOutput])
{
[self.captureSession addOutput:self.movieFileOutput];
}
else
{
*error = [NSError errorWithDomain:#"Error setting file output." code:101 userInfo:nil];
return;
}
}
As a result I received only thumbnail and complete audio but no video. Please help me< I would really appreciate that.
My problem
I am using AVFoundation to capture the frames of the video output every 5 seconds. When the user taps a button, the input camera should switch from the front one to the back one and the opposite. Problem is, every time I switch the back camera to the front camera it freezes (oddly enough, it works the other way around - meaning, front camera to back camera)!
The code I use
To switch between the cameras, I use the exact code taken from Apple's AVCam sample code with a slight change of variable names (so it will match my 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;
}
And to setup the AVCaptureSession, again, I use the exact same code from the AVCam sample code, with a slight change in the added output, (to match my needs):
- (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;
}
*Important note: the camera freezes right after the call to the output's delegate.
Can anyone please help me solve this? It seems as if I had tried almost everything!
Update #1
As requested, self is referring to a view controllers that presented the session's preview layer and manages all things related to the camera. In addition, I'm posting the code the handles the frontFacingCamera part, which is (just like all of the code that I have posted so far) taken from Apple's 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];
}
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;
}
Answer from here
EDITED : This from Square Cam Apple sample code. Works fine. Tested also. http://developer.apple.com/library/ios/#samplecode/SquareCam/Listings/SquareCam_SqareCamViewController_m.html
// use front/back camera
- (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;
}
I need to use iPhone Flash light in my app. But, while the user switch on the flash the camera does not take picture. How can i do this? Here i have attached my code. But, when i switch on the flash light, the camera takes picture.
AVCaptureDeviceInput *flashInput = [AVCaptureDeviceInput deviceInputWithDevice:device error: nil];
AVCaptureVideoDataOutput *output = [[AVCaptureVideoDataOutput alloc] init];
AVCaptureSession *session = [[AVCaptureSession alloc] init];
[session beginConfiguration];
[device lockForConfiguration:nil];
[device setTorchMode:AVCaptureTorchModeOn];
[device setFlashMode:AVCaptureFlashModeOn];
[session addInput:flashInput];
[session addOutput:output];
[device unlockForConfiguration];
[output release];
[session commitConfiguration];
[session startRunning];
[self setTorchSession:session];
Where i am wrong in coding? Please help me. Thanks in advance.
I have a torch button in my app which uses the following 3 methods.
- (void)initialiseTorch {
if (!session) {
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
session = [[AVCaptureSession alloc] init];
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error: nil];
[session addInput:input];
AVCaptureVideoDataOutput *output = [[AVCaptureVideoDataOutput alloc] init];
[session addOutput:output];
[session startRunning];
[output release];
}
}
- (void)releaseTorch {
if (session) {
[session stopRunning];
[session release];
session = nil;
}
}
- (void) lightButtonPressed {
if (!session) {
[self initialiseTorch];
}
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
[session beginConfiguration];
[device lockForConfiguration:nil];
if ([device torchMode] == AVCaptureTorchModeOn) {
[device setTorchMode:AVCaptureTorchModeOff];
} else {
[device setTorchMode:AVCaptureTorchModeOn];
}
[device unlockForConfiguration];
[session commitConfiguration];
}
The only difference I can see between our code is that you are also setting the Flash Mode. Also I configure my session, and then turn the torch on/off in a seperate beginConfiguration pass
check this...
- (void)torchOnOff: (BOOL) onOff
{
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
if ([device hasTorch]) {
[device lockForConfiguration:nil];
[device setTorchMode: onOff ? AVCaptureTorchModeOn : AVCaptureTorchModeOff];
[device unlockForConfiguration];
}
}
I'm trying to make a flashlight app for my iPhone. I have an iPhone 4 and would like to utilize the LED on my iPhone for my project. Can anyone help me to get started with that?
Here is a shorter version you can now use to turn the LED on or off:
- (void)torchOnOff: (BOOL) onOff
{
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
if ([device hasTorch]) {
[device lockForConfiguration:nil];
[device setTorchMode: onOff ? AVCaptureTorchModeOn : AVCaptureTorchModeOff];
[device unlockForConfiguration];
}
}
UPDATE: (March 2015)
You can also set the brightness of the torch:
- (void)setTorchToLevel:(float)torchLevel
{
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
if ([device hasTorch]) {
[device lockForConfiguration:nil];
if (torchLevel <= 0.0) {
[device setTorchMode:AVCaptureTorchModeOff];
}
else {
if (torchLevel >= 1.0)
torchLevel = AVCaptureMaxAvailableTorchLevel;
BOOL success = [device setTorchModeOnWithLevel:torchLevel error:nil];
}
[device unlockForConfiguration];
}
}
Use the following:
AVCaptureSession * session = [[AVCaptureSession alloc] init];
[session beginConfiguration];
AVCaptureDevice * device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
if ([device hasTorch] && [device hasFlash]){
[device lockForConfiguration:nil];
[device setTorchMode:AVCaptureTorchModeOn];
[device setFlashMode:AVCaptureFlashModeOn];
[device unlockForConfiguration];
AVCaptureDeviceInput * flashInput = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
if (flashInput){
[session addInput:flashInput];
}
AVCaptureVideoDataOutput * output = [[AVCaptureVideoDataOutput alloc] init];
[session addOutput:output];
[output release];
[session commitConfiguration];
[session startRunning];
}
[self setTorchSession:session];
[session release];
(From a discussion on iPhoneDevSDK)
When I leave the app and come back to it's 'on' sate sometimes it works fine by turning the torch/flash on but most of the time it either flashes or remains off.
AppDeligate.m
- (id) init {
torchState = TRUE;
if( (self=[super init] )) {
/// initialize flashlight
// test if this class even exists to ensure flashlight is turned on ONLY for iOS 4 and above
Class captureDeviceClass = NSClassFromString(#"AVCaptureDevice");
if (captureDeviceClass != nil) {
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
if ([device hasTorch] && [device hasFlash]){
if (device.torchMode == AVCaptureTorchModeOff) {
NSLog(#"Setting up flashlight for later use...");
AVCaptureDeviceInput *flashInput = [AVCaptureDeviceInput deviceInputWithDevice:device error: nil];
AVCaptureVideoDataOutput *output = [[AVCaptureVideoDataOutput alloc] init];
AVCaptureSession *session = [[AVCaptureSession alloc] init];
[session beginConfiguration];
[device lockForConfiguration:nil];
[session addInput:flashInput];
[session addOutput:output];
[device unlockForConfiguration];
[output release];
[session commitConfiguration];
[session startRunning];
[self setTorchSession:session];
[session release];
}
}
}
}
return self;
}
- (void)toggleTorch {
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
[device lockForConfiguration:nil];
// For the first 4 to 5 times comming back from multiask this first if hits and works properly
if (torchState == TRUE && device.torchMode == AVCaptureTorchModeOff) {
NSLog(#"AVCaptureTorchModeOff setting On");
// On the 4th or 5th time it flashes and stays off or does nothing staying OFF
// even though the NSLog fires
[device setTorchMode:AVCaptureTorchModeOn];
[device setFlashMode:AVCaptureFlashModeOn];
} else if (torchState == TRUE && device.torchMode == AVCaptureTorchModeOn) {
// Sometimes this randomly fires and every time ErrorNotification fires too
NSLog(#"AVCaptureTorchModeOn");
if (AVCaptureSessionRuntimeErrorNotification) {
NSLog(#"ERROR");
// Try to force but doesn't do anything
[device setTorchMode:AVCaptureTorchModeOn];
[device setFlashMode:AVCaptureFlashModeOn];
}
} else {
NSLog(#"ALL IS OFF");
// when torch is in the off state it returns off as it should
torchState = FALSE;
[device setTorchMode:AVCaptureTorchModeOff];
[device setFlashMode:AVCaptureFlashModeOff];
}
[device unlockForConfiguration];
}
-(void) applicationDidEnterForeground:(UIApplication*)application {
[self toggleTorch];
}
The only thing I haven't included in code is a touch even that calls toggleTorch for on/off. That piece works great so again, what I'm testing here is turning it on at launch aka DidEnterForeground as well as when the app is returned to from a multitask session.
I would change 2 things:
1. add it to ApplicationDidBecomeActive
2. don't use toggle torch but set the state you want it to be (so you won't turn it off twice or on twice...). So change the function to toggleTorchWithState...
That what I've done in one of my apps and that works perfectly.