如何限制 AVAssetWriter 在编码视频时使用过多内存?
How to limit AVAssetWriter from using too much memory when encoding a video?
我使用 AVAssetWriter
生成带有帧图像的视频(UIImage
数组)。当它进行编码工作时,内存使用量有时会飙升至超过 700MB。在我的 iPhone(使用 3GB MEM)上,这不会导致 OOM 问题,但我担心它会在较旧的 iPhone 中引起问题。
我能以某种方式限制 AVAssetWriter
内存使用吗?我猜在内部它可能使用一些队列来缓存帧字节,如果我可以指定缓存的大小,那么我可以设置内存的上限。但是我在文档中没有找到这样的options/settings。
这是我的代码:
let settings:[String:Any] = [
AVVideoCodecKey: AVVideoCodecH264,
AVVideoWidthKey: FRAME_SIZE,
AVVideoHeightKey: FRAME_SIZE
]
let assetWriter = AVAssetWriter(url: self.url!, fileType: AVFileType.mov)
let assetWriterInput = AVAssetWriterInput(mediaType: AVMediaType.video, outputSettings: settings)
self.assetWriter?.add(assetWriterInput)
let bufferAttributes:[String: Any] = [kCVPixelBufferPixelFormatTypeKey as String: Int(kCVPixelFormatType_32ARGB)]
let bufferAdapter = AVAssetWriterInputPixelBufferAdaptor(assetWriterInput: assetWriterInput, sourcePixelBufferAttributes: bufferAttributes)
let frameTime = CMTimeMake(1, 30)
self.assetWriter?.startWriting()
self.assetWriter?.startSession(atSourceTime: kCMTimeZero)
let mediaInputQueue = DispatchQueue(label: "mediaInputQueue")
var i = 0
assetWriterInput.requestMediaDataWhenReady(on: mediaInputQueue){
var localframes = frames
while(true){
if(localframes.isEmpty){
break
}
if (assetWriterInput.isReadyForMoreMediaData){
let image = localframes.removeFirst()
let pixelBuffer = self.newPixelBufferFrom(cgImage: image.cgImage!)
var time:CMTime
if i == 0 {
time = kCMTimeZero
} else {
time = CMTimeMake(Int64(i), frameTime.timescale)
}
bufferAdapter.append(pixelBuffer!, withPresentationTime: time)
// TODO: how to release memory?
i += 1
}
}
assetWriterInput.markAsFinished()
self.assetWriter?.finishWriting(completionHandler: {
finishedHandler()
})
}
不确定它是否有帮助,但我在 while
循环中遇到了类似的问题。你可以查看这个答案:
您可以试一试,看看是否有改善:
let pixelBuffer = autoreleasepool { return self.newPixelBufferFrom(cgImage: image.cgImage!) }
我使用 AVAssetWriter
生成带有帧图像的视频(UIImage
数组)。当它进行编码工作时,内存使用量有时会飙升至超过 700MB。在我的 iPhone(使用 3GB MEM)上,这不会导致 OOM 问题,但我担心它会在较旧的 iPhone 中引起问题。
我能以某种方式限制 AVAssetWriter
内存使用吗?我猜在内部它可能使用一些队列来缓存帧字节,如果我可以指定缓存的大小,那么我可以设置内存的上限。但是我在文档中没有找到这样的options/settings。
这是我的代码:
let settings:[String:Any] = [
AVVideoCodecKey: AVVideoCodecH264,
AVVideoWidthKey: FRAME_SIZE,
AVVideoHeightKey: FRAME_SIZE
]
let assetWriter = AVAssetWriter(url: self.url!, fileType: AVFileType.mov)
let assetWriterInput = AVAssetWriterInput(mediaType: AVMediaType.video, outputSettings: settings)
self.assetWriter?.add(assetWriterInput)
let bufferAttributes:[String: Any] = [kCVPixelBufferPixelFormatTypeKey as String: Int(kCVPixelFormatType_32ARGB)]
let bufferAdapter = AVAssetWriterInputPixelBufferAdaptor(assetWriterInput: assetWriterInput, sourcePixelBufferAttributes: bufferAttributes)
let frameTime = CMTimeMake(1, 30)
self.assetWriter?.startWriting()
self.assetWriter?.startSession(atSourceTime: kCMTimeZero)
let mediaInputQueue = DispatchQueue(label: "mediaInputQueue")
var i = 0
assetWriterInput.requestMediaDataWhenReady(on: mediaInputQueue){
var localframes = frames
while(true){
if(localframes.isEmpty){
break
}
if (assetWriterInput.isReadyForMoreMediaData){
let image = localframes.removeFirst()
let pixelBuffer = self.newPixelBufferFrom(cgImage: image.cgImage!)
var time:CMTime
if i == 0 {
time = kCMTimeZero
} else {
time = CMTimeMake(Int64(i), frameTime.timescale)
}
bufferAdapter.append(pixelBuffer!, withPresentationTime: time)
// TODO: how to release memory?
i += 1
}
}
assetWriterInput.markAsFinished()
self.assetWriter?.finishWriting(completionHandler: {
finishedHandler()
})
}
不确定它是否有帮助,但我在 while
循环中遇到了类似的问题。你可以查看这个答案:
您可以试一试,看看是否有改善:
let pixelBuffer = autoreleasepool { return self.newPixelBufferFrom(cgImage: image.cgImage!) }