Advertise Mobile SDKs Books Events Forum News Social Networking Support Us
Follow @iphonedevsdk on Twitter

Interface 2, Advanced iOS
Mockup & Code Gen
($9.99)

Make your own iPhone apps
and run them live!
(free)

Pic Frame Dynamo: Photo Editing
($0.99)

Abiliator
($1.99)

Want your application or service advertised on iPhone Dev SDK?

Go Back   iPhone Dev SDK Forum > iPhone SDK Development Forums > iPhone SDK Development > iPhone SDK Development - Advanced Discussion

Reply
 
LinkBack Thread Tools Display Modes
Old 04-13-2011, 11:48 PM   #1 (permalink)
Registered Member
 
Join Date: Dec 2010
Location: Moscow, Russia
Posts: 84
Pavel Volobuev is on a distinguished road
Default Make a Video from NSArray of UIImages

Hello everyone,
I'm trying to collect Video file from NSArray of UIImages, but has problem with video duration, i can't make a video more than 1 second, all of my frames collect in 1 second video, could you help with this?

My code see below please:
PHP Code:
-(void)writeImageAsMovie:(NSArray *)array toPath:(NSString*)path size:(CGSize)size duration:(int)duration 
{
    
NSError *error nil;
    
AVAssetWriter *videoWriter = [[AVAssetWriter allocinitWithURL:[NSURL fileURLWithPath:path
                                                           
fileType:AVFileTypeMPEG4 
                                                              error
:&error];
    
NSParameterAssert(videoWriter);
    
    
NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                                   
AVVideoCodecH264AVVideoCodecKey,
                                   [
NSNumber numberWithInt:size.width], AVVideoWidthKey,
                                   [
NSNumber numberWithInt:size.height], AVVideoHeightKey,
                                   
nil];
    
AVAssetWriterInputwriterInput = [[AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo
                                                                          outputSettings
:videoSettingsretain];
    
    
AVAssetWriterInputPixelBufferAdaptor *adaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:writerInput
                                                                                                                     sourcePixelBufferAttributes
:nil];
    
NSParameterAssert(writerInput);
    
NSParameterAssert([videoWriter canAddInput:writerInput]);
    [
videoWriter addInput:writerInput];
    
    
    
//Start a session:
    
[videoWriter startWriting];
    [
videoWriter startSessionAtSourceTime:kCMTimeZero];
    
    
CVPixelBufferRef buffer NULL;
    
buffer = [self pixelBufferFromCGImage:[[array objectAtIndex:0CGImagesize:CGSizeMake(480320)];
    
CVPixelBufferPoolCreatePixelBuffer (NULLadaptor.pixelBufferPool, &buffer);
    
    [
adaptor appendPixelBuffer:buffer withPresentationTime:kCMTimeZero];
    
int i 1;
    while (
writerInput.readyForMoreMediaData// every iteration i add my CGImage to buffer, but after 5th iteration readyForMoreMediaData sets to NO, Why???
    
{
        
NSLog(@"inside for loop %d",i);
        
CMTime frameTime CMTimeMake(110);
        
CMTime lastTime=CMTimeMake(i100);
        
CMTime presentTime=CMTimeAdd(lastTimeframeTime);
        
        if (
>= [array count]) 
        {
            
buffer NULL;
        } 
        else 
        {
            
buffer = [self pixelBufferFromCGImage:[[array objectAtIndex:iCGImagesize:CGSizeMake(480320)];
        }          
        
//CVBufferRetain(buffer);
        
        
if (buffer
        {
            
// append buffer
            
[adaptor appendPixelBuffer:buffer withPresentationTime:presentTime];
            
i++;
        } 
        else 
        {
            
// done!
            
            //Finish the session:
            
[writerInput markAsFinished];
            [
videoWriter finishWriting];                
            
            
CVPixelBufferPoolRelease(adaptor.pixelBufferPool);
            [
videoWriter release];
            [
writerInput release];
            
NSLog (@"Done");
            
//            [imageArray removeAllObjects];              
            
break;
        }
    }
  }
}

- (
IBAction)saveMovieToLibrary
{
    
NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"Documents/movie.mp4"]];
    
testImageArray = [[NSArray allocinitWithObjects:
                      [
UIImage imageNamed:@"add_ar.png"], 
                      [
UIImage imageNamed:@"add_ja.png"], 
                      [
UIImage imageNamed:@"add_ru.png"],
                      [
UIImage imageNamed:@"add_ru.png"],
                      [
UIImage imageNamed:@"add_ar.png"], 
                      [
UIImage imageNamed:@"add_ja.png"], 
                      [
UIImage imageNamed:@"add_ru.png"],
                      [
UIImage imageNamed:@"add_ar.png"], 
                      [
UIImage imageNamed:@"add_en.png"], nil];
   
    [
self writeImageAsMovie:testImageArray toPath:path size:CGSizeMake(480320duration:1];

Pavel Volobuev is offline   Reply With Quote
Old 04-15-2011, 04:59 AM   #2 (permalink)
Registered Member
 
Join Date: Dec 2010
Location: Moscow, Russia
Posts: 84
Pavel Volobuev is on a distinguished road
Default

Where the super coders? I need heeelp, please =)
Pavel Volobuev is offline   Reply With Quote
Old 04-18-2011, 09:12 AM   #3 (permalink)
Nuisance Developer
 
Join Date: Jul 2009
Location: Italy
Posts: 4,691
dany_dev is on a distinguished road
Default

ok, assuming that you want a video of 2 seconds with 10 fps, you need 20 UIImages (you can also insert in the array the same image more than 1 time).
So for example if you need a video of 3.4 seconds, set 10 fps and add 34 images.

with that code i'm able to create a video > 1 sec.

array is an NSArray with 20 UIImage on it, setting 10 fps, i have a video of 2 seconds.

Code:
 int i = 1;
    while (1) 
    {
		if(writerInput.readyForMoreMediaData){

			CMTime frameTime = CMTimeMake(1, 10 );
			CMTime lastTime=CMTimeMake(i, 10);
			CMTime presentTime=CMTimeAdd(lastTime, frameTime);
			
			if (i >= [array count]) 
			{
				buffer = NULL;
			} 
			else 
			{
				buffer = [self pixelBufferFromCGImage:[[array objectAtIndex:i] CGImage] size:CGSizeMake(480, 320)];
			}          
			
			
			if (buffer) 
			{
				// append buffer
				[adaptor appendPixelBuffer:buffer withPresentationTime:presentTime];
				i++;
			} 
			else 
			{
				
				//Finish the session:
				[writerInput markAsFinished];
				[videoWriter finishWriting];                
				
				CVPixelBufferPoolRelease(adaptor.pixelBufferPool);
				
				
				[videoWriter release];
				[writerInput release];
				NSLog (@"Done");
				break;
			}
		}
    }
it's not the cleanest code ever, and i have tested it just 2-3 times, but work.
__________________

Last edited by dany_dev; 04-20-2011 at 09:41 AM.
dany_dev is offline   Reply With Quote
Old 04-20-2011, 02:33 AM   #4 (permalink)
Registered Member
 
Join Date: Dec 2010
Location: Moscow, Russia
Posts: 84
Pavel Volobuev is on a distinguished road
Default

Thanks, it works perfectly on a Simulator, but on Device application is stops after first Loop and that's all. Device is stops, app stops. Why this can happen?
Pavel Volobuev is offline   Reply With Quote
Old 04-20-2011, 09:38 AM   #5 (permalink)
Nuisance Developer
 
Join Date: Jul 2009
Location: Italy
Posts: 4,691
dany_dev is on a distinguished road
Default

i tried just to execute it in background and worked

Code:
- (IBAction)makeAMovie
{

    [self performSelectorInBackground:(@selector(myMethod)) withObject:nil];

}

-(void) myMethod {

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    
    NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"Documents/movie.mp4"]];

    [self writeImageAsMovie:testImageArray toPath:path size:CGSizeMake(480, 320) duration:1];

    [pool drain];
}
__________________
dany_dev is offline   Reply With Quote
Old 04-20-2011, 11:32 PM   #6 (permalink)
Registered Member
 
Join Date: Dec 2010
Location: Moscow, Russia
Posts: 84
Pavel Volobuev is on a distinguished road
Default

It's really works perfectly, thanks a lot
Pavel Volobuev is offline   Reply With Quote
Old 04-24-2011, 09:58 AM   #7 (permalink)
Registered Member
 
Join Date: Apr 2011
Posts: 2
drfence is on a distinguished road
Default

I am trying to grab frames from an animating layer on the iphone. I've copied the two key methods below.

This code sample helped me a lot!! Thanks for posting. I couldn't figure out why mine was failing all the time. I used some code from another sample and mixed and matched and part of my problem was using a quicktime movie instead of AVFileTypeMPEG4.

The one strange thing I can't figure out is why this line of code always returns NO.

Code:
  if ([localAdaptor appendPixelBuffer:buffer withPresentationTime:presentTime] == NO) {
                    NSLog(@"failed to write frame to video %i", i);
                }
Is there anywhere I can find out by querying some api to know what is causing my adds to fail? Strangely I still get a movie and it moves correctly to my library and I can play it on my iphone 4.

I know I had it working at some point so something subtle changed and I can't figure out what that is. One thing is that my images are 320x380
and I was unsure what differing image sizes have to do with issues.

Other things I've read is that bad presentation times cause issues. I still don't exactly understand the logic for computing the presentation time either. Isn't it just the same as using i/10 instead of having to add presentation times?

Code:
-(UIImage*) getCurrentFrame {
 //   NSLog(@"MovieMaker:getCurrentFrame");
    UIGraphicsBeginImageContext(animationView.bounds.size);
    [animationView.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    return image;
}
Code:
- (CVPixelBufferRef) pixelBufferFromCGImage: (CGImageRef) image  size:(CGSize)imageSize
{
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                             [NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey,
                             [NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey,
                             nil];
    CVPixelBufferRef pxbuffer = NULL;
    CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, imageSize.width,
                                          imageSize.height, kCVPixelFormatType_32ARGB, (CFDictionaryRef) options, 
                                          &pxbuffer);
    NSParameterAssert(status == kCVReturnSuccess && pxbuffer != NULL);
    
    CVPixelBufferLockBaseAddress(pxbuffer, 0);
    void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer);
    NSParameterAssert(pxdata != NULL);
    
    CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(pxdata, imageSize.width,
                                                 imageSize.height, 8, 4*imageSize.width, rgbColorSpace, 
                                                 kCGImageAlphaNoneSkipFirst);
    NSParameterAssert(context);
    //    CGContextConcatCTM(context, frameTransform);
    CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image), 
                                           CGImageGetHeight(image)), image);
    CGColorSpaceRelease(rgbColorSpace);
    CGContextRelease(context);
    
    CVPixelBufferUnlockBaseAddress(pxbuffer, 0);
    
    return pxbuffer;
}
drfence is offline   Reply With Quote
Old 04-25-2011, 07:41 AM   #8 (permalink)
Registered Member
 
Join Date: Apr 2011
Posts: 2
drfence is on a distinguished road
Default

I figured out the issue. It was that the file already existed.
drfence is offline   Reply With Quote
Old 09-25-2011, 03:07 PM   #9 (permalink)
Registered Member
 
Join Date: Sep 2011
Posts: 1
jsmith is on a distinguished road
Default

Hi all,

Is there away to use this method to make video for an iphone 3? iphone 3 does not support H264 encoding, I've tried AVVideoCodecJPEG but the AVAssetWriter status is always AVAssetWriterStatusFailed

Got this from AVAssetWriterInput

Video output settings keys are defined in AVVideoSettings.h. Video output settings with keys from
<CoreVideo/CVPixelBuffer.h> are not currently supported. The only values currently supported for
AVVideoCodecKey are AVVideoCodecH264 and AVVideoCodecJPEG. AVVideoCodecH264 is not supported on iPhone 3G.
jsmith is offline   Reply With Quote
Reply

Bookmarks

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On



» Advertisements
» Online Users: 374
17 members and 357 guests
AyClass, baja_yu, checkright, dre, epaga, fvisticot, givensur, jPuzzle, Meoz, Newbie123, Objective Zero, Punkjumper, reficul, sacha1996, skrew88, tomtom100
Most users ever online was 1,387, 04-10-2012 at 04:21 AM.
» Stats
Members: 175,642
Threads: 94,110
Posts: 402,857
Top Poster: BrianSlick (7,990)
Welcome to our newest member, pinacate
Powered by vBadvanced CMPS v3.1.0

All times are GMT -5. The time now is 04:33 PM.
Powered by vBulletin® Version 3.8.0
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.3.0