Skip to content

Memory Warning and Crash #9

Closed
rnaud opened this Issue Aug 27, 2012 · 26 comments

8 participants

@rnaud
rnaud commented Aug 27, 2012

Hello, I am on a iPhone 4S, when I take a picture, I see a memory warning and when I try one or two filters my app crashes.
Everything works smoothly with the image picker

@rnaud
rnaud commented Aug 27, 2012

Alright, I'm reading through BradLarson/GPUImage#397
Did you find a fix in the end ?

@dmitric
dmitric commented Aug 27, 2012

@rnaud Can you show what line you are crashing at, and the steps you are taking to get the crash? Mine works fine so it's difficult for me to assess this. If you would like to have a go at #6 it would most likely solve your problem. I just don't have the time right this instant.

@rnaud
rnaud commented Aug 27, 2012

I definitely think this is related to #6. My app uses a few webviews so it's already hard on the memory so I think it crashes way sooner that it should. Sadly I have no line to give you. It goes into applicationDidReceiveMemoryWarning and then crashes almost immediately.

EDIT: but tell me if I can grab a log somewhere that could help you.

@dmitric
dmitric commented Aug 27, 2012

if you go step by step you can see where it goes. My guess, is that it's when it loads the full rez pic into GPU with GPUImagePicture in the autorelease block.

@rnaud
rnaud commented Sep 7, 2012

Alright a bit more of information. I am on iOS6 the last beta, Instruments shows me a 25MB peak in memory when I try to take a picture and then crashes.

@zyslovely

I get the same question
get memory warning

@natanrolnik

I am having the same problem, specially after taking 3, 4 pictures.

@dmitric
dmitric commented Oct 30, 2012

I am starting to integrate this into our app so I will most likely figure this out soon. My guess is that I just need to constrain the filters to a small size using GPUImage.

@zyslovely

just put the image picker to a smaller size is ok

@dmitric
dmitric commented Oct 30, 2012

Just so you guys know, the best way to fix is to just constrain the image using the crop filter a bit more. 83% on the width and height works. I tried using a dummy filter and used the forceProcessingAtSize but it slowed the whole thing down a lot.

I will commit fix once my internet isn't so wonky #sandy

@alexperri7

I was wondering if there has been any confirmed fix for this? I too am trying to get it to work on the 4S and it crashes right when I take a photo. Works on the iPhone 5.

@dmitric
dmitric commented Nov 1, 2012

@alexperri7 a couple things to do include making the cropFilter smaller -- something like 1900 x 1900 seems to works fine for me, or removing the blur effect pre image capture. The crashing appears to be from GPUImage using too much memory and there's not much else to do about it.

@alexperri7

No matter what values I set for the region of the cropFilter, it still crashes right when it runs [stillCamera capturePhotoAsImageProcessedUpToFilter:cropFilter... on line 358.

@dmitric
dmitric commented Nov 1, 2012

@alexperri7 can you give an example of the values? Try something like .75*.75 and .75 for width and height

@alexperri7

I tried extremely exaggerated values such as 0.1 and 0.075 for the width and height respectively and it worked once but not any other time. I just tried your values. Is this what you meant: cropFilter = [[GPUImageCropFilter alloc] initWithCropRegion:CGRectMake(0.0f, 0.0f, 0.75*0.75f, 0.75f)]; ?

@riegie
riegie commented Nov 2, 2012

Hey! I really love what you've done here! I have been having the same problems as @alexperri7 for quite some time! I'd really appreciate it you could help us find a work around or a solution for this. Thanks for the help, really appreciate it! :)

@dmitric
dmitric commented Nov 2, 2012

@alexperri7 @riegie This is what I have in my app and I don't crash on capture when presented as a modal view. Are your apps very memory intensive otherwise?

cropFilter = [[GPUImageCropFilter alloc]
                  initWithCropRegion:
                    CGRectMake(0.0f, 0.0f, 1.0f*0.82, 0.75f*0.82)];

Do you have the latest code, and Is your GPUImage up to date?

@alexperri7

Ok, so here are the results. We ran it on an iPod Touch 4G, iPhone 4 and iPhone 5 all on iOS 6 and it went smoothly. Going back to the iPhone 4S, it still crashes. The rest of our app doesn't use much memory, and we do have the latest code as well as the most recent GPUImage. Now we're unsure if it's an issue with our own 4S or the 4S model altogether.

@dmitric
dmitric commented Nov 2, 2012

@alexperri7 for what it's worth, I use a 4S and don't have this problem. I'm really not sure what else to say.

@dmitric
dmitric commented Nov 2, 2012

@alexperri7 okay been digging around a little more, how high resolution photo do you need? If 640 x 640 is all you need, you can use something like this with the imageFromCurrentlyProcessOutput function


-(IBAction) takePhoto:(id)sender{
    [self.photoCaptureButton setEnabled:NO];

    if (!isStatic) {
        UIImage *img = [cropFilter imageFromCurrentlyProcessedOutput];
        isStatic = YES;
        [stillCamera stopCameraCapture];
        [self removeAllTargets];
        [self.retakeButton setHidden:NO];
        [self.libraryToggleButton setHidden:YES];

        [self.cameraToggleButton setHidden:YES];
        [self.flashToggleButton setHidden:YES];
        @autoreleasepool {
            staticPicture = [[GPUImagePicture alloc] initWithImage:img smoothlyScaleOutput:YES];
            staticPictureOriginalOrientation = img.imageOrientation;
        }
        [self prepareFilter];
        [self.photoCaptureButton setTitle:@"Done" forState:UIControlStateNormal];
        [self.photoCaptureButton setImage:nil forState:UIControlStateNormal];
        [self.photoCaptureButton setEnabled:YES];
    } else {

        GPUImageOutput<GPUImageInput> *processUpTo;

        if (hasBlur) {
            processUpTo = blurFilter;
        } else {
            processUpTo = filter;
        }

        [staticPicture processImage];

        UIImage *currentFilteredVideoFrame = [processUpTo imageFromCurrentlyProcessedOutputWithOrientation:staticPictureOriginalOrientation];

        NSDictionary *info = [[NSDictionary alloc] initWithObjectsAndKeys:
                              UIImageJPEGRepresentation(currentFilteredVideoFrame, self.outputJPEGQuality), @"data", nil];
        [self.delegate imagePickerController:self
               didFinishPickingMediaWithInfo:info];
    }
}

@dmitric
dmitric commented Nov 2, 2012

The problem is that the crash occurs when you alloc the GPUImagePicture with the full res image.

Here's my thinking on how to solve this, as well as how to make the camera more responsive.

use imageFromCurrentlyProcessedOutput on the cropFilter to set the staticPicture var.

Then in the background, run the capturePhotoAsImageProcessedUpToFilter:cropFilter withCompletionHandler:^(UIImage *processed,NSError *error) and immediately save to disk.

If the user decides to save that image, we can load the full res version from disk, turn it into a GPUImagePicture and process it along with the desired filter when the camera is not actually running (saves a ton of memory this way), and then save that to camera roll.

I've just tested out the first part using the code above, and it is significantly more responsive, and flat out doesn't crash. Mine would crash sometimes before if I didn't crop at around 82% of the full res square and had the gaussian blur on. I will probably code up the second part, but it isn't necessary for my app right this instant.

@dmitric
dmitric commented Nov 2, 2012

I'm closing this with the latest commit, and opening a new issue for the full res solution

@dmitric dmitric closed this Nov 2, 2012
@dpestana

@dmitric I believe this is related to this issue. Your tips made me realize what I was doing wrong by assuming certain things which were of course incorrect (by the way, I bought the book you suggested). I'm now using Blend Filters at 2448 * 2448 resolution without any memory issues at all and without crashes. I'm using blend images with 640 * 640, which strangely (but a good thing) doesn't affect the final quality of the full resolution picture and causes almost no lags. I believe it might handle bigger blend pictures (with more quality), I'll have to try it because I found something else when I still got crashes when switching filters. On DLCImagePickerController.h I added (for purposes of blend):

GPUImagePicture *sourcePicture;

and then I added:

[sourcePicture removeAlltargets] to:

-(void) removeAllTargets

... in order to avoid crashes while switching between filters, both on static and live preview. The App now works great. Here is the code for Blend filters:

        filter = [[GPUImageFilterGroup alloc] init];

        UIImage *inputImage14 = [UIImage imageNamed:@"scratchy640.jpg"];
        sourcePicture = [[GPUImagePicture alloc] initWithImage:inputImage14 smoothlyScaleOutput:YES];
        GPUImageHardLightBlendFilter * overlay14 = [[GPUImageHardLightBlendFilter alloc] init];
        [(GPUImageFilterGroup *)filter addFilter:overlay14];
        [sourcePicture addTarget:overlay14 atTextureLocation:1];

        [sourcePicture processImage];

        GPUvintage *vintageFilter = [[GPUvintage alloc] init];
        [(GPUImageFilterGroup *)filter addFilter:vintageFilter];

        [overlay14 addTarget:vintageFilter];

        [(GPUImageFilterGroup *)filter setInitialFilters:[NSArray arrayWithObject:overlay14]];
        [(GPUImageFilterGroup *)filter setTerminalFilter:vintageFilter];

Hope it helps. It's working great here on iOS 5.1.1 / iPhone 4S.

@dmitric
dmitric commented Dec 16, 2012

hey @dpestana thanks a lot for the insight into blend filters. I'm sure other users will really appreciate that! The crashing happened when you integrate it into an app that takes up more memory than the sample project provided. Because the kernel handles unloading and loading UIImages into memory, if you have a lot of high res images and scroll through them quickly it tends to crash after a while. I'm not sure how adding a filter to the chain would make things stop crashing, is there something else you've done?

@dpestana

Hi @dmitric . I tried several things until I got this final result. What really solved my memory issues was what I mention above, adding the string [sourcePicture removeAlltargets] to -(void) removeAllTargets. I tested it extensively today, took several pictures, changed filters several times, retake, filters on stills, etc, etc... no problems until now. Tomorrow I'm going to try using bigger blend pictures (instead of the 640 * 640). I'll let you know. But please try this and let me know. Maybe you're right and I did something else and I don't remember. Thanks for the truly amazing tips and for your help. Much appreciated.

@tginsandiego

I just (this week) pulled the most recent version of the code, updated to the most recent version of GPUImage, and I'm also seeing this odd crash on an iPhone 4S test device. The suggested revision to takePhoto fixed it (thank you SO MUCH), but I have to wonder if it is actually some odd GPU race condition and not directly a memory error at all. I say this because my app occasionally has to ramp memory usage into the 1.5GB range (which it does without problems or crashes), while this crash occurs when app memory usage (before the picker call) is around 10 MB. One of those mysteries that may never be solved I guess. Huge kudos to everyone who has contributed to the library!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.