GPUImageMovieWriter представление кадраВремя

У меня есть GPUImageColorDodgeBlend фильтр с двумя подключенными входами:

  1. GPUImageVideoCamera который получает кадры с видеокамеры iPhone.
  2. GPUImageMovie который представляет собой видеофайл (MP4), который я хочу поместить поверх прямой трансляции с камеры.

GPUImageColorDodgeBlend Затем подключается к двум выходам:

  1. GPUImageImageView обеспечить живой предварительный просмотр смеси в действии.
  2. GPUImageMovieWriter записать фильм в хранилище после нажатия кнопки записи.

Теперь, до начала записи видео, все работает нормально 100% времени. GPUImageVideo отлично сочетается с видеоизображением с камеры в реальном времени, и никаких проблем или предупреждений не поступает.

Тем не менее, когда GPUImageMovieWriter начинает запись, вещи начинают работать неправильно в случайном порядке. Примерно в 80-90% случаев GPUImageMovieWriter работает отлично, ошибок и предупреждений нет и выводимое видео записано правильно.

Тем не менее, примерно в 10-20% случаев (и из того, что я вижу, это довольно случайно), во время записи, кажется, что-то идет не так (хотя предварительный просмотр на экране продолжает работать нормально).

В частности, я начинаю получать сотни и сотни Program appending pixel buffer at time: ошибки.

Эта ошибка происходит от - (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex метод в GPUImageWriter,

Эта проблема вызвана проблемами с frameTime значения, которые сообщаются этому методу.

Из того, что я вижу, проблема вызвана тем, что устройство записи иногда получает кадры, пронумерованные видеокамерой (которые обычно имеют очень высокие значения времени, например 64616612394291, со шкалой времени 1000000000). Но иногда писатель получает кадры, пронумерованные GPUImageMovie которые пронумерованы намного ниже (например, 200200 со шкалой времени 30000).

Кажется, что GPUImageWriter счастлив, пока значения кадра увеличиваются, но как только значение кадра уменьшается, оно прекращает запись и просто выдает Program appending pixel buffer at time: ошибки.

Я, кажется, делаю что-то довольно распространенное, и об этом нигде не сообщалось как об ошибке, поэтому мои вопросы таковы (ответы на любые или на все из них приветствуются - на них не обязательно обязательно отвечать последовательно как отдельные вопросы):

  • Где сделать frameTime значения берутся - почему это так произвольно, frameTime нумеруется в соответствии с GPUImageVideoCamera источник или GPUImageMovie источник? Почему между ними существует альтернатива - не должна ли схема нумерации кадров быть одинаковой по всем кадрам?

  • Правильно ли я считаю, что эта проблема вызвана frameTimes?

  • ... если так, то почему GPUImageView принять и отобразить frameTimeS просто отлично на экране 100% времени, пока GPUImageMovieWriter требует их заказать?

  • ... и если да, как я могу гарантировать, что frameTimes, которые входят, действительны? Я пытался добавить if (frameTime.value < previousFrameTime.value) return; пропустить любые кадры с меньшими номерами, которые работают - большую часть времени. К сожалению, когда я установил playsAtActualSpeed на GPUImageMovie это имеет тенденцию становиться намного менее эффективным, поскольку все кадры в конечном итоге пропускаются после определенного момента.

...или, возможно, это ошибка, и в этом случае мне нужно будет сообщить об этом на GitHub - но мне было бы интересно узнать, есть ли здесь что-то, что я упустил из виду, как frameTimeс работой.

1 ответ

Решение

Я нашел потенциальное решение этой проблемы, которое я реализовал как хакерский, но, возможно, можно расширить до правильного решения.

Я проследил источник времени до GPUImageTwoInputFilter который по существу мультиплексирует два входных источника в один выход кадров.

В методе - (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndexфильтр ждет, пока не соберет кадр из первого источника (textureInput == 0) и второй, а затем направляет эти кадры к своим целям.

Проблема (на мой взгляд) в том, что метод просто использует frameTime какой кадр идет вторым (исключая случаи неподвижных изображений, для которых CMTIME_IS_INDEFINTE(frameTime) == YES что я не рассматриваю сейчас, потому что я не работаю с неподвижными изображениями), которые не всегда могут быть в одном кадре (по какой-либо причине).

Соответствующий код, который проверяет оба кадра и отправляет их на обработку, выглядит следующим образом:

  if ((hasReceivedFirstFrame && hasReceivedSecondFrame) || updatedMovieFrameOppositeStillImage)
    {
        [super newFrameReadyAtTime:frameTime atIndex:0]; // this line has the problem
        hasReceivedFirstFrame = NO;
        hasReceivedSecondFrame = NO;
    }

То, что я сделал, настроил приведенный выше код для [super newFrameReadyAtTime:firstFrameTime atIndex:0] так что он всегда использует frameTime с первого входа и полностью игнорирует frameTime со второго входа. Пока все работает нормально, вот так. (Было бы еще интересно, чтобы кто-нибудь дал мне знать, почему это написано так, учитывая, что GPUImageMovieWriter кажется настаивает на увеличении frameTimes, который метод как есть не гарантирует.)

Предостережение: это почти наверняка сломается полностью, если вы работаете только с неподвижными изображениями, в этом случае у вас будет CMTIME_IS_INDEFINITE(frameTime) == YES для вашего первого входаframeTime,

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