真的好久没写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

通过AVFoundation获取摄像头数据[Swift]的更多相关文章

  1. HTML5 Web缓存和运用程序缓存(cookie,session)

    这篇文章主要介绍了HTML5 Web缓存和运用程序缓存(cookie,session),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. iOS Swift上弃用后Twitter.sharedInstance().session()?. userName的替代方案

    解决方法如果您仍在寻找解决方案,请参阅以下内容:

  3. 使用Fabric SDK iOS访问Twitter用户时间线

    我试图在这个问题上挣扎两天.我正在使用FabricSDK和Rest工具包,试图为Twitter使用不同的RestAPIWeb服务.我可以使用具有authTokenSecret,authToken和其他值的会话对象的TWTRLogInButton成功登录.当我尝试获取用户时间线时,我总是得到失败的响应,作为:{“errors”:[{“code”:215,“message”:“BadAuthentic

  4. ios – 如何从Apple Watch调用iPhone上定义的方法

    有没有办法从Watchkit扩展中调用iPhone上的类中定义的方法?根据我的理解,目前在Watchkit和iPhone之间进行本地通信的方法之一是使用NSUserDefaults,但还有其他方法吗?

  5. ios – 如何将视频从AVAssetExportSession保存到相机胶卷?

    在此先感谢您的帮助.解决方法只需使用session.outputURL=…

  6. ios – 使用AVCaptureSession sessionPreset = AVCaptureSessionPresetPhoto拉伸捕获的照片

    解决方法所以我解决了我的问题.这是我现在使用的代码,它工作正常:…重要的输出imagaView:一些额外的信息:相机图层必须是全屏,并且outputimageView也必须是.我希望这些对某些人来说也是有用的信息.

  7. 我可以在iOS中自定义Twitter工具包的登录按钮吗?

    我已经下载了Twitter工具包框架并添加了用Twitter登录的代码.但是,我不希望登录按钮看起来像那样.我想要一个用于登录的自定义按钮.我能这样做吗?我只想使用这个框架,因为这也适用于iOS系统帐户.解决方法根据document:在按下按钮中添加代码:Objective-C的迅速

  8. ios – AVCaptureSession条形码扫描

    解决方法以下是我所拥有的项目代码示例,可以帮助您走上正确的轨道

  9. ios – 如何在Watch OS 2中引用不支持的框架

    有没有办法将框架链接到扩展名?

  10. ios7 – 在iOS 7中设置Alamofire中的自定义HTTP标头不工作

    解决方法我得到它的工作这对iOS7没有影响:然而,这将适用于iOS7和8:

随机推荐

  1. Swift UITextField,UITextView,UISegmentedControl,UISwitch

    下面我们通过一个demo来简单的实现下这些控件的功能.首先,我们拖将这几个控件拖到storyboard,并关联上相应的属性和动作.如图:关联上属性和动作后,看看实现的代码:

  2. swift UISlider,UIStepper

    我们用两个label来显示slider和stepper的值.再用张图片来显示改变stepper值的效果.首先,这三个控件需要全局变量声明如下然后,我们对所有的控件做个简单的布局:最后,当slider的值改变时,我们用一个label来显示值的变化,同样,用另一个label来显示stepper值的变化,并改变图片的大小:实现效果如下:

  3. preferredFontForTextStyle字体设置之更改

    即:

  4. Swift没有异常处理,遇到功能性错误怎么办?

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  5. 字典实战和UIKit初探

    ios中数组和字典的应用Applicationschedule类别子项类别名称优先级数据包contactsentertainment接触UIKit学习用Swift调用CocoaTouchimportUIKitletcolors=[]varbackView=UIView(frame:CGRectMake(0.0,0.0,320.0,CGFloat(colors.count*50)))backView

  6. swift语言IOS8开发战记21 Core Data2

    上一话中我们简单地介绍了一些coredata的基本知识,这一话我们通过编程来实现coredata的使用。还记得我们在coredata中定义的那个Model么,上面这段代码会加载这个Model。定义完方法之后,我们对coredata的准备都已经完成了。最后强调一点,coredata并不是数据库,它只是一个框架,协助我们进行数据库操作,它并不关心我们把数据存到哪里。

  7. swift语言IOS8开发战记22 Core Data3

    上一话我们定义了与coredata有关的变量和方法,做足了准备工作,这一话我们来试试能不能成功。首先打开上一话中生成的Info类,在其中引用头文件的地方添加一个@objc,不然后面会报错,我也不知道为什么。

  8. swift实战小程序1天气预报

    在有一定swift基础的情况下,让我们来做一些小程序练练手,今天来试试做一个简单地天气预报。然后在btnpressed方法中依旧增加loadWeather方法.在loadWeather方法中加上信息的显示语句:运行一下看看效果,如图:虽然显示出来了,但是我们的text是可编辑状态的,在storyboard中勾选Editable,再次运行:大功告成,而且现在每次单击按钮,就会重新请求天气情况,大家也来试试吧。

  9. 【iOS学习01】swift ? and !  的学习

    如果不初始化就会报错。

  10. swift语言IOS8开发战记23 Core Data4

    接着我们需要把我们的Rest类变成一个被coredata管理的类,点开Rest类,作如下修改:关键字@NSManaged的作用是与实体中对应的属性通信,BinaryData对应的类型是NSData,CoreData没有布尔属性,只能用0和1来区分。进行如下操作,输入类名:建立好之后因为我们之前写的代码有些地方并不适用于coredata,所以编译器会报错,现在来一一解决。

返回
顶部