Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

I want to release the CVPixelBufferRef in swift

I want to create a video from image.
So, I was the source of the link to the reference.
Link:CVPixelBufferPool Error ( kCVReturnInvalidArgument/-6661)

func writeAnimationToMovie(path: String, size: CGSize, animation: Animation) -> Bool {   
    var error: NSError?
    let writer = AVAssetWriter(URL: NSURL(fileURLWithPath: path), fileType: AVFileTypeQuickTimeMovie, error: &error)

    let videoSettings = [AVVideoCodecKey: AVVideoCodecH264, AVVideoWidthKey: size.width, AVVideoHeightKey: size.height]

    let input = AVAssetWriterInput(mediaType: AVMediaTypeVideo, outputSettings: videoSettings)
    let pixelBufferAdaptor = AVAssetWriterInputPixelBufferAdaptor(assetWriterInput: input, sourcePixelBufferAttributes: nil)
    input.expectsMediaDataInRealTime = true
    writer.addInput(input)

    writer.startWriting()
    writer.startSessionAtSourceTime(kCMTimeZero)

    var buffer: CVPixelBufferRef

    var frameCount = 0
    for frame in animation.frames {
        let rect = CGRectMake(0, 0, size.width, size.height)
        let rectPtr = UnsafeMutablePointer<CGRect>.alloc(1)
        rectPtr.memory = rect
        buffer = pixelBufferFromCGImage(frame.image.CGImageForProposedRect(rectPtr, context: nil, hints: nil).takeUnretainedValue(), size)
        var appendOk = false
        var j = 0
        while (!appendOk && j < 30) {
            if pixelBufferAdaptor.assetWriterInput.readyForMoreMediaData {
                let frameTime = CMTimeMake(Int64(frameCount), 10)
                appendOk = pixelBufferAdaptor.appendPixelBuffer(buffer, withPresentationTime: frameTime)
                // appendOk will always be false
                NSThread.sleepForTimeInterval(0.05)
            } else {
                NSThread.sleepForTimeInterval(0.1)
            }
            j++
        }
        if (!appendOk) {
            println("Doh, frame \(frame) at offset \(frameCount) failed to append")
        }
    }

    input.markAsFinished()
    writer.finishWritingWithCompletionHandler({
        if writer.status == AVAssetWriterStatus.Failed {
            println("oh noes, an error: \(writer.error.description)")
        } else {
            println("hrmmm, there should be a movie?")
        }
    })

    return true;
 }


func pixelBufferFromCGImage(image: CGImageRef, size: CGSize) -> CVPixelBufferRef {
    let options = [
        kCVPixelBufferCGImageCompatibilityKey: true,
        kCVPixelBufferCGBitmapContextCompatibilityKey: true]
    var pixBufferPointer = UnsafeMutablePointer<Unmanaged<CVPixelBuffer>?>.alloc(1)

    let status = CVPixelBufferCreate(
        nil,
        UInt(size.width), UInt(size.height),
        OSType(kCVPixelFormatType_32ARGB),
        options,
        pixBufferPointer)

    CVPixelBufferLockBaseAddress(pixBufferPointer.memory?.takeUnretainedValue(), 0)

    let rgbColorSpace = CGColorSpaceCreateDeviceRGB()
    let bitmapinfo =  CGBitmapInfo.fromRaw(CGImageAlphaInfo.NoneSkipFirst.toRaw())

    var pixBufferData:UnsafeMutablePointer<(Void)> = CVPixelBufferGetBaseAddress(pixBufferPointer.memory?.takeUnretainedValue())

    let context = CGBitmapContextCreate(
        pixBufferData,
        UInt(size.width), UInt(size.height),
        8, UInt(4 * size.width),
        rgbColorSpace, bitmapinfo!)

    CGContextConcatCTM(context, CGAffineTransformMakeRotation(0))
    CGContextDrawImage(
        context,
        CGRectMake(0, 0, CGFloat(CGImageGetWidth(image)), CGFloat(CGImageGetHeight(image))),
    image)

    CVPixelBufferUnlockBaseAddress(pixBufferPointer.memory?.takeUnretainedValue(), 0)
    return pixBufferPointer.memory!.takeUnretainedValue()

}

Something even after the Movies can be as under the image remains in memory. I believe or not than is left PixcelBuffer.

I had a method CVPixelBufferRelease(buffer) to release the PixcelBuffer when the Objective-c, I'm no longer can use this in Swift. How do I release the PixcelBuffer doing?

If anyone could help, I'd really appreciate it.

1 enter image description here

2 enter image description here

like image 676
s0hno Avatar asked Mar 14 '15 14:03

s0hno


Video Answer


2 Answers

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
}
like image 142
Sebastian Krogull Avatar answered Sep 28 '22 16:09

Sebastian Krogull


I had same problem, but I have solved.

Use this: autoreleasepool

    var boolWhile = true
    while (boolWhile) {

        autoreleasepool({() -> () in

            if(input.readyForMoreMediaData) {
                presentTime = CMTimeMake(Int64(ii), fps)

                if(ii >= arrayImages.count){
    ...
like image 35
Donghee Seo Avatar answered Sep 28 '22 14:09

Donghee Seo