2

I am trying to create a video with an input of images using AVAssetWriterInput for which I need to create a pixel buffer of my images.

For that I call the function below which works, but after creating a few videos the app receives a memory warning and crashes. I have debugged it using Instruments and it appears I have a memory leak here.

I have tried to put the variables pixelBufferPointer and pxData as class variables and destroy/dealloc once the video is created but that didn't appear to make any difference. Is there something that I should be doing to release this memory?

func createPixelBufferFromCGImage(image: CGImageRef) -> CVPixelBufferRef {
    let options = [
        "kCVPixelBufferCGImageCompatibilityKey": true,
        "kCVPixelBufferCGBitmapContextCompatibilityKey": true
    ]

    var videoWidth = 496
    var videoHeight = 668

    let frameSize = CGSizeMake(CGFloat(videoWidth), CGFloat(videoHeight))

    var pixelBufferPointer = UnsafeMutablePointer<Unmanaged<CVPixelBuffer>?>.alloc(1)

    var status:CVReturn = CVPixelBufferCreate(
        kCFAllocatorDefault,
        Int(frameSize.width),
        Int(frameSize.height),
        OSType(kCVPixelFormatType_32ARGB),
        options,
        pixelBufferPointer
    )

    var lockStatus:CVReturn = CVPixelBufferLockBaseAddress(pixelBufferPointer.memory?.takeUnretainedValue(), 0)

    var pxData:UnsafeMutablePointer<(Void)> = CVPixelBufferGetBaseAddress(pixelBufferPointer.memory?.takeUnretainedValue())

    let bitmapinfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.NoneSkipFirst.rawValue)
    let rgbColorSpace:CGColorSpace = CGColorSpaceCreateDeviceRGB()

    var context:CGContextRef = CGBitmapContextCreate(
        pxData,
        Int(frameSize.width),
        Int(frameSize.height),
        8,
        //4 * CGImageGetWidth(image),
        4 * Int(frameSize.width),
        rgbColorSpace,
        bitmapinfo
    )

    CGContextDrawImage(context, CGRectMake(0, 0, frameSize.width, frameSize.height), image)

    CVPixelBufferUnlockBaseAddress(pixelBufferPointer.memory?.takeUnretainedValue(), 0)

    UIGraphicsEndImageContext()

    return pixelBufferPointer.memory!.takeUnretainedValue()
}
Brian
  • 14,610
  • 7
  • 35
  • 43
carlosb
  • 182
  • 2
  • 8

4 Answers4

0

Take a look at Memory leak on CIContext createCGImage at iOS 9?

I'm having a similar issue, the leak is due to the following code

CGImageRef processedCGImage = [_context createCGImage:ciImage
                                                             fromRect:[ciImage extent]];

Here for more contextual info: Memory Leak in CMSampleBufferGetImageBuffer

Community
  • 1
  • 1
loretoparisi
  • 15,724
  • 11
  • 102
  • 146
  • Thanks for your quick reply. I am not sure if it is the same bug because I am running this code on iOS 8.3 and I am also not using createCGImage – carlosb Oct 13 '15 at 19:13
  • that is right, but I have some suspects, infact those primitives CVPixelBufferGetBaseAddress, CGBitmapContextCreate, CGContextDrawImage are the same used when dealing with a createCGImage using a CIContext. I'm sure they are related. – loretoparisi Oct 13 '15 at 19:25
0

You don't have to use the UnsafeMutablePointer types. You were probably trying to convert from some Objective-C example. I was doing the same thing but eventually found how to do it without. Try

var pixelBufferPointer: CVPixelBuffer?
...
var status:CVReturn = CVPixelBufferCreate(
    kCFAllocatorDefault,
    Int(frameSize.width),
    Int(frameSize.height),
    OSType(kCVPixelFormatType_32ARGB),
    options,
    &pixelBufferPointer
)

and

var pxData = CVPixelBufferGetBaseAddress(pixelBufferPointer)

Then you don't have to do the takeUnRetainedValue, etc.

You might also try using AVAssetWriterInputPixelBufferAdaptor and a pixel buffer pool. That is supposed to be more efficient. See this example

Community
  • 1
  • 1
Russell Austin
  • 409
  • 3
  • 7
  • i already set that code but it seems memory leak from buffer while frames in loop. –  Dec 22 '20 at 07:04
0

The Unmanaged<CVPixelBuffer> is leaking.

I would prefer Russell Austin's answer, but I couldn't figure out how to pass the pixelBufferPointer to CVPixelBufferCreate without syntax error (swift noob). Failing that, changing the line

return pixelBufferPointer.memory!.takeUnretainedValue()

to

return pixelBufferPointer.memory!.takeRetainedValue()

fixes the leak

Rhythmic Fistman
  • 34,352
  • 5
  • 87
  • 159
  • Which issue @RB1509? – Rhythmic Fistman Jan 01 '21 at 08:20
  • thanks for your reply :) i have an issue regarding record a view and i am not able to ask question so can you please help me to short out it? –  Jan 01 '21 at 09:35
  • var buffer:CVPixelBuffer? autoreleasepool { buffer = self.pixelBufferFromImage(image: image) } if buffer != nil { let result = self.adapter.append(buffer!, withPresentationTime: present) if !result { print(self.writer.error) } buffer = nil } –  Jan 01 '21 at 09:38
  • that is my code i can't able to provide full code but i debug as well and this code take memory upto 1.34 Gb on my device while recording view, it occurs crash. one more thing that code is in writeVideoFromImageFrames which will use to convert video from images. –  Jan 01 '21 at 09:40
  • You need to show some more code, especially `pixelBufferFromImage` - why can't you ask a question? – Rhythmic Fistman Jan 01 '21 at 10:35
  • Sorry, we are no longer accepting questions from this account. See the Help Center to learn more. –  Jan 01 '21 at 11:21
  • it shows me like this whenever i try to ask question. –  Jan 01 '21 at 11:22
  • wait i will share you link where you can see my code. –  Jan 01 '21 at 11:23
  • https://drive.google.com/file/d/10of8wqXaw2_XVZctpshVNly7Z156ikMT/view?usp=sharing –  Jan 01 '21 at 11:25
  • can you please check it. –  Jan 01 '21 at 11:26
  • there i make 2 function for cvpixelbuffer. one of them i used in my code but that crash on memory leaks. –  Jan 01 '21 at 11:35
  • you need to ask a new question with the above code. fwiw it looks like `frameBuffer` is never drained – Rhythmic Fistman Jan 01 '21 at 17:49
  • frameBuffer is never drained. Means ?? –  Jan 02 '21 at 03:59
0

When using CVPixelBufferCreate the UnsafeMutablePointer has to be destroyed after retrieving the memory of it.

When I create a CVPixelBuffer, I do it like this:

func allocPixelBuffer() -> CVPixelBuffer {
    let pixelBufferAttributes : CFDictionary = [...]
    let pixelBufferOut = UnsafeMutablePointer<CVPixelBuffer?>.alloc(1)
    _ = CVPixelBufferCreate(kCFAllocatorDefault, 
                            Int(Width), 
                            Int(Height), 
                            OSType(kCVPixelFormatType_32ARGB),
                            pixelBufferAttributes, 
                            pixelBufferOut)

    let pixelBuffer = pixelBufferOut.memory!
    pixelBufferOut.destroy()
    return pixelBuffer
}
Sebastian Krogull
  • 1,468
  • 1
  • 15
  • 31