Видео от GPUImageMovie имеет красную рамку в начале

Спасибо за просмотр этого вопроса.

Я создаю фильм из GPUImageMovieComposition и GPUImageWriter, и иногда (5% ~ 10 %) фильм имеет красные рамки в начале.

Пожалуйста, научите меня, почему это явление происходит.

Я использую AVFileTypeMPEG4 в качестве образца файла, но AVFileTypeQuickTimeMovie также является тем же.

_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];

РЕШЕНИЕ

Наконец-то я смог найти способ решить... но не идеальный способ...

Я модифицировал
- (void)processMovieFrame:(CVPixelBufferRef)movieFrame withSampleTime:(CMTime)currentSampleTime
в GPUImageMovie.m немного.

когда currentSampleTime установлена, вся красная рамка имеет currentSampleTime.value == 0поэтому я избегал настройки currentSampleTime когда currentSampleTime.value == 0

Вот несколько кодов, которые я на самом деле использовал.

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

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

Это исправление применимо к последним версиям GPUImage с 27 мая по 01 июля 2014 года.

Единственное найденное мной решение, которое спасло меня от этой проблемы, - это возврат к фиксации e98cc813b. Я понял это, используя git bisect и выполняя серию тестов обработки на том же видео. Этот коммит уже имел все необходимые функциональные возможности для моего проекта, и для его стабильности потребовалось всего несколько изменений. Вы можете посмотреть изменения здесь: https://github.com/crazyjooe/GPUImage.

Кроме того, после большого количества испытаний я могу сказать, что сама обработка стала намного более стабильной, особенно с точки зрения отмены. Интересно, как обработка видео стала менее надежной и стабильной после всех внесенных изменений.

Другие вопросы по тегам