2014-04-08 73 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

相關問題