内存管理-CVPixelBuffer到UIImage,使用CIImage和VTCreateCGImageFromCVPixelBuffer的区别

时间:2018-08-15 05:58:54

标签: ios swift uiimage cgimage cvpixelbuffer

我有两个解决方案将CVPixelBuffer转换为UIImage

  1. 使用CIImage及其上下文

第一个解决方案是使用CIImageCIContext

func readAssetAndCache(completion: @escaping () -> Void) {

    /** Setup AVAssetReader **/
    reader.startReading()

    let context = CIContext()
    while let sampleBuffer = generator.trackoutput.copyNextSampleBuffer() {
        autoreleasepool {
            guard let imageBuffer: CVPixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { return }

            let ciImage = CIImage(cvImageBuffer: imageBuffer)
            guard let cgImage = context.createCGImage(ciImage, from: ciImage.extent) else { return }

            if let image = UIImage(cgImage: cgImage) {
                CacheManager.default.cache(image: image, forKey: "CachedImages") {
                   completion()
                }
            }
        }
    }
}
  1. 使用VTCreateCGImageFromCVPixelBuffer

代码看起来像这样。

func readAssetAndCache(completion: @escaping () -> Void) {

        /** Setup AVAssetReader **/

    reader.startReading()

    while let sampleBuffer = generator.trackoutput.copyNextSampleBuffer() {
        autoreleasepool {
            guard let imageBuffer: CVPixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { return }

            if let image = UIImage(pixelBuffer: imageBuffer,
                                   scale: 1.0,
                                   orientation: self.imageOrientation) {
                CacheManager.default.cache(image: image, forKey: "CachedImages") {

                        completion()
                    }
                }
            }
        }
    }
}

在此解决方案中,我使用此扩展方法。

import UIKit
import VideoToolbox

extension UIImage {
    public convenience init?(pixelBuffer: CVPixelBuffer, scale: CGFloat, orientation: UIImageOrientation) {
            var image: CGImage?
            VTCreateCGImageFromCVPixelBuffer(pixelBuffer, nil, &image)

            guard let cgImage = image else { return nil }

            self.init(cgImage: cgImage, scale: scale, orientation: orientation)
        }
    }

从视频中提取图像的整个过程如下。

整个过程

  1. 连续提取所有帧。
  2. 使用OperationQueue在磁盘上同时缓存每个映像。

问题

使用CIContext及其createCGImage(ciImage:rect:)同时缓存图像时,会出现问题。在第一种情况下,内存占用量将增加,直到所有缓存过程结束。但是,第二种方式是,当每个workItem完成时,它将释放其内存。

我真的不知道为什么。

这是我与此问题有关的缓存方法。

func cache(image: UIImage, forKey key: String, completion: @escaping () -> Void) {

    let operation = BlockOperation(block: { [weak self] in
        guard let `self` = self else { return }
        self.diskCache(image: image)
    })
    operation.completionBlock = completion
    operationQueue.addOperation(operation)
}

func diskCache(image: UIImage) {
    let data = UIImageJPEGRepresentation(image, 1.0)

    let key = "\(self.identifierPrefix).jpg"

    FileManager.default.createFile(atPath: self.cachePath.appendingPathComponent(key).path,
                                   contents: data, attributes: nil)
}

0 个答案:

没有答案