7

This question is an extension to:
Link-1: Creating an image out of the ios surface and saving it
Link-2: Taking Screenshots from iOS app - emulating Display recorder (query on the internals)

(Refer Link-1) I have the code for taking screenshots in the background working. But as stated, it requires a sleep of 2 sec to work uninterruptedly, otherwise the OS suspends the app. I figured out the reason could be that I am not explicitly releasing the IOSurface I create.
Reason - Using the link http://pastie.org/pastes/3734430 given by Victor Ronin, the capture works fine even without the sleep. I tried releasing the destSurf (destination surface that I have created) using CFRelease after I write the image each time, but that doesn't work.

Any help on when, how and whether or not to release a created IOSurface, will be really useful. Thanks.

Update
So, this is what exactly happens. (Referring Link-1)

IOSurfaceRef destSurf = IOSurfaceCreate(dict);
IOSurfaceAcceleratorRef outAcc;
IOSurfaceAcceleratorCreate(NULL, 0, &outAcc);

CFDictionaryRef ed = (__bridge CFDictionaryRef)[NSDictionary dictionaryWithObjectsAndKeys: nil];
IOSurfaceAcceleratorTransferSurface(outAcc, screenSurface, destSurf, ed, NULL);

IOSurfaceUnlock(screenSurface, kIOSurfaceLockReadOnly, &aseed);

CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, IOSurfaceGetBaseAddress(destSurf), (width*height*4), NULL);
CGImageRef cgImage=CGImageCreate(width, height, 8, 8*4, IOSurfaceGetBytesPerRow(destSurf), CGColorSpaceCreateDeviceRGB(), kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little, provider, NULL, YES, kCGRenderingIntentDefault);
UIImage *image = [UIImage imageWithCGImage: cgImage];
CGImageRelease(cgImage);
UIImageWriteToSavedPhotosAlbum(image, self, nil, nil);
CFRelease(destSurf);
  1. The call to CFRelease takes place and app crashes. There are no images saved. However, if you put in a sleep of 1-2 sec prior to the release, it works fine.
  2. If you skip the call to UIImageWriteToSavePhotosAlbum(), everything works fine and capture goes without interruption.
    I am still not clear on what exactly is the problem and how to solve it. Any help is highly appreciated.
Community
  • 1
  • 1
Hrishikesh_Pardeshi
  • 995
  • 4
  • 19
  • 45

1 Answers1

3

I think you need to release surface. It's create by API IOSurfaceCreate which isn't managed by autorelease's.

As example I found following code where it's released:

https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=8&cad=rja&ved=0CF0QFjAH&url=http%3A%2F%2Fcode.google.com%2Fp%2Fsyphon-framework%2Fsource%2Fbrowse%2Ftags%2Fpublic-beta-1%2FSyphonServer.m%3Fr%3D3&ei=i_zRUMWQDMqw0AHs7IHYDA&usg=AFQjCNG9yO3sUf-ZQy-W_h_Q9WJMm4hqgw

http://www.opensource.apple.com/source/WebCore/WebCore-7536.24/platform/graphics/surfaces/mac/GraphicsSurfaceMac.cpp?txt

What happens if you try to release it with CFRelease? Does it crash or does it have the same 2 secs problem?

Victor Ronin
  • 22,758
  • 18
  • 92
  • 184
  • Thanks. The app crashes if I use CFRelease with the surface I create. However, if I use it on the screen surface I have grabbed from IOMobileBufferGetLayerDefaultSurface. – Hrishikesh_Pardeshi Dec 19 '12 at 18:17
  • 1
    Try to see what is the retain number for this object using CFGetRetainCount. My assumption that it should be one. Also, try to have very simple example (just create a IOSurface and release it immediately), just to make sure that none of other calls lead to this crash. – Victor Ronin Dec 19 '12 at 18:32
  • I will check both of it and get back to you. Also, just to clarify, if the RetainCount is 1, it would mean I could not release the object? What do I do in that case? – Hrishikesh_Pardeshi Dec 19 '12 at 18:37
  • 1
    I recommend to read up this: http://stackoverflow.com/questions/6578/understanding-reference-counting-with-cocoa-and-objective-c (It's quite big and complex subject) – Victor Ronin Dec 19 '12 at 18:48
  • So, I got confused with the retain count and reference count only to find it is the same thing. I checked up the retain count for the surface, it is 1 and so it is eligible to be released (if it has to be). The release works fine but it has to be called after some sleep so that it allows the operation of Image creation and saving to be completed entirely. – Hrishikesh_Pardeshi Dec 20 '12 at 06:05
  • 1
    @Hrishikesh_Pardeshi as you described the problem yourself, it must be easy to fix with the surface being released at the completion selector, UIKit reference mentions asynchronous processing of `UIImageWriteToSavedPhotosAlbum` so the crash is expected. – A-Live Dec 20 '12 at 11:33