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

原创 2015年11月25日 19:49:00

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

相关文章推荐

[iOS Swift3.0/Oc] 摄像头实时获取视频流效果 简单记录

Oc参考贴: iOS从摄像头获得实时视频流Swift 3.01.创建 会话对象+输入对象+输出对象为了能实时看到摄像机获取的视频图像,还要创建一个 预览图层(AVCaptureVideoPreview...

swift3 访问相册和摄像头

第一步:需要在项目中的Info.plist中添加相应的键 访问相册:Privacy - Photo Library Usage Description 访问摄像头:Privacy ...
  • EIamor
  • EIamor
  • 2017年05月10日 11:07
  • 463

从ffmpeg的AVFrame得到iOS的CVPixelBuffer

个人在之前的一篇文章《在iOS端使用AVSampleBufferDisplayLayer进行视频渲染》中提到,可以使用iOS8.0新出的AVSampleBufferDisplayLayer进行视频的渲...

iOS直接获取摄像头数据

需要添加的  Framework :CoreMedia, CoreVideo QuartzCore, AVFoundation  MyAVController.h:  #import   #...

读取视频帧的几种方法(自己整理)

1、第一种方法 #include "opencv2/opencv.hpp" using namespace cv; int main(int, char**) { VideoCapture cap(...

Swift - 二维码QRCode的读取(从图片读取 ,或通过摄像头扫描)

1,直接读取图片中的二维码 使用 CIDetector 可以很方便的检测并读取二维码。下面是一个从 UIImage 中读取二维码的样例,我们要把图片上所有的二维码信息都打印出来。 代...
  • leafgw
  • leafgw
  • 2016年04月08日 14:39
  • 991

iOS 获取视频的任意一帧

项目要求根据服务器返回的视频和秒数,生成该视频的预览图。 网上一搜关键词 “iOS 视频 帧” 结果都是:iOS如何获取视频的第一帧。 但是如果我不想要第一帧,要第s秒的第x帧怎么办? 先贴如何...

Android获取摄像头视频帧并实时处理(转载)

原文出处:http://blog.csdn.net/jefry_xdz/article/details/7901587  Android有一种机制,如果想在回调函数onPreviewFram...

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

Swift - 二维码QRCode的读取(从图片读取 ,或通过摄像头扫描)

1,直接读取图片中的二维码 使用 CIDetector 可以很方便的检测并读取二维码。下面是一个从 UIImage 中读取二维码的样例,我们要把图片上所有的二维码信息都打印出来。 ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:通过AVFoundation获取摄像头数据[Swift]
举报原因:
原因补充:

(最多只允许输入30个字)