2014-04-08 34 views
2

我想动态地将视觉效果更改为正在运行的视频。我正在使用GPUImage框架来改变视觉效果。我从Here下载了示例项目。在这个GPUImage中,我选择了SimpleVideoFileFilter示例。这个例子运行一个过滤器,只是我修改了代码,目前它支持10个过滤器。我的问题是,视频文件在GPUImageView中播放,现在我选择另一个过滤器。突然间,视频效果也在变化。但那个视频是从一开始就开始的。我想为当前正在播放的视频动态更改过滤器。 我的代码是:如何将动态视觉效果添加到iOS中运行的视频?

#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]; 
} 

请帮我解决这个问题。

+2

为什么重新运行'[self getVideo:movieURL];'每次更改过滤器设置?当然,这会重新启动您的视频。只需更改过滤器属性或换出过滤器,而无需重新生成电影实例。您可以轻松暂停影片,更换滤镜,然后重新开始播放动画以动态更改这些效果。 –

+0

Hi @BradLarson,首先感谢您宝贵的GPUImage框架。其实我很担心这个问题。请帮我解决这个问题。我不知道如何动态更换过滤器。您是否可以编辑上述代码并发布回答。 – Sabs

+0

@BradLarson如何暂停正在运行的电影? –

回答

0

我自己找到了答案。解决办法是,

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

} 

应用筛选

-(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]; 
} 

播放视频与影响

- (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; 
     } 

    }]; 
} 

完蛋了。现在,当我选择任何过滤器时,它会重新填满。所以内存问题解决了。现在它对我的应用程序工作正常。

+0

对于迟到的答复抱歉,并感谢您的解决方案。我只是试过你的代码,但我没有得到我的预期。每当过滤器发生变化时,我都需要恢复视频。目前它从应用每个过滤器的起点开始播放。请建议。 – QUserS

相关问题