Это достигается путем изменения масштаба отметки времени из входной временной базы (т. Е. FPS в виде дроби, например, 24 кадра в секунду станет 1/24) в выходную временную базу.
Сначала устанавливается временная база на основе запрошенного FPS:
link->time_base = av_inv_q(s->framerate);
При фильтрации количество выходных кадров рассчитывается на основе количества входных кадров в буфере, масштабируя это число между двумя временными базами, так что в основном кадры × ввод / вывод. Обратите внимание, что buf->pts - s->first_pts
видимому, представляет собой количество кадров, а не фактическую разницу во времени PTS.
/* number of output frames */
delta = av_rescale_q_rnd(buf->pts - s->first_pts, inlink->time_base,
outlink->time_base, s->rounding) - s->frames_out ;
Так, например, при временной базе ввода 0,042 (24 кадра в секунду), выходе 0,33 (3 кадра в секунду), и у вас есть 12 кадров ввода в буфере, вы получите 12 × 0,042 / 0,33 кадра, который округляется до ближайшего ближайшего целое число 2 - таким образом, два кадра должны быть сгенерированы. Если у вас 24 кадра, вы получите, конечно, три кадра. Для 35 кадров во входном буфере вы получите четыре выходных кадра.
Если эта дельта меньше 1, кадры в буфере могут быть отброшены, поскольку в этом временном интервале кадр не требуется. Если, с другой стороны, дельта больше единицы, это количество кадров, которое необходимо вывести для входного буфера.
Для новых кадров значение PTS масштабируется на основе времени ввода и вывода:
buf_out->pts = av_rescale_q(s->first_pts, inlink->time_base,
outlink->time_base) + s->frames_out;
На практике это означает, что вам придется смотреть на PTS вашего входного видео, делать расчеты того, сколько кадров в секунду может иметь ваш вывод, а затем распределять их равномерно, отбрасывая кадры по мере необходимости. Если вы хотите быть очень точным, я бы порекомендовал отладку исходного кода с помощью нескольких тестовых видео.
Боюсь, я не могу придумать более практичного решения, чем ответ, который я опубликовал здесь недавно, в котором я объясняю, как показать PTS каждого кадра в видео, частота кадров которого была изменена:
ffmpeg -i input.mp4 -t 10 -filter:v "fps=fps=25, showinfo" -f null - 2>&1 grep pts_time | awk '{print $6}' | cut -d: -f2
Эти временные метки принадлежат каждому выходному кадру и соответствующему ему входному времени PTS.