媒体采集的几个东西。这里所需要明白的是,在这个流程中,这里会存在几个对象:
- AVCaptureDevice。这里代表抽象的硬件设备。
- AVCaptureInput。这里代表输入设备(可以是它的子类),它配置抽象硬件设备的ports。
- AVCaptureOutput。它代表输出数据,管理着输出到一个movie或者图像。
- AVCaptureSession。它是input和output的桥梁。它协调着intput到output的数据传输。
- 导入框架、遵循协议
#import <AVFoundation/AVFoundation.h>
// 遵循协议
AVCaptureMetadataOutputObjectsDelegate
- 判断相机的状态
AVAuthorizationStatus authorizationStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
switch (authorizationStatus) {
case AVAuthorizationStatusNotDetermined: {
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler: ^(BOOL granted) {
if (granted) {
[self startCapture];
} else {
[self alertMessage:@"访问受限"];
}
}];
break;
}
case AVAuthorizationStatusAuthorized: {
[self startCapture];
break;
}
case AVAuthorizationStatusRestricted:
case AVAuthorizationStatusDenied: {
[self alertMessage:@"访问受限"];
break;
}
default: {
break;
}
}
- 打开相机
- (void)startCapture{
AVCaptureSession *session = [[AVCaptureSession alloc] init];
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
NSError *error;
AVCaptureDeviceInput *deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
if (deviceInput) {
[session addInput:deviceInput];
AVCaptureMetadataOutput *metadataOutput = [[AVCaptureMetadataOutput alloc] init];
[metadataOutput setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
[session addOutput:metadataOutput]; // 这行代码要在设置 metadataObjectTypes 前
metadataOutput.metadataObjectTypes = @[AVMetadataObjectTypeQRCode,AVMetadataObjectTypeCode128Code,AVMetadataObjectTypeEAN13Code]; // 设置识别图片类型
AVCaptureVideoPreviewLayer *previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
previewLayer.frame = self.view.frame;
[self.view.layer insertSublayer:previewLayer atIndex:0];
__weak typeof(self) weakSelf = self;
[[NSNotificationCenter defaultCenter] addObserverForName:AVCaptureInputPortFormatDescriptionDidChangeNotification
object:nil
queue:[NSOperationQueue currentQueue]
usingBlock: ^(NSNotification *_Nonnull note) {
metadataOutput.rectOfInterest = [previewLayer metadataOutputRectOfInterestForRect:weakSelf.scanRect];
// 如果不设置,整个屏幕都可以扫
}];
// 设置扫描界面布局
QRScanView *scanView = [[QRScanView alloc] initWithScanRect:self.scanRect];
[self.view addSubview:scanView];
[session startRunning];
} else {
NSLog(@"%@", error);
[self alertMessage:error.localizedDescription];
}
}
- 处理扫描到的图片
#pragma mark - AVCaptureMetadataOutputObjectsDelegate
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{
AVMetadataMachineReadableCodeObject *metadataObject = metadataObjects.firstObject;
// 成功后系统不会停止扫描,用isQRCodeCaptured变量来控制。
if (self.isQRCodeCaptured == NO) {
self.isQRCodeCaptured = YES;
NSString *decodeMessage = @"未扫描到二维码、条形码";
if ([metadataObject.type isEqualToString:AVMetadataObjectTypeQRCode]) {
// 二维码
decodeMessage = metadataObject.stringValue;
}else if ([metadataObject.type isEqualToString:AVMetadataObjectTypeCode128Code]){
// 条形码
decodeMessage = metadataObject.stringValue;
}else if ([metadataObject.type isEqualToString:AVMetadataObjectTypeEAN13Code]){
// ISBN书号条码、EAN13码
decodeMessage = metadataObject.stringValue;
}
NSLog(@"%@",decodeMessage);
}
}
AVCaptureMetadataOutput:
相机扫描结果种类
metadataObjectTypes:
// 二维码
AVMetadataObjectTypeQRCode
// 条形码
// Code128
AVMetadataObjectTypeCode128Code
// Code39
AVMetadataObjectTypeCode39Code
// Code39Mod43
AVMetadataObjectTypeCode39Mod43Code
// Code93
AVMetadataObjectTypeCode93Code
// UPC-E商品条码
AVMetadataObjectTypeUPCECode
// EAN-13商品条码/UPC-A商品条码/ISBN书号条码
AVMetadataObjectTypeEAN13Code
// EAN-8商品条码
AVMetadataObjectTypeEAN8Code
// PDF417
AVMetadataObjectTypePDF417Code
// 交叉25码
AVMetadataObjectTypeInterleaved2of5Code
// ITF14
AVMetadataObjectTypeITF14Code
// Aztec
AVMetadataObjectTypeAztecCode
// 数据矩阵
AVMetadataObjectTypeDataMatrixCode