I have problem with AVAssetImageGenerator. Quality of thumbnail is middle, size of pictures on the average around 50 kilobytes. I create a lot of thumbnails from video file my code:
- (UIImage *)generateThumbnailImage: (NSString *)srcVideoPath atTime:(CMTime)time
{
NSURL *url = [NSURL fileURLWithPath:srcVideoPath];
if ([srcVideoPath rangeOfString:@"://"].location == NSNotFound)
{
url = [NSURL URLWithString:[[@"file://localhost" stringByAppendingString:srcVideoPath] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
}
else
{
url = [NSURL URLWithString:[srcVideoPath stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];
}
AVAsset *asset = [AVAsset assetWithURL:url];
AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
imageGenerator.requestedTimeToleranceAfter = kCMTimeZero; // needed to get a precise time (http://stackoverflow.com/questions/5825990/i-cannot-get-a-precise-cmtime-for-generating-still-image-from-1-8-second-video)
imageGenerator.requestedTimeToleranceBefore = kCMTimeZero; // ^^
imageGenerator.appliesPreferredTrackTransform = YES; // crucial to have the right orientation for the image (http://stackoverflow.com/questions/9145968/getting-video-snapshot-for-thumbnail)
NSError *error;
CMTimeAdd(kCMTimeZero, asset.duration);
CGImageRef imageRef = [imageGenerator copyCGImageAtTime:time actualTime:NULL error:&error];
UIImage *thumbnail = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef); // CGImageRef won't be released by ARC
NSLog(@"error: %@", error);
return thumbnail;
}
- (void) createThumbnail: (NSString *)srcVideoPath atTime:(CMTime)time (NSInteger *) width:(NSInteger *) height:(NSInteger *)thumbQuality
{
//Image processing
UIImage* thumbnail = [self generateThumbnailImage:srcVideoPath atTime:time];
CGSize newSize = CGSizeMake(width, height);
thumbnail = [self scaleImage:thumbnail toSize:newSize];
NSString *cacheDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *outputFilePath = [cacheDir stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", outputFileName, @"jpg"]];
[UIImageJPEGRepresentation(thumbnail, thumbQuality) writeToFile:outputFilePath atomically:YES]
}
- (UIImage*)scaleImage:(UIImage*)image toSize:(CGSize)newSize;{
float oldWidth = image.size.width;
float scaleFactor = newSize.width / oldWidth;
float newHeight = image.size.height * scaleFactor;
float newWidth = oldWidth * scaleFactor;
UIGraphicsBeginImageContext(CGSizeMake(newWidth, newHeight));
[image drawInRect:CGRectMake(0, 0, newWidth, newHeight)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
The CGImageRef log gives error after creating 294 thumbnails:
Error Domain=AVFoundationErrorDomain Code=-11839 "Cannot Decode" UserInfo={NSLocalizedRecoverySuggestion=Stop any other actions that decode media and try again., NSLocalizedFailureReason=The decoder required for this media is busy., NSLocalizedDescription=Cannot Decode, NSUnderlyingError=0x1000d660 {Error Domain=NSOSStatusErrorDomain Code=-12913 "(null)"}}
How to fix it? How to release or stop any actions of decoder?
I'm using this code in cordova plugin. I have loop by javascript to generate thumbnails for specific time. I have tried with generateCGImagesAsynchronouslyForTimes I got same result.