Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AVAssetImageGenerator random failings in iOS7

I have an AVComposition and a AVVideoComposition that I generate thumbs for every half second or so of the video. I use the animation tool for some overlays. I execute the call on an operation Queue and it triggers after certain types of edits. The operation queue is serial not async, so the process never runs concurrent and I have verified this. The code below is executing on the main thread within another NSOperation that is in the serial Queue.

Now my problem is, thumbs randomly fail with no pattern. I can run it once and have it all succeed. I can run it again with the exact same arguments, and have some thumbs fail. I can run it again and have different thumbs fail.

It seems to be related to how much other activity is going on as well in other threads, like querying a lot of items from the ALAssetLibrary or MediaFramework.

I will also mention this worked in iOS6 without this problem.

I do create copies of the AVComposition and AVVideoComposition before I generate the thumbs.

Anyone have any pointers for me?

I appreciate it.

//this must be called on the main thread to correctly generate overlays
[[NSOperationQueue mainQueue] addOperationWithBlock:^{

    AVAsset *asset = avComposition;

    AVAssetImageGenerator *generator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
    generator.appliesPreferredTrackTransform = TRUE;

    AVMutableVideoComposition *mutableVideoComposition = (AVMutableVideoComposition *) avVideoComposition.mutableCopy;
    CALayer *baseSyncLayer = [CALayer layer];
    baseSyncLayer.frame = CGRectMake(0, 0, resolution.width, resolution.height);
    CALayer *videoLayer = [CALayer layer];
    videoLayer.frame = CGRectMake(0, 0, resolution.width, resolution.height);
    [baseSyncLayer addSublayer:videoLayer];
    __unused NSArray *imageLayers = [MovieCompositionService applyImageAnimations:avComposition andLayer:baseSyncLayer andProject:project fileRender:YES addTextOverlays:addTextOverlays andResolution:resolution];
    mutableVideoComposition.animationTool = [AVVideoCompositionCoreAnimationTool videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:baseSyncLayer];
    generator.videoComposition = mutableVideoComposition;

    NSMutableArray *images = [[NSMutableArray alloc] init];

    __block BOOL hasErrors = NO;

    AVAssetImageGeneratorCompletionHandler handler = ^(CMTime requestedTime, CGImageRef im, CMTime actualTime, AVAssetImageGeneratorResult result, NSError *error) {
        if (!hasErrors) {

            DDLogVerbose(@"ACTUAL GENERATION TIME %f", CMTimeGetSeconds(actualTime));

            if (result != AVAssetImageGeneratorSucceeded) {
                DDLogError(@"Failed to generate thumb: %@", error.localizedDescription);
                hasErrors = YES;
                [generator cancelAllCGImageGeneration];
                finishBlock(images, YES);
            } else {
                [images addObject:[UIImage imageWithCGImage:im]];

                if (CMTIME_COMPARE_INLINE(requestedTime, ==, ((NSValue *) timeIntervals.lastObject).CMTimeValue)) {
                    DDLogVerbose(@"Movie composition thumb generation complete");
                    finishBlock(images, NO);
                }
            }
        }
    };

    generator.maximumSize = thumbSize;
    [generator generateCGImagesAsynchronouslyForTimes:timeIntervals completionHandler:handler];
}];
like image 224
JADurham909 Avatar asked Nov 11 '22 21:11

JADurham909


1 Answers

I used the following for generating the thumbnail.

- (void)getThumbnailImageForTime:(float)instance_time withCompletion:(void(^)(UIImage *))completion
{
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul);
    dispatch_async(queue, ^{
        __block UIImage *thumb ;
        AVPlayerItem *playerItem = [AVPlayerItem playerItemWithURL:self.videoUrl];
        AVAssetImageGenerator *_generator;
        _generator = [AVAssetImageGenerator assetImageGeneratorWithAsset:playerItem.asset];

        AVAssetImageGeneratorCompletionHandler handler = ^(CMTime requestedTime, CGImageRef image, CMTime actualTime, AVAssetImageGeneratorResult result, NSError *error) {
            if (result == AVAssetImageGeneratorSucceeded) {
                thumb = [UIImage imageWithCGImage:image];
                NSLog(@"Succesfully generater the thumbnail!!!");
            } else {
                NSLog(@"Failed to generater the thumbnail!!!");
                NSLog(@"Error : %@",error.localizedDescription);
                [self performSelector:@selector(retryingThumbnialGeneration) withObject:nil afterDelay:1.0f];
            }
            dispatch_async(dispatch_get_main_queue(), ^{
                 completion(thumb);
            });
        };

        [_generator generateCGImagesAsynchronouslyForTimes:[NSArray arrayWithObject:[NSValue valueWithCMTime:CMTimeMakeWithSeconds(2,10)]] completionHandler:handler];

    });

}
like image 188
Vishnu Kumar. S Avatar answered Nov 15 '22 07:11

Vishnu Kumar. S