[FFmpeg-devel] [PATCH 1/3] lavfi: add haldclutsrc filter.

Stefano Sabatini stefasab at gmail.com
Sun May 26 23:21:03 CEST 2013


On date Saturday 2013-05-25 17:10:55 +0200, Clément Bœsch encoded:
> TODO: minor bump
> ---
>  doc/filters.texi           |   9 ++-
>  libavfilter/Makefile       |   1 +
>  libavfilter/allfilters.c   |   1 +
>  libavfilter/vsrc_testsrc.c | 136 +++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 146 insertions(+), 1 deletion(-)
> 
> diff --git a/doc/filters.texi b/doc/filters.texi
> index 8bb132e..1dadba4 100644
> --- a/doc/filters.texi
> +++ b/doc/filters.texi
> @@ -7394,10 +7394,12 @@ ffplay -f lavfi life=s=300x200:mold=10:r=60:ratio=0.1:death_color=#C83232:life_c
>  @end example
>  @end itemize
>  
> - at section color, nullsrc, rgbtestsrc, smptebars, smptehdbars, testsrc
> + at section color, haldclutsrc, nullsrc, rgbtestsrc, smptebars, smptehdbars, testsrc
>  
>  The @code{color} source provides an uniformly colored input.
>  
> +The @code{haldclutsrc} source provides an identity Hald CLUT.

Maybe you could mention Eskil Steenberg's website:
http://www.quelsolaar.com/technology/clut.html

since that's the only place where a reader can find some information
about Hald CLUTs.

> +
>  The @code{nullsrc} source returns unprocessed video frames. It is
>  mainly useful to be employed in analysis / debugging tools, or as the
>  source for filters which ignore the input data.
> @@ -7426,6 +7428,11 @@ source. It can be the name of a color (case insensitive match) or a
>  0xRRGGBB[AA] sequence, possibly followed by an alpha specifier. The
>  default value is "black".
>  
> + at item level
> +Specify the level of the Hald CLUT, only available in the @code{haldclutsrc}

> +source. A level of @code{N} generates a picture of @code{N*N*N} by @code{N*N*N}

pixels?

Please also specify default value and range.

Also assuming N levels I'd assume N*N*N different RGB triplets to
encode in the image. Where am I wrong?

> +to be used an identity matrix for 3D lookup tables.

as identity matrix ?

> +
>  @item size, s
>  Specify the size of the sourced video, it may be a string of the form
>  @var{width}x at var{height}, or the name of a size abbreviation. The
> diff --git a/libavfilter/Makefile b/libavfilter/Makefile
> index fa601b5..f53afb2 100644
> --- a/libavfilter/Makefile
> +++ b/libavfilter/Makefile
> @@ -196,6 +196,7 @@ OBJS-$(CONFIG_ZMQ_FILTER)                    += f_zmq.o
>  OBJS-$(CONFIG_CELLAUTO_FILTER)               += vsrc_cellauto.o
>  OBJS-$(CONFIG_COLOR_FILTER)                  += vsrc_testsrc.o
>  OBJS-$(CONFIG_FREI0R_SRC_FILTER)             += vf_frei0r.o
> +OBJS-$(CONFIG_HALDCLUTSRC_FILTER)            += vsrc_testsrc.o
>  OBJS-$(CONFIG_LIFE_FILTER)                   += vsrc_life.o
>  OBJS-$(CONFIG_MANDELBROT_FILTER)             += vsrc_mandelbrot.o
>  OBJS-$(CONFIG_MPTESTSRC_FILTER)              += vsrc_mptestsrc.o
> diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c
> index 0f2442d..075ecca 100644
> --- a/libavfilter/allfilters.c
> +++ b/libavfilter/allfilters.c
> @@ -193,6 +193,7 @@ void avfilter_register_all(void)
>      REGISTER_FILTER(CELLAUTO,       cellauto,       vsrc);
>      REGISTER_FILTER(COLOR,          color,          vsrc);
>      REGISTER_FILTER(FREI0R,         frei0r_src,     vsrc);
> +    REGISTER_FILTER(HALDCLUTSRC,    haldclutsrc,    vsrc);
>      REGISTER_FILTER(LIFE,           life,           vsrc);
>      REGISTER_FILTER(MANDELBROT,     mandelbrot,     vsrc);
>      REGISTER_FILTER(MPTESTSRC,      mptestsrc,      vsrc);
> diff --git a/libavfilter/vsrc_testsrc.c b/libavfilter/vsrc_testsrc.c
> index 075026d..0083f12 100644
> --- a/libavfilter/vsrc_testsrc.c
> +++ b/libavfilter/vsrc_testsrc.c
> @@ -71,6 +71,9 @@ typedef struct {
>  
>      /* only used by rgbtest */
>      uint8_t rgba_map[4];
> +
> +    /* only used by haldclut */
> +    int level;
>  } TestSourceContext;
>  
>  #define OFFSET(x) offsetof(TestSourceContext, x)
> @@ -269,6 +272,139 @@ AVFilter avfilter_vsrc_color = {
>  
>  #endif /* CONFIG_COLOR_FILTER */
>  
> +#if CONFIG_HALDCLUTSRC_FILTER
> +
> +static const AVOption haldclutsrc_options[] = {
> +    { "level", "set level", OFFSET(level), AV_OPT_TYPE_INT, {.i64 = 6}, 2, 8, FLAGS },
> +    COMMON_OPTIONS
> +    { NULL }
> +};
> +
> +AVFILTER_DEFINE_CLASS(haldclutsrc);
> +
> +static void haldclutsrc_fill_picture(AVFilterContext *ctx, AVFrame *frame)
> +{
> +    int i, j, k, x = 0, y = 0, is16bit = 0, step;
> +    uint32_t alpha = 0;

> +    const TestSourceContext *s = ctx->priv;

Please use a more meaningful name ("test" is used in the rest of the
file).

> +    int level = s->level;
> +    float scale;
> +    const int w = frame->width;
> +    const int h = frame->height;
> +    const uint8_t *data = frame->data[0];
> +    const int linesize  = frame->linesize[0];
> +    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format);
> +    uint8_t rgba_map[4];
> +
> +    av_assert0(w == h && w == level*level*level);
> +
> +    ff_fill_rgba_map(rgba_map, frame->format);
> +
> +    switch (frame->format) {
> +    case AV_PIX_FMT_RGB48:
> +    case AV_PIX_FMT_BGR48:
> +    case AV_PIX_FMT_RGBA64:
> +    case AV_PIX_FMT_BGRA64:
> +        is16bit = 1;
> +        alpha = 0xfffff;

shouldn't it be    0xffff ?

> +        break;
> +    case AV_PIX_FMT_RGBA:
> +    case AV_PIX_FMT_BGRA:
> +    case AV_PIX_FMT_ARGB:
> +    case AV_PIX_FMT_ABGR:
> +        alpha = 0xff;
> +        break;
> +    }
> +
> +    step  = av_get_padded_bits_per_pixel(desc) >> (3 + is16bit);
> +    scale = ((float)(1 << (8*(is16bit+1))) - 1) / (level*level - 1);
> +
> +#define LOAD_CLUT(nbits) do {                                                   \
> +    uint##nbits##_t *dst = ((uint##nbits##_t *)(data + y*linesize)) + x*step;   \
> +    dst[rgba_map[0]] = av_clip_uint##nbits(i * scale);                          \
> +    dst[rgba_map[1]] = av_clip_uint##nbits(j * scale);                          \
> +    dst[rgba_map[2]] = av_clip_uint##nbits(k * scale);                          \
> +    if (step == 4)                                                              \
> +        dst[rgba_map[3]] = alpha;                                               \
> +} while (0)
> +
> +    level *= level;

nit: a distinct level2 variable may be less confusing

> +    for (k = 0; k < level; k++) {
> +        for (j = 0; j < level; j++) {
> +            for (i = 0; i < level; i++) {
> +                if (!is16bit)
> +                    LOAD_CLUT(8);
> +                else
> +                    LOAD_CLUT(16);
> +                if (++x == w) {
> +                    x = 0;
> +                    y++;
> +                }
> +            }
> +        }
> +    }
> +}
> +
> +static av_cold int haldclutsrc_init(AVFilterContext *ctx)
> +{
> +    TestSourceContext *s = ctx->priv;
> +    s->fill_picture_fn = haldclutsrc_fill_picture;
> +    s->draw_once = 1;
> +    return init(ctx);
> +}
> +
> +static int haldclutsrc_query_formats(AVFilterContext *ctx)
> +{
> +    static const enum AVPixelFormat pix_fmts[] = {
> +        AV_PIX_FMT_RGB24,  AV_PIX_FMT_BGR24,
> +        AV_PIX_FMT_RGBA,   AV_PIX_FMT_BGRA,
> +        AV_PIX_FMT_ARGB,   AV_PIX_FMT_ABGR,
> +        AV_PIX_FMT_0RGB,   AV_PIX_FMT_0BGR,
> +        AV_PIX_FMT_RGB0,   AV_PIX_FMT_BGR0,
> +        AV_PIX_FMT_RGB48,  AV_PIX_FMT_BGR48,
> +        AV_PIX_FMT_RGBA64, AV_PIX_FMT_BGRA64,
> +        AV_PIX_FMT_NONE,
> +    };
> +    ff_set_common_formats(ctx, ff_make_format_list(pix_fmts));
> +    return 0;
> +}
> +
> +static int haldclutsrc_config_props(AVFilterLink *outlink)
> +{
> +    AVFilterContext *ctx = outlink->src;
> +    TestSourceContext *s = ctx->priv;
> +

> +    if (outlink->w || outlink->h) {
> +        av_log(ctx, AV_LOG_ERROR, "output size must be configured with a level option\n");
> +        return AVERROR(EINVAL);
> +    }
> +    s->w = s->h = s->level * s->level * s->level;

You could disable this option in this source, and set w/h depending on
the level. Implies that you have to add size to the list of non-common
options for the other sources (more lines but looks like the right
thing to do).

[...]
-- 
FFmpeg = Fiendish Faithful Multimedia Political Educated Gymnast


More information about the ffmpeg-devel mailing list