【问题标题】:CIContext + createCGImage + UIImage CrashCIContext + createCGImage + UIImage 崩溃
【发布时间】:2016-10-30 18:49:08
【问题描述】:

我在做什么:

我从 AVFoundation 中的 didOutputSampleBuffer 获取 CMSampleBuffer 并运行几个过滤器并将它们输出到 UIImage 每次代理吐出一个缓冲区。

工作原理:

所有过滤器都可以正常工作。它给了我想要的输出。在新手机(iPhone 6/6s/7)上一切正常;但是,它会在几秒钟后冻结在 iPhone 5s 上。

滤镜和 UIImage 输出:

let inputImage = self.bufferImage!

let filter = CIFilter(name: "CIPixellate")
let beginImage = inputImage
filter!.setValue(beginImage, forKey: kCIInputImageKey)

let filter3 = CIFilter(name: "CIColorMonochrome")
filter3!.setValue(filter!.outputImage, forKey: kCIInputImageKey)
filter3!.setValue(CIColor(red: 1, green:0, blue: 0), forKey: kCIInputColorKey)
filter3!.setValue(200.0, forKey: kCIInputIntensityKey)

let filter2 = CIFilter(name: "CIMultiplyBlendMode")
filter2!.setValue(filter3!.outputImage, forKey: kCIInputImageKey)
filter2!.setValue(inputImage, forKey: kCIInputBackgroundImageKey)
let output2 = filter2!.outputImage

let cgimg = self.context.createCGImage(output2!, fromRect: output2!.extent)
let newImage = UIImage(CGImage: cgimg!)
dispatch_sync(dispatch_get_main_queue()) {
     self.imageView?.image = newImage
}
self.context.clearCaches()

我将 CIContext 创建为:

let context = CIContext(options: nil)

我也尝试强制 CIContext 在硬件上渲染,反之亦然。

我觉得,内存/空间/泄漏/等有些东西用完了,虽然,当它冻结时,Xcode 中没有错误,只是应用程序处于冻结状态。我在最后添加了 self.context.clearCaches(),如果没有真正改变原始问题的任何内容。

这只发生在速度较慢的设备上 - 在这种情况下为 5S,在 6/6s/7 上运行平稳,没有任何问题。

我的完整 didOutputSampleBuffer 供参考:

func captureOutput(captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, fromConnection connection: AVCaptureConnection!) {
    connection.videoOrientation = .Portrait
    let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)

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

    let baseAddress = CVPixelBufferGetBaseAddress(imageBuffer!)

    let bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer!)

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

    let colorSpace = CGColorSpaceCreateDeviceRGB()

    let bitmap = CGBitmapInfo(rawValue: CGBitmapInfo.ByteOrder32Little.rawValue|CGImageAlphaInfo.PremultipliedFirst.rawValue)
    let context = CGBitmapContextCreate(baseAddress, width, height, 8,
                                        bytesPerRow, colorSpace, bitmap.rawValue)

    let quartzImage = CGBitmapContextCreateImage(context!)

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

    self.bufferImage = CIImage(CGImage: quartzImage!)

            let inputImage = self.bufferImage!

            let filter = CIFilter(name: "CIPixellate")
            let beginImage = inputImage
            filter!.setValue(beginImage, forKey: kCIInputImageKey)

            let filter3 = CIFilter(name: "CIColorMonochrome")
            filter3!.setValue(filter!.outputImage, forKey: kCIInputImageKey)
            filter3!.setValue(CIColor(red: 1, green:0, blue: 0), forKey: kCIInputColorKey)
            filter3!.setValue(200.0, forKey: kCIInputIntensityKey)

            let filter2 = CIFilter(name: "CIMultiplyBlendMode")
            filter2!.setValue(filter3!.outputImage, forKey: kCIInputImageKey)
            filter2!.setValue(inputImage, forKey: kCIInputBackgroundImageKey)
            let output2 = filter2!.outputImage

            let cgimg = self.context.createCGImage(output2!, fromRect: output2!.extent)
            let newImage = UIImage(CGImage: cgimg!)

            dispatch_async(dispatch_get_main_queue()) {
                self.imageView?.image = newImage
            }
            self.context.clearCaches()
}

更新

我能够通过更改获取像素缓冲区成为 CIImage 的方法来解决冻结问题:

let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)!
self.bufferImage = CIImage(CVPixelBuffer: pixelBuffer)

取出didOutputSampleBuffer开头的大部分代码。

但是,现在 CPU 使用率非常高! Xcode 显示“能源影响”很高!

【问题讨论】:

    标签: ios xcode uiimage cgcontext ciimage


    【解决方案1】:

    你是说:

    dispatch_sync(dispatch_get_main_queue()) {
         self.imageView?.image = newImage
    }
    

    你没有任何理由等待这个调用的结果。请改用dispatch_async

    (更好的是:找出你是否在主线程上。如果是,请不要使用dispatch 任何东西。)

    【讨论】:

    • 我很抱歉。我正在尝试从异步同步。我将OP编辑回异步。我必须转到主线程,didOutputSampleBuffer 正在另一个线程中发生。
    • 当我不使用 dispatch_sync(dispatch_get_main_queue()) 时,self.imageView?.image 根本不会显示。
    • 我能想到的唯一原因是self.imageViewnil。尝试记录并查看。
    • iPhone 5s (1) 较慢并且 (2) 不是多线程的。也许您应该尝试丢帧...?
    • 它是双核而不是四核。当你做你正在做的事情时,会有很大的不同。你应该使用 Instruments 来掌握这里发生的事情。
    猜你喜欢
    • 1970-01-01
    • 2017-09-04
    • 1970-01-01
    • 2017-03-07
    • 1970-01-01
    • 1970-01-01
    • 2012-09-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多