我试图创建图像阵列的视频,它的工作,但只能在模拟器。看来主要问题是内存使用情况。我已经优化阵列,但它显然是不够的,而我的应用程序崩溃的最后阶段,当它试图将图像转换为帧。巨大的内存消耗,同时图像转换为帧
我说:“阵”,但我真的不使用图像的阵列,我创建他们即时(我是从我的视频源获得正确的框架,并运用它的覆盖图像,之后我将这个图像转换为新视频的帧)。
func getTheCombinedImage(frameNumber: Int)->UIImage {
let videoURLAsset = videoAsset as! AVURLAsset
let generator:AVAssetImageGenerator = AVAssetImageGenerator(asset: videoURLAsset)
generator.requestedTimeToleranceBefore = kCMTimeZero
generator.requestedTimeToleranceAfter = kCMTimeZero
var actualTime : CMTime = CMTimeMake(0, 0)
let duration:CMTime = CMTimeMake(Int64(frameNumber), Int32(30))
let frameRef:CGImageRef = try! generator.copyCGImageAtTime(duration, actualTime: &actualTime)
let sourceImage:UIImage = UIImage(CGImage: frameRef)
let tempImage:UIImage = getTheTempImage(frameNumber)
UIGraphicsBeginImageContext(sourceImage.size)
sourceImage.drawInRect(CGRect(x: 0, y: 0, width: sourceImage.size.width, height: sourceImage.size.height), blendMode: CGBlendMode.Normal, alpha: 1.0)
tempImage.drawInRect(CGRect(x: 0, y: 0, width: tempImage.size.width, height: tempImage.size.height), blendMode: CGBlendMode.Normal, alpha: 1.0)
let combinedImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return combinedImage
}
看起来这个函数在内存方面不是很好(也许在其他方面也是如此)。看来,我没有在这里释放什么应该被释放但什么?
当我不使用此功能,我的内存情况要好得多:
而且,我认为,这是不够的,因为内存使用180MB的仍然过高,并经过转换为视频我的内存使用水平是100-110 MB(而不是55-60 MB之前)。在仪器/分配我可以看到很多JVTLib实例从VideoToolbox(如JVTLib_101510(JVTLib_101496,INT)*) - 我觉得他们需要转换和_CVPixelBufferStandardMemoryLayout实例 - 我想这些的是由我创建显然我在这里也没有发布任何东西。
func appendPixelBufferForImageAtURL(image: UIImage, pixelBufferAdaptor: AVAssetWriterInputPixelBufferAdaptor, presentationTime: CMTime) -> Bool {
var appendSucceeded = true
autoreleasepool {
var pixelBuffer: CVPixelBuffer? = nil
let status: CVReturn = CVPixelBufferPoolCreatePixelBuffer(kCFAllocatorDefault, pixelBufferAdaptor.pixelBufferPool!, &pixelBuffer)
if let pixelBuffer = pixelBuffer where status == 0 {
let managedPixelBuffer = pixelBuffer
fillPixelBufferFromImage(image, pixelBuffer: managedPixelBuffer)
appendSucceeded = pixelBufferAdaptor.appendPixelBuffer(pixelBuffer, withPresentationTime: presentationTime)
} else {
NSLog("error: Failed to allocate pixel buffer from pool")
}
}
return appendSucceeded
}
我不明白这里有什么问题。
func fillPixelBufferFromImage(image: UIImage, pixelBuffer: CVPixelBufferRef) {
let imageData = CGDataProviderCopyData(CGImageGetDataProvider(image.CGImage))
CVPixelBufferLockBaseAddress(pixelBuffer, 0)
let pixelData = CVPixelBufferGetBaseAddress(pixelBuffer)
let bitmapInfo = CGImageAlphaInfo.PremultipliedFirst.rawValue
let rgbColorSpace = CGColorSpaceCreateDeviceRGB()
let context = CGBitmapContextCreate(
pixelData,
Int(self.externalInputSize.width),
Int(self.externalInputSize.height),
8,
CVPixelBufferGetBytesPerRow(pixelBuffer),
rgbColorSpace,
bitmapInfo
)
let imageDataProvider = CGDataProviderCreateWithCFData(imageData)
CGContextDrawImage(context, CGRectMake(0, 0, self.externalInputSize.width, self.externalInputSize.height), image.CGImage)
CVPixelBufferUnlockBaseAddress(pixelBuffer, 0)
}
我不是在这里释放上下文但似乎我没有做到这一点斯威夫特(Do you need to release CGContextRef in Swift?)
更新:谢谢,伙计们
现在的工作。是什么帮助(如果有人有相同的问题):
不把图像转换成数组(我发布这个问题之前修正了这个,但仍然)
不要惊慌和autoreleasepool一切。
尝试优化内存使用无处不在(降低您的内存使用量开始越高,你的内存上限)。
放处理后的图像变成财产。
图像的分辨率是多少? – heximal
为了强调@十六进制的注释,'UIImage'每个像素需要四个字节。因此,一张1000x1000的图像需要400万字节的RAM,并且这个大小的1000张图像的阵列需要40亿字节(不计算阵列本身的开销)。 – nhgrif
图像的分辨率取决于视频分辨率。我的测试文件是640x360。但是我没有使用数组来创建图像,我正在按需创建每个图像。 – lithium