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
68static uint32_t
pixel_diff(uint32_t x, uint32_t y,
const uint32_t *r2y)
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);
244 if (y >= input->
height - 2) {
246 if (y == input->
height - 1) {
251 for (x = 0; x < input->
width; x++) {
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) \
323static int xbr##size##x(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \
325 xbr_filter(arg, jobnr, nb_jobs, size); \
340 outlink->w = inlink->
w *
s->n;
341 outlink->h = inlink->
h *
s->n;
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];
419 .p.priv_class = &xbr_class,
static AVFormatContext * ctx
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
int ff_filter_execute(AVFilterContext *ctx, avfilter_action_func *func, void *arg, int *ret, int nb_jobs)
int ff_filter_get_nb_threads(AVFilterContext *ctx)
Get number of threads for current filter instance.
static int filter_frame(DBEDecodeContext *s, AVFrame *frame)
int(* init)(AVBSFContext *ctx)
@ AV_OPT_TYPE_INT
Underlying C type is int.
#define AVFILTER_FLAG_SLICE_THREADS
The filter supports multithreading by splitting frames into multiple parts and processing them concur...
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
#define PD(a, b)
Pack two delta values (a,b) into one 16-bit word according with endianness of the host machine.
static int config_output(AVBitStreamFilterLink *outlink)
#define u(width, name, range_min, range_max)
#define FILTER_INPUTS(array)
#define FILTER_OUTPUTS(array)
static int ff_slice_pos(int total, int jobnr, int nb_jobs)
Compute the boundary index for a slice when work of size total is split into nb_jobs slices.
#define FILTER_SINGLE_PIXFMT(pix_fmt_)
#define AVFILTER_DEFINE_CLASS(fname)
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
static int slice_end(AVCodecContext *avctx, AVFrame *pict, int *got_output)
Handle slice ends.
#define AV_PIX_FMT_0RGB32
Describe the class of an AVClass context structure.
A link between two filters.
int w
agreed upon image width
int h
agreed upon image height
AVFilterContext * dst
dest filter
A filter pad used for either input or output.
This structure describes decoded (raw) audio or video data.
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
Used for passing data between threads.
const uint32_t * rgbtoyuv
uint32_t rgbtoyuv[1<< 24]
static uint32_t pixel_diff(uint32_t x, uint32_t y, const uint32_t *r2y)
#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)
static const AVOption xbr_options[]
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
#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)
static const AVFilterPad xbr_outputs[]
static av_always_inline void xbr_filter(const ThreadData *td, int jobnr, int nb_jobs, int n)
static const AVFilterPad xbr_inputs[]
int(* xbrfunc_t)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
#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)
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
static int slice_start(SliceContext *sc, VVCContext *s, VVCFrameContext *fc, const CodedBitstreamUnit *unit, const int is_first_slice)