Рендеринг видео в игровом движке с Dynami c FPS - PullRequest
2 голосов
/ 16 февраля 2020

Я пытаюсь воспроизвести предварительно экспортированное видео в моем игровом движке и наткнулся на проблемы при попытке запланировать кадры. А именно, в то время как видео экспортируется с фиксированным FPS, движок имеет динамическую частоту кадров c (которая может быть выше или ниже, чем у видео). При попытке выбрать, какой видеокадр отображать в текущем кадре движка, мои алгоритмы продолжают сталкиваться с крайними случаями, которые ухудшают либо скорость видео, либо распределение видеокадров.

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

  1. Произвольная стабильная частота кадров в двигатель с погрешностью ~ 5%. (Например, если среднее время кадра составляет 33,333 мс, все длительности кадра будут находиться в диапазоне 31,6666 мс - 35 мс.)
  2. Произвольная полустабильная частота кадров, при этом <5% кадров имеют продолжительность за пределами допустимой погрешности. </li>
  3. Стабильная частота кадров, которая может измениться на другую стабильную частоту кадров при воспроизведении видео.

В этих 3 ситуациях должно выполняться следующее:

  1. При наблюдении в течение произвольного периода времени скорость рендеринга видео совпадает со скоростью, с которой видео будет воспроизводиться с исходным FPS.
  2. При наблюдении в течение произвольного периода времени, в течение которого двигатель имел стабильную частоту кадров, распределение кадров должно быть сбалансированным.

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

  1. Действительно наивное решение, в котором дельта-время текущего кадра умножается на частоту кадров, результат округляется, и воспроизведение видео увеличивается на такое количество кадров. Хотя это решение отлично работает на некоторых частотах кадров, разница в скорости слишком велика для других. Например, если скорость видео составляет 60 кадров в секунду, а движок воспроизводится со скоростью 30 кадров в секунду, каждый кадр движка будет улучшать воспроизведение видео на 2 кадра, что идеально. Однако даже при ~ 39 FPS из-за эффекта округления воспроизведение все равно будет продвигаться только на 2 кадра в каждом кадре движка, что приводит к снижению скорости видео.
  2. Решение на основе временной шкалы, где мы отслеживаем накопленную продолжительность всех предыдущих кадров двигателя. Суммируя это и длительность текущего кадра движка, затем округляя его до ближайшего кратного длительности видеокадра, мы получаем приблизительный видеокадр, который должен отображаться в движке. Это решение идеально уравновешивает скорость видео, но есть много крайних случаев, когда распределение кадров становится очень несбалансированным, что приводит к заиканию в видео. Используя тот же пример, что и ранее, с видео со скоростью 60FPS и двигателем со скоростью 30FPS, есть крайний случай, когда один кадр с длительностью ~ 41,66666 мс приведет к ситуации, когда видеокадры будут продвинуты как (1, 3, 1, 3, 1, 3 ....) вместо (2, 2, 2, 2, 2, 2 ...).

Наверное, мои вопросы: есть ли проблема с известными алгоритмами и эвристика, которая может быть сведена к этому? Если нет, есть ли хороший heuristi c, который даст лучшие результаты в 3 ситуациях, которые я описал выше?

Ответы [ 2 ]

1 голос
/ 16 февраля 2020

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

Для каждого выбора кадра мы могли бы рассмотреть два вида ошибок. Пусть w будет разницей между временем настенных часов, когда будет отображаться выбранный кадр, и временем, когда оно должно показывать в соответствии с частотой кадров видео. Пусть d будет ошибкой в ​​разнице между временем показа выбранного кадра и ранее показанного кадра.

Определите относительные веса A и B из этих ошибок, а затем выберите кадр, который минимизирует Aw 2 + Bd 2

0 голосов
/ 17 февраля 2020

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

Таким образом, 1, 3, 1, 3, 1, 3 ... даст 2, 2, 2, 2, 2 ... и 2, 3, 2, 3, 2, 3 будут производить 2, 3, 2, 3, 2 ... и т. Д. c

псевдокод:

int prevValue = 0
int error = 0;
bool firstValue = true;
int getNextValue(int value)
{
    if(firstValue)
    {
        prevValue = value;
        firstValue = false;
    }
    int sum = value + prevValue + error;
    error = sum % 2; 
    prevValue = value;
    return sum / 2; // integer division
}
...