通过AVFoundation获取摄像头数据[Swift]
2015-11-25 19:49
447 查看
真的好久没写Blog了。。囧
捕捉硬件数据需要用到以下几个类
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
捕捉硬件数据需要用到以下几个类
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
相关文章推荐
- Apple Swift学习教程
- 康诺云推出三款智能硬件产品,为健康管理业务搭建数据池
- C#实现控制摄像头的类
- Swift中实现点击、双击、捏、旋转、拖动、划动、长按手势的类和方法介绍
- Swift编程中的泛型解析
- Swift中定义二维数组的方法及遍历方法示例
- Android 开发随手笔记之使用摄像头拍照
- C#实现调用本机摄像头实例
- 简单分析Swift语言的一些基本特征
- Swift与C语言指针结合使用实例
- Swift心得笔记之控制流
- 用Swift构建一个简单的iOS邮件应用的方法
- unity3d调用手机或电脑摄像头
- 苹果公司推出的新编程语言Swift简介和入门教程
- python获取各操作系统硬件信息的方法
- Python获取电脑硬件信息及状态的实现方法
- Python中使用摄像头实现简单的延时摄影技术