iOS AVCaptureVideoPreviewLayer not showing in UIView?

10,471

Solution 1

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];

Solution 2

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];
   });
Share:
10,471
Corey
Author by

Corey

__________ .__ \______ \ _________ ____ | |__ | _// _ \__ \ _/ ___\| | \ | | ( [_] ) __ \\ \___| Y \ |____|_ /\____(____ /\___ ]___| / \/ \/ \/ \/

Updated on June 03, 2022

Comments

  • Corey
    Corey about 2 years

    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?

  • Aki
    Aki about 10 years
    If I remember correctly you can use it on both main thread and some other thread. If you run it on the main thread, it might affect your performance though based on your use case. The key is that any video rendering has to be run on the main thread.