我試圖創建圖像陣列的視頻,它的工作,但只能在模擬器。看來主要問題是內存使用情況。我已經優化陣列,但它顯然是不夠的,而我的應用程序崩潰的最後階段,當它試圖將圖像轉換爲幀。巨大的內存消耗,同時圖像轉換爲幀
我說:「陣」,但我真的不使用圖像的陣列,我創建他們即時(我是從我的視頻源獲得正確的框架,並運用它的覆蓋圖像,之後我將這個圖像轉換爲新視頻的幀)。
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