我想在swift中发布CVPixelBufferRef

时间:2015-03-14 14:30:55

标签: ios iphone swift avfoundation

我想从图片创建一个视频 所以,我是参考链接的来源 链接: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()

}

即使电影可以在图像下方保留在内存中。 我相信或不是留下了PixcelBuffer。

我有一个方法CVPixelBufferRelease(缓冲区)来释放PixcelBuffer,当Objective-c,我不能在Swift中使用它时。如何释放PixcelBuffer呢?

如果有人可以提供帮助,我真的很感激。

1 enter image description here

2 enter image description here

3 个答案:

答案 0 :(得分:2)

使用CVPixelBufferCreate后,UnsafeMutablePointer必须销毁后才能检索memory

当我创建CVPixelBuffer时,我这样做:

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
}

答案 1 :(得分:2)

我有同样的问题,但我已经解决了。

使用:autoreleasepool

    var boolWhile = true
    while (boolWhile) {

        autoreleasepool({() -> () in

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

                if(ii >= arrayImages.count){
    ...

答案 2 :(得分:0)

尝试更改

 return pixBufferPointer.memory!.takeUnretainedValue()

return pixBufferPointer.memory!.takeRetainedValue()

避免泄露CVPixelBuffer s