Swift 3 CGImage Memory issue



我在 Swift3 的代码中有这个函数,实际上我几乎是从 Apple 示例代码中翻译而来的。

我的应用处理来自从相机捕获实时源的 sampleBuffer。

此函数正确创建并从 CMSampleBuffer 返回图像。它工作正常,但内存不断增长,直到应用程序崩溃。

使用仪器,我看到有一些图像数据没有被释放。如果我在我做"context.makeImage"的行上发表评论,记忆就会保持下降。阅读该 func 文档时,它说它从上下文中复制数据。所以我认为有一些数据被复制,一个副本没有发布。

"问题"是 Swift 会自动处理 CoreFoundations 内存保留/释放,所以我无法处理它。

如您所见,我尝试使用自动发布池,但它不起作用。

知道吗?

谢谢

func image(from sampleBuffer:CMSampleBuffer) -> UIImage?{
    /* https://developer.apple.com/library/content/qa/qa1702/_index.html */
    let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)
    guard imageBuffer != nil else{
        return nil
    }
    return autoreleasepool{ () -> UIImage in
        CVPixelBufferLockBaseAddress(imageBuffer!, .readOnly);
        let baseAddress = CVPixelBufferGetBaseAddress(imageBuffer!)
        // Get the number of bytes per row for the pixel buffer
        let bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer!);
        // Get the pixel buffer width and height
        let width = CVPixelBufferGetWidth(imageBuffer!);
        let height = CVPixelBufferGetHeight(imageBuffer!);
        let colorSpace = CGColorSpaceCreateDeviceRGB();
        let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedFirst.rawValue)
            .union(.byteOrder32Little)
        // Create a bitmap graphics context with the sample buffer data
        let context = CGContext(data: baseAddress, width: width, height: height, bitsPerComponent: 8,
                                bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo.rawValue);
        // Create a Quartz image from the pixel data in the bitmap graphics context
        let quartzImage = context!.makeImage();
        // Unlock the pixel buffer
        CVPixelBufferUnlockBaseAddress(imageBuffer!,.readOnly);
        let image = UIImage(cgImage: quartzImage!)
        return image
    }
}

我找到了解决问题的方法。

我不知道UIKit不是线程安全的。似乎在与 main 不同的线程中执行该代码不允许系统按预期释放内存。

在主线程上,内存被正确释放和管理。

与其他不符合 ARC 标准的 Core* 库一样,您可能需要将 CM 调用包装在自动发布中。

func image(from sampleBuffer:CMSampleBuffer) -> UIImage?{
 
    var ret: UIImage?
    autoreleasepool {
        /* https://developer.apple.com/library/content/qa/qa1702/_index.html */
        let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)

        CVPixelBufferLockBaseAddress(imageBuffer!, .readOnly);
        let baseAddress = CVPixelBufferGetBaseAddress(imageBuffer!)
        // Get the number of bytes per row for the pixel buffer
        let bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer!);
        // Get the pixel buffer width and height
        let width = CVPixelBufferGetWidth(imageBuffer!);
        let height = CVPixelBufferGetHeight(imageBuffer!);
        let colorSpace = CGColorSpaceCreateDeviceRGB();
        let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedFirst.rawValue)
            .union(.byteOrder32Little)
        // Create a bitmap graphics context with the sample buffer data
        let context = CGContext(data: baseAddress, width: width, height: height, bitsPerComponent: 8,
                                bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo.rawValue);
        // Create a Quartz image from the pixel data in the bitmap graphics context
        let quartzImage = context!.makeImage();
        // Unlock the pixel buffer
        CVPixelBufferUnlockBaseAddress(imageBuffer!,.readOnly);
        let image = UIImage(cgImage: quartzImage!)
        ret = image
    }
    return ret
}

有关详细信息,请参阅此答案。

最新更新