views:

138

answers:

2

I have a simple foundation tool that exports every frame of a movie as a .tiff file. Here is the relevant code:

NSString* movieLoc = [NSString stringWithCString:argv[1]];
QTMovie *sourceMovie = [QTMovie movieWithFile:movieLoc error:nil];
int i=0;

while (QTTimeCompare([sourceMovie currentTime], [sourceMovie duration]) != NSOrderedSame) {
    // save image of movie to disk  
    NSAutoreleasePool *arp = [[NSAutoreleasePool alloc] init];

    NSString *filePath = [NSString stringWithFormat:@"/somelocation_%d.tiff", i++];
    NSData *currentImageData = [[sourceMovie currentFrameImage] TIFFRepresentation];
    [currentImageData writeToFile:filePath atomically:NO];
    NSLog(@"%@", filePath);

    [sourceMovie stepForward];
    [arp release];
}

[pool drain];
return 0;

As you can see, in order to prevent very large memory buildups with the various transparently-autoreleased variables in the loop, we create, and flush, an autoreleasepool with every run through the loop.

However, over the course of stepping through a movie, the amount of memory used by the program still gradually increases. Instruments is not detecting any memory leaks per se, but the object trace shows certain General Data blocks to be increasing in size.

[Edited out reference to slowdown as it doesn't seem to be as much of a problem as I thought.]

Edit: let's knock out some parts of the code inside the loop & see what we find out...

Test 1

while (banana) {
    NSAutoreleasePool *arp = [[NSAutoreleasePool alloc] init];
    NSString *filePath = [NSString stringWithFormat:@"/somelocation_%d.tiff", i++];
    NSLog(@"%@", filePath);

    [sourceMovie stepForward];
    [arp release];
}

Here we simply loop over the whole movie, creating the filename and logging it.

Memory characteristics: remains at 15MB usage for the duration.

Test 2

while (banana) {
    NSAutoreleasePool *arp = [[NSAutoreleasePool alloc] init];
    NSImage *image = [sourceMovie currentFrameImage];

    [sourceMovie stepForward];
    [arp release];
}

Here we add back in the creation of the NSImage from the current frame.

Memory characteristics: gradually increasing memory usage. RSIZE is at 60MB by frame 200; 75MB by f300.

Test 3

while (banana) {
    NSAutoreleasePool *arp = [[NSAutoreleasePool alloc] init];
    NSImage *image = [sourceMovie currentFrameImage];
    NSData *imageData = [image TIFFRepresentation];

    [sourceMovie stepForward];
    [arp release];
}

We've added back in the creation of an NSData object from the NSImage.

Memory characteristics: Memory usage is again increasing: 62MB at f200; 75MB at f300. In other words, largely identical.

It looks like a memory leak in the underlying system QTMovie uses to do currentFrameImage, to me.

+1  A: 

The easiest way to find a memory leak is to run your program under a profiler. Xcode includes excellent profiling tools, the one you need is under Run->Start with Performance Tool->Leaks. It is pretty simple to use, too.

unbeli
Thanks for the tip. No leaks are being found, though the object allocation trace appears to be growing in some parts, I have absolutely no clue where when it comes to interpreting long lists of calls from deep inside QuickTime, for instance!
Benji XVI
I mean, if there was a classic leak, caused by incorrect memory management, we would expect it to be obvious in the code here, wouldn't we, what with it being so simple. So I was really wondering if there was some deeper behaviour, originally perhaps related to ARPs, but also maybe QTMovie behaviour, that someone could shed light on! That latter one is quite the specialized request, now I come to think of it :)
Benji XVI
A: 

This does indeed look like a memory leak internal to QTKit.

Benji XVI
PS if anyone has a better answer, I will gladly accept it instead of this lousy one!
Benji XVI