[FFmpeg-devel] [PATCH] Complete rewrite of the "fps" video filter section. More accurate.

list+ffmpeg-dev at jdlh.com list+ffmpeg-dev at jdlh.com
Mon Apr 27 09:17:47 EEST 2020

From: Jim DeLaHunt <from+ffmpeg-dev at jdlh.com>

This is a complete rewrite of the documentation for the "fps" video
filter. It describes the filter's behaviour more clearly and accurately.
I based the rewrite on reading the source code in vf_fps.c closely.

No code, or other documentation files, are touched by this change.

Signed-off-by: Jim DeLaHunt <from+ffmpeg-dev at jdlh.com>
 doc/filters.texi | 167 ++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 149 insertions(+), 18 deletions(-)

diff --git a/doc/filters.texi b/doc/filters.texi
index 71a6787289..bd4a1ad2a9 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -11139,27 +11139,34 @@ format=pix_fmts=yuv420p|yuv444p|yuv410p
 @section fps
-Convert the video to specified constant frame rate by duplicating or dropping
-frames as necessary.
+Generate a video, having the specified constant frame rate, from the frames of 
+the input video, by copying or duplicating or dropping input frames based on 
+their input presentation time stamps (PTSs). The output video has new PTSs. You 
+can choose the method for rounding from input PTS to output PTS. 
 It accepts the following parameters:
 @table @option
 @item fps
-The desired output frame rate. The default is @code{25}.
+The output frame rate, as a number of frames per second. This value can be an 
+integer, real, or rational number, or an abbreviation. The default is @code{25}.
 @item start_time
-Assume the first PTS should be the given value, in seconds. This allows for
-padding/trimming at the start of stream. By default, no assumption is made
-about the first frame's expected PTS, so no padding or trimming is done.
-For example, this could be set to 0 to pad the beginning with duplicates of
-the first frame if a video stream starts after the audio stream or to trim any
-frames with a negative PTS.
+The time, in seconds from the start of the input stream, which is converted to 
+an input starting PTS value and an output starting PTS value. 
+If set, @var{fps} drops input frames
+which have PTS values less than the input starting PTS. If not set, the input 
+and output starting PTS values are zero, but @var{fps} drops no input frames based 
+on PTS. 
+(See details below.)
 @item round
-Timestamp (PTS) rounding method.
+Rounding method to use when calculating output Presentation Timestamp 
+(PTS) integer values from input PTS values. If the calculated output PTS value
+is not exactly an integer, then the method determines which of the two 
+neighbouring integer values to choose.
-Possible values are:
+Possible method names are:
 @table @option
 @item zero
 round towards 0
@@ -11170,43 +11177,167 @@ round towards -infinity
 @item up
 round towards +infinity
 @item near
-round to nearest
+round to nearest (and if exactly at midpoint, away from 0)
 @end table
 The default is @code{near}.
 @item eof_action
-Action performed when reading the last frame.
+Action which @var{fps} takes with the final input frame. The input video passes
+in an ending input PTS, which @var{fps} converts to an ending output PTS. 
+ at var{fps} drops any input frames with a PTS at or after this ending PTS.
 Possible values are:
 @table @option
 @item round
-Use same timestamp rounding method as used for other frames.
+Use same rounding method as for other frames, to convert the ending input PTS
+to output PTS.
 @item pass
-Pass through last frame if input duration has not been reached yet.
+Round the ending input PTS using @code{up}. This can have the effect of passing
+through one last input frame. 
 @end table
 The default is @code{round}.
 @end table
-Alternatively, the options can be specified as a flat string:
+Alternatively, the options may be specified as a flat string:
+ at var{fps} generates an output video with integer Presentation Time Stamp (PTS) 
+values which increment by one each output frame, and with a time base set to 
+the inverse of the given frame rate. @var{fps} copies, duplicates, or drops 
+input frames, in sequence, to the output video. It does so according to their 
+input PTS values, as converted to seconds (via the input time base), then 
+rounded to output PTS values. 
+ at var{fps} sets output PTS values in terms of a time line which starts at
+zero. The integer PTS value multipled by the output time base gives a point 
+in seconds of that output frame on that timeline. If the @var{start_time} 
+parameter is not set, or is zero, the first output frame's PTS value is zero. 
+Otherwise, the first PTS value is the output starting PTS value calculated
+from the @var{start_time} parameter. 
+ at var{fps} interprets input PTS values in terms of the same time line. It 
+multiplies the input PTS value by the input time base time, to get a frame 
+position in seconds on the time line. It rounds that position to an integer 
+output PTS value. For example, if the input video has a frame rate
+of 30 fps, a time base of 1/30 seconds, and its first frame has a 
+PTS of 300, then @var{fps} treats that frame as occurring 10 seconds (300 * 1/30 
+seconds) after the start of the video, even though it is the first frame.
+Setting a @code{start_time} value allows for padding/trimming at the 
+start of stream. For example, @code{start_time} could be set to 0 to pad the 
+beginning with duplicates of the first frame if a video stream starts after 
+the audio stream or to trim any frames with a negative PTS. When 
+ at code{start_time} is not set, the @var{fps} filter makes no assumption about 
+the first frame's expected PTS, and does not pad or trim input frames which 
+have a PTS set.
 See also the @ref{setpts} filter.
+ at subsection Details
+ at var{fps} emits exactly one frame for each output PTS value. If there is 
+exactly one input frame with an input PTS which converts to the current output 
+PTS value, @var{fps} emits that frame. If there are multiple frames which 
+convert to the same output PTS value, @var{fps} emits the final frame of that 
+group, and drops the previous frames. If no input frame PTS converts to a given 
+output PTS value, @var{fps} emits another copy of the previously emitted frame. 
+When the first input frame converts to an output PTS after the first frame, then 
+ at var{fps} emits copies of that first frame until the output PTS reaches the 
+converted value of that first frame's input PTS. 
+ at var{fps} always drops input frames which have no PTS value set, regardless
+of the @var{start_time} parameter. 
+The @var{frame rate} value may be provided in a variety of forms. Each form is
+converted into a rational number, with an integer numerator and denominator. 
+Each value must be zero or greater.
+ at itemize
+ at item
+An integer number, e.g. @code{25}. This converts to the rational number 
+ at code{25/1}.
+ at item
+A real number, e.g. @code{3.14145926}. This converts to a rational number, 
+e.g. @code{954708/303893}
+ at item
+A rational number. The numerator and denominator may be either integers or real
+numbers. e.g. @code{30/1.001} or @code{30000/1001}, which both convert to 
+ at code{30000/1001}.
+ at item 
+An abbreviation. e.g @code{ntsc} as @code{30000/1001}, 
+ at code{ntsc-film} as @code{24000/1001}. See the complete list at 
+ at ref{Video rate,,the "Video rate" section in the ffmpeg-utils(1) manual,ffmpeg-utils}.
+ at end itemize
+ at var{fps} defines a sync point, where one input PTS value is treated as occuring
+at the same moment as one output PTS value. IT calcluates other PTS values
+as positive or negative time offsets from this sync point. 
+This affects the details of how rounding works. If @var{start_time} is set, 
+then the input and output PTS values which @var{fps} calculates from this 
+become the sync point. Otherwise, input and output PTS values of zero are 
+the sync point.
+Note that @var{fps} does not assume that input frames are separated by exactly 
+1/frame_rate seconds. It takes the input PTS values literally. If the increment 
+of PTS between frames varies along the video, fps will treat those frames as
+happening at varying time intervals. 
+As a consequence, if you have a video which is supposed to be at a certain frame 
+rate, but in reality the frames were not always captured at the exactly right 
+moment, and if the input PTS values reflect that variation, then you can pass 
+this video through an @var{fps} filter set to the same frame rate. A @var{round} 
+method of @code{near} will pass through each input frame exactly once, and 
+the output video will have new PTS values which reflect the exact time interval 
+(1/frame rate) between frames.
+Because @var{fps} treats input PTS values at face value when converting them to
+time on the time line, and because that time line starts at zero, an input 
+video with PTS values that do not start at zero might yield unexpected results.
+Suppose the input PTS values start with the value 300, which converts to 10
+seconds after the sync point. Then @var{fps} will repeat the first frame of the
+input video to fill the first 10 seconds of the output video. (However, 
+ at command{ffmpeg} may suppress those repeated frames, depending on the 
+ at option{-vsync} setting.) If you set @var{start_time} to 10 seconds, then 
+ at var{fps} sets the sync point to the PTS values converted from the 10 second 
+moment on the time line. It no longer repeats the first frame. And, it starts 
+the output PTS at the value corresponding to 10 seconds, instead of zero.
 @subsection Examples
-A typical usage in order to set the fps to 25:
+A typical usage in order to emit a video with a frame rate of 25 frames per second:
 @end example
-Sets the fps to 24, using abbreviation and rounding method to round to nearest:
+Emit a video with a frame rate of 24 frames per second, using an abbreviation, 
+and rounding method to round to nearest:
 @end example
+ at item
+If an input video is supposed to have a frame rate of 29.97 frames per second
+(NTSC standard), but the time base is 3003/90000, and the PTS values increment 
+variably at slightly more and less than that rate, this emits a video with the 
+same frames, but with a new time base and PTS values that increment at exactly 
+the NTSC rate. If some frames were dropped by the recorder, but the PTS values 
+still reflect when the remaining frames were captured, this will also repeat 
+frames to fill the gaps from the dropped frames.
+ at example
+ at end example
 @end itemize
 @section framepack

More information about the ffmpeg-devel mailing list