Dies geschieht durch die Neuskalierung von Zeitstempelwerten von der Eingabezeitbasis (dh FPS als Bruchwert, z. B. 24 fps würde 1/24), zur Ausgabezeitbasis.
Zuerst wird die Zeitbasis basierend auf der angeforderten FPS festgelegt:
link->time_base = av_inv_q(s->framerate);
Beim Filtern wird die Anzahl der Ausgangsframes basierend auf der Anzahl der Eingangsframes im Puffer berechnet, wobei diese Anzahl zwischen den beiden Zeitbasen skaliert wird, also im Grunde Frames × Input / Output . Beachten Sie, dass es sich buf->pts - s->first_pts
offensichtlich um eine Anzahl von Frames handelt, nicht um einen tatsächlichen Unterschied in der PTS-Zeit.
/* 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 ;
Wenn die Eingabezeitbasis beispielsweise 0,042 (24 fps) und der Ausgang 0,33 (3 fps) beträgt und Sie 12 Eingabefelder im Puffer haben, erhalten Sie 12 × 0,042 / 0,33- Frames, die auf die nächsten gerundet werden Integer 2 - also sollen zwei Frames erzeugt werden. Wenn Sie 24 Frames haben, erhalten Sie natürlich drei Frames. Für 35 Frames im Eingangspuffer erhalten Sie vier Output-Frames.
Wenn dieses Delta kleiner als 1 ist, können die Frames im Puffer gelöscht werden, da in diesem Zeitraum kein Frame benötigt wird. Wenn andererseits das Delta größer als eins ist, muss die Anzahl der Frames für den Eingangspuffer ausgegeben werden.
Bei neuen Frames wird der PTS-Wert basierend auf den Zeitbasen der Eingabe und Ausgabe skaliert:
buf_out->pts = av_rescale_q(s->first_pts, inlink->time_base, outlink->time_base) + s->frames_out;
In der Praxis bedeutet dies, dass Sie sich das PTS Ihres Eingangsvideos ansehen müssen, wie viele Frames pro Sekunde Ihre Ausgabe haben kann, und diese dann gleichmäßig verteilen, indem Sie Frames je nach Bedarf löschen. Wenn Sie extrem präzise sein möchten, würde ich empfehlen, den Quellcode mit ein paar Testvideos zu debuggen.
Ich fürchte, ich kann keine praktischere Lösung finden als die Antwort, die ich vor kurzem hier gepostet habe und in der ich erkläre, wie der PTS jedes Frames in einem Video gezeigt wird, dessen Framerate geändert wurde:
ffmpeg -i input.mp4 -t 10 -filter:v "fps=fps=25, showinfo" -f null - 2>&1 grep pts_time | awk '' | cut -d: -f2
Diese Zeitstempel gehören zu jedem Ausgangsrahmen und seiner entsprechenden PTS-Eingangszeit.