[FFmpeg-devel] [Patch] New filter -- dejudder
Lukasz Marek
lukasz.m.luki at gmail.com
Wed Jan 29 21:03:38 CET 2014
On 29.01.2014 18:52, Nicholas Robbins wrote:
> This filter removes the judder introduced by -vf pullup into videos that were partially telescened.
>
>
> 0001-Adding-dejudder-filter-to-remove-judder-produced-by-.patch
>
>
> From 7f0d67bf66ba2f0ee47cd6bdde368e351e075844 Mon Sep 17 00:00:00 2001
> From: Nicholas Robbins<nickrobbins at yahoo.com>
> Date: Wed, 29 Jan 2014 12:47:44 -0500
> Subject: [PATCH] Adding dejudder filter to remove judder produced by partialy
> telescened material.
>
> Signed-off-by: Nicholas Robbins<nickrobbins at yahoo.com>
> ---
> libavfilter/Makefile | 1 +
> libavfilter/allfilters.c | 1 +
> libavfilter/vf_dejudder.c | 162 ++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 164 insertions(+)
> create mode 100644 libavfilter/vf_dejudder.c
Missing doc and change log update
You are inconsistent with spaces around =+-*/ personally I don't care
much about it, but inconsistency in commit should be fixed.
Also spaces between if/for and ( are missing.
> +typedef struct {
> + const AVClass *class;
> + int64_t *ringbuff;
> + int a,b,c,d;
Can they be more meaningful?
> + int64_t new,next;
I know this is C, but I try to not use reserved words for C++. new can
be replaced anyway with something more specific, like new_pts?
And also, new can be moved to local variable in filter_frame, and next
variable seems to be not used at all.
> + int startcount;
maybe start_count?
> +
> + /* options */
> + int cycle;
> +} DejudderContext;
> +
> +#define OFFSET(x) offsetof(DejudderContext, x)
> +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM
> +
> +static const AVOption dejudder_options[] = {
> + {"cycle", "length of cycle to use for dejuddering",
I'm not native speaker so I may be wrong, but "length of the cycle"
seems more natural to me.
> + OFFSET(cycle), AV_OPT_TYPE_INT, {.i64 = 4}, 2, 240, .flags = FLAGS},
> + {NULL}
> +};
> +
> +AVFILTER_DEFINE_CLASS(dejudder);
> +
> +static int config_out_props(AVFilterLink *outlink)
> +{
> + AVFilterContext *ctx = outlink->src;
> + DejudderContext *dj = ctx->priv;
> + AVFilterLink *inlink = outlink->src->inputs[0];
> +
> + outlink->time_base =av_mul_q(inlink->time_base,av_make_q(1,2*(dj->cycle)));
> + outlink->frame_rate =av_mul_q(inlink->frame_rate,av_make_q(2*(dj->cycle),1));
> +
> + av_log(ctx, AV_LOG_VERBOSE, "%d cycle dejudder.\n", dj->cycle );
> +
> + return 0;
> +}
> +
> +
> +static av_cold int dejudder_init(AVFilterContext *ctx)
> +{
> + DejudderContext *dj = ctx->priv;
> +
> + dj->ringbuff=(int64_t *)av_mallocz(sizeof(int64_t)*(dj->cycle+2));
A cast seems to be unneeded.
> + if (!dj->ringbuff) return AVERROR(ENOMEM);
Moving return to new line makes it a bit more readable.
> +
> + dj->new=0;
> + dj->a=0;
> + dj->b=1;
> + dj->c=2;
> + dj->d=3;
> + dj->startcount=dj->cycle+2;
> +
> + return 0;
> +}
> +
> +
> +static av_cold void dejudder_uninit(AVFilterContext *ctx)
> +{
> + DejudderContext *dj = ctx->priv;
> +
> + av_freep(&(dj->ringbuff));
> +}
> +
> +
> +
no need to make 3 lines break.
> +static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
> +{
> + int i;
> + AVFilterContext *ctx = inlink->dst;
> + AVFilterLink *outlink = ctx->outputs[0];
> + DejudderContext *dj = ctx->priv;
> + int64_t *judbuff = dj->ringbuff;
> + int64_t next, offset;
> +
> +
> + next = frame->pts;
> +
> + if( dj->startcount ){
> + (dj->startcount)--;
> + dj->new = next*2*dj->cycle;
> + } else {
> + if(next<judbuff[dj->b]){
> + offset = next+judbuff[dj->c]-judbuff[dj->d]-judbuff[dj->a];
> + for(i=0;i<dj->cycle+2;i++) judbuff[i] += offset;
> + }
> + dj->new += (dj->cycle-1)*( judbuff[dj->c] - judbuff[dj->a] )
> + + (dj->cycle+1)*( next - judbuff[dj->d] ) ;
> + }
> +
> + judbuff[dj->b] = next;
> + dj->a=dj->b;
> + dj->b=dj->c;
> + dj->c=dj->d;
> + dj->d = (dj->d+1) % (dj->cycle+2);
> +
> + frame->pts = dj->new;
> +
> + for(i=0;i<dj->cycle+2;i++) av_log(ctx, AV_LOG_DEBUG, "%"PRId64"\t", judbuff[i]);
move av_log to new line.
> + av_log(ctx, AV_LOG_DEBUG, "next=%"PRId64", new=%"PRId64"\n", next, frame->pts);
> +
> + return ff_filter_frame(outlink, frame);
> +}
> +
> +
> +static const AVFilterPad dejudder_inputs[] = {
> + {
> + .name = "default",
> + .type = AVMEDIA_TYPE_VIDEO,
> + .filter_frame = filter_frame,
> + },
> + { NULL }
> +};
> +
> +static const AVFilterPad dejudder_outputs[] = {
> + {
> + .name = "default",
> + .type = AVMEDIA_TYPE_VIDEO,
> + .config_props = config_out_props,
> + },
> + { NULL }
> +};
> +
> +AVFilter ff_vf_dejudder = {
> + .name = "dejudder",
> + .description = NULL_IF_CONFIG_SMALL("Remove judder produced by pullup"),
> + .priv_size = sizeof(DejudderContext),
> + .priv_class = &dejudder_class,
> + .inputs = dejudder_inputs,
> + .outputs = dejudder_outputs,
> + .init = dejudder_init,
> + .uninit = dejudder_uninit,
> +};
I don't know filters API nor algorithm so can review at this point of view.
--
Best Regards,
Lukasz Marek
Microsoft isn't evil, they just make really crappy operating systems. -
Linus Torvalds
More information about the ffmpeg-devel
mailing list