65
AVCaptureVideoPreviewLayer *avLayer = 
                [AVCaptureVideoPreviewLayer layerWithSession:session];
avLayer.frame = self.view.frame;
[self.view.layer addSublayer:avLayer];

I use AVCaptureVideoPreviewLayer to display video on the view. But the video's view didn't fill up the full iPhone4's screen.(two grey bar at the right&left side)

I want the video fills up full screen. How can I deal with it? Thank you very much!

enter image description here

bcye
  • 758
  • 5
  • 22
Rafer
  • 1,170
  • 2
  • 10
  • 15

7 Answers7

190

Maybe this solves it?

CGRect bounds=view.layer.bounds;
avLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
avLayer.bounds=bounds;
avLayer.position=CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds));
flitzwald
  • 20,200
  • 2
  • 32
  • 28
14

One potential cause of confusion is that the AVCaptureVideoPreviewLayer is a CoreAnimation layer and in all of the answers above is being positioned statically (e.g. without constraints) relative a view. If you use constraints to layout the view, these don't automatically resize the preview layer.

This means that you cannot set up the preview layer in viewDidLoad as the layout has not yet taken place and the preview layer will sized how it was in Interface Builder.

Instead, override viewDidLayoutSubviews on your ViewController and position the preview layer there.

- (void)viewDidLayoutSubviews
{
    CGRect bounds=view.layer.bounds;
    avLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;  
    avLayer.bounds=bounds;
    avLayer.position=CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds));
}
marko
  • 9,029
  • 4
  • 30
  • 46
11

@fitzwald's answer will give you the desired result, but there is an easier way. What is happening is that the session preset defaults to Video - High (which doesn't match the aspect ratio of the screen). A full screen preview (like in Camera.app) can be achieved by using the Photo preset. Simply set

session.sessionPreset = AVCaptureSessionPresetPhoto;

before you start your session. Here's the Apple Documentation if you want to learn more.

eschurter
  • 686
  • 1
  • 7
  • 8
  • 4
    I think that's wrong. Two things: firstly, using presetPhoto breaks built-in behaviours (e.g. the AVCaptureVideoPreviewLayer will refuse to stream live video if you set this preset). Secondly, I found it still wouldn't auto-resize to fill the CALayer. – Adam Apr 26 '11 at 10:34
  • Also, that link you provide doesn't help - Apple has NOT yet documented this variable ("sessionPreset") nor any of the values. iOS 4 has been live for almost a year now, so perhaps we'll get some documentation soon. (fingers crossed) – Adam Apr 26 '11 at 10:35
  • 1
    @Adam, to your first point, I'm using the presetPhoto successfully to both fill the screen and show video. I don't know where you're running into a problem. I'm looking for a way to share my _setupPreviewLayer code. As far as your second comment, it's not well documented, but it's how Apple recommends you set up your preview layers. If you have access to the WWDC 2010 sample code, there were some very helpful examples. AVCamDemo and PinchyPreview helped me a lot. – eschurter Apr 29 '11 at 18:29
  • `AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:nil]; [captureSession addInput:input]; [captureSession setSessionPreset:@"AVCaptureSessionPresetPhoto"]; previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:captureSession]; [self applyDefaults]; previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; previewLayer.backgroundColor = [[UIColor blackColor] CGColor]; [previewParentView.layer insertSublayer:previewLayer atIndex:1];` – eschurter Apr 29 '11 at 18:30
  • Your code above appears to be using flitzwald's solution, instead of the solution you suggested originally? – Adam May 01 '11 at 11:21
  • 1
    I agree with @eschurter - Notice that just 'AspectFill'ing will get you a false impression of the frame the camera sees. Just try switching to the built in camera (without moving), and you'll see you don't have the same frame. It's indeed due to aspect ratio. You can read a summary here: http://developer.apple.com/library/ios/#documentation/AudioVideo/Conceptual/AVFoundationPG/Articles/03_MediaCapture.html (The 640x480 preset will also help, not necessarily Photo) – Oded Ben Dov May 22 '11 at 15:17
  • This solution accounts better for actual camera frames as mentioned by @OdedBenDov. When just using aspect fill I would take a photo and have additional space that wasn't showing in the preview. – SuperGuyAbe Sep 10 '14 at 21:34
9

For Google's sake, this is the accepted answer but using Swift which is slightly different:

var bounds:CGRect = self.view.layer.bounds
previewLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill
previewLayer?.bounds = bounds
previewLayer?.position = CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds))
Raj
  • 3,791
  • 5
  • 43
  • 56
4

The accepted answer

Swift 3:

  let bounds = view.layer.bounds
  self.cameraLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
  self.cameraLayer.bounds = bounds
  self.cameraLayer.position = CGPoint(x:bounds.midX, y:bounds.midY)
  self.cameraView?.layer.addSublayer(self.cameraLayer)

Swift 4:

  let bounds = view.layer.bounds
  self.cameraLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
  self.cameraLayer.bounds = bounds
  self.cameraLayer.position = CGPoint(x:bounds.midX, y:bounds.midY)
  self.cameraView?.layer.addSublayer(self.cameraLayer)
Allen
  • 2,979
  • 1
  • 29
  • 34
2

Swift 5

I solve the problem by using the following code:

    let bounds = view.layer.bounds
    let previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
    view.layer.addSublayer(previewLayer)
    previewLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
    previewLayer.bounds = bounds
    previewLayer.position = CGPoint(x:bounds.midX, y:bounds.midY)
Angela Li
  • 21
  • 1
1

I use the following code to achieve this

previewLayer.frame = CGRectMake(0, 0, self.view.frame.size.width,self.view.frame.size.height);
previewLayer.orientation = [[UIDevice currentDevice] orientation];
previewLayer.contentsGravity = kCAGravityResizeAspectFill;
raju_kr
  • 143
  • 2
  • 11