FFmpeg
Loading...
Searching...
No Matches
vf_colorkey.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2015 Timo Rothenpieler <timo@rothenpieler.org>
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include "config_components.h"
22
23#include "libavutil/opt.h"
24#include "libavutil/pixdesc.h"
25#include "avfilter.h"
26#include "drawutils.h"
27#include "filters.h"
28
29typedef struct ColorkeyContext {
30 const AVClass *class;
31
32 /* color offsets rgba */
33 uint8_t co[4];
34
35 uint8_t colorkey_rgba[4];
37 float blend;
38 double scale;
39 int depth;
40 int max;
41
43 int jobnr, int nb_jobs);
45
46static int do_colorkey_pixel(const uint8_t *colorkey_rgba, int r, int g, int b,
47 float similarity, float iblend, int max, double scale)
48{
49 double dr, dg, db, diff;
50
51 dr = r * scale - colorkey_rgba[0];
52 dg = g * scale - colorkey_rgba[1];
53 db = b * scale - colorkey_rgba[2];
54
55 diff = sqrt((dr * dr + dg * dg + db * db) / (255.0 * 255.0 * 3.0));
56
57 if (iblend < 10000.0) {
58 return av_clipd((diff - similarity) * iblend, 0.0, 1.0) * max;
59 } else {
60 return (diff > similarity) ? max : 0;
61 }
62}
63
64#define COLORKEY_SLICE(name, type) \
65static int do_colorkey_slice##name(AVFilterContext *avctx, \
66 void *arg, \
67 int jobnr, int nb_jobs) \
68{ \
69 AVFrame *frame = arg; \
70 const int slice_start = ff_slice_pos(frame->height, jobnr, nb_jobs); \
71 const int slice_end = ff_slice_pos(frame->height, jobnr + 1, nb_jobs); \
72 ColorkeyContext *ctx = avctx->priv; \
73 const float similarity = ctx->similarity; \
74 const float iblend = 1.f / ctx->blend; \
75 const uint8_t *colorkey_rgba = ctx->colorkey_rgba; \
76 const uint8_t *co = ctx->co; \
77 const double scale = ctx->scale; \
78 const int max = ctx->max; \
79 \
80 for (int y = slice_start; y < slice_end; y++) { \
81 type *dst = (type *)(frame->data[0] + y * frame->linesize[0]);\
82 \
83 for (int x = 0; x < frame->width; x++) { \
84 const int o = x * 4; \
85 \
86 dst[o + co[3]] = do_colorkey_pixel(colorkey_rgba, \
87 dst[o + co[0]], \
88 dst[o + co[1]], \
89 dst[o + co[2]], \
90 similarity, iblend, max, scale); \
91 } \
92 } \
93 \
94 return 0; \
95}
96
97COLORKEY_SLICE(8, uint8_t)
98COLORKEY_SLICE(16, uint16_t)
99
100#define COLORHOLD_SLICE(name, type, htype) \
101static int do_colorhold_slice##name(AVFilterContext *avctx, void *arg, \
102 int jobnr, int nb_jobs) \
103{ \
104 AVFrame *frame = arg; \
105 const int slice_start = ff_slice_pos(frame->height, jobnr, nb_jobs); \
106 const int slice_end = ff_slice_pos(frame->height, jobnr + 1, nb_jobs); \
107 ColorkeyContext *ctx = avctx->priv; \
108 const int depth = ctx->depth; \
109 const int max = ctx->max; \
110 const int half = max / 2; \
111 const uint8_t *co = ctx->co; \
112 const uint8_t *colorkey_rgba = ctx->colorkey_rgba; \
113 const float similarity = ctx->similarity; \
114 const float iblend = 1.f / ctx->blend; \
115 const double scale = ctx->scale; \
116 \
117 for (int y = slice_start; y < slice_end; ++y) { \
118 type *dst = (type *)(frame->data[0] + y * frame->linesize[0]); \
119 \
120 for (int x = 0; x < frame->width; ++x) { \
121 int o, t, r, g, b; \
122 \
123 o = x * 4; \
124 r = dst[o + co[0]]; \
125 g = dst[o + co[1]]; \
126 b = dst[o + co[2]]; \
127 \
128 t = do_colorkey_pixel(colorkey_rgba, r, g, b, \
129 similarity, iblend, max, scale); \
130 \
131 if (t > 0) { \
132 htype a = (r + g + b) / 3; \
133 htype rt = max - t; \
134 \
135 dst[o + co[0]] = (a * t + r * rt + half) >> depth; \
136 dst[o + co[1]] = (a * t + g * rt + half) >> depth; \
137 dst[o + co[2]] = (a * t + b * rt + half) >> depth; \
138 } \
139 } \
140 } \
141 \
142 return 0; \
143}
144
145COLORHOLD_SLICE(8, uint8_t, int)
146COLORHOLD_SLICE(16, uint16_t, int64_t)
147
149{
150 AVFilterContext *avctx = link->dst;
151 ColorkeyContext *ctx = avctx->priv;
152 int res;
153
154 if (res = ff_filter_execute(avctx, ctx->do_slice, frame, NULL,
155 FFMIN(frame->height, ff_filter_get_nb_threads(avctx))))
156 return res;
157
158 return ff_filter_frame(avctx->outputs[0], frame);
159}
160
162{
163 AVFilterContext *avctx = outlink->src;
164 ColorkeyContext *ctx = avctx->priv;
166
167 ctx->depth = desc->comp[0].depth;
168 ctx->max = (1 << ctx->depth) - 1;
169 ctx->scale = 255.0 / ctx->max;
170 outlink->w = avctx->inputs[0]->w;
171 outlink->h = avctx->inputs[0]->h;
172 outlink->time_base = avctx->inputs[0]->time_base;
173 ff_fill_rgba_map(ctx->co, outlink->format);
174
175 if (!strcmp(avctx->filter->name, "colorkey")) {
176 ctx->do_slice = ctx->max == 255 ? do_colorkey_slice8 : do_colorkey_slice16;
177 } else {
178 ctx->do_slice = ctx->max == 255 ? do_colorhold_slice8 : do_colorhold_slice16;
179 }
180
181 return 0;
182}
183
193
194static const AVFilterPad colorkey_inputs[] = {
195 {
196 .name = "default",
197 .type = AVMEDIA_TYPE_VIDEO,
199 .filter_frame = filter_frame,
200 },
201};
202
204 {
205 .name = "default",
206 .type = AVMEDIA_TYPE_VIDEO,
207 .config_props = config_output,
208 },
209};
210
211#define OFFSET(x) offsetof(ColorkeyContext, x)
212#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM
213
214#if CONFIG_COLORKEY_FILTER
215
216static const AVOption colorkey_options[] = {
217 { "color", "set the colorkey key color", OFFSET(colorkey_rgba), AV_OPT_TYPE_COLOR, { .str = "black" }, 0, 0, FLAGS },
218 { "similarity", "set the colorkey similarity value", OFFSET(similarity), AV_OPT_TYPE_FLOAT, { .dbl = 0.01 }, 0.00001, 1.0, FLAGS },
219 { "blend", "set the colorkey key blend value", OFFSET(blend), AV_OPT_TYPE_FLOAT, { .dbl = 0.0 }, 0.0, 1.0, FLAGS },
220 { NULL }
221};
222
223AVFILTER_DEFINE_CLASS(colorkey);
224
225const FFFilter ff_vf_colorkey = {
226 .p.name = "colorkey",
227 .p.description = NULL_IF_CONFIG_SMALL("Turns a certain color into transparency. Operates on RGB colors."),
228 .p.priv_class = &colorkey_class,
230 .priv_size = sizeof(ColorkeyContext),
234 .process_command = ff_filter_process_command,
235};
236
237#endif /* CONFIG_COLORKEY_FILTER */
238#if CONFIG_COLORHOLD_FILTER
239
240static const AVOption colorhold_options[] = {
241 { "color", "set the colorhold key color", OFFSET(colorkey_rgba), AV_OPT_TYPE_COLOR, { .str = "black" }, 0, 0, FLAGS },
242 { "similarity", "set the colorhold similarity value", OFFSET(similarity), AV_OPT_TYPE_FLOAT, { .dbl = 0.01 }, 0.00001, 1.0, FLAGS },
243 { "blend", "set the colorhold blend value", OFFSET(blend), AV_OPT_TYPE_FLOAT, { .dbl = 0.0 }, 0.0, 1.0, FLAGS },
244 { NULL }
245};
246
247AVFILTER_DEFINE_CLASS(colorhold);
248
250 .p.name = "colorhold",
251 .p.description = NULL_IF_CONFIG_SMALL("Turns a certain color range into gray. Operates on RGB colors."),
252 .p.priv_class = &colorhold_class,
254 .priv_size = sizeof(ColorkeyContext),
258 .process_command = ff_filter_process_command,
259};
260
261#endif /* CONFIG_COLORHOLD_FILTER */
const FFFilter ff_vf_colorhold
const FFFilter ff_vf_colorkey
static AVFormatContext * ctx
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition avfilter.c:1068
int ff_filter_process_command(AVFilterContext *ctx, const char *cmd, const char *arg, char *res, int res_len, int flags)
Generic processing of user supplied commands that are set in the same way as the filter options.
Definition avfilter.c:906
int ff_filter_execute(AVFilterContext *ctx, avfilter_action_func *func, void *arg, int *ret, int nb_jobs)
Definition avfilter.c:1696
int ff_filter_get_nb_threads(AVFilterContext *ctx)
Get number of threads for current filter instance.
Definition avfilter.c:846
Main libavfilter public API header.
#define FLAGS
Definition cmdutils.c:598
#define av_clipd
Definition common.h:148
#define NULL
Definition coverity.c:32
long long int64_t
Definition coverity.c:34
#define max(a, b)
static AVFrame * frame
static int filter_frame(DBEDecodeContext *s, AVFrame *frame)
Definition dolby_e.c:1067
int ff_fill_rgba_map(uint8_t *rgba_map, enum AVPixelFormat pix_fmt)
Definition drawutils.c:80
misc drawing utilities
@ AV_OPT_TYPE_FLOAT
Underlying C type is float.
Definition opt.h:270
@ AV_OPT_TYPE_COLOR
Underlying C type is uint8_t[4].
Definition opt.h:322
#define AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC
Some filters support a generic "enable" expression option that can be used to enable or disable a fil...
Definition avfilter.h:196
#define AVFILTER_FLAG_SLICE_THREADS
The filter supports multithreading by splitting frames into multiple parts and processing them concur...
Definition avfilter.h:166
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
#define r
Definition input.c:42
#define b
Definition input.c:43
static void scale(int *out, const int *in, const int w, const int h, const int shift)
Definition intra.c:278
static int config_output(AVBitStreamFilterLink *outlink)
const char * arg
Definition jacosubdec.c:65
#define FILTER_INPUTS(array)
Definition filters.h:264
#define FILTER_OUTPUTS(array)
Definition filters.h:265
#define AVFILTERPAD_FLAG_NEEDS_WRITABLE
The filter expects writable frames from its input link, duplicating data buffers if needed.
Definition filters.h:59
#define FILTER_PIXFMTS_ARRAY(array)
Definition filters.h:244
#define AVFILTER_DEFINE_CLASS(fname)
Definition filters.h:478
#define av_cold
Definition attributes.h:117
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition internal.h:88
const char * desc
Definition libsvtav1.c:83
#define FFMIN(a, b)
Definition macros.h:49
AVOptions.
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3460
#define AV_PIX_FMT_RGBA64
Definition pixfmt.h:535
AVPixelFormat
Pixel format.
Definition pixfmt.h:71
@ AV_PIX_FMT_NONE
Definition pixfmt.h:72
@ AV_PIX_FMT_ARGB
packed ARGB 8:8:8:8, 32bpp, ARGBARGB...
Definition pixfmt.h:99
@ AV_PIX_FMT_BGRA
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition pixfmt.h:102
@ AV_PIX_FMT_ABGR
packed ABGR 8:8:8:8, 32bpp, ABGRABGR...
Definition pixfmt.h:101
@ AV_PIX_FMT_RGBA
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition pixfmt.h:100
#define AV_PIX_FMT_BGRA64
Definition pixfmt.h:540
Describe the class of an AVClass context structure.
Definition log.h:76
An instance of a filter.
Definition avfilter.h:273
AVFilterLink ** inputs
array of pointers to input links
Definition avfilter.h:281
const AVFilter * filter
the AVFilter of which this is an instance
Definition avfilter.h:276
void * priv
private data for use by the filter
Definition avfilter.h:288
AVFilterLink ** outputs
array of pointers to output links
Definition avfilter.h:285
A filter pad used for either input or output.
Definition filters.h:40
const char * name
Filter name.
Definition avfilter.h:219
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
AVOption.
Definition opt.h:428
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition pixdesc.h:69
uint8_t co[4]
Definition vf_colorkey.c:33
uint8_t colorkey_rgba[4]
Definition vf_colorkey.c:35
int(* do_slice)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition vf_colorkey.c:42
static enum AVPixelFormat pixel_fmts[]
Definition vf_amplify.c:52
static const AVFilterPad colorkey_outputs[]
static int do_colorkey_pixel(const uint8_t *colorkey_rgba, int r, int g, int b, float similarity, float iblend, int max, double scale)
Definition vf_colorkey.c:46
static const AVFilterPad colorkey_inputs[]
static av_cold int config_output(AVFilterLink *outlink)
#define COLORKEY_SLICE(name, type)
Definition vf_colorkey.c:64
#define COLORHOLD_SLICE(name, type, htype)
#define OFFSET(x)
const char * g
Definition vf_curves.c:128
static av_always_inline int diff(const struct color_info *a, const struct color_info *b, const int trans_thresh)