[FFmpeg-devel] [PATCH] lavfi/fps: rescale input PTS immediately.
Nicolas George
george at nsup.org
Sat Jan 25 19:37:58 CET 2014
Keeping it in its original time base leads to more complex code
and systematic rounding errors.
Also change default rounding direction: rounding down is more
logical, rounding up was a workaround for the systematic errors.
Fix trac ticket #3329 and part of #2674.
Signed-off-by: Nicolas George <george at nsup.org>
---
libavfilter/vf_fps.c | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
The 24->48 part of #2674 is due to the lack of frame duration or EOF PTS.
I intend to propose an API that will allow, amongst other things, EOF PTS.
This code also has a lot of room for improvement. Amongst other things:
* Use AV_OPT_TYPE_DURATION for start_time and get rid of floating-point
arithmetic.
* Keep the first frame separately from the FIFO.
diff --git a/libavfilter/vf_fps.c b/libavfilter/vf_fps.c
index e6266cc..c835e7b 100644
--- a/libavfilter/vf_fps.c
+++ b/libavfilter/vf_fps.c
@@ -65,7 +65,7 @@ typedef struct FPSContext {
static const AVOption fps_options[] = {
{ "fps", "A string describing desired output framerate", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, { .str = "25" }, .flags = V|F },
{ "start_time", "Assume the first PTS should be this value.", OFFSET(start_time), AV_OPT_TYPE_DOUBLE, { .dbl = DBL_MAX}, -DBL_MAX, DBL_MAX, V },
- { "round", "set rounding method for timestamps", OFFSET(rounding), AV_OPT_TYPE_INT, { .i64 = AV_ROUND_NEAR_INF }, 0, 5, V|F, "round" },
+ { "round", "set rounding method for timestamps", OFFSET(rounding), AV_OPT_TYPE_INT, { .i64 = AV_ROUND_DOWN }, 0, 5, V|F, "round" },
{ "zero", "round towards 0", OFFSET(rounding), AV_OPT_TYPE_CONST, { .i64 = AV_ROUND_ZERO }, 0, 5, V|F, "round" },
{ "inf", "round away from 0", OFFSET(rounding), AV_OPT_TYPE_CONST, { .i64 = AV_ROUND_INF }, 0, 5, V|F, "round" },
{ "down", "round towards -infty", OFFSET(rounding), AV_OPT_TYPE_CONST, { .i64 = AV_ROUND_DOWN }, 0, 5, V|F, "round" },
@@ -141,8 +141,7 @@ 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;
+ buf->pts = s->first_pts + s->frames_out;
if ((ret = ff_filter_frame(outlink, buf)) < 0)
return ret;
@@ -177,6 +176,10 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
int64_t delta;
int i, ret;
+ if (buf->pts != AV_NOPTS_VALUE)
+ buf->pts = av_rescale_q_rnd(buf->pts, inlink->time_base,
+ outlink->time_base, s->rounding);
+
s->frames_in++;
/* discard frames until we get the first timestamp */
if (s->pts == AV_NOPTS_VALUE) {
@@ -189,10 +192,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
double first_pts = s->start_time * AV_TIME_BASE;
first_pts = FFMIN(FFMAX(first_pts, INT64_MIN), INT64_MAX);
s->first_pts = s->pts = av_rescale_q(first_pts, AV_TIME_BASE_Q,
- inlink->time_base);
- av_log(ctx, AV_LOG_VERBOSE, "Set first pts to (in:%"PRId64" out:%"PRId64")\n",
- s->first_pts, av_rescale_q(first_pts, AV_TIME_BASE_Q,
- outlink->time_base));
+ outlink->time_base);
+ av_log(ctx, AV_LOG_VERBOSE, "Set first pts to %"PRId64"\n",
+ s->first_pts);
} else {
s->first_pts = s->pts = buf->pts;
}
@@ -211,8 +213,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
}
/* number of output frames */
- delta = av_rescale_q_rnd(buf->pts - s->pts, inlink->time_base,
- outlink->time_base, s->rounding);
+ delta = buf->pts - s->pts;
if (delta < 1) {
/* drop the frame and everything buffered except the first */
@@ -254,8 +255,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
s->dup++;
}
- buf_out->pts = av_rescale_q(s->first_pts, inlink->time_base,
- outlink->time_base) + s->frames_out;
+ buf_out->pts = s->first_pts + s->frames_out;
if ((ret = ff_filter_frame(outlink, buf_out)) < 0) {
av_frame_free(&buf);
@@ -267,7 +267,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
flush_fifo(s->fifo);
ret = write_to_fifo(s->fifo, buf);
- s->pts = s->first_pts + av_rescale_q(s->frames_out, outlink->time_base, inlink->time_base);
+ s->pts = s->first_pts + s->frames_out;
return ret;
}
--
1.8.5.2
More information about the ffmpeg-devel
mailing list