问题
This might be a silly question but sorry for that as i am a newbie to iPhone.
I want to generate images for every frames of video and display that in UIScrollview inside UIImageView.
When i am trying to do that i am getting memory warning and my app crashes.
Below is my code.
- (IBAction)onCameraButtonPressed:(id)sender
{
// Initialize UIImagePickerController to select a movie from the camera roll.
UIImagePickerController *videoPicker = [[UIImagePickerController alloc] init];
videoPicker.delegate = self;
videoPicker.modalPresentationStyle = UIModalPresentationCurrentContext;
videoPicker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
videoPicker.mediaTypes = @[(NSString*)kUTTypeMovie];
[self presentViewController:videoPicker animated:YES completion:nil];
}
#pragma mark Image Picker Controller Delegate
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
[self dismissViewControllerAnimated:YES completion:nil];
currentVideoURL = info[UIImagePickerControllerReferenceURL];
//Video URL = assets-library://asset/asset.MOV?id=D0A4A3EE-C5F3-49C8-9E45-ADF775B9FA8C&ext=MOV
//NSLog(@"Video URL = %@",currentVideoURL);
//imageIndex = 0;
for (UIImageView *subView in thumbnailScrollView.subviews)
{
[subView removeFromSuperview];
}
[self generateThumbnailsFromVideoURL:currentVideoURL];
//[self generateAVAssetThumbnails:currentVideoURL];
//[self appleImageGenerator:currentVideoURL];
}
- (void)generateThumbnailsFromVideoURL:(NSURL *)videoURL
{
AVURLAsset *asset=[[AVURLAsset alloc] initWithURL:videoURL options:nil];
//NSLog(@"Video duration %lld seconds",asset.duration.value/asset.duration.timescale);
int videoDuration = (asset.duration.value/asset.duration.timescale);
if (cmTimeArray.count>0) {
[cmTimeArray removeAllObjects];
}
for (int i = 0; i<videoDuration; i++)
{
int64_t tempInt = i;
CMTime tempCMTime = CMTimeMake(tempInt,1);
int32_t interval = 15;
for (int j = 1; j<16; j++)
{
CMTime newCMtime = CMTimeMake(j,interval);
CMTime addition = CMTimeAdd(tempCMTime, newCMtime);
[cmTimeArray addObject:[NSValue valueWithCMTime:addition]];
}
}
//NSLog(@"Array of time %@ count = %d",cmTimeArray, cmTimeArray.count);
/*for(int t=0;t < asset.duration.value;t++) {
CMTime thumbTime = CMTimeMake(t,asset.duration.timescale);
NSValue *v=[NSValue valueWithCMTime:thumbTime];
[cmTimeArray addObject:v];
}
NSLog(@"Array of time %@ count = %d",cmTimeArray, cmTimeArray.count);*/
__block int i = 0;
//__block UIImage *currentImage = nil;
AVAssetImageGeneratorCompletionHandler handler = ^(CMTime requestedTime, CGImageRef im, CMTime actualTime, AVAssetImageGeneratorResult result, NSError *error){
if (result == AVAssetImageGeneratorSucceeded) {
// currentImage = [UIImage imageWithCGImage:im];
//[framesArray addObject:[UIImage imageWithCGImage:im]];
[self performSelectorOnMainThread:@selector(insertImageToScrollView:) withObject:[UIImage imageWithCGImage:im] waitUntilDone:NO];
}
else
NSLog(@"Ouch: %@", error.description);
i++;
imageIndex = i;
if(i == cmTimeArray.count) {
//[self performSelectorOnMainThread:@selector(insertImageToScrollView:) withObject:framesArray waitUntilDone:YES];
}
};
// Launching the process...
self.generator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
self.generator.appliesPreferredTrackTransform=TRUE;
self.generator.requestedTimeToleranceBefore = kCMTimeZero;
self.generator.requestedTimeToleranceAfter = kCMTimeZero;
self.generator.maximumSize = CGSizeMake(40, 40);
[self.generator generateCGImagesAsynchronouslyForTimes:cmTimeArray completionHandler:handler];
}
-(void)insertImageToScrollView:(UIImage *)image
{
int xPosition = (5*imageIndex)+(WIDTH*imageIndex)+OFFSET;
UIImageView *currentImageView = [[UIImageView alloc]initWithFrame:CGRectMake(xPosition, 5, WIDTH, WIDTH)];
currentImageView.tag = imageIndex+10;
currentImageView.image = image;
[thumbnailScrollView addSubview:currentImageView];
[thumbnailScrollView setContentSize:CGSizeMake(xPosition+WIDTH+5,thumbnailScrollView.frame.size.height)];
}
回答1:
You are loading all images into the view, but only a few are displayed at any one given time. Depending on the amount of images, this could take up a LOT of memory.
You could consider the following approach:
Generate all the images and write them to local storage, store the file-urls of the images in an array.
Now for your scrollview, only add images as they are needed, when you scroll to the next ones. When adding images, you load them from disk and add them to your view. Take a look at this example code for a horizontal infinite scrollview: https://code.google.com/p/iphone-infinite-horizontal-scroller.
You could also use an ordinary UITableView with a custom cell, only showing the image.
回答2:
I found my mistake. I was assigning original/full image to my 40*40 image view. That was generating memory warning. To solve provide required image size while generating image using below code.
self.generator.maximumSize = CGSizeMake(40, 40);
来源:https://stackoverflow.com/questions/16083786/how-to-generate-images-from-already-recorded-video-using-avassetimagegeneratorco