[FFmpeg-devel] port mplayer eq filter to libavfilter

Stefano Sabatini stefano.sabatini-lala
Tue Nov 23 19:18:11 CET 2010


On date Tuesday 2010-11-23 22:22:47 +0800, William Yu encoded:
> I have fix the problem mention below.
> and change to directly process the input picture.
> Please check it again.
> BTW, I had send a mail to D Richard Felker III <dalias <at> aerifal.cx>.
> If he agree relicense these under LGPL. I will patch it to LGPL. Thanks.
> 
> 2010/11/22 Stefano Sabatini <stefano.sabatini-lala at poste.it>:
> > On date Monday 2010-11-22 15:15:25 +0100, Stefano Sabatini encoded:
> >> On date Monday 2010-11-22 20:33:11 +0800, William Yu encoded:
> > [...]
> >> > +}
> >> > +
> >> > +static void end_frame(AVFilterLink *link)
> >>
> >> inlink for enhanced readability
> >>
> >> > +{
> >> > + ? ?EQContext * eq = link->dst->priv;
> >> > + ? ?AVFilterBufferRef *in ?= link->cur_buf;
> >> > + ? ?AVFilterBufferRef *out = link->dst->outputs[0]->out_buf;
> >> > +
> >> > + ? ?eq->process(out->data[0], out->linesize[0],
> >> > + ? ? ? ?in->data[0], in->linesize[0],
> >> > + ? ? ? ?link->w, link->h, eq->brightness, eq->contrast);
> >> > + ? ?copy_chroma(in,out,link);
> >
> > Also is it really necessary to copy the chroma planes to a new frame?
> > Maybe It would be possible to directly process the input picture, no need to
> > allocate another one and to copy back the chroma planes.
> >
> > Regards.
> > --
> > FFmpeg = Fundamentalist & Free Multipurpose Portable Ecumenical God
> > _______________________________________________
> > ffmpeg-devel mailing list
> > ffmpeg-devel at mplayerhq.hu
> > https://lists.mplayerhq.hu/mailman/listinfo/ffmpeg-devel
> >

> diff --git a/Changelog b/Changelog
> index dc949cd..6a6a0c7 100644
> --- a/Changelog
> +++ b/Changelog
> @@ -59,6 +59,7 @@ version <next>:
>  - overlay filter added
>  - rename aspect filter to setdar, and pixelaspect to setsar
>  - IEC 61937 demuxer
> +- eq video filter added
>  
>  
>  version 0.6:
> diff --git a/configure b/configure
> index 7dcb50f..c076ea9 100755
> --- a/configure
> +++ b/configure
> @@ -1405,6 +1405,7 @@ udp_protocol_deps="network"
>  # filters
>  blackframe_filter_deps="gpl"
>  cropdetect_filter_deps="gpl"
> +eq_filter_deps="gpl"
>  frei0r_filter_deps="frei0r dlopen strtok_r"
>  ocv_smooth_filter_deps="libopencv"
>  yadif_filter_deps="gpl"
> diff --git a/doc/filters.texi b/doc/filters.texi
> index 1cba2d6..0a45e7b 100644
> --- a/doc/filters.texi
> +++ b/doc/filters.texi
> @@ -257,6 +257,38 @@ drawbox
>  drawbox=10:20:200:60:red@@0.5"
>  @end example
>  
> + at section eq
> +
> +Adjust brightness or contrast of the input video.

or -> and/or

> +
> +It accepts the following parameters:
> + at var{brightness}:@var{constrast}
> +
> +Negative values for the amount will descrease the corresponding value
> +for the lightness or contrast of the input video, while positive
> +values will increase the corresponding value.
> +
> + at table @option
> +
> + at item brightness
> +Set the brightness amount. It can be an integer between -100
> +and 100, default value is 0.
> +
> + at item contrast
> +Set the contrast amount. It can be an integer between -100
> +and 100, default value is 0.
> +
> + at end table
> +
> + at example
> +# increase lightness and contrast by 20 percent
> +eq=20:20
> +
> +# decrease lightness and contrast by 20 percent
> +eq=-20:-20
> +
> + at end example
> +
>  @section fifo
>  
>  Buffer input images and send them when they are requested.
> diff --git a/libavfilter/Makefile b/libavfilter/Makefile
> index 210510f..37df7ee 100644
> --- a/libavfilter/Makefile
> +++ b/libavfilter/Makefile
> @@ -23,6 +23,7 @@ OBJS-$(CONFIG_BLACKFRAME_FILTER)             += vf_blackframe.o
>  OBJS-$(CONFIG_CROP_FILTER)                   += vf_crop.o
>  OBJS-$(CONFIG_CROPDETECT_FILTER)             += vf_cropdetect.o
>  OBJS-$(CONFIG_DRAWBOX_FILTER)                += vf_drawbox.o
> +OBJS-$(CONFIG_EQ_FILTER)                     += vf_eq.o
>  OBJS-$(CONFIG_FIFO_FILTER)                   += vf_fifo.o
>  OBJS-$(CONFIG_FORMAT_FILTER)                 += vf_format.o
>  OBJS-$(CONFIG_FREI0R_FILTER)                 += vf_frei0r.o
> diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c
> index 9e3ba14..dae6848 100644
> --- a/libavfilter/allfilters.c
> +++ b/libavfilter/allfilters.c
> @@ -44,6 +44,7 @@ void avfilter_register_all(void)
>      REGISTER_FILTER (CROP,        crop,        vf);
>      REGISTER_FILTER (CROPDETECT,  cropdetect,  vf);
>      REGISTER_FILTER (DRAWBOX,     drawbox,     vf);
> +    REGISTER_FILTER (EQ,          eq,          vf);
>      REGISTER_FILTER (FIFO,        fifo,        vf);
>      REGISTER_FILTER (FORMAT,      format,      vf);
>      REGISTER_FILTER (FREI0R,      frei0r,      vf);
> diff --git a/libavfilter/eq.h b/libavfilter/eq.h
> new file mode 100644
> index 0000000..f6b98d2
> --- /dev/null
> +++ b/libavfilter/eq.h
> @@ -0,0 +1,18 @@
> +/*
> + * Ported to FFmpeg from MPlayer libmpcodecs/vf_eq.c
> + * Port copyright (C) 2010 William Yu <genwillyu at gmail dot com>

Ehm missing LGPL notice. Also I'd prefer to just use:
 * Copyright (c) 2010 William Yu <genwillyu at gmail dot com>
 * Copyright (c) 200X Richard Felker <genwillyu at gmail dot com>

so it's easier to understand which the copyright holders are. You can
mention this is a port in the @file notice of vf_eq.c.

> + *
> + * @file libavfilter/eq.h
> + */
> +
> +#ifndef AVFILTER_EQ_H
> +#define AVFILTER_EQ_H
> +
> +#include "avfilter.h"
> +
> +void ff_eq_filter_process_mmx(uint8_t *dest,
> +                              int dstride, uint8_t *src, int sstride,
> +                              int w, int h, int brightness,
> +                              int contrast);
> +
> +#endif /* AVFILTER_EQ_H */
> diff --git a/libavfilter/vf_eq.c b/libavfilter/vf_eq.c
> new file mode 100644
> index 0000000..dba556d
> --- /dev/null
> +++ b/libavfilter/vf_eq.c
> @@ -0,0 +1,138 @@
> +/*

> + * Ported to FFmpeg from MPlayer libmpcodecs/vf_eq.c
> + * Port copyright (C) 2010 William Yu <genwillyu at gmail dot com>

Same here as above.

> + *
> + * @file libavfilter/vf_eq.c
> + */
> +
> +#include "libavutil/cpu.h"
> +#include "libavutil/common.h"
> +#include "avfilter.h"
> +#include "eq.h"
> +
> +typedef struct EQContext {
> +    int brightness;         ///< scale from -100 to 100
> +    int contrast;           ///< scale from -100 to 100
> +    void (*process)(        ///< process function
> +        unsigned char *dest,
> +        int dstride,
> +        unsigned char *src,
> +        int sstride,
> +        int w, int h,
> +        int brightness,
> +        int contrast);
> +}  EQContext;
> +

> +static void process_c(unsigned char *dest, int dstride, unsigned char *src, int sstride,
> +            int w, int h, int brightness, int contrast)

Nits: dest -> dst
      sstride -> src_stride
      dstride -> dst_stride

> +{
> +    int i;
> +    int pel;
> +    int dstep = dstride-w;
> +    int sstep = sstride-w;
> +
> +    contrast = ((contrast+100)*256*256)/100;
> +    brightness = ((brightness+100)*511)/200-128 - (contrast>>9);
> +
> +    while (h--) {
> +        for (i = w; i; i--) {
> +            pel = ((*src++* contrast)>>16) + brightness;
> +            if (pel&768) pel = (-pel)>>31;
> +            *dest++ = pel;
> +        }
> +        src += sstep;
> +        dest += dstep;
> +    }
> +}
> +
> +static int query_formats(AVFilterContext *ctx)
> +{
> +    enum PixelFormat pix_fmts[] = {
> +        PIX_FMT_YUV420P,  PIX_FMT_YUV422P,  PIX_FMT_YUV444P,  PIX_FMT_YUV410P,
> +        PIX_FMT_YUV411P,  PIX_FMT_YUV440P,  PIX_FMT_YUVJ420P, PIX_FMT_YUVJ422P,
> +        PIX_FMT_YUVJ444P, PIX_FMT_YUVJ440P, PIX_FMT_NONE
> +    };
> +
> +    avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts));
> +
> +    return 0;
> +}
> +
> +static av_cold int init(AVFilterContext *ctx, const char * args, void * opaque)
> +{
> +    EQContext * eq = ctx->priv;
> +    av_unused int cpu_flags = av_get_cpu_flags();
> +
> +    eq->brightness = 0;
> +    eq->contrast = 0;
> +
> +    if (args)
> +        sscanf(args, "%d:%d", &(eq->brightness), &(eq->contrast));
> +
> +    if (eq->brightness < -100 || eq->brightness > 100 ||
> +        eq->contrast < -100 || eq->contrast > 100) {
> +        av_log(ctx, AV_LOG_ERROR,
> +                "Invalid brightness or contrast value %d:%d\n",
> +                eq->brightness, eq->contrast);
> +        return AVERROR(EINVAL);
> +    }
> +
> +    av_log(ctx, AV_LOG_INFO,
> +        "brightness and contrast value %d:%d\n",
> +        eq->brightness, eq->contrast);

Nit:
   av_log(ctx, AV_LOG_INFO, "brightness:%d contrast:%d\n",
          eq->brightness, eq->contrast);

simpler and easier to parse, also more consistent with the other
filters.

> +    eq->process = NULL;
> +    if (eq->brightness || eq->contrast) {
> +        eq->process = process_c;
> +        if (HAVE_MMX && cpu_flags & AV_CPU_FLAG_MMX) {
> +            av_log(ctx,AV_LOG_INFO,"use mmx\n");
> +            eq->process = ff_eq_filter_process_mmx;
> +        }
> +    }

you can merge the two info logs and have:
   "brightness:%d contrast:%d use_mmx:%d\n"


> +    return 0;
> +}
> +
> +static void start_frame(AVFilterLink * link, AVFilterBufferRef *picref)
> +{
> +    AVFilterBufferRef *ref2 = avfilter_ref_buffer(picref,~0);
> +
> +    avfilter_start_frame(link->dst->outputs[0], ref2);
> +}

this is not required

> +
> +static void end_frame(AVFilterLink *inlink)
> +{
> +    EQContext * eq = inlink->dst->priv;
> +    AVFilterBufferRef *in  = inlink->cur_buf;
> +
> +    if ( eq->process )
> +        eq->process(in->data[0], in->linesize[0],
> +            in->data[0], in->linesize[0],
> +            inlink->w, inlink->h, eq->brightness, eq->contrast);
> +
> +    avfilter_unref_buffer(in);
> +    avfilter_draw_slice(inlink->dst->outputs[0], 0, inlink->h, 1);
> +    avfilter_end_frame(inlink->dst->outputs[0]);
> +}
> +
> +static void null_draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
> +{
> +}

As Bobby pointed out you can exploit cache locality for enhanced
performance and put the code in draw_slice, as it is done in the
drawbox filter, check also the documentation of slicify.

[...]
-- 
FFmpeg = Freak and Fierce MultiPurpose Evil Guru



More information about the ffmpeg-devel mailing list