Search code examples
iosvideogpuimage

GPUImageMovie pause while applying filter


I am using Brad Larson's great library GPUImage for my application. Currently I am stuck with an issue. My application captures 10 second videos and after that allows filter applying. While applying filters in GPUImageMovie, I am not able to pause the play and apply new filter so that video will play continuously without starting from the beginning.

I saw an open github issue here. If anyone faced similar issue and found a solution, please post your answers. Thanks in advance.


Solution

  • And finally I fixed this after too many searches and try. We need to initiate GPUImageMovie with AVPlayerItem instead of URL. I got this valuable clue from here.

    I am posting my code which I am currently using in my application and it is working as expected. But there are performance issues in iPod 6.1 and I am working on enhancements of the same.

    Initial method to setup GPUImageMovie,

    - (void)setupVideo
    {
        playerItem = [[AVPlayerItem alloc]initWithURL:self.recordSession.outputUrl];
        player = [AVPlayer playerWithPlayerItem:playerItem];
    
        movieFile = [[GPUImageMovie alloc] initWithPlayerItem:playerItem];
    
        movieFile.runBenchmark = YES;
        movieFile.playAtActualSpeed = YES;
        [self.view sendSubviewToBack:self.videoView];
    
        [movieFile addTarget:filter];
        [filter addTarget:self.videoView];
    
        [movieFile startProcessing];
        movieRunning = YES;
    
        dispatch_async(dispatch_get_main_queue(), ^{
            self.playButton.hidden = YES;
        });
    
        player.rate = 1.0;
    }
    

    This method is called when user clicks on a filter button.

    - (void)filterClicked:(UIButton *)button
    {
        // Set paused time. If player reaches end of the video, set pausedTime to 0.
        if (CMTIME_COMPARE_INLINE(pausedTime, !=,  player.currentItem.asset.duration)) {
            pausedTime = player.currentTime;
        } else {
            pausedTime = CMTimeMake(0, 600.0);
        }
        [self.videoView setBackgroundColor:[UIColor clearColor]];
    
        [movieFile cancelProcessing];
    
        switch (button.tag)
        {
        case 0:
            filter = [[GPUImageFilter alloc] init];
            break;
        case 1:
            filter = [[GPUImageColorInvertFilter alloc] init];
            break;
        case 2:
            filter = [[GPUImageEmbossFilter alloc] init];
            break;
        case 3:
            filter = [[GPUImageGrayscaleFilter alloc] init];
            break;
        default:
            filter = [[GPUImageFilter alloc] init];
            break;
        }
    
        [self filterVideo];
    
    }
    

    After filter generation, video play resume is handled in this method.

    - (void)filterVideo {
    
        // AVPlayerItem is initialized with required url
    
        playerItem = [[AVPlayerItem alloc]initWithURL:self.outputUrl]; 
        [player replaceCurrentItemWithPlayerItem:playerItem];
    
        //GPUImageMovie is initialized with AVPlayerItem
    
        movieFile = [[GPUImageMovie alloc] initWithPlayerItem:playerItem];
    
        movieFile.runBenchmark = YES;
        movieFile.playAtActualSpeed = YES;
    
        // Adding targets for movieFile and filter
    
        [movieFile addTarget:filter];
        [filter addTarget:self.videoView]; // self.videoView is my GPUImageView
    
        [movieFile startProcessing];
        movieRunning = YES;
    
        dispatch_async(dispatch_get_main_queue(), ^{
            self.playButton.hidden = YES;
        });
    
        // Player rate is set to 0 means player is paused
    
        [player setRate:0.0];
    
        // Seeking to the point where video was paused
    
         if (CMTIME_COMPARE_INLINE(pausedTime, !=, player.currentItem.asset.duration)) {
            [player seekToTime:pausedTime];
        }
        [player play];
    }