真的好久没写Blog了。。囧
捕捉硬件数据需要用到以下几个类
AVCaptureSession AVCaptureDeviceInput AVCaptureVideoDataOutput AVCaptureVideoPreviewLayer
AVCaptureSession
控制着硬件的Input以及数据的Output(就理解为控制器吧)
AVCaptureDeviceInput
硬件的输入(从AVCaptureDevice对象中捕捉输入相关得数据)
AVCaptureVideoDataOutput
视频数据的输出(AVCaptureOutput的子类,捕捉输出相关得属性)
AVCaptureVideoPreviewLayer
预览视图
说下大概得逻辑
初始化Session(负责协调输入,输出数据交互)
通过AVCaptureDevice.defaultDeviceWithMediaType方法来获取AVCaptureDevice(音频,视频) 具体看你传进去得参数而定
初始化输入,输出 对象
设置输出画质,将输入,输出 对象添加进session中
创建GCD并设置输出对象的相关回调
代码部分
检测摄像头权限是否可用以及跳转设置的函数
func checkVideoAuth()
func openSettings()这里的跳转设置函数是在IOS8以后才可使用的
摄像头输入输出设置的相关设置
func setupCamera()
完整代码如下
//
// ViewController.swift
// CameraExample
//
// Created by Peter_Qin on 15/11/20.
// copyright © 2015年 Chin_Hui. All rights reserved.
//
import UIKit
import AVFoundation
class ViewController: UIViewController,AVCaptureVideoDataOutputSampleBufferDelegate,UIAlertViewDelegate {
/// 摄像头授权状态
var cameraAuthStatus: AVAuthorizationStatus!
/// 预览Layer
var captureVideoPreviewLayer: AVCaptureVideoPreviewLayer!
/// Session
var session: AVCaptureSession!
/// 硬件Input
var captureInput:AVCaptureDeviceInput!
/// 数据Output
var captureOutput:AVCaptureVideoDataOutput!
var customImgView: UIImageView!
/**
跳转至设置
*/
func openSettings() {
let settingsURL:NSURL = NSURL(string:UIApplicationopenSettingsURLString)!
UIApplication.sharedApplication().openURL(settingsURL)
}
/**
Check video authorization status
*/
func checkVideoAuth() {
switch AVCaptureDevice.authorizationStatusForMediaType(AVMediaTypeVideo)
{
case AVAuthorizationStatus.Authorized://已经授权
self.cameraAuthStatus = AVAuthorizationStatus.Authorized
break
case AVAuthorizationStatus.NotDetermined:
AVCaptureDevice.requestAccessForMediaType(AVMediaTypeVideo,completionHandler: { (granted: Bool) -> Void in
if(granted){
//受限制
self.cameraAuthStatus = AVAuthorizationStatus.Restricted
exit(0)
}
})
break
case AVAuthorizationStatus.Denied:
AVCaptureDevice.requestAccessForMediaType(AVMediaTypeVideo,completionHandler: { (granted: Bool) -> Void in
if(!granted){
//否认
self.cameraAuthStatus = AVAuthorizationStatus.Denied
let warnMsg:UIAlertView = UIAlertView(title: "提示",message: "摄像头权限未未开启,点击确认跳转至设置",delegate: self,cancelButtonTitle: "确认")
warnMsg.show()
}
})
break
default:
break
}
}
/**
摄像头设置相关 By Hui
*/
func setupCamera() {
self.session = AVCaptureSession()
let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)!
self.captureOutput = AVCaptureVideoDataOutput()
do{
try self.captureInput = AVCaptureDeviceInput(device: device)
}catch let error as NSError{
print(error)
}
self.checkVideoAuth()
self.session.beginConfiguration()
//画面质量设置
self.session.sessionPreset = AVCaptureSessionPreset1920x1080
self.captureOutput.videoSettings = [kCVPixelBufferPixelFormatTypeKey:NSNumber(unsignedInt: kCVPixelFormatType_32BGRA),kCVPixelBufferWidthKey:NSNumber(integer: 1920),kCVPixelBufferHeightKey:NSNumber(integer: 1080)]
if(self.session.canAddInput(self.captureInput)){
self.session.addInput(self.captureInput)
}
if(self.session.canAddOutput(self.captureOutput)){
self.session.addOutput(self.captureOutput)
}
let subQueue:dispatch_queue_t = dispatch_queue_create("subQueue",nil)
captureOutput.setSampleBufferDelegate(self,queue: subQueue)
//预览Layer设置
self.captureVideoPreviewLayer = AVCaptureVideoPreviewLayer(session: self.session)
self.captureVideoPreviewLayer.frame = CGRectMake(self.view.frame.size.width/2 - (320/2),320,240)
self.captureVideoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
self.view.layer.addSublayer(self.captureVideoPreviewLayer)
self.session.commitConfiguration()
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view,typically from a nib.
self.setupCamera()
self.customImgView = UIImageView(frame: CGRectMake(self.captureVideoPreviewLayer.frame.origin.x,250,240))
self.view.addSubview(self.customImgView)
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.session.startRunning()
}
override func viewWilldisappear(animated: Bool) {
self.session.stopRunning()
super.viewWilldisappear(animated)
}
/**
数据流BufferRef转Image
- parameter sampleBuffer: 数据流
- returns: UIImage
*/
func getimageData(sampleBuffer:CMSampleBuffer!)-> UIImage {
let imageBuffer:CVImageBufferRef = CMSampleBufferGetimageBuffer(sampleBuffer)!
CVPixelBufferLockBaseAddress(imageBuffer,0)
let bytesPerRow:size_t = CVPixelBufferGetBytesPerRow(imageBuffer)
let width:size_t = CVPixelBufferGetWidth(imageBuffer)
let height:size_t = CVPixelBufferGetHeight(imageBuffer)
let safepoint:UnsafeMutablePointer<Void> = CVPixelBufferGetBaseAddress(imageBuffer)
let bitMapInfo:UInt32 = CGBitmapInfo.ByteOrder32Little.rawValue | CGImageAlphaInfo.PremultipliedFirst.rawValue
//RGB
let colorSpace: CGColorSpaceRef = CGColorSpaceCreateDeviceRGB()!
let context:CGContextRef = CGBitmapContextCreate(safepoint,width,height,8,bytesPerRow,colorSpace,bitMapInfo)!
let quartimage: CGImageRef = CGBitmapContextCreateImage(context)!
CVPixelBufferUnlockBaseAddress(imageBuffer,0)
return UIImage(CGImage: quartimage,scale: 1,orientation: UIImageOrientation.Right)
}
//AVCaptureVideoDataOutputSampleBufferDelegate
func captureOutput(captureOutput: AVCaptureOutput!,didOutputSampleBuffer sampleBuffer: CMSampleBuffer!,fromConnection connection: AVCaptureConnection!){
let localImg = self.getimageData(sampleBuffer)
//GCD 主线程队列中刷新UI
dispatch_async(dispatch_get_main_queue()) { () -> Void in
self.customImgView.image = localImg
}
}
//UIAlertViewDelegate
func alertView(alertView: UIAlertView,clickedButtonAtIndex buttonIndex: Int){
if(buttonIndex == 0){
self.openSettings()
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// dispose of any resources that can be recreated.
}
}
Developer官网有个Example 叫 AVCam-iOS