這篇文章將介紹如何使用AVCaptureVideoPreviewLayer
來對捕捉視頻數(shù)據(jù)進行實時預(yù)覽劫樟。在進行介紹使用方式前跑慕,先看看相關(guān)的概念。
視頻重力
在AVCaptureVideoPreviewLayer
中我們可以通過videoGravity
來設(shè)置視頻重力轰坊。這個視頻重力的效果就好比我們常用的UIImageView
中的contentMode
一樣火本,是視頻顯示的填充模式。一共有三種模式温学,分別為(AVLayerVideoGravityResizeAspect
為默認值):
AVLayerVideoGravityResizeAspect
在顯示的承載層區(qū)域內(nèi)部縮放視頻略贮,保持視頻原始寬高比。類似UIViewContentMode
中UIViewContentModeScaleAspectFit
的效果。
AVLayerVideoGravityResizeAspectFill
按照視頻的寬高比將視頻拉伸填滿整個圖層刨肃,通常導(dǎo)致視頻圖片被裁剪古拴。類似UIViewContentMode
中UIViewContentModeScaleAspectFill
的效果。
使用該模式真友,會讓我們覺得拍攝回來的圖片比原先的大黄痪,這是因為預(yù)覽是部分而已。
AVLayerVideoGravityResize
拉伸視頻內(nèi)容以匹配承載層大小盔然,類似UIViewContentMode
中UIViewContentModeScaleToFill
的效果桅打。
坐標系轉(zhuǎn)換
AVCaptureVideoPreviewLayer
定義了兩個方法用于坐標系直接的轉(zhuǎn)換:
-
屏幕坐標系 => 設(shè)備坐標系:
- (CGPoint)captureDevicePointOfInterestForPoint:(CGPoint)pointInLayer;
-
設(shè)備坐標系 => 屏幕坐標系:
- (CGPoint)pointForCaptureDevicePointOfInterest:(CGPoint)captureDevicePointOfInterest;
預(yù)覽視圖的實現(xiàn)
重點為以下兩步:
- 使用重寫
+ (Class)layerClass;
的方式,創(chuàng)建出AVCaptureVideoPreviewLayer
- ※ 為
AVCaptureVideoPreviewLayer
的session
屬性賦值愈案,綁定預(yù)覽圖層與捕捉會話
PS:通過AVCaptureVideoPreviewLayer
的connection
屬性可以獲取預(yù)覽視圖在捕捉會話里面的連接挺尾,通過連接我們可以修改視頻方向等重要屬性,十分便利站绪。
#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;
// 根據(jù)狀態(tài)欄位置設(shè)置視頻方向
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