Управление памятью - CVPixelBuffer для UIImage, разница между использованием CIImage и VTCreateCGImageFromCVPixelBuffer

Я получил два решения преобразования CVPixelBuffer в UIImage,

  1. Использование CIImage и его контекста

Первое решение использует CIImage а также CIContext,

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:), Следы памяти увеличиваются до конца всего процесса кэширования в первом сценарии. Но, во-вторых, он освобождает свою память после завершения каждого рабочего элемента.

Я действительно не знаю почему.

Вот мой метод кэширования, связанный с этой проблемой.

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 ответов

Другие вопросы по тегам