Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS AVCaptureVideoPreviewLayer not showing in UIView?

The Problem

I have a sample application from Apple (SquareCam) that I'm using as reference to create a custom interface for a camera. I'm using the AVFoundation framework. If I build and run the project from Apple, the app runs as expected. However, if I take the same code from that project and place it in a new project in Xcode, the video preview will not display.

I have simplified the code down to the essential components to run a video preview layer. Again, this code runs fine as is in the Apple (SquareCam) project, but does not display in my new project.

The Code

- (void)setupAVCapture {
    NSError *error = nil;

    AVCaptureSession *session = [AVCaptureSession new];
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
        [session setSessionPreset:AVCaptureSessionPreset640x480];
    else
        [session setSessionPreset:AVCaptureSessionPresetPhoto];

    // Select a video device, make an input
    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    AVCaptureDeviceInput *deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];

    if ([session canAddInput:deviceInput])
        [session addInput:deviceInput];

    previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
    [previewLayer setBackgroundColor:[[UIColor blackColor] CGColor]];
    [previewLayer setVideoGravity:AVLayerVideoGravityResizeAspect];
    CALayer *rootLayer = [previewView layer];
    [rootLayer setMasksToBounds:YES];
    [previewLayer setFrame:[rootLayer bounds]];
    [rootLayer addSublayer:previewLayer];
    [session startRunning];
}

- (void)viewDidLoad {
    [super viewDidLoad];
    [self setupAVCapture];
}

What Have I Tried?

I have all of the outlets set up correctly. I have all of the framework libraries in my build phase. Both projects are using storyboard. What's odd is that I am able to capture an image from the camera and even switch the source from front to back. But the preview will not display. The Apple project was not setup with ARC. So, I updated the project to use ARC. Again, runs great in the Apple project, but not in a new project.

Thoughts?

Any ideas on what the issue could be? Is there a project setting that could cause this?

like image 295
Corey Avatar asked Mar 20 '13 19:03

Corey


2 Answers

I had a similar issue in my project. From your code excerpt, it is hard to tell who is invoking setupAVCapture method. In my case, I had to ensure that AVCaptureVideoPreviewLayer is created on the main thread.

There are couple of options. You can invoke setupAVCapture on the main application thread by wrapping the call in the following block:

dispatch_async(dispatch_get_main_queue(), ^{
   // call setupAVCapture() method in here
});

If that is not an option, you can only do that on the following part of your code:

  dispatch_async(dispatch_get_main_queue(), ^{
    previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
    [previewLayer setBackgroundColor:[[UIColor blackColor] CGColor]];
    [previewLayer setVideoGravity:AVLayerVideoGravityResizeAspect];
    CALayer *rootLayer = [previewView layer];
    [rootLayer setMasksToBounds:YES];
    [previewLayer setFrame:[rootLayer bounds]];
    [rootLayer addSublayer:previewLayer];
   });
like image 116
Aki Avatar answered Sep 22 '22 12:09

Aki


Had the same issue and the key was setting the AVCaptureVideoPreviewLayer's frame to the bounds of the UIView:

// Setup camera preview image
AVCaptureVideoPreviewLayer *previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:_captureSession];
previewLayer.frame = _cameraPreview.bounds;
[_cameraPreview.layer addSublayer:previewLayer];
like image 45
Brenden Avatar answered Sep 24 '22 12:09

Brenden