AVAssetReaderOutput memory issue

Refresh

December 2018

Views

529 time

2

I am using AVAssetReaderOutput (more specifically AVAssetReaderTrackOutput) to process video on a frame by frame basis. I get successive frames of the video using the copyNextSampleBuffer() method. I do not maintain any references to the frames after processing, yet I see progressive memory consumption as I loop through and read the entire video, and the memory usage is approximately the size of the video. This is problematic when dealing with large (>1GB) files. Initially I thought I may have a memory leak, but I have isolated the issue to the AVAssetReaderTrackOutput object.

For instance, if I merely loop through the video and use the copyNextSampleBuffer() method, I see the memory consumption issue. In the following code snippet, asset is an AVURLAsset object initialized from the video file:

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()
}

I have thought about modifying the reading method to read and process the video in shorter segments to avoid excessive memory usage, but I am unable to release the memory consumed by the AVAssetReaderTrackOutput object. For instance, if I set the object to nil after using it, the memory is not released according to the Xcode debug navigator:

videoTrackOutput = nil
assetReader = nil

Am I missing something? Is there another way to release the memory that appears to be used by the videoTrackOutput object?

If not, is there any other way to read the video frame by frame that does not have this issue?

1 answers

1

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

Собственности следует за Создать правило .

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

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