首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >iOS CVPixelBufferCreate泄漏了斯威夫特2中的内存

iOS CVPixelBufferCreate泄漏了斯威夫特2中的内存
EN

Stack Overflow用户
提问于 2015-11-16 23:32:10
回答 2查看 2.6K关注 0票数 4

我正在尝试将图像转换成视频,正确的方法似乎是使用带有AVAssetWriter的AVAssetWriterInputPixelBufferAdaptor,它运行良好,但它泄漏了内存。

当我将CGImage转换为CVPixelBuffer时,我调用CVPixelBufferCreate,它从不释放内存。

代码语言:javascript
复制
func CGImageToPixelBuffer(image: CGImageRef, frameSize: CGSize) -> CVPixelBuffer {

    // stupid CFDictionary stuff
    let keys: [CFStringRef] = [kCVPixelBufferCGImageCompatibilityKey, kCVPixelBufferCGBitmapContextCompatibilityKey]
    let values: [CFTypeRef] = [kCFBooleanTrue, kCFBooleanTrue]
    let keysPointer = UnsafeMutablePointer<UnsafePointer<Void>>.alloc(1)
    let valuesPointer =  UnsafeMutablePointer<UnsafePointer<Void>>.alloc(1)
    keysPointer.initialize(keys)
    valuesPointer.initialize(values)
    let options = CFDictionaryCreate(kCFAllocatorDefault, keysPointer, valuesPointer, keys.count,
        UnsafePointer<CFDictionaryKeyCallBacks>(), UnsafePointer<CFDictionaryValueCallBacks>())

    let buffer = UnsafeMutablePointer<CVPixelBuffer?>.alloc(1)

    // here's the leak >:[
    let status = CVPixelBufferCreate(kCFAllocatorDefault, Int(frameSize.width), Int(frameSize.height),
        kCVPixelFormatType_32ARGB, options, buffer)

    CVPixelBufferLockBaseAddress(pixelBuffer.memory!, 0);
    let bufferData = CVPixelBufferGetBaseAddress(buffer.memory!);

    let rgbColorSpace = CGColorSpaceCreateDeviceRGB();
    let context = CGBitmapContextCreate(bufferData, Int(frameSize.width),
        Int(frameSize.height), 8, 4*Int(frameSize.width), rgbColorSpace,
        CGImageAlphaInfo.NoneSkipFirst.rawValue);

    CGContextDrawImage(context, CGRectMake(0, 0,
        CGFloat(CGImageGetWidth(image)),
        CGFloat(CGImageGetHeight(image))), image);

    CVPixelBufferUnlockBaseAddress(pixelBuffer.memory!, 0);
    return buffer.memory!
}

下面是调用CGImageToPixelBuffer的代码

代码语言:javascript
复制
func saveImageAsVideoFile(path: NSURL, image: UIImage, duration: Double) {
    let writer = try! AVAssetWriter(URL: path, fileType: AVFileTypeQuickTimeMovie)

    let videoSettings: NSDictionary = [
        AVVideoCodecKey : AVVideoCodecH264,
        AVVideoWidthKey : NSNumber(integer: Int(image.size.width)),
        AVVideoHeightKey : NSNumber(integer: Int(image.size.height))
    ]
    let input = AVAssetWriterInput(mediaType: AVMediaTypeVideo, outputSettings: videoSettings as? [String : AnyObject])
    let inputAdaptor = AVAssetWriterInputPixelBufferAdaptor(assetWriterInput: input, sourcePixelBufferAttributes: nil)
    input.expectsMediaDataInRealTime = false
    writer.addInput(input)
    writer.startWriting()
    writer.startSessionAtSourceTime(kCMTimeZero)

    // leak starts here
    let buffer = CGImageToPixelBuffer(image.CGImage!, frameSize: image.size)

    // append 30 frames to AVAssetWriter thing
    for i in 0..<30
        if input.readyForMoreMediaData {
            inputAdaptor.appendPixelBuffer(buffer, withPresentationTime: CMTimeMake(i, 30))
        }
    }

    //CVPixelBufferRelease(buffer) ??

    input.markAsFinished()
    writer.finishWritingWithCompletionHandler({ () -> Void in
        print("yay")
    })
}

在CVPixelBufferRelease 2中无法使用

CVPixelBufferCreate不返回guys code 2中的非托管指针,所以我不能使用这个guys code

我已经尝试过手动调用破坏和解除对不安全指针,没有任何效果。

每次调用它时,都会增加内存使用量,如果调用足够多,就会使设备崩溃。

如有任何帮助或建议,将不胜感激。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-11-17 01:41:32

您的let buffer = UnsafeMutablePointer<CVPixelBuffer?>.alloc(1)不是由一个dealloc来平衡的,但是添加它似乎并不能修复漏洞。不过,简单地使用CVPixelBuffer?可以做到这一点,而且看起来更简单:

代码语言:javascript
复制
var buffer: CVPixelBuffer?

// TODO: handle status != noErr
let status = CVPixelBufferCreate(kCFAllocatorDefault, Int(frameSize.width), Int(frameSize.height),
    kCVPixelFormatType_32ARGB, options, &buffer)

CVPixelBufferLockBaseAddress(buffer!, 0);
let bufferData = CVPixelBufferGetBaseAddress(buffer!);

let rgbColorSpace = CGColorSpaceCreateDeviceRGB();
let context = CGBitmapContextCreate(bufferData, Int(frameSize.width),
    Int(frameSize.height), 8, 4*Int(frameSize.width), rgbColorSpace,
    CGImageAlphaInfo.NoneSkipFirst.rawValue);

CGContextDrawImage(context, CGRectMake(0, 0,
    CGFloat(CGImageGetWidth(image)),
    CGFloat(CGImageGetHeight(image))), image);

CVPixelBufferUnlockBaseAddress(buffer!, 0);

您还应该更早地处理status != noErr并打开可选缓冲区,以避免所有这些buffer!

票数 1
EN

Stack Overflow用户

发布于 2015-11-23 11:46:58

我也有类似的泄密。我不确定,但我认为以下几点可以使用:

代码语言:javascript
复制
let bufferPointer = UnsafeMutablePointer<CVPixelBuffer?>.alloc(1)
...
let pixelBuffer = bufferPointer.memory!
bufferPointer.destroy()
return pixelBuffer
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33746584

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档