我正在尝试将我从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 {
}
答案 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