这篇文章将介绍如何使用AVCaptureVideoPreviewLayer
来对捕捉视频数据进行实时预览。在进行介绍使用方式前,先看看相关的概念。
视频重力
在AVCaptureVideoPreviewLayer
中我们可以通过videoGravity
来设置视频重力。这个视频重力的效果就好比我们常用的UIImageView
中的contentMode
一样,是视频显示的填充模式。一共有三种模式,分别为(AVLayerVideoGravityResizeAspect
为默认值):
AVLayerVideoGravityResizeAspect
在显示的承载层区域内部缩放视频,保持视频原始宽高比。类似UIViewContentMode
中UIViewContentModeScaleAspectFit
的效果。
AVLayerVideoGravityResizeAspectFill
按照视频的宽高比将视频拉伸填满整个图层,通常导致视频图片被裁剪。类似UIViewContentMode
中UIViewContentModeScaleAspectFill
的效果。
使用该模式,会让我们觉得拍摄回来的图片比原先的大,这是因为预览是部分而已。
AVLayerVideoGravityResize
拉伸视频内容以匹配承载层大小,类似UIViewContentMode
中UIViewContentModeScaleToFill
的效果。
坐标系转换
坐标系AVCaptureVideoPreviewLayer
定义了两个方法用于坐标系直接的转换:
-
屏幕坐标系 => 设备坐标系:
- (CGPoint)captureDevicePointOfInterestForPoint:(CGPoint)pointInLayer;
-
设备坐标系 => 屏幕坐标系:
- (CGPoint)pointForCaptureDevicePointOfInterest:(CGPoint)captureDevicePointOfInterest;
预览视图的实现
重点为以下两步:
- 使用重写
+ (Class)layerClass;
的方式,创建出AVCaptureVideoPreviewLayer
- ※ 为
AVCaptureVideoPreviewLayer
的session
属性赋值,绑定预览图层与捕捉会话
PS:通过AVCaptureVideoPreviewLayer
的connection
属性可以获取预览视图在捕捉会话里面的连接,通过连接我们可以修改视频方向等重要属性,十分便利。
#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
网友评论