您的位置:首页 > 移动开发 > Swift

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

2015-11-25 19:49 447 查看
真的好久没写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<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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息