使用 AVAssetWriter 将大量图像写入视频文件时的高峰值内存使用率
Posted
技术标签:
【中文标题】使用 AVAssetWriter 将大量图像写入视频文件时的高峰值内存使用率【英文标题】:high peak memory usage when writing large amount images to video file using AVAssetWriter 【发布时间】:2013-12-12 09:00:12 【问题描述】:我创建了一个使用 AvAssetWriter 将图像组装成视频文件的函数。论坛中有一些关于此实现的主题。我已经使用 AVAssetWriter 成功编写了视频。我的问题不是这个实现,而是关于内存消耗。就我而言,当我编写 4 秒 30FPS 视频 1024*768 时,峰值内存使用量将在 300MB 左右。对于更长的时间,10 秒等,它会因内存警告而崩溃。问题是在将每个图像写入视频文件的循环过程中,内存使用量是累积的。循环后,内存使用量将恢复到正常水平而不会泄漏。
以下代码是循环的一次迭代。它将新图像附加到 avassetwriter
CVPixelBufferRef buffer = [self pixelBufferFromCGImage:[newimg CGImage]
size:CGSizeMake(self.frameOrigWidth, self.frameOrigHeight) poolRef:adaptor.pixelBufferPool];
BOOL append_ok = NO;
int j = 0;
CMTime frameTime = CMTimeMake(frameCount,(int32_t)FPS);
while (!append_ok && j < 30) //attemp maximum 30 times
if (adaptor.assetWriterInput.readyForMoreMediaData)
if(frameCount==0) append_ok = [adaptor appendPixelBuffer:buffer
withPresentationTime:kCMTimeZero];
else append_ok = [adaptor appendPixelBuffer:buffer withPresentationTime:frameTime];
[NSThread sleepForTimeInterval:0.05];//use sleep instead of runloop because it is not in main thread
else
[NSThread sleepForTimeInterval:0.1];
j++;
if(buffer) CVBufferRelease(buffer);
即使最后一行释放了缓冲区,在整个循环过程中内存也不会释放,我猜是因为编写器保留了这个缓冲区直到循环结束,编写器执行结束写入。
我尝试使用 @autoreleasepool 来包装这部分。它有效地阻止了峰值内存使用积累,但即使没有运行错误,它也不再成功写入视频文件。
以上解释来自真实设备调试。
我想到的可能的解决方案是分段写入,或者在写入周期中暂停几次,让缓冲区真正被写入器释放。但我没有找到办法做到这一点。我感谢任何知道解决此峰值内存问题的方法的人。
【问题讨论】:
我目前使用的解决方案是将写入任务分成不同的段,每个段写入一个文件。在循环结束时,我使用 AVMutableComposition 组合所有小文件。通过这种方法,峰值内存出现在每个段中。因为每个segment没有多少imgs要写,内存不会消耗太多。我很欣赏其他想法 【参考方案1】:我和你有同样的问题
我尝试在里面使用 sleepForTimeInterval
(void)didReceiveMemoryWarning我希望当这个事件触发时,它会暂停主进程并且给一点时间 系统刷新未使用的内存
但我不知道这是否有效
【讨论】:
只是为了让你知道我使用前面提到的方法来解决它。您可以将导出视频任务拆分为多个短视频生成。然后最后将它们合并在一起。这对我来说很好。我的应用程序已经上架了应用程序商店,您可以查看它以了解此方法可用于生成长时间视频。我的应用是“动画DIY”以上是关于使用 AVAssetWriter 将大量图像写入视频文件时的高峰值内存使用率的主要内容,如果未能解决你的问题,请参考以下文章