I want to capture images in certain cases, for example, when a button is pressed; but I don’t want to show the video preview screen. I assume captureStillImageAsynchronouslyFromConnection is what I need to use for this scenario. Currently, I can capture an image if I show a preview of the video. However, if I remove the code to show the preview, the application will exit with the following output:
2012-04-07 11: 25: 54.898 imCapWOPreview [748: 707] *** The application terminated due to the uncaught exception "NSInvalidArgumentException", reason: "*** - [AVCaptureStillImageOutput captureStillImageAsynchronouslyFromConnection: completeHandler:] - inactive / invalid connection. *** The first roll stack calls: (0x336ee8bf 0x301e21e5 0x3697c35d 0x34187 0x33648435 0x310949eb 0x310949a7 0x31094985 0x310946f5 0x3109502d 0x3109350f 0x31092f01 0x310794ed 0x31078d2d 0x37db7df3 0x336c2553 0x336c24f5 0x336c1343 0x336444dd 0x336443a5 0x37db6fcd 0x310a7743 0x33887 0x3382c) termination throwing exception (lldb)
So here is my implementation:
BIDViewController.h:
Relevant staff inside BIDViewController.m:
#import "BIDViewController.h" @interface BIDViewController () @end @implementation BIDViewController @synthesize capturedIm; @synthesize videoPreview; - (void)viewDidLoad { [super viewDidLoad]; [self setupAVCapture]; } - (BOOL)setupAVCapture { NSError *error = nil; AVCaptureSession *session = [AVCaptureSession new]; [session setSessionPreset:AVCaptureSessionPresetHigh]; /* AVCaptureVideoPreviewLayer *captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session]; captureVideoPreviewLayer.frame = self.videoPreview.bounds; [self.videoPreview.layer addSublayer:captureVideoPreviewLayer]; */ // Select a video device, make an input AVCaptureDevice *backCamera = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:backCamera error:&error]; if (error) return NO; if ([session canAddInput:input]) [session addInput:input]; // Make a still image output stillImageOutput = [AVCaptureStillImageOutput new]; NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys: AVVideoCodecJPEG, AVVideoCodecKey, nil]; [stillImageOutput setOutputSettings:outputSettings]; if ([session canAddOutput:stillImageOutput]) [session addOutput:stillImageOutput]; [session startRunning]; return YES; } - (IBAction)doCap:(id)sender { 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; } } [stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *__strong error) { // Do something with the captured image }]; }
With the above code, if doCap is called, a crash occurs. On the other hand, if I remove the following comments in the setupAVCapture function
/* AVCaptureVideoPreviewLayer *captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session]; captureVideoPreviewLayer.frame = self.videoPreview.bounds; [self.videoPreview.layer addSublayer:captureVideoPreviewLayer]; */
then it works without any problems.
In conclusion, my questions are: how can I capture images in controlled instances without previewing?
ali gurbuz
source share