iOS CVPixelBufferCreate 在 swift 2 中泄漏内存
iOS CVPixelBufferCreate leaking memory in swift 2
我正在尝试将图像转换为视频,正确的方法似乎是使用带有 AVAssetWriterInputPixelBufferAdaptor 的 AVAssetWriter,它运行良好,但它会泄漏内存。
当我将 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 在 swift 2
中不可用
CVPixelBufferCreate 没有 return swift 2 中的非托管指针,所以我不能使用这个 guys code
我试过在 unsafepointer 上手动调用 destroy 和 dealloc,但无济于事。
每次调用它都会增加内存使用量,如果调用次数过多会导致设备崩溃
如有任何帮助或建议,我们将不胜感激。
你的 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!
s。
我也有类似的泄漏。我不确定,但我认为可以使用以下内容:
let bufferPointer = UnsafeMutablePointer<CVPixelBuffer?>.alloc(1)
...
let pixelBuffer = bufferPointer.memory!
bufferPointer.destroy()
return pixelBuffer
我正在尝试将图像转换为视频,正确的方法似乎是使用带有 AVAssetWriterInputPixelBufferAdaptor 的 AVAssetWriter,它运行良好,但它会泄漏内存。
当我将 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 在 swift 2
中不可用CVPixelBufferCreate 没有 return swift 2 中的非托管指针,所以我不能使用这个 guys code
我试过在 unsafepointer 上手动调用 destroy 和 dealloc,但无济于事。
每次调用它都会增加内存使用量,如果调用次数过多会导致设备崩溃
如有任何帮助或建议,我们将不胜感激。
你的 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!
s。
我也有类似的泄漏。我不确定,但我认为可以使用以下内容:
let bufferPointer = UnsafeMutablePointer<CVPixelBuffer?>.alloc(1)
...
let pixelBuffer = bufferPointer.memory!
bufferPointer.destroy()
return pixelBuffer