[FFmpeg-devel] [PATCHv3] avfilter/vf_chromakey: Add chromakey video filter

Clément Bœsch u at pkh.me
Sun Sep 20 12:07:28 CEST 2015


On Fri, Sep 18, 2015 at 04:27:54PM +0200, Timo Rothenpieler wrote:
> ---
>  Changelog                  |   1 +
>  MAINTAINERS                |   1 +
>  doc/filters.texi           |  45 +++++++++++
>  libavfilter/Makefile       |   1 +
>  libavfilter/allfilters.c   |   1 +
>  libavfilter/version.h      |   2 +-
>  libavfilter/vf_chromakey.c | 198 +++++++++++++++++++++++++++++++++++++++++++++
>  7 files changed, 248 insertions(+), 1 deletion(-)
>  create mode 100644 libavfilter/vf_chromakey.c
> 
[...]
> +static void get_pixel_uv(AVFrame *frame, int x, int y, uint8_t *u, uint8_t *v)
> +{
> +    if (x < 0 || x >= frame->width || y < 0 || y >= frame->height) {
> +        return;
> +    }
> +

> +    if (frame->format == AV_PIX_FMT_YUVA420P || frame->format == AV_PIX_FMT_YUVA422P)
> +        x /= 2;
> +
> +    if (frame->format == AV_PIX_FMT_YUVA420P)
> +        y /= 2;

Why not use the usual subsampling mechanism? (using vsub/hsub etc)

> +
> +    *u = frame->data[1][frame->linesize[1] * y + x];
> +    *v = frame->data[2][frame->linesize[2] * y + x];
> +}
> +
> +static int do_chromakey_slice(AVFilterContext *avctx, void *arg, int jobnr, int nb_jobs)
> +{
> +    AVFrame *frame = arg;
> +
> +    const int slice_start = (frame->height * jobnr) / nb_jobs;
> +    const int slice_end = (frame->height * (jobnr + 1)) / nb_jobs;
> +
> +    ChromakeyContext *ctx = avctx->priv;
> +
> +    int x, y, xo, yo;
> +    uint8_t u[9], v[9];
> +
> +    memset(u, ctx->chromakey_uv[0], sizeof(u));
> +    memset(v, ctx->chromakey_uv[1], sizeof(v));
> +

> +    for (y = slice_start; y < slice_end; ++y) {
> +        for (x = 0; x < frame->width; ++x) {
> +            for (yo = 0; yo < 3; ++yo) {
> +                for (xo = 0; xo < 3; ++xo) {

nit: pre increment is not the prefered style (this is not c++, there is no
need for a more confusing syntax)

> +                    get_pixel_uv(frame, x + xo - 1, y + yo - 1, &u[yo * 3 + xo], &v[yo * 3 + xo]);
> +                }
> +            }
> +

> +            frame->data[3][frame->linesize[3] * y + x] = do_chromakey_pixel(ctx, u, v);

You might want to check if saving a bunch of dereferencing in the inner
loop helps performance.

> +        }
> +    }
> +
> +    return 0;
> +}
> +
> +static int filter_frame(AVFilterLink *link, AVFrame *frame)
> +{
> +    AVFilterContext *avctx = link->dst;
> +    int res;
> +

> +    if (res = av_frame_make_writable(frame))
> +        return res;

You have a .needs_writable attribute somewhere for that purpose

> +
> +    if (res = avctx->internal->execute(avctx, do_chromakey_slice, frame, NULL, FFMIN(frame->height, avctx->graph->nb_threads)))
> +        return res;
> +
> +    return ff_filter_frame(avctx->outputs[0], frame);
> +}
> +

> +#define FIXNUM(x) ((int) ((x) * (1 << 10) + 0.5))

lrint()?

> +#define RGB_TO_U(rgb) (((- FIXNUM(0.16874) * rgb[0] - FIXNUM(0.33126) * rgb[1] + FIXNUM(0.50000) * rgb[2] + (1 << 9) - 1) >> 10) + 128)
> +#define RGB_TO_V(rgb) (((  FIXNUM(0.50000) * rgb[0] - FIXNUM(0.41869) * rgb[1] - FIXNUM(0.08131) * rgb[2] + (1 << 9) - 1) >> 10) + 128)
> +
[...]

-- 
Clément B.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20150920/b0fc8b9a/attachment.sig>


More information about the ffmpeg-devel mailing list