Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AVAssetImageGenerator performance issue

I am trying to create a video gallery.

To display videos I am using a UICollectionView. Each UICollectionViewCell has a background with video thumbnail. To generate a video thumbnail I am using a method with logic:

AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:url options:nil];

AVAssetImageGenerator *generator = [[AVAssetImageGenerator alloc] initWithAsset:asset];

generator.appliesPreferredTrackTransform = YES;

CMTime time = CMTimeMakeWithSeconds(0,15);

AVAssetImageGeneratorCompletionHandler handler = ^(CMTime timeRequested, CGImageRef image, CMTime timeActual, AVAssetImageGeneratorResult result, NSError *error)
{
    NSLog(@"handler^()");

    if (result == AVAssetImageGeneratorSucceeded)
    {
        thumbnail = [UIImage imageWithCGImage: image];

        success(thumbnail);
    }

    else
    {
        failure(error);
    }
};

CGSize maximumSize = CGSizeMake(CLIPBOARD_COLLECTION_VIEW_CELL_WIDTH, CLIPBOARD_COLLECTION_VIEW_CELL_HEIGHT);

generator.maximumSize = maximumSize;

NSLog(@"generateCGImagesAsynchronouslyForTimes:");
[generator generateCGImagesAsynchronouslyForTimes:[NSArray arrayWithObject:[NSValue valueWithCMTime:time]] completionHandler:handler];

I have noticed that generateCGImagesAsynchronouslyForTimes doesn't work fully asynchronously. There a time space between this method calls. This causes a big lag while I am loading table view cells. If I comment line [generator generateCGImagesAsynchronouslyForTimes:[NSArray arrayWithObject:[NSValue valueWithCMTime:time]] completionHandler:handler] then there are no visible lag (nor images).

How can I solve this performance issue?

like image 990
Daumantas Versockas Avatar asked Apr 28 '15 20:04

Daumantas Versockas


1 Answers

The AVAssetImageGeneratorCompletionHandler block is not guaranteed to be called on the main thread:

Concurrent Programming with AV Foundation

Callouts from AV Foundation—invocations of blocks, key-value observers, and notification handlers—are not guaranteed to be made on any particular thread or queue. Instead, AV Foundation invokes these handlers on threads or queues on which it performs its internal tasks. You are responsible for testing whether the thread or queue on which a handler is invoked is appropriate for the tasks you want to perform. If it’s not (for example, if you want to update the user interface and the callout is not on the main thread), you must redirect the execution of your tasks to a safe thread or queue that you recognize, or that you create for the purpose.

Does calling success and failure with dispatch_async fix the issue?

dispatch_async(dispatch_get_main_queue(), ^{
    if (success) {
        success();
    }
)};
like image 191
jszumski Avatar answered Oct 19 '22 07:10

jszumski