内存警告OpenGL iOS应用程序
我正在开发一个丰富的图形iOS应用程序。在一个实例中,我们的应用程序占用的内存是250 MB。我会从相机中取出每一帧,用OpenGL着色器进行处理并提取一些数据。每次我使用相机获取要处理的帧时,我都会看到内存增加到280 MB。当我停止捕获帧时,内存恢复到250 MB。如果我重复启动相机和退出的过程10次,比如说,我会收到一个内存警告,尽管没有观察到内存泄漏。我这里不使用弧。我正在维护一个自动发布池,其中包括一个帧的整个处理过程。我在分析时没有发现任何泄漏。10次之后,内存似乎达到了250MB。我不确定记忆警告的原因。有什么见解吗?我很高兴提供进一步的信息。Opengl版本-ES 2.0,iOS版本-7.0您必须使用ARC,它将自动释放坏内存,并使您的应用程序优化根据其他一些问题,如此问题和此问题,问题可能是您没有删除Opengl资源VBO、纹理、渲染缓冲、,不管你什么时候处理完它们 看不到代码,谁知道呢?您是否只是使用EagleContext的presentRenderbuffer方法渲染帧缓冲区?那么,您将如何处理传递给CVOpenGLESTextureCacheCreateTextureFromImage的像素缓冲区?像素缓冲区是典型使用场景中唯一的大量内存来源 但是,如果要将渲染缓冲区中的数据交换到另一个缓冲区(例如glReadPixels),则引入了几个内存占用中的一个。如果您交换到的缓冲区是一个CoreGraphics缓冲区,例如,通过CGDataProvider,那么您是否包含了数据释放回调,或者在创建提供程序时是否将nil作为参数传递?交换缓冲区后是否刷新 如果您提供代码,我可以确定这些问题的答案;如果您认为不这样做就可以解决这个问题,但希望看到在最困难的用例场景中成功管理内存的工作代码,那么可能有: 为方便起见,我在下面提供了一些代码。将其放置在对presentRenderbuffer方法的任何调用之后,如果您不想像我在下面的示例中所做的那样将缓冲区呈现到CaeAglayer中的显示,则注释掉该调用: //[_contextpresentrenderbuffer:GL_RENDERBUFFER]内存警告OpenGL iOS应用程序,ios,opengl-es,Ios,Opengl Es,我正在开发一个丰富的图形iOS应用程序。在一个实例中,我们的应用程序占用的内存是250 MB。我会从相机中取出每一帧,用OpenGL着色器进行处理并提取一些数据。每次我使用相机获取要处理的帧时,我都会看到内存增加到280 MB。当我停止捕获帧时,内存恢复到250 MB。如果我重复启动相机和退出的过程10次,比如说,我会收到一个内存警告,尽管没有观察到内存泄漏。我这里不使用弧。我正在维护一个自动发布池,其中包括一个帧的整个处理过程。我在分析时没有发现任何泄漏。10次之后,内存似乎达到了250MB。
dispatch_async(dispatch_get_main_queue(), ^{
@autoreleasepool {
// To capture the output to an OpenGL render buffer...
NSInteger myDataLength = _backingWidth * _backingHeight * 4;
GLubyte *buffer = (GLubyte *) malloc(myDataLength);
glPixelStorei(GL_UNPACK_ALIGNMENT, 8);
glReadPixels(0, 0, _backingWidth, _backingHeight, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
// To swap the pixel buffer to a CoreGraphics context (as a CGImage)
CGDataProviderRef provider;
CGColorSpaceRef colorSpaceRef;
CGImageRef imageRef;
CVPixelBufferRef pixelBuffer;
@try {
provider = CGDataProviderCreateWithData(NULL, buffer, myDataLength, &releaseDataCallback);
int bitsPerComponent = 8;
int bitsPerPixel = 32;
int bytesPerRow = 4 * _backingWidth;
colorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
imageRef = CGImageCreate(_backingWidth, _backingHeight, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);
} @catch (NSException *exception) {
NSLog(@"Exception: %@", [exception reason]);
} @finally {
if (imageRef) {
// To convert the CGImage to a pixel buffer (for writing to a file using AVAssetWriter)
pixelBuffer = [CVCGImageUtil pixelBufferFromCGImage:imageRef];
// To verify the integrity of the pixel buffer (by converting it back to a CGIImage, and thendisplaying it in a layer)
imageLayer.contents = (__bridge id)[CVCGImageUtil cgImageFromPixelBuffer:pixelBuffer context:_ciContext];
}
CGDataProviderRelease(provider);
CGColorSpaceRelease(colorSpaceRef);
CGImageRelease(imageRef);
}
}
});
。
.
释放CGDataProvider类实例中数据的回调:
static void releaseDataCallback (void *info, const void *data, size_t size) {
free((void*)data);
}
CVCGImageUtil类接口和实现文件分别为:
@import Foundation;
@import CoreMedia;
@import CoreGraphics;
@import QuartzCore;
@import CoreImage;
@import UIKit;
@interface CVCGImageUtil : NSObject
+ (CGImageRef)cgImageFromPixelBuffer:(CVPixelBufferRef)pixelBuffer context:(CIContext *)context;
+ (CVPixelBufferRef)pixelBufferFromCGImage:(CGImageRef)image;
+ (CMSampleBufferRef)sampleBufferFromCGImage:(CGImageRef)image;
@end
#import "CVCGImageUtil.h"
@implementation CVCGImageUtil
+ (CGImageRef)cgImageFromPixelBuffer:(CVPixelBufferRef)pixelBuffer context:(CIContext *)context
{
// CVPixelBuffer to CoreImage
CIImage *image = [CIImage imageWithCVPixelBuffer:pixelBuffer];
image = [image imageByApplyingTransform:CGAffineTransformMakeRotation(M_PI)];
CGPoint origin = [image extent].origin;
image = [image imageByApplyingTransform:CGAffineTransformMakeTranslation(-origin.x, -origin.y)];
// CoreImage to CGImage via CoreImage context
CGImageRef cgImage = [context createCGImage:image fromRect:[image extent]];
// CGImage to UIImage (OPTIONAL)
//UIImage *uiImage = [UIImage imageWithCGImage:cgImage];
//return (CGImageRef)uiImage.CGImage;
return cgImage;
}
+ (CVPixelBufferRef)pixelBufferFromCGImage:(CGImageRef)image
{
CGSize frameSize = CGSizeMake(CGImageGetWidth(image),
CGImageGetHeight(image));
NSDictionary *options =
[NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES],
kCVPixelBufferCGImageCompatibilityKey,
[NSNumber numberWithBool:YES],
kCVPixelBufferCGBitmapContextCompatibilityKey,
nil];
CVPixelBufferRef pxbuffer = NULL;
CVReturn status =
CVPixelBufferCreate(
kCFAllocatorDefault, frameSize.width, frameSize.height,
kCVPixelFormatType_32ARGB, (__bridge CFDictionaryRef)options,
&pxbuffer);
NSParameterAssert(status == kCVReturnSuccess && pxbuffer != NULL);
CVPixelBufferLockBaseAddress(pxbuffer, 0);
void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer);
CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(
pxdata, frameSize.width, frameSize.height,
8, CVPixelBufferGetBytesPerRow(pxbuffer),
rgbColorSpace,
(CGBitmapInfo)kCGBitmapByteOrder32Little |
kCGImageAlphaPremultipliedFirst);
CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image),
CGImageGetHeight(image)), image);
CGColorSpaceRelease(rgbColorSpace);
CGContextRelease(context);
CVPixelBufferUnlockBaseAddress(pxbuffer, 0);
return pxbuffer;
}
+ (CMSampleBufferRef)sampleBufferFromCGImage:(CGImageRef)image
{
CVPixelBufferRef pixelBuffer = [CVCGImageUtil pixelBufferFromCGImage:image];
CMSampleBufferRef newSampleBuffer = NULL;
CMSampleTimingInfo timimgInfo = kCMTimingInfoInvalid;
CMVideoFormatDescriptionRef videoInfo = NULL;
CMVideoFormatDescriptionCreateForImageBuffer(
NULL, pixelBuffer, &videoInfo);
CMSampleBufferCreateForImageBuffer(kCFAllocatorDefault,
pixelBuffer,
true,
NULL,
NULL,
videoInfo,
&timimgInfo,
&newSampleBuffer);
return newSampleBuffer;
}
@end
谢谢我发出命令删除所有FBO、纹理和渲染缓冲区。