summaryrefslogtreecommitdiff
path: root/libavfilter/vf_fps.c
diff options
context:
space:
mode:
authorThierry Foucu <tfoucu@gmail.com>2017-09-12 18:45:57 -0700
committerMichael Niedermayer <michael@niedermayer.cc>2017-09-15 02:24:31 +0200
commiteea64ef4cfb593cbe28465f45e6bd4c41a79cae1 (patch)
treed8cb703ebb50634495f58eff0fba77aa1ddc04a4 /libavfilter/vf_fps.c
parentc6314cd750dfba2505a232cc16541395c986613a (diff)
downloadffmpeg-eea64ef4cfb593cbe28465f45e6bd4c41a79cae1.tar.gz
vf_fps: when reading EOF, using current_pts to duplicate the last frame if needed.
Fix ticket #2674 Tested with examples from ticket 2674. Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
Diffstat (limited to 'libavfilter/vf_fps.c')
-rw-r--r--libavfilter/vf_fps.c44
1 files changed, 39 insertions, 5 deletions
diff --git a/libavfilter/vf_fps.c b/libavfilter/vf_fps.c
index 20ccd797d1..09fc66a73c 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,45 @@ 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 the delta is equal to 1, it means we just need to output
+ * the last frame. Greater than 1 means we will need duplicate
+ * delta-1 frames */
+ 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++;
+ if (j > 0) s->dup++;
+ }
+ } else {
+ /* for delta less or equal to 0, we should drop the frame,
+ * otherwise, we will have one or more extra frames */
+ av_frame_free(&buf);
+ s->drop++;
+ }
+ }
}
return 0;
}