Go to the documentation of this file.
37 #define LB_MASK 0x00FEFEFE
38 #define RED_BLUE_MASK 0x00FF00FF
39 #define GREEN_MASK 0x0000FF00
59 #define OFFSET(x) offsetof(XBRContext, x)
60 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
68 static uint32_t
pixel_diff(uint32_t x, uint32_t y,
const uint32_t *r2y)
70 #define YMASK 0xff0000
71 #define UMASK 0x00ff00
72 #define VMASK 0x0000ff
73 #define ABSDIFF(a,b) (abs((int)(a)-(int)(b)))
75 uint32_t yuv1 = r2y[x & 0xffffff];
76 uint32_t yuv2 = r2y[y & 0xffffff];
83 #define ALPHA_BLEND_128_W(a, b) ((((a) & LB_MASK) >> 1) + (((b) & LB_MASK) >> 1))
84 #define ALPHA_BLEND_BASE(a, b, m, s) ( (RED_BLUE_MASK & (((a) & RED_BLUE_MASK) + (((((b) & RED_BLUE_MASK) - ((a) & RED_BLUE_MASK)) * (m)) >> (s)))) \
85 | (GREEN_MASK & (((a) & GREEN_MASK) + (((((b) & GREEN_MASK) - ((a) & GREEN_MASK)) * (m)) >> (s)))))
86 #define ALPHA_BLEND_32_W(a, b) ALPHA_BLEND_BASE(a, b, 1, 3)
87 #define ALPHA_BLEND_64_W(a, b) ALPHA_BLEND_BASE(a, b, 1, 2)
88 #define ALPHA_BLEND_192_W(a, b) ALPHA_BLEND_BASE(a, b, 3, 2)
89 #define ALPHA_BLEND_224_W(a, b) ALPHA_BLEND_BASE(a, b, 7, 3)
91 #define df(A, B) pixel_diff(A, B, r2y)
92 #define eq(A, B) (df(A, B) < 155)
94 #define FILT2(PE, PI, PH, PF, PG, PC, PD, PB, PA, G5, C4, G0, D0, C1, B1, F4, I4, H5, I5, A0, A1, \
95 N0, N1, N2, N3) do { \
96 if (PE != PH && PE != PF) { \
97 const unsigned e = df(PE,PC) + df(PE,PG) + df(PI,H5) + df(PI,F4) + (df(PH,PF)<<2); \
98 const unsigned i = df(PH,PD) + df(PH,I5) + df(PF,I4) + df(PF,PB) + (df(PE,PI)<<2); \
100 const unsigned px = df(PE,PF) <= df(PE,PH) ? PF : PH; \
101 if (e < i && (!eq(PF,PB) && !eq(PH,PD) || eq(PE,PI) \
102 && (!eq(PF,I4) && !eq(PH,I5)) \
103 || eq(PE,PG) || eq(PE,PC))) { \
104 const unsigned ke = df(PF,PG); \
105 const unsigned ki = df(PH,PC); \
106 const int left = ke<<1 <= ki && PE != PG && PD != PG; \
107 const int up = ke >= ki<<1 && PE != PC && PB != PC; \
109 E[N3] = ALPHA_BLEND_224_W(E[N3], px); \
110 E[N2] = ALPHA_BLEND_64_W( E[N2], px); \
113 E[N3] = ALPHA_BLEND_192_W(E[N3], px); \
114 E[N2] = ALPHA_BLEND_64_W( E[N2], px); \
116 E[N3] = ALPHA_BLEND_192_W(E[N3], px); \
117 E[N1] = ALPHA_BLEND_64_W( E[N1], px); \
119 E[N3] = ALPHA_BLEND_128_W(E[N3], px); \
122 E[N3] = ALPHA_BLEND_128_W(E[N3], px); \
128 #define FILT3(PE, PI, PH, PF, PG, PC, PD, PB, PA, G5, C4, G0, D0, C1, B1, F4, I4, H5, I5, A0, A1, \
129 N0, N1, N2, N3, N4, N5, N6, N7, N8) do { \
130 if (PE != PH && PE != PF) { \
131 const unsigned e = df(PE,PC) + df(PE,PG) + df(PI,H5) + df(PI,F4) + (df(PH,PF)<<2); \
132 const unsigned i = df(PH,PD) + df(PH,I5) + df(PF,I4) + df(PF,PB) + (df(PE,PI)<<2); \
134 const unsigned px = df(PE,PF) <= df(PE,PH) ? PF : PH; \
135 if (e < i && (!eq(PF,PB) && !eq(PF,PC) || !eq(PH,PD) && !eq(PH,PG) || eq(PE,PI) \
136 && (!eq(PF,F4) && !eq(PF,I4) || !eq(PH,H5) && !eq(PH,I5)) \
137 || eq(PE,PG) || eq(PE,PC))) { \
138 const unsigned ke = df(PF,PG); \
139 const unsigned ki = df(PH,PC); \
140 const int left = ke<<1 <= ki && PE != PG && PD != PG; \
141 const int up = ke >= ki<<1 && PE != PC && PB != PC; \
143 E[N7] = ALPHA_BLEND_192_W(E[N7], px); \
144 E[N6] = ALPHA_BLEND_64_W( E[N6], px); \
149 E[N7] = ALPHA_BLEND_192_W(E[N7], px); \
150 E[N5] = ALPHA_BLEND_64_W( E[N5], px); \
151 E[N6] = ALPHA_BLEND_64_W( E[N6], px); \
154 E[N5] = ALPHA_BLEND_192_W(E[N5], px); \
155 E[N7] = ALPHA_BLEND_64_W( E[N7], px); \
156 E[N2] = ALPHA_BLEND_64_W( E[N2], px); \
159 E[N8] = ALPHA_BLEND_224_W(E[N8], px); \
160 E[N5] = ALPHA_BLEND_32_W( E[N5], px); \
161 E[N7] = ALPHA_BLEND_32_W( E[N7], px); \
164 E[N8] = ALPHA_BLEND_128_W(E[N8], px); \
170 #define FILT4(PE, PI, PH, PF, PG, PC, PD, PB, PA, G5, C4, G0, D0, C1, B1, F4, I4, H5, I5, A0, A1, \
171 N15, N14, N11, N3, N7, N10, N13, N12, N9, N6, N2, N1, N5, N8, N4, N0) do { \
172 if (PE != PH && PE != PF) { \
173 const unsigned e = df(PE,PC) + df(PE,PG) + df(PI,H5) + df(PI,F4) + (df(PH,PF)<<2); \
174 const unsigned i = df(PH,PD) + df(PH,I5) + df(PF,I4) + df(PF,PB) + (df(PE,PI)<<2); \
176 const unsigned px = df(PE,PF) <= df(PE,PH) ? PF : PH; \
177 if (e < i && (!eq(PF,PB) && !eq(PH,PD) || eq(PE,PI) \
178 && (!eq(PF,I4) && !eq(PH,I5)) \
179 || eq(PE,PG) || eq(PE,PC))) { \
180 const unsigned ke = df(PF,PG); \
181 const unsigned ki = df(PH,PC); \
182 const int left = ke<<1 <= ki && PE != PG && PD != PG; \
183 const int up = ke >= ki<<1 && PE != PC && PB != PC; \
185 E[N13] = ALPHA_BLEND_192_W(E[N13], px); \
186 E[N12] = ALPHA_BLEND_64_W( E[N12], px); \
187 E[N15] = E[N14] = E[N11] = px; \
188 E[N10] = E[N3] = E[N12]; \
191 E[N11] = ALPHA_BLEND_192_W(E[N11], px); \
192 E[N13] = ALPHA_BLEND_192_W(E[N13], px); \
193 E[N10] = ALPHA_BLEND_64_W( E[N10], px); \
194 E[N12] = ALPHA_BLEND_64_W( E[N12], px); \
198 E[N14] = ALPHA_BLEND_192_W(E[N14], px); \
199 E[N7 ] = ALPHA_BLEND_192_W(E[N7 ], px); \
200 E[N10] = ALPHA_BLEND_64_W( E[N10], px); \
201 E[N3 ] = ALPHA_BLEND_64_W( E[N3 ], px); \
205 E[N11] = ALPHA_BLEND_128_W(E[N11], px); \
206 E[N14] = ALPHA_BLEND_128_W(E[N14], px); \
210 E[N15] = ALPHA_BLEND_128_W(E[N15], px); \
224 const int nl =
output->linesize[0] >> 2;
225 const int nl1 = nl + nl;
226 const int nl2 = nl1 + nl;
230 uint32_t *
E = (uint32_t *)(
output->data[0] + y *
output->linesize[0] * n);
231 const uint32_t *sa2 = (uint32_t *)(
input->data[0] + y *
input->linesize[0] - 8);
232 const uint32_t *sa1 = sa2 - (
input->linesize[0]>>2);
233 const uint32_t *sa0 = sa1 - (
input->linesize[0]>>2);
234 const uint32_t *sa3 = sa2 + (
input->linesize[0]>>2);
235 const uint32_t *sa4 = sa3 + (
input->linesize[0]>>2);
252 const uint32_t
B1 = sa0[2];
253 const uint32_t PB = sa1[2];
254 const uint32_t PE = sa2[2];
255 const uint32_t PH = sa3[2];
256 const uint32_t H5 = sa4[2];
258 const int pprev = 2 - (x > 0);
259 const uint32_t
A1 = sa0[pprev];
260 const uint32_t PA = sa1[pprev];
261 const uint32_t
PD = sa2[pprev];
262 const uint32_t PG = sa3[pprev];
263 const uint32_t G5 = sa4[pprev];
265 const int pprev2 = pprev - (x > 1);
266 const uint32_t
A0 = sa1[pprev2];
267 const uint32_t D0 = sa2[pprev2];
268 const uint32_t G0 = sa3[pprev2];
270 const int pnext = 3 - (x ==
input->
width - 1);
271 const uint32_t
C1 = sa0[pnext];
272 const uint32_t PC = sa1[pnext];
273 const uint32_t
PF = sa2[pnext];
274 const uint32_t PI = sa3[pnext];
275 const uint32_t I5 = sa4[pnext];
277 const int pnext2 = pnext + 1 - (x >=
input->
width - 2);
278 const uint32_t
C4 = sa1[pnext2];
279 const uint32_t F4 = sa2[pnext2];
280 const uint32_t I4 = sa3[pnext2];
284 E[nl] =
E[nl + 1] = PE;
286 FILT2(PE, PI, PH,
PF, PG, PC,
PD, PB, PA, G5,
C4, G0, D0,
C1,
B1, F4, I4, H5, I5,
A0,
A1, 0, 1, nl, nl+1);
287 FILT2(PE, PC,
PF, PB, PI, PA, PH,
PD, PG, I4,
A1, I5, H5,
A0, D0,
B1,
C1, F4,
C4, G5, G0, nl, 0, nl+1, 1);
288 FILT2(PE, PA, PB,
PD, PC, PG,
PF, PH, PI,
C1, G0,
C4, F4, G5, H5, D0,
A0,
B1,
A1, I4, I5, nl+1, nl, 1, 0);
289 FILT2(PE, PG,
PD, PH, PA, PI, PB,
PF, PC,
A0, I5,
A1,
B1, I4, F4, H5, G5, D0, G0,
C1,
C4, 1, nl+1, 0, nl);
292 E[nl] =
E[nl+1] =
E[nl+2] =
293 E[nl1] =
E[nl1+1] =
E[nl1+2] = PE;
295 FILT3(PE, PI, PH,
PF, PG, PC,
PD, PB, PA, G5,
C4, G0, D0,
C1,
B1, F4, I4, H5, I5,
A0,
A1, 0, 1, 2, nl, nl+1, nl+2, nl1, nl1+1, nl1+2);
296 FILT3(PE, PC,
PF, PB, PI, PA, PH,
PD, PG, I4,
A1, I5, H5,
A0, D0,
B1,
C1, F4,
C4, G5, G0, nl1, nl, 0, nl1+1, nl+1, 1, nl1+2, nl+2, 2);
297 FILT3(PE, PA, PB,
PD, PC, PG,
PF, PH, PI,
C1, G0,
C4, F4, G5, H5, D0,
A0,
B1,
A1, I4, I5, nl1+2, nl1+1, nl1, nl+2, nl+1, nl, 2, 1, 0);
298 FILT3(PE, PG,
PD, PH, PA, PI, PB,
PF, PC,
A0, I5,
A1,
B1, I4, F4, H5, G5, D0, G0,
C1,
C4, 2, nl+2, nl1+2, 1, nl+1, nl1+1, 0, nl, nl1);
300 E[0] =
E[1] =
E[2] =
E[3] =
301 E[nl] =
E[nl+1] =
E[nl+2] =
E[nl+3] =
302 E[nl1] =
E[nl1+1] =
E[nl1+2] =
E[nl1+3] =
303 E[nl2] =
E[nl2+1] =
E[nl2+2] =
E[nl2+3] = PE;
305 FILT4(PE, PI, PH,
PF, PG, PC,
PD, PB, PA, G5,
C4, G0, D0,
C1,
B1, F4, I4, H5, I5,
A0,
A1, nl2+3, nl2+2, nl1+3, 3, nl+3, nl1+2, nl2+1, nl2, nl1+1, nl+2, 2, 1, nl+1, nl1, nl, 0);
306 FILT4(PE, PC,
PF, PB, PI, PA, PH,
PD, PG, I4,
A1, I5, H5,
A0, D0,
B1,
C1, F4,
C4, G5, G0, 3, nl+3, 2, 0, 1, nl+2, nl1+3, nl2+3, nl1+2, nl+1, nl, nl1, nl1+1, nl2+2, nl2+1, nl2);
307 FILT4(PE, PA, PB,
PD, PC, PG,
PF, PH, PI,
C1, G0,
C4, F4, G5, H5, D0,
A0,
B1,
A1, I4, I5, 0, 1, nl, nl2, nl1, nl+1, 2, 3, nl+2, nl1+1, nl2+1, nl2+2, nl1+2, nl+3, nl1+3, nl2+3);
308 FILT4(PE, PG,
PD, PH, PA, PI, PB,
PF, PC,
A0, I5,
A1,
B1, I4, F4, H5, G5, D0, G0,
C1,
C4, nl2, nl1, nl2+1, nl2+3, nl2+2, nl1+1, nl, 0, nl+1, nl1+2, nl1+3, nl+3, nl+2, 1, 2, 3);
322 #define XBR_FUNC(size) \
323 static int xbr##size##x(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \
325 xbr_filter(arg, jobnr, nb_jobs, size); \
366 out->width = outlink->
w;
367 out->height = outlink->
h;
376 static const xbrfunc_t xbrfuncs[] = {xbr2x, xbr3x, xbr4x};
381 for (bg = -255; bg < 256; bg++) {
382 for (rg = -255; rg < 256; rg++) {
383 const uint32_t
u = (uint32_t)((-169*rg + 500*bg)/1000) + 128;
384 const uint32_t v = (uint32_t)(( 500*rg - 81*bg)/1000) + 128;
385 int startg =
FFMAX3(-bg, -rg, 0);
386 int endg =
FFMIN3(255-bg, 255-rg, 255);
387 uint32_t y = (uint32_t)(( 299*rg + 1000*startg + 114*bg)/1000);
388 c = bg + rg * (1 << 16) + 0x010101 * startg;
389 for (
g = startg;
g <= endg;
g++) {
390 s->rgbtoyuv[
c] = ((y++) << 16) + (
u << 8) + v;
396 s->func = xbrfuncs[
s->n - 2];
423 .priv_class = &xbr_class,
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
#define u(width, name, range_min, range_max)
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
static const AVFilterPad xbr_outputs[]
filter_frame For filters that do not use the this method is called when a frame is pushed to the filter s input It can be called at any time except in a reentrant way If the input frame is enough to produce output
The exact code depends on how similar the blocks are and how related they are to the and needs to apply these operations to the correct inlink or outlink if there are several Macros are available to factor that when no extra processing is inlink
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
#define FILTER_INPUTS(array)
This structure describes decoded (raw) audio or video data.
static const AVFilterPad xbr_inputs[]
#define PD(a, b)
Pack two delta values (a,b) into one 16-bit word according with endianness of the host machine.
const char * name
Filter name.
A link between two filters.
static int slice_end(AVCodecContext *avctx, AVFrame *pict, int *got_output)
Handle slice ends.
static const AVOption xbr_options[]
A filter pad used for either input or output.
int(* xbrfunc_t)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
uint32_t rgbtoyuv[1<< 24]
#define FILTER_OUTPUTS(array)
Describe the class of an AVClass context structure.
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
static av_always_inline void xbr_filter(const ThreadData *td, int jobnr, int nb_jobs, int n)
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
static int config_output(AVFilterLink *outlink)
const uint32_t * rgbtoyuv
and forward the test the status of outputs and forward it to the corresponding return FFERROR_NOT_READY If the filters stores internally one or a few frame for some input
int w
agreed upon image width
int ff_filter_get_nb_threads(AVFilterContext *ctx)
Get number of threads for current filter instance.
Used for passing data between threads.
const char * name
Pad name.
static int slice_start(SliceContext *sc, VVCContext *s, VVCFrameContext *fc, const CodedBitstreamUnit *unit, const int is_first_slice)
#define AV_PIX_FMT_0RGB32
#define FILT4(PE, PI, PH, PF, PG, PC, PD, PB, PA, G5, C4, G0, D0, C1, B1, F4, I4, H5, I5, A0, A1, N15, N14, N11, N3, N7, N10, N13, N12, N9, N6, N2, N1, N5, N8, N4, N0)
int h
agreed upon image height
int ff_filter_execute(AVFilterContext *ctx, avfilter_action_func *func, void *arg, int *ret, int nb_jobs)
@ AV_OPT_TYPE_INT
Underlying C type is int.
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
#define AVFILTER_FLAG_SLICE_THREADS
The filter supports multithreading by splitting frames into multiple parts and processing them concur...
static uint32_t pixel_diff(uint32_t x, uint32_t y, const uint32_t *r2y)
static av_cold int init(AVFilterContext *ctx)
#define flags(name, subs,...)
AVFILTER_DEFINE_CLASS(xbr)
#define FILTER_SINGLE_PIXFMT(pix_fmt_)
#define FILT2(PE, PI, PH, PF, PG, PC, PD, PB, PA, G5, C4, G0, D0, C1, B1, F4, I4, H5, I5, A0, A1, N0, N1, N2, N3)
#define FILT3(PE, PI, PH, PF, PG, PC, PD, PB, PA, G5, C4, G0, D0, C1, B1, F4, I4, H5, I5, A0, A1, N0, N1, N2, N3, N4, N5, N6, N7, N8)