【iOS】自定义相机(三)预览视图

这篇文章将介绍如何使用AVCaptureVideoPreviewLayer来对捕捉视频数据进行实时预览。在进行介绍使用方式前,先看看相关的概念。

视频重力

AVCaptureVideoPreviewLayer中我们可以通过videoGravity来设置视频重力。这个视频重力的效果就好比我们常用的UIImageView中的contentMode一样,是视频显示的填充模式。一共有三种模式,分别为(AVLayerVideoGravityResizeAspect为默认值):

AVLayerVideoGravityResizeAspect

在显示的承载层区域内部缩放视频,保持视频原始宽高比。类似UIViewContentModeUIViewContentModeScaleAspectFit的效果。

AVLayerVideoGravityResizeAspect

AVLayerVideoGravityResizeAspectFill

按照视频的宽高比将视频拉伸填满整个图层,通常导致视频图片被裁剪。类似UIViewContentModeUIViewContentModeScaleAspectFill的效果。

AVLayerVideoGravityResizeAspectFill

使用该模式,会让我们觉得拍摄回来的图片比原先的大,这是因为预览是部分而已。

AVLayerVideoGravityResize

拉伸视频内容以匹配承载层大小,类似UIViewContentModeUIViewContentModeScaleToFill的效果。

AVLayerVideoGravityResize

坐标系转换

坐标系

AVCaptureVideoPreviewLayer定义了两个方法用于坐标系直接的转换:

  • 屏幕坐标系 => 设备坐标系- (CGPoint)captureDevicePointOfInterestForPoint:(CGPoint)pointInLayer;
  • 设备坐标系 => 屏幕坐标系- (CGPoint)pointForCaptureDevicePointOfInterest:(CGPoint)captureDevicePointOfInterest;

预览视图的实现

重点为以下两步:

  1. 使用重写+ (Class)layerClass;的方式,创建出AVCaptureVideoPreviewLayer
  2. ※ 为AVCaptureVideoPreviewLayersession属性赋值,绑定预览图层与捕捉会话

PS:通过AVCaptureVideoPreviewLayerconnection属性可以获取预览视图在捕捉会话里面的连接,通过连接我们可以修改视频方向等重要属性,十分便利。

#import "SCVideoPreviewView.h"

@implementation SCVideoPreviewView

+ (Class)layerClass {
    return [AVCaptureVideoPreviewLayer class];
}

- (AVCaptureVideoPreviewLayer*)videoPreviewLayer {
    return (AVCaptureVideoPreviewLayer *)self.layer;
}

- (void)awakeFromNib {
    [super awakeFromNib];
    [self prepare];
}

- (instancetype)init {
    if (self = [super init]) {
        [self prepare];
    }
    return self;
}

- (void)prepare {
    [self.videoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
}

- (CGPoint)captureDevicePointForPoint:(CGPoint)point {
    AVCaptureVideoPreviewLayer *layer = (AVCaptureVideoPreviewLayer *)self.layer;
    return [layer captureDevicePointOfInterestForPoint:point];
}

- (AVCaptureSession*)captureSession {
    return self.videoPreviewLayer.session;
}

- (void)setCaptureSession:(AVCaptureSession*)captureSession {
    self.videoPreviewLayer.session = captureSession;
    // 根据状态栏位置设置视频方向
    UIInterfaceOrientation statusBarOrientation = [UIApplication sharedApplication].statusBarOrientation;
    AVCaptureVideoOrientation initialVideoOrientation = AVCaptureVideoOrientationPortrait;
    if (statusBarOrientation != UIInterfaceOrientationUnknown) {
        initialVideoOrientation = (AVCaptureVideoOrientation)statusBarOrientation;
    }
    // videoPreviewLayer 也有 connection
    self.videoPreviewLayer.connection.videoOrientation = initialVideoOrientation;
}

- (AVCaptureVideoOrientation)videoOrientation {
    return self.videoPreviewLayer.connection.videoOrientation;
}

@end

SCVideoPreviewView代码

你可能感兴趣的:(【iOS】自定义相机(三)预览视图)