Ios GPUImage内存错误
我正在为iOS上录制的视频的帧图像添加失真效果。对于分辨率为640 x 640的14秒视频,应用程序因内存错误而崩溃。我认为所有的内存都得到了适当的释放 我觉得很奇怪,分析器告诉我应用程序的最大消耗量约为20MB!我也没有发现内存泄漏。CoreImage库在整个处理过程中确实积累了大约580 MB的内存,但每次处理帧后都会释放内存,因此不会导致崩溃 如果我把失真过滤器注释掉,一切都正常,所以我假设错误在过滤部分。我正在安装iOS 8的iPhone 5s上进行测试 这是GPUImage中的错误吗? 为什么我不能配置过多的内存消耗 我感谢你的每一个回答 这是一段相关的代码:Ios GPUImage内存错误,ios,iphone,image-processing,memory-management,gpuimage,Ios,Iphone,Image Processing,Memory Management,Gpuimage,我正在为iOS上录制的视频的帧图像添加失真效果。对于分辨率为640 x 640的14秒视频,应用程序因内存错误而崩溃。我认为所有的内存都得到了适当的释放 我觉得很奇怪,分析器告诉我应用程序的最大消耗量约为20MB!我也没有发现内存泄漏。CoreImage库在整个处理过程中确实积累了大约580 MB的内存,但每次处理帧后都会释放内存,因此不会导致崩溃 如果我把失真过滤器注释掉,一切都正常,所以我假设错误在过滤部分。我正在安装iOS 8的iPhone 5s上进行测试 这是GPUImage中的错误吗?
- (CIImage *) render:(CIImage*)targetImage imageContext:(CIContext*) imageContext
facialFeatures:(NSArray*)facialFeatures currentFrameInd:(int)frameInd
{
if ( !facialFeatures ) return targetImage;
@autoreleasepool {
CGImageRef inputImage = [imageContext createCGImage:targetImage fromRect:[targetImage extent]];
GPUImagePicture *sourcePicture = [[GPUImagePicture alloc] initWithCGImage:inputImage];
GPUImageOutput *currentOutput = sourcePicture;
// Search through multiple faces.
for ( ArtechFacialFeature *facialFeature in facialFeatures ) {
// Create the distortion for one face.
for ( ArtechImageDistortionDescription *distortion in distortions ) {
GPUImageFilter *imageFilter = [self createDistortionFilter:distortion
facialFeature:facialFeature imageExtent:targetImage.extent];
[currentOutput addTarget:imageFilter];
currentOutput = imageFilter;
}
}
[currentOutput useNextFrameForImageCapture];
[sourcePicture processImage];
UIImage *currentFilteredVideoFrame = [currentOutput imageFromCurrentFramebuffer];
targetImage = [targetImage initWithCGImage:currentFilteredVideoFrame.CGImage];
[sourcePicture removeAllTargets];
currentFilteredVideoFrame = nil;
sourcePicture = nil;
currentOutput = nil;
CFRelease( inputImage );
}
return targetImage;
}
我突然想到的一件事是,你正在创建一个新的图像,并在每个传入帧上创建一系列新的过滤器。这将是非常低效的,并且可能会使GPUImage中的内部帧缓冲缓存系统过载 相反,从GPUImage纹理输入开始创建过滤器链。分配过滤器一次,仅在每个新帧上更改其属性。对于输入,如果您将核心图像输出渲染到由纹理支持的OpenGL ES上下文中,然后将该纹理馈送到GPUImage中,您将避免使用非常昂贵的内存和性能方面的GPU->CPU->GPU路径,并将所有内容保留在GPU上 使用一次创建并对每个帧重复使用的过滤器,内部帧缓冲缓存机制应该能够将内存使用限制在一个恒定且相对较低的值 确实可能是由于一个退化的情况而导致泄漏,我不经常以这种频率建立和拆除过滤器,因此在释放过程中可能存在竞争条件,但无论如何,尝试重新设计以重用过滤器可能是更好的方法
关于您报告的20MB值,这很可能来自分配工具,它隐藏了OpenGL ES内存使用情况。相反,请查看内存监视器,了解应用程序内存使用总量的真实读数。我敢打赌它会更高。我突然想到的一件事是,你在每个传入帧上创建了一个新图像和一系列新过滤器。这将是非常低效的,并且可能会使GPUImage中的内部帧缓冲缓存系统过载
- (void)addObservers {
[[NSNotificationCenter defaultCenter]addObserver:self
selector:@selector(applicationDidEnterBackground:)
name:UIApplicationDidEnterBackgroundNotification
object:nil];
[[NSNotificationCenter defaultCenter]addObserver:self
selector:@selector(applicationDidBecomeActive:)
name:UIApplicationDidBecomeActiveNotification
object:nil];
}
- (void)removeObservers {
[[NSNotificationCenter defaultCenter]removeObserver:self
name:UIApplicationDidEnterBackgroundNotification
object:nil];
[[NSNotificationCenter defaultCenter]removeObserver:self
name:UIApplicationDidBecomeActiveNotification
object:nil];
}
相反,从GPUImage纹理输入开始创建过滤器链。分配过滤器一次,仅在每个新帧上更改其属性。对于输入,如果您将核心图像输出渲染到由纹理支持的OpenGL ES上下文中,然后将该纹理馈送到GPUImage中,您将避免使用非常昂贵的内存和性能方面的GPU->CPU->GPU路径,并将所有内容保留在GPU上
使用一次创建并对每个帧重复使用的过滤器,内部帧缓冲缓存机制应该能够将内存使用限制在一个恒定且相对较低的值
确实可能是由于一个退化的情况而导致泄漏,我不经常以这种频率建立和拆除过滤器,因此在释放过程中可能存在竞争条件,但无论如何,尝试重新设计以重用过滤器可能是更好的方法
关于您报告的20MB值,这很可能来自分配工具,它隐藏了OpenGL ES内存使用情况。相反,请查看内存监视器,了解应用程序内存使用总量的真实读数。我打赌会更高。这个答案将帮助您采取记忆预防措施-谢谢您的评论!我认为所有的内存都得到了适当的释放。我在探查器中找不到泄漏或过量内存消耗。这才是真正让我讨厌的部分我想消耗更多内存的原因应该是嵌套结构。尝试以块方式或在后台重新格式化它。我不确定GPUImageFilter的内存结构-它可能也使用缓存。for循环在1-3个过滤器之间创建,这些过滤器链接在一起。不应该完全破坏记忆。我添加了自动释放池,以便在每次帧处理后释放内存。不应缓存AFAIK GPUImageFilter。即使是,它也应该在内存压力下释放?这个答案将帮助你采取内存预防措施-谢谢你的评论!我认为所有的内存都得到了适当的释放。我在探查器中找不到泄漏或过量内存消耗。这才是真正让我讨厌的部分我想消耗更多内存的原因应该是嵌套结构。尝试以块方式或在后台重新格式化它。我不确定GPUImageFilter的内存结构-它可能也使用缓存。for循环在1-3个过滤器之间创建,这些过滤器链接在一起。应该
- (void)addObservers {
[[NSNotificationCenter defaultCenter]addObserver:self
selector:@selector(applicationDidEnterBackground:)
name:UIApplicationDidEnterBackgroundNotification
object:nil];
[[NSNotificationCenter defaultCenter]addObserver:self
selector:@selector(applicationDidBecomeActive:)
name:UIApplicationDidBecomeActiveNotification
object:nil];
}
- (void)removeObservers {
[[NSNotificationCenter defaultCenter]removeObserver:self
name:UIApplicationDidEnterBackgroundNotification
object:nil];
[[NSNotificationCenter defaultCenter]removeObserver:self
name:UIApplicationDidBecomeActiveNotification
object:nil];
}
不要完全破坏记忆。我添加了自动释放池,以便在每次帧处理后释放内存。不应缓存AFAIK GPUImageFilter。即使是,它也应该在记忆压力下释放?非常感谢你的回答,布拉德!!我更改了代码,以便在开始处理时创建一次过滤器链。400,不幸的是,结果是一样的。我仔细检查了过滤器是否只创建了一次!我还没有实现您关于使用GPUImageTextureInput的建议,因为我目前不知道输入图像的纹理ID。我的印象是AVFoundation直接将视频帧加载到帧缓冲区?我对目前的性能很满意,但GPUImagePicture的使用是否会导致内存错误?我对Apple/iOS开发有点陌生,无法找到内存监视器仪器?它可能会停产吗?活动监视器显示实际内存使用情况,如果我理解正确,它应该显示CPU和GPU内存消耗。在应用程序崩溃之前,它仍然是20MB左右。@Senad-如果您不需要在将视频帧发送到GPUImage之前通过核心图像进行处理,您可以使用GPUImageVideoCamera并从中提取像素缓冲区,然后并行地将其交给核心图像。看起来你正在使用面部特征检测,如果这就是你所需要的,这将很好地工作。FilterShowcase示例提供了一个示例,说明了如何做到这一点。此外,如果我在测试时将视频分辨率降低100像素,我可以处理视频,但在接近结束时会收到大量内存警告。在处理下一个视频时,我得到了相同的结果。因此,这不是一个永久性的内存分配/泄漏,而是在处理过程中积累起来的。我们将非常感谢您的想法和意见!!:@Senad-关于内存监视器,它看起来已经被合并到活动监视器中。这将为您提供真实内存大小的准确总读取。如果你想在一段时间内回顾这一点,你可能需要让它跟踪检查负责人,以便在应用程序执行的特定时间点进行监控。非常感谢你的回答,Brad!!我更改了代码,以便在开始处理时创建一次过滤器链。400,不幸的是,结果是一样的。我仔细检查了过滤器是否只创建了一次!我还没有实现您关于使用GPUImageTextureInput的建议,因为我目前不知道输入图像的纹理ID。我的印象是AVFoundation直接将视频帧加载到帧缓冲区?我对目前的性能很满意,但GPUImagePicture的使用是否会导致内存错误?我对Apple/iOS开发有点陌生,无法找到内存监视器仪器?它可能会停产吗?活动监视器显示实际内存使用情况,如果我理解正确,它应该显示CPU和GPU内存消耗。在应用程序崩溃之前,它仍然是20MB左右。@Senad-如果您不需要在将视频帧发送到GPUImage之前通过核心图像进行处理,您可以使用GPUImageVideoCamera并从中提取像素缓冲区,然后并行地将其交给核心图像。看起来你正在使用面部特征检测,如果这就是你所需要的,这将很好地工作。FilterShowcase示例提供了一个示例,说明了如何做到这一点。此外,如果我在测试时将视频分辨率降低100像素,我可以处理视频,但在接近结束时会收到大量内存警告。在处理下一个视频时,我得到了相同的结果。因此,这不是一个永久性的内存分配/泄漏,而是在处理过程中积累起来的。我们将非常感谢您的想法和意见!!:@Senad-关于内存监视器,它看起来已经被合并到活动监视器中。这将为您提供真实内存大小的准确总读取。如果您想在一段时间内查看此问题,您可能需要让它跟踪检查负责人,以便在应用程序执行的特定时间点进行监控。抱歉,但此答案似乎与问题无关抱歉,但此答案似乎与问题无关