2015-11-16 9 views
2

Я пытаюсь преобразовать изображение в видео, и, как представляется, правильный способ использует AVAssetWriter с AVAssetWriterInputPixelBufferAdaptor, и он работает хорошо, но он теряет память.iOS CVPixelBufferСоздать утечку памяти в swift 2

Когда я конвертирую CGImage в CVPixelBuffer, я вызываю CVPixelBufferCreate, который никогда не освобождает его память.

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

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 не возвращает неуправляемый указатель в быстром 2, так что я не могу использовать это guys code

Я пробовал вручную вызвать destroy и dealloc на unsafepointer, но безрезультатно.

каждый раз, когда он назвал это увеличивает использование памяти, и произойдет сбой устройства при вызове достаточно memory profile

Любая помощь или советы будут оценены.

ответ

1

Ваш let buffer = UnsafeMutablePointer<CVPixelBuffer?>.alloc(1) не уравновешен dealloc, однако добавление, похоже, не устраняет утечку. Простое использование CVPixelBuffer? делает, хотя и кажется, проще:

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! с.

0

У меня также есть аналогичная утечка. Я не уверен, но я думаю, что можно использовать следующее:

let bufferPointer = UnsafeMutablePointer<CVPixelBuffer?>.alloc(1) 
... 
let pixelBuffer = bufferPointer.memory! 
bufferPointer.destroy() 
return pixelBuffer 

 Смежные вопросы

  • Нет связанных вопросов^_^