1

i'm cutting video frame by frame and than give effect in frame (using aviary SDK) and than create video of that images.

well my code creates video with the expected duration but when i play this video it will play stickly (not smoothly).

Here is my code.

- (IBAction)generateVideo:(id)sender
{
    NSLog(@"Enter in generateVideo Action");

    NSString *videoPath = [[Util mySaveFileToPath] stringByAppendingString:@"/video2.mp4"];

    UIImage * img = (UIImage *)[arrFramesOfVideo objectAtIndex:0];

    [self exportImages:arrFramesOfVideo asVideoToPath:videoPath withFrameSize:img.size framesPerSecond:framePerSec numberOfSecondsPerFrame:(1/framePerSec)];
}

well fps i'm getting at the time when i'm fetching frames from video using AVAssetTrack so i think there is no prob with that.

- (void)exportImages:(NSMutableArray *)imageArray asVideoToPath:(NSString *)videoOutputPath withFrameSize:(CGSize)imageSize framesPerSecond:(float)fps numberOfSecondsPerFrame:(float)numberOfSecondsPerFrame
{
    NSError *error = nil;
    NSLog(@"Start building video from defined frames.");
    NSLog(@"Video Path = %@",videoOutputPath);
    AVAssetWriter *videoWriter = [[AVAssetWriter alloc] initWithURL:[NSURL fileURLWithPath:videoOutputPath] fileType:AVFileTypeQuickTimeMovie error:&error];


    NSParameterAssert(videoWriter);

    NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                               AVVideoCodecH264, AVVideoCodecKey,
                               [NSNumber numberWithInt:imageSize.width], AVVideoWidthKey,
                               [NSNumber numberWithInt:imageSize.height], AVVideoHeightKey,
                               nil];

    AVAssetWriterInput* videoWriterInput = [AVAssetWriterInput
                                        assetWriterInputWithMediaType:AVMediaTypeVideo
                                        outputSettings:videoSettings];

    NSLog(@"videoWriterInput == %@",videoWriterInput);
    AVAssetWriterInputPixelBufferAdaptor *adaptor = [AVAssetWriterInputPixelBufferAdaptor
    assetWriterInputPixelBufferAdaptorWithAssetWriterInput:videoWriterInput
        sourcePixelBufferAttributes:nil];

    NSParameterAssert(videoWriterInput);
    NSParameterAssert([videoWriter canAddInput:videoWriterInput]);
    videoWriterInput.expectsMediaDataInRealTime = YES;
    [videoWriter addInput:videoWriterInput];

    //Start a session:
    [videoWriter startWriting];
    [videoWriter startSessionAtSourceTime:kCMTimeZero];

    CVPixelBufferRef buffer = NULL;

    //convert uiimage to CGImage.
     int  frameCount = 0;
    //double numberOfSecondsPerFrame = 6;
    double frameDuration = fps * numberOfSecondsPerFrame;

    //for(VideoFrame * frm in imageArray)
    NSLog(@"**************************************************");
    //for(UIImage * img in imageArray)
    for (int i = 0; i < arrFramesOfVideo.count; i++)
    {
        //NSLog(@"in loop");
        UIImage * img = (UIImage *)[arrFramesOfVideo objectAtIndex:i];
        buffer = [self pixelBufferFromCGImage:[img CGImage]];
        //dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.001 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

        if (adaptor.assetWriterInput.readyForMoreMediaData)
        {  
            NSLog(@"frameCount == %d",frameCount);
            CMTime frameTime = CMTimeMake(i*numberOfSecondsPerFrame * 10000,10000);
            //CMTime frameTime = CMTimeMakeWithSeconds(frameCount*numberOfSecondsPerFrame, fps);
            CMTimeShow(frameTime);
            //CMTime frameTime = CMTimeMake(frameCount*frameDuration,fps);
            [adaptor appendPixelBuffer:buffer withPresentationTime:frameTime];
            frameCount ++;
            CVPixelBufferRelease(buffer);
        }
        else
        {
            i--;
            NSLog(@"adaptor not ready.");
            [NSThread sleepForTimeInterval:0.0001];
        }

    //});
    }
    NSLog(@"**************************************************");

    //Finish the session:
    [videoWriterInput markAsFinished];
    //[videoWriter finishWriting];

    [videoWriter finishWritingWithCompletionHandler:^{

        if (videoWriter.status == AVAssetWriterStatusFailed)
        {
            NSLog(@"Movie Save Failed.");
        }
        else
        {
            NSLog(@"Movie Saved.");
        }

    }];

    NSLog(@"Write Ended");
    NSLog(@"Video Path = %@",videoOutputPath);
}

And other code is default for getting buffer i don't think it is required in this question B'coz it is common (without any changes).

If any body done this please help me i spent one day for this but still not found any solution.

Thank you!

4

0 回答 0