AVCaptureVideoPreviewLayer running slower with time - ios

I have a UIViewController where i set an AVCaptureVideoPreviewLayer on the init method to take pictures. When the photo is taken i dismiss the UIViewController.
Each time i open this UIViewController, the Ipad run slower until it crashes. I get a memory warning, so i think something its not being free, in the other hand, I am using ARC so i suppouse that each time i dismiss the UIViewController it frees the memory.
Here is the code on the init method of the UIViewController:
session = [[AVCaptureSession alloc] init];
session.sessionPreset = AVCaptureSessionPresetMedium;
AVCaptureVideoPreviewLayer *captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
captureVideoPreviewLayer.affineTransform = CGAffineTransformMakeRotation(M_PI+M_PI_2);
captureVideoPreviewLayer.frame = CGRectMake(45, 55, 512, 387);
[self.cameraPlace.layer addSublayer:captureVideoPreviewLayer];
NSArray *cameras=[AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
AVCaptureDevice *device = [cameras objectAtIndex:1];
NSError *error = nil;
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
[session addInput:input];
stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys: AVVideoCodecJPEG, AVVideoCodecKey, nil];
[stillImageOutput setOutputSettings:outputSettings];
[session addOutput:stillImageOutput];
[session startRunning];
Do i have something wrong? or do you have any clue?

I was having the same problem because I was adding a layer with a session that was already added.
self.captureVideoPreviewLayer = [AVCaptureVideoPreviewLayer
layerWithSession:self.session];
on the above line please set a breakpoint, you will observe it will take 3-4 seconds to proceed. Sometimes it creates a memory warning and sometimes it doesn't.
so just add check whether it is already added or not like below.
NSError *error;
[self.deviceCamera lockForConfiguration:&error];
if (self.session == nil)
{
self.session = [[AVCaptureSession alloc] init];
self.captureVideoPreviewLayer = [AVCaptureVideoPreviewLayer
layerWithSession:self.session];
CGRect screenBounds = [[UIScreen mainScreen]bounds];
self.captureVideoPreviewLayer.frame = screenBounds;
self.captureVideoPreviewLayer.videoGravity =
AVLayerVideoGravityResizeAspectFill; // to fill the camera fullscreen view
self.userInteractionEnabled = YES;
if ([self.session canAddInput:_input]) {
[self.session addInput:_input];
}
}
[self.session startRunning];
[self.layer addSublayer:self.captureVideoPreviewLayer];
if (self.stillImageOutput == nil)
{
self.stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys: AVVideoCodecJPEG, AVVideoCodecKey, nil];
[self.stillImageOutput setOutputSettings:outputSettings];
NSString* preset = 0;
if (!preset) {
preset = AVCaptureSessionPresetPhoto;
}
if ([self.session canSetSessionPreset:preset]) {
self.session.sessionPreset = preset;
}
if ([self.session canAddOutput:self.stillImageOutput]) {
[self.session addOutput:self.stillImageOutput];
}
}
objective-c ios avcapturesession

Related

How to adjust my UIButton to maintain the aspect ratio

I have made a View Controller on my storyboard and added to buttons to it,
I am starting a AVCaptureSession on my View Controller's view like this,
AVCaptureSession *session = [[AVCaptureSession alloc] init];
session.sessionPreset = AVCaptureSessionPresetMedium;
CALayer *viewLayer = self.view.layer;
NSLog(#"viewLayer = %#", viewLayer);
AVCaptureVideoPreviewLayer *captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
captureVideoPreviewLayer.frame = self.view.layer.bounds;
[self.view.layer addSublayer: captureVideoPreviewLayer];
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
NSError *error = nil;
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
if (!input) {
// Handle the error appropriately.
NSLog(#"ERROR: trying to open camera: %#", error);
}
[session addInput:input];
[session startRunning];
stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys: AVVideoCodecJPEG, AVVideoCodecKey, nil];
[stillImageOutput setOutputSettings:outputSettings];
[session addOutput:stillImageOutput];
My problem is that my buttons get hidden as the preview layer takes up the whole screen I want the preview layer to assume whole screen but also want to display the buttons for capturing and closing the session
How can I go about it?
Try moving your button on top of the view controller views hierarchy with:
[self.view sendSubviewToFront:button];
Do it after you've added captureVideoPreviewLayer as sublayer.

Custom Camera View Not Working on iOS 8/Xcode 6

So I had this code working on another app of mine to take photos on a custom camera view when I had iOS 7 on my phone and Xcode 5.1, now on iOS 8 and Xcode 6, the camera works but I can't see the live view of the camera in my leftVertical UIView. Here's my code, would appreciate any help Thanks!
#import <AVFoundation/AVFoundation.h>
session = [[AVCaptureSession alloc] init];
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
[session setSessionPreset:AVCaptureSessionPreset352x288];
else
[session setSessionPreset:AVCaptureSessionPreset352x288];
AVCaptureDevice *inputDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
NSError *error;
AVCaptureDeviceInput *deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:inputDevice error:&error];
if ([session canAddInput:deviceInput]) {
[session addInput:deviceInput];
}
AVCaptureVideoPreviewLayer *previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
[previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
CALayer *rootLayer = [[self view] layer];
[rootLayer setMasksToBounds:YES];
CGRect frame = self.leftVertical.frame;
[previewLayer setFrame:frame];
[rootLayer insertSublayer:previewLayer atIndex:0];
//////////////////////////
stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys:AVVideoCodecJPEG, AVVideoCodecKey, nil];
[stillImageOutput setOutputSettings:outputSettings];
[session addOutput:stillImageOutput];
[session startRunning];
try this...
In –viewWillAppear: start camera capture on main thread, like this..
dispatch_async(dispatch_get_main_queue(), ^{
if (![session isRunning])
{
[session startRunning];
}
});

zbar barcode scanning from only image no image view or camera roll

Hi if i make a image capture screen with this
-(void)initializecam{
AVCaptureSession *session = [[AVCaptureSession alloc] init];
session.sessionPreset = AVCaptureSessionPresetMedium;
CALayer *viewLayer = self.vImagePreview.layer;
NSLog(#"viewLayer = %#", viewLayer);
AVCaptureVideoPreviewLayer *captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
captureVideoPreviewLayer.frame = self.vImagePreview.bounds;
[captureVideoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
[self.vImagePreview.layer addSublayer:captureVideoPreviewLayer];
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
NSError *error = nil;
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
if (!input) {
// Handle the error appropriately.
NSLog(#"ERROR: trying to open camera: %#", error);
}
[session addInput:input];
_stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys: AVVideoCodecJPEG, AVVideoCodecKey, nil];
[_stillImageOutput setOutputSettings:outputSettings];
[session addOutput:_stillImageOutput];
[session startRunning];
}
So now i want to use zbar bar code scanning. Any one know how to do this. I searched a lot but all there is they use the image capture view and how to modify that view. All i need is that i have an image[not in camera roll] and i want to scan it by zbar no image capture view or anything. Please help. Is there is any other free library except zbar to do this??
it can be done by this
- (void)scan {
// ADD: present a barcode reader that scans from the camera feed
ZBarReaderController *reader = [ZBarReaderController new];
reader.readerDelegate = self;
ZBarImageScanner *scanner = reader.scanner;
// EXAMPLE: disable rarely used I2/5 to improve performance
[scanner setSymbology: ZBAR_I25
config: ZBAR_CFG_ENABLE
to: 0];
CGImageRef imgCG = self.imgCameraView.image.CGImage;
id<NSFastEnumeration> results = [reader scanImage:imgCG];
ZBarSymbol *symbol = nil;
for(ZBarSymbol *symbolF in results){
// EXAMPLE: just grab the first barcode
symbol=symbolF;
break;
}
if([symbol.data length]>0){
NSLog(#"Bar Code ID = %#",symbol.data);
self.ticketCode=symbol.data;
[self verifybarCode];
self.vImagePreview.hidden=FALSE;
}
else
{
[[iToast makeText:AMLocalizedString(#"Image Is Not Properly Scanned\nTry Again", nil)] show];
self.vImagePreview.hidden=FALSE;
}
}
Previously i was taking ZBarReaderViewController

Get Camera Preview to AVCaptureVideoPreviewLayer

I was trying to get the camera input to show on a preview layer view.
self.cameraPreviewView is tied to a UIView in IB
Here is my current code that I put together from the AV Foundation Programming Guide. But the preview never shows
AVCaptureSession *session = [[AVCaptureSession alloc] init];
session.sessionPreset = AVCaptureSessionPresetHigh;
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
NSError *error = nil;
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
if (!input) {
NSLog(#"Couldn't create video capture device");
}
[session addInput:input];
// Create video preview layer and add it to the UI
AVCaptureVideoPreviewLayer *newCaptureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
UIView *view = self.cameraPreviewView;
CALayer *viewLayer = [view layer];
newCaptureVideoPreviewLayer.frame = view.bounds;
[viewLayer addSublayer:newCaptureVideoPreviewLayer];
self.cameraPreviewLayer = newCaptureVideoPreviewLayer;
[session startRunning];
So after some trial and error and looking at apple's AVCam Sample Code
I wrapped the PreviewLayer code and session startRunning into a grand central dispatch block like so and it started working.
dispatch_async(dispatch_get_main_queue(), ^{
AVCaptureVideoPreviewLayer *newCaptureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
UIView *view = self.cameraPreviewView;
CALayer *viewLayer = [view layer];
newCaptureVideoPreviewLayer.frame = view.bounds;
[viewLayer addSublayer:newCaptureVideoPreviewLayer];
self.cameraPreviewLayer = newCaptureVideoPreviewLayer;
[session startRunning];
});
here is my code, it works perfect for me , you can refer to it
- (void)initCapture
{
AVCaptureDevice *inputDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
AVCaptureDeviceInput *captureInput = [AVCaptureDeviceInput deviceInputWithDevice:inputDevice error:nil];
if (!captureInput) {
return;
}
AVCaptureVideoDataOutput *captureOutput = [[AVCaptureVideoDataOutput alloc] init];
/* captureOutput:didOutputSampleBuffer:fromConnection delegate method !*/
[captureOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()];
NSString* key = (NSString*)kCVPixelBufferPixelFormatTypeKey;
NSNumber* value = [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA];
NSDictionary* videoSettings = [NSDictionary dictionaryWithObject:value forKey:key];
[captureOutput setVideoSettings:videoSettings];
self.captureSession = [[AVCaptureSession alloc] init];
NSString* preset = 0;
if (!preset) {
preset = AVCaptureSessionPresetMedium;
}
self.captureSession.sessionPreset = preset;
if ([self.captureSession canAddInput:captureInput]) {
[self.captureSession addInput:captureInput];
}
if ([self.captureSession canAddOutput:captureOutput]) {
[self.captureSession addOutput:captureOutput];
}
//handle prevLayer
if (!self.captureVideoPreviewLayer) {
self.captureVideoPreviewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.captureSession];
}
//if you want to adjust the previewlayer frame, here!
self.captureVideoPreviewLayer.frame = self.view.bounds;
self.captureVideoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
[self.view.layer addSublayer: self.captureVideoPreviewLayer];
[self.captureSession startRunning];
}

Camera Preview does not fill screen

This is how I am setting up the camera preview in landscape mode in my iPad3
- (void)viewDidAppear:(BOOL)animated
{
AVCaptureSession *session = [[AVCaptureSession alloc] init];
session.sessionPreset = AVCaptureSessionPreset640x480;
CALayer *viewLayer = self.vImagePreview.layer;
NSLog(#"viewLayer = %#", viewLayer);
AVCaptureVideoPreviewLayer *captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
captureVideoPreviewLayer.frame = self.vImagePreview.bounds;
[self.vImagePreview.layer addSublayer:captureVideoPreviewLayer];
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
NSError *error = nil;
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
if (!input) {
// Handle the error appropriately.
NSLog(#"ERROR: trying to open camera: %#", error);
}
[session addInput:input];
stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys: AVVideoCodecJPEG, AVVideoCodecKey, nil];
[stillImageOutput setOutputSettings:outputSettings];
[session addOutput:stillImageOutput];
[session startRunning];
}
In the storyboard, I set the view to fill the entire screen, however it ends up looking like this:
And furthermore, the image is also rotated 90º degrees. How can I change this, so I can make the camera preview fill the entire screen?
Thanks.
Rotate your layer:
switch (self.interfaceOrientation)
{
case UIInterfaceOrientationLandscapeRight:
[captureVideoPreviewLayer setAffineTransform:CGAffineTransformMakeRotation(-M_PI / 2)];
break;
case UIInterfaceOrientationLandscapeLeft:
[captureVideoPreviewLayer setAffineTransform:CGAffineTransformMakeRotation(M_PI / 2)];
break;
}
[self.vImagePreview.layer addSublayer:captureVideoPreviewLayer];

Resources