通过AVFoundation获取摄像头数据[Swift]

真的好久没写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), 0, 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, 320, 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 = 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

你可能感兴趣的:(IOS)