意外发现AVCaptureVideoDataOutput中的CMSampleBuffer为

时间:2017-01-12 21:19:04

标签: ios swift uiimage cmsamplebuffer

我正在尝试将我从AVCaptureVideoDataOutput委托(作为CMSampleBuffer)获取的帧转换为UIImage。但是我得到fatal error: unexpectedly found nil while unwrapping an Optional value有人可以告诉我我的代码有什么问题吗?我假设我的sampleBufferToUIImage函数有问题。

将CMSampleBuffer转换为UIImage的功能:

func sampleBufferToUIImage(sampleBuffer: CMSampleBuffer) -> UIImage{

    let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)

    CVPixelBufferLockBaseAddress(imageBuffer!, CVPixelBufferLockFlags(rawValue: 0))

    let baseAddress = CVPixelBufferGetBaseAddress(imageBuffer!)

    let bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer!)

    let width = CVPixelBufferGetWidth(imageBuffer!)
    let height = CVPixelBufferGetHeight(imageBuffer!)

    let colorSpace = CGColorSpaceCreateDeviceRGB()

    let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.noneSkipFirst.rawValue | CGBitmapInfo.byteOrder32Little.rawValue)

    let context = CGContext(data: baseAddress, width: width, height: height, bitsPerComponent: 8, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo.rawValue)

    // *********Getting the error from this line***********
    let quartzImage = context!.makeImage()

    CVPixelBufferUnlockBaseAddress(imageBuffer!, CVPixelBufferLockFlags(rawValue: 0))

    let image = UIImage(cgImage: quartzImage!)

    return image

}

委托我阅读框架:

func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!) {

    if count <= 0 {
        // Calling my function to convert to UIImage.
        let image = sampleBufferToUIImage(sampleBuffer: sampleBuffer)
        let imageData = UIImagePNGRepresentation(image)
        uploadImage(jpgData: imageData)
    }

    count = count + 1
}

设置AVSession:

func setupCameraSession() {

    captureSession.sessionPreset = AVCaptureSessionPresetHigh

    // Declare AVCaptureDevice to default(back camera).  The "as" changes removes the optional?
    let captureDevice = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo) as AVCaptureDevice

    do {
        let deviceInput = try AVCaptureDeviceInput(device: captureDevice)

        if (captureSession.canAddInput(deviceInput) == true) {
            captureSession.addInput(deviceInput)
        }

        let dataOutput = AVCaptureVideoDataOutput()
        dataOutput.videoSettings = [(kCVPixelBufferPixelFormatTypeKey as NSString) : NSNumber(value: kCVPixelFormatType_420YpCbCr8BiPlanarFullRange as UInt32)]
        dataOutput.alwaysDiscardsLateVideoFrames = true

        if (captureSession.canAddOutput(dataOutput) == true) {
            captureSession.addOutput(dataOutput)
        }


    } catch {

    }

2 个答案:

答案 0 :(得分:2)

试试这个,在Swift 3上为我工作

// Sample buffer handling delegate function
func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!) {

    let myPixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)
    myCIimage         = CIImage(cvPixelBuffer: myPixelBuffer!)
    videoImage        = UIImage(ciImage: myCIimage)
    uIimage.image = videoImage
}

// AV会话

func startVideoDisplay() {        
    do {
        let tryDeviceInput = try AVCaptureDeviceInput(device: cameraDevice)
        cameraCaptureSession.addInput(tryDeviceInput)
    } catch { print(error.localizedDescription) }

    caViewLayer = AVCaptureVideoPreviewLayer(session: cameraCaptureSession)
    view.layer.addSublayer(caViewLayer)

    cameraCaptureSession.startRunning()

    let myQueue = DispatchQueue(label: "se.paredes.FunAV", qos: .userInteractive, attributes: .concurrent)

    let theOutput = AVCaptureVideoDataOutput()
    theOutput.videoSettings = [(kCVPixelBufferPixelFormatTypeKey as NSString): NSNumber(value:kCVPixelFormatType_32BGRA)]
    theOutput.alwaysDiscardsLateVideoFrames = true
    theOutput.setSampleBufferDelegate(self, queue: myQueue)

    if cameraCaptureSession.canAddOutput(theOutput) {
        cameraCaptureSession.addOutput(theOutput)
    }
    cameraCaptureSession.commitConfiguration()
}

答案 1 :(得分:1)

AVCaptureVideoDataOutput的视频设置不正确。将kCVPixelFormatType_420YpCbCr8BiPlanarFullRange更改为kCVPixelFormatType_32BGRA