[FFmpeg-devel] [PATCH] vf_fps: when reading EOF, using current_pts to duplicate the last frame if needed.

Thomas Mundt tmundt75 at gmail.com
Tue Sep 12 03:01:39 EEST 2017


Hi Thierry,

2017-09-11 23:00 GMT+02:00 Thierry Foucu <tfoucu at gmail.com>:

> Fix ticket #2674
> Tested with examples from ticket 2674.
> ---
>  libavfilter/vf_fps.c        | 40 +++++++++++++++++++++++++++++++++++-----
>  tests/ref/fate/filter-fps   |  6 ++++++
>  tests/ref/fate/filter-fps-r |  4 ++++
>  tests/ref/fate/m4v-cfr      |  1 -
>  4 files changed, 45 insertions(+), 6 deletions(-)
>
> diff --git a/libavfilter/vf_fps.c b/libavfilter/vf_fps.c
> index 20ccd797d1..c0d68d8972 100644
> --- a/libavfilter/vf_fps.c
> +++ b/libavfilter/vf_fps.c
> @@ -34,6 +34,8 @@
>  #include "libavutil/opt.h"
>  #include "libavutil/parseutils.h"
>
> +#define FF_INTERNAL_FIELDS 1
> +#include "framequeue.h"
>  #include "avfilter.h"
>  #include "internal.h"
>  #include "video.h"
> @@ -137,13 +139,41 @@ static int request_frame(AVFilterLink *outlink)
>              AVFrame *buf;
>
>              av_fifo_generic_read(s->fifo, &buf, sizeof(buf), NULL);
> -            buf->pts = av_rescale_q(s->first_pts,
> ctx->inputs[0]->time_base,
> -                                    outlink->time_base) + s->frames_out;
> +            if (av_fifo_size(s->fifo)) {
> +                buf->pts = av_rescale_q(s->first_pts,
> ctx->inputs[0]->time_base,
> +                                        outlink->time_base) +
> s->frames_out;
>
> -            if ((ret = ff_filter_frame(outlink, buf)) < 0)
> -                return ret;
> +                if ((ret = ff_filter_frame(outlink, buf)) < 0)
> +                    return ret;
>
> -            s->frames_out++;
> +                s->frames_out++;
> +            } else {
> +                /* This is the last frame, we may have to duplicate it to
> match
> +                 * the last frame duration */
> +                int j;
> +                int delta = av_rescale_q_rnd(ctx->inputs[0]->current_pts
> - s->first_pts,
> +                                             ctx->inputs[0]->time_base,
> +                                             outlink->time_base,
> s->rounding) - s->frames_out ;
> +                if (delta > 0 ) {
> +                    for (j = 0; j < delta; j++) {
> +                        AVFrame *dup = av_frame_clone(buf);
> +
> +                        av_log(ctx, AV_LOG_DEBUG, "Duplicating frame.\n");
> +                        dup->pts = av_rescale_q(s->first_pts,
> ctx->inputs[0]->time_base,
> +                                                outlink->time_base) +
> s->frames_out;
> +
> +                        if ((ret = ff_filter_frame(outlink, dup)) < 0)
> +                            return ret;
> +
> +                        s->frames_out++;
>
Duplicated frames are reported to verbose log by the dup variable.
You need to insert something like if(j) s->dup++ here.
Otherwise the log becomes wrong, as in the 48fps example:
Parsed_fps_0 @ 0x34ea4a0] 24 frames in, 48 frames out; 0 frames dropped,
23 frames duplicated.

Anyway, the conversion results are accurate now for any sample I tested.
Thanks.


More information about the ffmpeg-devel mailing list