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?
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();
}
)};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With