2016-01-17 3 views
1

Я использую AVAssetReaderOutput (более конкретно AVAssetReaderTrackOutput) для обработки видео по кадрам. Я получаю последовательные кадры видео, используя метод copyNextSampleBuffer(). Я не поддерживаю никаких ссылок на фреймы после обработки, но я вижу прогрессивное потребление памяти, когда я просматриваю и просматриваю все видео, а объем использования памяти примерно равен размеру видео. Это проблема при работе с большими (> 1 ГБ) файлами. Первоначально я думал, что у меня может быть утечка памяти, но я выделил проблему для объекта AVAssetReaderTrackOutput.AVAssetReaderOutput memory issue

Например, если я просто просматриваю видео и использую метод copyNextSampleBuffer(), я вижу проблему с потреблением памяти. В следующем фрагменте кода, актив является объектом AVURLAsset инициализируется из видеофайла:

guard let videoTrack = asset.tracksWithMediaType(AVMediaTypeVideo).first else { return } 
let outputSettings: [String: AnyObject] = [kCVPixelBufferPixelFormatTypeKey as String: NSNumber(unsignedInt: kCVPixelFormatType_32ARGB)] 
videoTrackOutput = AVAssetReaderTrackOutput(track: videoTrack, outputSettings: outputSettings) 
videoTrackOutput.alwaysCopiesSampleData = false 
assetReader.addOutput(videoTrackOutput) 
let _ = assetReader.startReading() 
while self.assetReader.status == AVAssetReaderStatus.Reading { 
    videoTrackOutput.copyNextSampleBuffer() 
} 

Я думал об изменении способа чтения для чтения и обработки видео в более короткие сегменты, чтобы избежать чрезмерного использования памяти, но я не удалось освободить память, потребляемую объектом AVAssetReaderTrackOutput. Например, если установить объект в ноль после его использования, память не освобождается в соответствии с Xcode отладки навигатора:

videoTrackOutput = nil 
assetReader = nil 

я упускаю что-то? Есть ли другой способ освободить память, которая, по-видимому, используется объектом videoTrackOutput?

Если нет, есть ли другой способ прочитать видео кадр за кадром, который не имеет этой проблемы?

ответ

1

Если обратиться к документации для copyNextSampleBuffer, вы обратите внимание на следующее:

собственности следует The Create Rule.

Правило создания из Core Foundation: если функция включает слова «Создать» или «Копировать», то вы несете ответственность за освобождение возвращенного объекта. ARC делает это для вас автоматически для объектов, управляемых ARC, но CMSampleBuffer не управляется ARC.

Итак, когда вы закончите с этим объектом, вам необходимо позвонить CFRelease, чтобы избежать утечки памяти.

+0

Я пробовал это, но компилятор дает ошибку при попытке вызвать CFRelease: «CFRelease» недоступен: объекты Core Foundation автоматически управляются памятью. Есть ли другой способ освободить буфер? – jbaraga

+0

Является ли приведенный выше код действительно показательным для вашего реального кода? Вы называете это в цикле? Если это так, вам нужно добавить блок autoreleasepool {} в цикле, или вы можете увеличить потребление памяти (хотя в конечном итоге оно исчезнет). –

+0

Хорошее предложение, но, к сожалению, оно не влияет на использование памяти. Даже после того, как блок кода завершил выполнение, память не будет выпущена. Я не поддерживаю никаких ссылок на буфер. – jbaraga