jbaraga
jbaraga

Reputation: 656

AVAssetReaderOutput memory issue

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?

Upvotes: 2

Views: 1475

Answers (1)

Rob Napier
Rob Napier

Reputation: 299275

If you consult the docs for copyNextSampleBuffer, you'll note the following:

Ownership follows the The Create Rule.

The Create Rule is from Core Foundation: If a function includes the words "Create" or "Copy" then you are responsible for releasing the returned object. ARC does this for you automatically for ARC-managed objects, but CMSampleBuffer is not ARC-managed.

So when you're done with this object, you need to call CFRelease on it to avoid leaking memory.

Upvotes: 3

Related Questions