[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