objective-cimageavfoundationvideo-processingavassetimagegenerator

[AVFoundation]: Thumbnail generation hangs after some time


I have server application which serves informations about the videos on server. One of the requests is URL:PORT/video/:id/:time ... which I parse and get the video file, prepare the time and ask method to generate the thumbnail. It works for first 5 minutes really fast (generates image under 200ms), then the process of image generation suddenly takes even 10 seconds...

Do you have any idea why ? Code used:

-(NSImage *)thumbnailAt: (CMTime)        time
               withSize: (NSSize)        size
                  error: (NSError **)    error {

    @autoreleasepool {
         if ( self.assetChanged ) {
             self.generate = [[AVAssetImageGenerator alloc] initWithAsset:_asset];
             self.generate.appliesPreferredTrackTransform = TRUE;
             self.assetChanged = NO;
         }

         self.generate.maximumSize = NSSizeToCGSize(size);

         CGImageRef imageReference = [self.generate copyCGImageAtTime:time actualTime:NULL error:error];

        if ( imageReference != nil ) {
            NSImage* ret = [[NSImage alloc] initWithCGImage:imageReference size:size];
            CGImageRelease(imageReference);
            return ret;
        }

        return nil;
    }
}

Any idea what I am doing wrong or any suggestion how to do it differently (eg. using AVAssetReader) ?


Solution

  • In the end I solved it by using different approach: I used asynchronous images

    -(NSImage *)createAsyncThumbnailAtTime:(CMTime)time withSize:(NSSize)size {
        if ( self.updated ) {
            [_generator cancelAllCGImageGeneration]; // Stop we did not comply in time.
            _generator = [AVAssetImageGenerator assetImageGeneratorWithAsset:_asset];
            _generator.maximumSize = NSSizeToCGSize(size);
        }
    
        NSMutableArray * times = [NSMutableArray array];
        [times addObject:[NSValue valueWithCMTime:time]];
    
        __block NSImage * image;
        __block BOOL finished = NO;
    
        [_generator generateCGImagesAsynchronouslyForTimes:times completionHandler:^(CMTime requestedTime, CGImageRef imageRef, CMTime actualTime, AVAssetImageGeneratorResult result, NSError *error) {
    
            image = nil;
    
            if ( result == AVAssetImageGeneratorCancelled ) {
                image = nil;
                NSLog(@"CANCELLED %@", error);
                finished = YES;
            }
            else
                if ( result == AVAssetImageGeneratorFailed ) {
                    image   = nil;
                    NSLog(@"FAILDED %@", error);
                    finished = YES;
                }
                else /* result == AVAssetImageGeneratorSucessed */
                {
                    image = [[NSImage alloc] initWithCGImage:imageRef size:size];
                    finished = YES;
                }
        }];
    
        while ( !finished ) {
            [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
        }
    
        return thumbnail->image;
    }