[FFmpeg-devel] [PATCH 1/3] lavfi: add haldclutsrc filter.
Paul B Mahol
onemda at gmail.com
Sun May 26 22:03:18 CEST 2013
On 5/25/13, Clement Boesch <ubitux at gmail.com> wrote:
> 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.
> +
> 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}
> +to be used an identity matrix for 3D lookup tables.
> +
> @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;
> + 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;
> + 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;
> + 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);
> + }
I find this ugly. If filter does not allow user to change w/h, options for
changing w/h should not be available.
Also if something else sets w/h, it should be ignored/replaced.
> + s->w = s->h = s->level * s->level * s->level;
> + return config_props(outlink);
> +}
> +
> +static const AVFilterPad haldclutsrc_outputs[] = {
> + {
> + .name = "default",
> + .type = AVMEDIA_TYPE_VIDEO,
> + .request_frame = request_frame,
> + .config_props = haldclutsrc_config_props,
> + },
> + { NULL }
> +};
> +
> +AVFilter avfilter_vsrc_haldclutsrc = {
> + .name = "haldclutsrc",
> + .description = NULL_IF_CONFIG_SMALL("Provide an identity Hald
> CLUT."),
> + .priv_class = &haldclutsrc_class,
> + .priv_size = sizeof(TestSourceContext),
> + .init = haldclutsrc_init,
> + .uninit = uninit,
> + .query_formats = haldclutsrc_query_formats,
> + .inputs = NULL,
> + .outputs = haldclutsrc_outputs,
> +};
> +#endif /* CONFIG_HALDCLUTSRC_FILTER */
> +
> #if CONFIG_NULLSRC_FILTER
>
> #define nullsrc_options options
> --
> 1.8.2.3
Rest lgtm.
I wonder if something similar could be done for yuvs.
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
More information about the ffmpeg-devel
mailing list