Как ограничить использование AVAssetWriter слишком большого объема памяти при кодировании видео? - PullRequest
0 голосов
/ 21 июня 2019

Я использую AVAssetWriter для создания видео с изображениями кадров (массив UIImage). Когда он выполняет кодирование, использование памяти иногда достигает 700 МБ. На моем iPhone (с 3GB MEM) это не вызывает проблемы с OOM, но я боюсь, что это вызовет проблемы в старых iPhone.

enter image description here

Можно ли как-то ограничить использование памяти AVAssetWriter? Я предполагаю, что внутренне он может использовать некоторую очередь для кэширования байтов кадра, если я могу указать размер кэша, то я могу установить верхний предел памяти. Но я не нашел таких параметров / настроек в документации.

Вот мой код:

    let settings:[String:Any] = [
        AVVideoCodecKey: AVVideoCodecH264,
        AVVideoWidthKey: FRAME_SIZE,
        AVVideoHeightKey: FRAME_SIZE
    ]
    let assetWriter = AVAssetWriter(url: self.url!, fileType: AVFileType.mov)        
    let assetWriterInput = AVAssetWriterInput(mediaType: AVMediaType.video, outputSettings: settings)
    self.assetWriter?.add(assetWriterInput)

    let bufferAttributes:[String: Any] = [kCVPixelBufferPixelFormatTypeKey as String: Int(kCVPixelFormatType_32ARGB)]
    let bufferAdapter = AVAssetWriterInputPixelBufferAdaptor(assetWriterInput: assetWriterInput, sourcePixelBufferAttributes: bufferAttributes)
    let frameTime = CMTimeMake(1, 30)

    self.assetWriter?.startWriting()
    self.assetWriter?.startSession(atSourceTime: kCMTimeZero)

    let mediaInputQueue = DispatchQueue(label: "mediaInputQueue")

    var i = 0

    assetWriterInput.requestMediaDataWhenReady(on: mediaInputQueue){
        var localframes = frames
        while(true){
            if(localframes.isEmpty){
                break
            }
            if (assetWriterInput.isReadyForMoreMediaData){
                let image = localframes.removeFirst()
                let pixelBuffer = self.newPixelBufferFrom(cgImage: image.cgImage!)

                var time:CMTime
                if i == 0 {
                    time = kCMTimeZero
                } else {
                    time = CMTimeMake(Int64(i), frameTime.timescale)
                }

                bufferAdapter.append(pixelBuffer!, withPresentationTime: time)

                // TODO: how to release memory?
                i += 1
            }
        }
        assetWriterInput.markAsFinished()
        self.assetWriter?.finishWriting(completionHandler: {
                finishedHandler()
        })
    }

1 Ответ

1 голос
/ 21 июня 2019

Не уверен, поможет ли это, но у меня была похожая проблема внутри цикла while. Вы можете проверить этот ответ: Приводит ли симулятор ios iPhone к анализу использования памяти?

Вы можете попробовать и посмотреть, улучшится ли он:

let pixelBuffer = autoreleasepool { return self.newPixelBufferFrom(cgImage: image.cgImage!) }

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...