[FFmpeg-devel] [PATCH 2/2] libavfilter/vf_fps: Rewrite using activate callback
Calvin Walton
calvin.walton at kepstin.ca
Mon Feb 19 23:57:40 EET 2018
Just a few comments on your review:
On Sun, 2018-02-18 at 19:01 +0100, Nicolas George wrote:
> > @@ -91,31 +94,46 @@ static av_cold int init(AVFilterContext *ctx)
> > {
> > FPSContext *s = ctx->priv;
> >
> > - if (!(s->fifo = av_fifo_alloc_array(2, sizeof(AVFrame*))))
> > - return AVERROR(ENOMEM);
> > + /* Pass INT64_MIN/MAX through unchanged to avoid special cases
> > for AV_NOPTS_VALUE */
> > + s->rounding = s->rounding | AV_ROUND_PASS_MINMAX;
>
> Since rounding is exposed as an option with explicit bounds, it would
> probably be better to keep AV_ROUND_PASS_MINMAX out of the field and
> only include it when actually calling av_rescale_q_rnd().
Makes sense, easy change.
> > @@ -128,194 +146,238 @@ static int config_props(AVFilterLink* link)
> >
> > link->time_base = av_inv_q(s->framerate);
> > link->frame_rate= s->framerate;
> > - link->w = link->src->inputs[0]->w;
> > - link->h = link->src->inputs[0]->h;
>
> Looks unrelated.
I can split this into a separate cleanup patch, then.
> > +
> > + /* Convert the start time option to output timebase and save
> > it */
> > + if (s->start_time != DBL_MAX && s->start_time !=
> > AV_NOPTS_VALUE) {
> > + double first_pts = s->start_time * AV_TIME_BASE;
> > + first_pts = FFMIN(FFMAX(first_pts, INT64_MIN), INT64_MAX);
>
> It would probably better to issue an error when the value is out of
> representable range.
I'll make this a fatal error. I considered adjusting the range of
accepted values on the AVOption, but it would be tricky to get right,
with rounding issues and whatnot (and I'm not sure that using DBL_MAX
as an invalid/default value would still work).
>
> > + s->start_pts = av_rescale_q_rnd(first_pts, AV_TIME_BASE_Q,
> > + link->time_base, s->rounding);
>
> Nit: indentation.
Do you prefer the style of matching the indentation level of wrapped
parameters to the ( of the function? I can do that, I'll try to make it
consistent in the file.
> > - return ret;
> > -}
> > + ret = ff_inlink_consume_frame(inlink, &frame);
> > + /* Caller must have run ff_inlink_check_available_frame first
> > */
> > + av_assert1(ret);
>
> Negative error codes must still be checked.
Ah, took me a moment looking at this function's return values again to
understand why this was needed. I'll add the error handling code.
> > +
> > + ret = ff_filter_frame(outlink, frame);
> > + if (ret >= 0) {
> > + s->frames_out++;
> > + s->dup += dup;
> > + }
>
> Minor nit: I would rather have "if (ret < 0) return ret;" and make
> the
> incrementation unconditional.
Making the incrementation unconditional simplifies the flow quite a
bit, I'll make that change.
> > [static int void write_frame_eof()]
> This whole function seems to implement the very same logic as
> write_frame() with just s->status_pts instead of s->frames[1]->pts. It
> should be factored.
I thought about doing this, but it'll make the conditionals quite a bit
more complicated. I'll spend some time trying to figure out a better
way to handle this.
> > +static void update_eof_pts(AVFilterContext *ctx, FPSContext *s, AVFilterLink *inlink, AVFilterLink *outlink)
> > +{
> > + /* Convert status_pts to outlink timebase */
> > + int eof_rounding = (s->eof_action == EOF_ACTION_PASS) ? AV_ROUND_UP : s->rounding;
> > + s->status_pts = av_rescale_q_rnd(s->status_pts, inlink->time_base,
> > + outlink->time_base, eof_rounding);
>
> Nit: indentation. Also, I do not like the fact that s->status_pts can be
> in different time bases depending on the part of the code. I would
> prefer if ff_inlink_acknowledge_status() is used with a temp variable,
> passed as argument to update_eof_pts(), and only the s->status_pts is
> set.
This is something that was bugging me a bit as well, I'll make the
change.
> >
> > - s->frames_out++;
> > + /* Buffered frames are available, so generate an output frame */
> > + if (s->frames_count == 2 && ff_outlink_frame_wanted(outlink) >= 0) {
>
> Do not check ff_outlink_frame_wanted() here: if the filter is activated
> and can produce a frame, produce it.
Alright.
>
> > + ret = write_frame(ctx, s, outlink);
> > + /* Couldn't generate a frame: e.g. a frame was dropped */
> > + if (ret == AVERROR(EAGAIN)) {
> > + /* Schedule us to perform another step */
> > + ff_filter_set_ready(ctx, 100);
> > + return 0;
> > + }
>
> I do not like the use of EAGAIN for this. It may conflict with strange
> error codes returned by other filters. It should not happen, but it
> could. I would advice to define a specific error code for this file
> only, like FFERROR_REDO in libavformat/internal.h. Or, even better, add
> "int *again" as an extra argument to write_frame() and return the
> condition like that.
I like the solution with adding an extra return argument to the
function to keep this status separate from the error return codes. I'll
make this change.
--
Calvin Walton <calvin.walton at kepstin.ca>
More information about the ffmpeg-devel
mailing list