2
votes

I want to change a visual effects dynamically to running videos. Am using GPUImage framework for changing the visual effects. I downloaded the sample project from Here. In this GPUImage, I choosed SimpleVideoFileFilter example. This example runs with one filter, just i modified the code and currently it supports 10 filters. My issue is, Video file is playing in GPUImageView, now i select another filter. Suddenly the video effect is also changing. But that video is starts from beginning. I want to change the filter dynamically for current playing video. My Code is :

#pragma mark - Play Video with Effects

- (void)getVideo:(NSURL *)url
{
    movieFile = [[GPUImageMovie alloc] initWithURL:url];

    movieFile.runBenchmark = YES;
    movieFile.playAtActualSpeed = YES;
    //    filter = [[GPUImagePixellateFilter alloc] init];


    [movieFile addTarget:filter];

    // Only rotate the video for display, leave orientation the same for recording
    filterView = (GPUImageView *)self.view;
    [filter addTarget:filterView];

    // In addition to displaying to the screen, write out a processed version of the movie to disk
    NSString *pathToMovie = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/Movie.m4v"];
    unlink([pathToMovie UTF8String]); // If a file already exists, AVAssetWriter won't let you record new frames, so delete the old movie
    NSURL *movieURL1 = [NSURL fileURLWithPath:pathToMovie];

    movieWriter = [[GPUImageMovieWriter alloc] initWithMovieURL:movieURL1 size:CGSizeMake(640.0, 480.0)];
    [filter addTarget:movieWriter];

    // Configure this for video from the movie file, where we want to preserve all video frames and audio samples
    movieWriter.shouldPassthroughAudio = YES;
    movieFile.audioEncodingTarget = movieWriter;
    [movieFile enableSynchronizedEncodingUsingMovieWriter:movieWriter];

    [movieWriter startRecording];
    [movieFile startProcessing];

    [movieWriter setCompletionBlock:^{
        [filter removeTarget:movieWriter];
        [movieWriter finishRecording];
        UISaveVideoAtPathToSavedPhotosAlbum(pathToMovie, nil, nil, nil);
    }];
}

- (void)event:(UIButton*)sender
{
    [filter removeTarget:filterView];
    UIButton *selectedBtn = sender;
    [movieFile removeTarget:filter];
    switch (selectedBtn.tag)
    {
        case 0:
            filter = [[GPUImageBrightnessFilter alloc] init];
            break;
        case 1:
            filter = [[GPUImageGrayscaleFilter alloc] init];
            break;
        case 2:
            filter = [[GPUImageSketchFilter alloc] init];
            break;
        case 3:
            filter = [[GPUImageToonFilter alloc] init];
            break;
        case 4:
            filter = [[GPUImageMonochromeFilter alloc] init];
            break;
        case 5:
            filter = [[GPUImagePixellateFilter alloc] init];
            break;
        case 6:
            filter = [[GPUImageCrosshatchFilter alloc] init];
            break;
        case 7:
            filter = [[GPUImageVignetteFilter alloc] init];
            break;
        case 8:
            filter = [[GPUImageColorInvertFilter alloc] init];
            break;
        case 9:
            filter = [[GPUImageLevelsFilter alloc] init];
            [(GPUImageLevelsFilter *)filter setRedMin:1.0 gamma:1.0 max:0.0 minOut:0.5 maxOut:0.5];
            break;

        default:
            break;        
    }
    [self getVideo:movieURL];
}

Please help me to resolve this issue.

2
Why are you re-running [self getVideo:movieURL]; every time you change a filter setting? Of course that would restart your video. Simply change filter properties or swap out filters without regenerating your movie instance. You can easily pause the movie, change out the filters, and restart the movie to dynamically change these effects.Brad Larson
Hi @BradLarson, First of all thanks for your valuable GPUImage Framework. Actually am struck for this issue. Please help me to resolve this. I don't know how to swap out the filters dynamically. Will you please edit above mentioned code and post as answer.Sabs
@BradLarson how to pause a running movie?Arjun Sa
I am also facing this same issue. Please post a solution.QUserS
@QUserS - Posted the solutions.Sabs

2 Answers

0
votes

I found the answer by myself. Solution is,

- (void)event:(UIButton*)sender
{
    //  isMoviePlayCompleted = NO;
    if (btnTag != sender.tag)
    {
        btnTag = (int)sender.tag;
        NSLog(@"tag:%d",btnTag);
        [self applyFilter:sender.tag];
    }

}

Applying Filter

    -(void) applyFilter:(NSInteger) tag
    {
        [[NSFileManager defaultManager] removeItemAtURL:saveTempUrl error:nil];
        recording = NO;
        switch (tag)
        {
            case 0:
                filter =nil;
                filter  = [[GPUImagePixellateFilter alloc] init];
                [(GPUImagePixellateFilter *)filter setFractionalWidthOfAPixel:0.0];
                break;
            case 1:
                filter =nil;
                filter = [[GPUImageGrayscaleFilter alloc] init];
                break;
            case 2:
                filter =nil;
                filter = [[GPUImageSketchFilter alloc] init];
                break;
            case 3:
                filter =nil;
                filter = [[GPUImageToonFilter alloc] init];
                break;
            case 4:
                filter =nil;
                filter = [[GPUImageMonochromeFilter alloc] init];
                break;
            case 5:
                filter =nil;
                filter = [[GPUImageVignetteFilter alloc] init];
                break;
      default:
                break;
        }

        [self getVideo:movieURL];
}

Play Video with Effects

- (void)getVideo:(NSURL *)url
{

        [filter removeAllTargets];
        movieFile.audioEncodingTarget = nil;
        [movieWriter cancelRecording];
        [movieFile cancelProcessing];
        [movieWriter finishRecording];
        movieWriter = nil;
        movieFile = nil;
        filterView = nil;
    recording = YES;
    anAsset = [[AVURLAsset alloc] initWithURL:url options:nil];
    movieFile = [[GPUImageMovie alloc] initWithURL:url];
        movieFile.delegate = self;
        movieFile.runBenchmark = NO;
    movieFile.playAtActualSpeed = YES;

        [movieFile addTarget:filter];

    // Only rotate the video for display, leave orientation the same for recording
    filterView = (GPUImageView *)self.view;

        [filter addTarget:filterView];

        NSString *pathName = [NSString stringWithFormat:@"Doc.MOV"];
        // In addition to displaying to the screen, write out a processed version of the movie to disk
        NSString *pathToMovie = [NSTemporaryDirectory() stringByAppendingPathComponent:pathName];
        NSFileManager *fileTmp = [[NSFileManager alloc] init];
        if ([fileTmp fileExistsAtPath:pathToMovie]) {
            [fileTmp removeItemAtPath:pathToMovie error:nil];
        }
        unlink([pathToMovie UTF8String]); // If a file already exists, AVAssetWriter won't let you record new frames, so delete the old movie
        saveTempUrl =  [NSURL fileURLWithPath:pathToMovie];
        movieWriter = [[GPUImageMovieWriter alloc] initWithMovieURL:saveTempUrl size:size];
        [filter addTarget:movieWriter];
[movieFile enableSynchronizedEncodingUsingMovieWriter:movieWriter];
    [movieWriter startRecording];
    [movieFile startProcessing];
    __unsafe_unretained typeof(self) weakSelf = self;
    [weakSelf->movieWriter setCompletionBlock:^{

        NSLog(@"write completed");
        [filter removeTarget:movieWriter];
        [movieWriter finishRecording];
        movieWriter = nil;
        movieFile = nil;
        filterView = nil;
        recording = NO;
        if (saveFilter)
        {
            saveFilter = NO;
            UISaveVideoAtPathToSavedPhotosAlbum([saveTempUrl path], self, @selector(video:didFinishSavingWithError:contextInfo:), nil);
            shareFilter = YES;
        }

    }];
}

Thats it. now when i choose any filter, it witt fill newly. so memory issue is solved. now its working fine for my application.

0
votes
// Use this code

 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(movieFinished) name:MPMoviePlayerPlaybackDidFinishNotification object:videoPlayer];
[videoPlayer play];


-(void)movieFinished
{
[videoPlayer play];
 } 



-(void) playTheVideo:(NSURL *)videoURL
{
NSTimeInterval time= videoPlayer.currentPlaybackTime;
UIView *parentView = imageViewFiltered; // adjust as needed
CGRect bounds = parentView.bounds; // get bounds of parent view
CGRect subviewFrame = CGRectInset(bounds, 0, 0); 
videoPlayer.view.frame = subviewFrame;
videoPlayer.view.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
[parentView addSubview:videoPlayer.view];
videoPlayer.contentURL = videoURL;
[videoPlayer setCurrentPlaybackTime:time];
[videoPlayer stop];
NSLog(@"Videoplayer stop or play in this view ");
[videoPlayer play];
self.showLoading = NO;
self.showLoading =NO;
}