4

Thank you for seeing this question.

I create a movie from GPUImageMovieComposition and GPUImageWriter, and sometimes (5% ~ 10 %) the movie has red frames at the beginning.

Please teach me why this phenomenon occur.

I use AVFileTypeMPEG4 as a sample filetype but AVFileTypeQuickTimeMovie is also same.

_movieFile = [[GPUImageMovieComposition alloc] initWithComposition:composition andVideoComposition:videoComposition andAudioMix:nil];
_movieFile.playAtActualSpeed = YES;

_movieWriter = [[GPUImageMovieWriter alloc] initWithMovieURL:processedMovieURL
                                                        size:CGSizeMake(1280.0, 720.0)
                                                    fileType:AVFileTypeMPEG4
                                              outputSettings:videoSetting];
_movieWriter.shouldPassthroughAudio = NO;
[_movieWriter setVideoInputReadyCallback:nil];
[_movieWriter setHasAudioTrack:YES audioSettings:audioSetting];
[_movieFile addTarget:_movieWriter];
_movieFile.audioEncodingTarget = _movieWriter;
[_movieFile enableSynchronizedEncodingUsingMovieWriter:_movieWriter];    

[_movieWriter startRecording];
[_movieFile startProcessing];

SOLUTION

Finally I could find the way to solve... but not perfect way...

I modified
- (void)processMovieFrame:(CVPixelBufferRef)movieFrame withSampleTime:(CMTime)currentSampleTime
at GPUImageMovie.m little bit.

When currentSampleTime is set, all red frame has currentSampleTime.value == 0 so I avoided setting currentSampleTime when currentSampleTime.value == 0

Here are some codes which I actually used.

 for (id<GPUImageInput> currentTarget in targets)
  {
       NSInteger indexOfObject = [targets indexOfObject:currentTarget];
       NSInteger targetTextureIndex = [[targetTextureIndices objectAtIndex:indexOfObject] integerValue];
       if(currentSampleTime.value != 0){
           [currentTarget newFrameReadyAtTime:currentSampleTime atIndex:targetTextureIndex];
       }
   }
4

2 回答 2

2

在我的情况下,由GPUImageMovieWriter录制的视频的开头不是红色而是空白帧

问题是音频样本出现得更早,然后视频帧和assetWriter 会话开始更早,然后第一个视频帧变得可用。

我已经通过替换此代码来修改processAudioBuffer函数来解决这个问题

if (CMTIME_IS_INVALID(startTime))
{
  runSynchronouslyOnContextQueue(_movieWriterContext, ^{
    if ((audioInputReadyCallback == NULL) && (assetWriter.status != AVAssetWriterStatusWriting))
    {
      [assetWriter startWriting];
    }
    [assetWriter startSessionAtSourceTime:currentSampleTime];
    startTime = currentSampleTime;
  });
}

在这

if (CMTIME_IS_INVALID(startTime))
{
  NSLog(@"0: Had to drop an audio frame: %@", CFBridgingRelease(CMTimeCopyDescription(kCFAllocatorDefault, currentSampleTime)));
  if (_shouldInvalidateAudioSampleWhenDone)
  {
    CMSampleBufferInvalidate(audioBuffer);
  }
  CFRelease(audioBuffer);
  return;
}

该修复适用于 2014 年 5 月 27 日至 7 月 1 日期间的最新版本 GPUImage。

于 2014-07-07T05:16:54.553 回答
1

到目前为止,我发现的唯一让我摆脱这个问题的解决方案是恢复提交 e98cc813b。我通过使用git bisect并在同一视频上执行批量处理测试来解决这个问题。这个提交已经具备了我的项目所需的所有功能,并且只需要进行少量更改即可使其更加稳定。您可以在此处查看更改:https ://github.com/crazyjooe/GPUImage 。

此外,经过大量测试,我可以说处理本身变得更加稳定,尤其是在取消方面。我想知道在引入所有更改之后,视频处理如何变得不那么可靠和稳定。

于 2014-05-14T19:21:57.693 回答