2 * This file is part of FFmpeg.
4 * Copyright (C) 2011, 2012 Hyllian/Jararaca - sergiogdb@gmail.com
6 * Copyright (c) 2014 Arwa Arif <arwaarif1994@gmail.com>
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 * XBR Filter is used for depixelization of image.
26 * This is based on Hyllian's xBR shader.
28 * @see http://www.libretro.com/forums/viewtopic.php?f=6&t=134
29 * @see https://github.com/yoyofr/iFBA/blob/master/fba_src/src/intf/video/scalers/xbr.cpp
31 * @todo add threading and FATE test
34 #include "libavutil/opt.h"
35 #include "libavutil/avassert.h"
36 #include "libavutil/pixdesc.h"
39 #define RGB_MASK 0x00FFFFFF
40 #define LB_MASK 0x00FEFEFE
41 #define RED_BLUE_MASK 0x00FF00FF
42 #define GREEN_MASK 0x0000FF00
47 uint32_t rgbtoyuv[1<<24];
50 #define OFFSET(x) offsetof(XBRContext, x)
51 static const AVOption xbr_options[] = {
52 { "n", "set scale factor", OFFSET(n), AV_OPT_TYPE_INT, {.i64 = 3}, 2, 4, },
56 AVFILTER_DEFINE_CLASS(xbr);
58 static uint32_t df(uint32_t x, uint32_t y, const uint32_t *r2y)
60 #define YMASK 0xff0000
61 #define UMASK 0x00ff00
62 #define VMASK 0x0000ff
64 uint32_t yuv1 = r2y[x & 0xffffff];
65 uint32_t yuv2 = r2y[y & 0xffffff];
67 return (abs((yuv1 & YMASK) - (yuv2 & YMASK)) >> 16) +
68 (abs((yuv1 & UMASK) - (yuv2 & UMASK)) >> 8) +
69 abs((yuv1 & VMASK) - (yuv2 & VMASK));
72 #define ALPHA_BLEND_128_W(dst, src) dst = ((src & LB_MASK) >> 1) + ((dst & LB_MASK) >> 1)
74 #define ALPHA_BLEND_32_W(dst, src) \
75 dst = ((RED_BLUE_MASK & ((dst & RED_BLUE_MASK) + ((((src & RED_BLUE_MASK) - \
76 (dst & RED_BLUE_MASK))) >>3))) | (GREEN_MASK & ((dst & GREEN_MASK) + \
77 ((((src & GREEN_MASK) - (dst & GREEN_MASK))) >>3))))
79 #define ALPHA_BLEND_64_W(dst, src) \
80 dst = ((RED_BLUE_MASK & ((dst & RED_BLUE_MASK) + ((((src & RED_BLUE_MASK) - \
81 (dst & RED_BLUE_MASK))) >>2))) | (GREEN_MASK & ((dst & GREEN_MASK) + \
82 ((((src & GREEN_MASK) - (dst & GREEN_MASK))) >>2))))
84 #define ALPHA_BLEND_192_W(dst, src) \
85 dst = ((RED_BLUE_MASK & ((dst & RED_BLUE_MASK) + ((((src & RED_BLUE_MASK) - \
86 (dst & RED_BLUE_MASK)) * 3) >>2))) | (GREEN_MASK & ((dst & GREEN_MASK) + \
87 ((((src & GREEN_MASK) - (dst & GREEN_MASK)) * 3) >>2))))
89 #define ALPHA_BLEND_224_W(dst, src) \
90 dst = ((RED_BLUE_MASK & ((dst & RED_BLUE_MASK) + ((((src & RED_BLUE_MASK) - \
91 (dst & RED_BLUE_MASK)) * 7) >>3))) | (GREEN_MASK & ((dst & GREEN_MASK) + \
92 ((((src & GREEN_MASK) - (dst & GREEN_MASK)) * 7) >>3))))
94 #define LEFT_UP_2_2X(N3, N2, N1, PIXEL)\
95 ALPHA_BLEND_224_W(E[N3], PIXEL); \
96 ALPHA_BLEND_64_W( E[N2], PIXEL); \
99 #define LEFT_2_2X(N3, N2, PIXEL)\
100 ALPHA_BLEND_192_W(E[N3], PIXEL); \
101 ALPHA_BLEND_64_W( E[N2], PIXEL); \
103 #define UP_2_2X(N3, N1, PIXEL)\
104 ALPHA_BLEND_192_W(E[N3], PIXEL); \
105 ALPHA_BLEND_64_W( E[N1], PIXEL); \
107 #define DIA_2X(N3, PIXEL)\
108 ALPHA_BLEND_128_W(E[N3], PIXEL); \
110 #define eq(A, B, r2y)\
111 (df(A, B, r2y) < 155)\
113 #define FILTRO(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,r2y) \
114 ex = (PE!=PH && PE!=PF); \
117 e = (df(PE,PC,r2y)+df(PE,PG,r2y)+df(PI,H5,r2y)+df(PI,F4,r2y))+(df(PH,PF,r2y)<<2); \
118 i = (df(PH,PD,r2y)+df(PH,I5,r2y)+df(PF,I4,r2y)+df(PF,PB,r2y))+(df(PE,PI,r2y)<<2); \
119 if ((e<i) && ( !eq(PF,PB,r2y) && !eq(PH,PD,r2y) || eq(PE,PI,r2y) && (!eq(PF,I4,r2y) && !eq(PH,I5,r2y)) || eq(PE,PG,r2y) || eq(PE,PC,r2y)) )\
121 ke=df(PF,PG,r2y); ki=df(PH,PC,r2y); \
122 ex2 = (PE!=PC && PB!=PC); ex3 = (PE!=PG && PD!=PG); px = (df(PE,PF,r2y) <= df(PE,PH,r2y)) ? PF : PH; \
123 if ( ((ke<<1)<=ki) && ex3 && (ke>=(ki<<1)) && ex2 ) \
125 LEFT_UP_2_2X(N3, N2, N1, px)\
127 else if ( ((ke<<1)<=ki) && ex3 ) \
129 LEFT_2_2X(N3, N2, px);\
131 else if ( (ke>=(ki<<1)) && ex2 ) \
133 UP_2_2X(N3, N1, px);\
142 ALPHA_BLEND_128_W( E[N3], ((df(PE,PF,r2y) <= df(PE,PH,r2y)) ? PF : PH)); \
146 static void xbr2x(AVFrame * input, AVFrame * output, const uint32_t * r2y)
148 unsigned int e, i,px;
149 unsigned int ex, ex2, ex3;
153 int next_line = output->linesize[0]>>2;
155 for (y = 0; y < input->height; y++) {
160 uint32_t * E = (uint32_t *)(output->data[0] + y * output->linesize[0] * 2);
162 /* middle. Offset of -8 is given */
163 uint32_t * sa2 = (uint32_t *)(input->data[0] + y * input->linesize[0] - 8);
165 uint32_t * sa1 = sa2 - (input->linesize[0]>>2);
167 uint32_t * sa0 = sa1 - (input->linesize[0]>>2);
169 uint32_t * sa3 = sa2 + (input->linesize[0]>>2);
171 uint32_t * sa4 = sa3 + (input->linesize[0]>>2);
180 if (y >= input->height - 2) {
182 if (y == input->height - 1) {
189 for (x = 0; x < input->width; x++) {
190 uint32_t B1 = sa0[2];
191 uint32_t PB = sa1[2];
192 uint32_t PE = sa2[2];
193 uint32_t PH = sa3[2];
194 uint32_t H5 = sa4[2];
196 uint32_t A1 = sa0[pprev];
197 uint32_t PA = sa1[pprev];
198 uint32_t PD = sa2[pprev];
199 uint32_t PG = sa3[pprev];
200 uint32_t G5 = sa4[pprev];
202 uint32_t A0 = sa1[pprev2];
203 uint32_t D0 = sa2[pprev2];
204 uint32_t G0 = sa3[pprev2];
216 if (x >= input->width - 2) {
217 if (x == input->width - 1) {
250 E[0] = E[1] = E[next_line] = E[next_line + 1] = PE; // 0, 1, 2, 3
252 FILTRO(PE, PI, PH, PF, PG, PC, PD, PB, PA, G5, C4, G0, D0, C1, B1, F4, I4, H5, I5, A0, A1, 0, 1, next_line, next_line+1,r2y);
253 FILTRO(PE, PC, PF, PB, PI, PA, PH, PD, PG, I4, A1, I5, H5, A0, D0, B1, C1, F4, C4, G5, G0, next_line, 0, next_line+1, 1,r2y);
254 FILTRO(PE, PA, PB, PD, PC, PG, PF, PH, PI, C1, G0, C4, F4, G5, H5, D0, A0, B1, A1, I4, I5, next_line+1, next_line, 1, 0,r2y);
255 FILTRO(PE, PG, PD, PH, PA, PI, PB, PF, PC, A0, I5, A1, B1, I4, F4, H5, G5, D0, G0, C1, C4, 1, next_line+1, 0, next_line,r2y);
274 #define LEFT_UP_2_3X(N7, N5, N6, N2, N8, PIXEL)\
275 ALPHA_BLEND_192_W(E[N7], PIXEL); \
276 ALPHA_BLEND_64_W( E[N6], PIXEL); \
281 #define LEFT_2_3X(N7, N5, N6, N8, PIXEL)\
282 ALPHA_BLEND_192_W(E[N7], PIXEL); \
283 ALPHA_BLEND_64_W( E[N5], PIXEL); \
284 ALPHA_BLEND_64_W( E[N6], PIXEL); \
287 #define UP_2_3X(N5, N7, N2, N8, PIXEL)\
288 ALPHA_BLEND_192_W(E[N5], PIXEL); \
289 ALPHA_BLEND_64_W( E[N7], PIXEL); \
290 ALPHA_BLEND_64_W( E[N2], PIXEL); \
293 #define DIA_3X(N8, N5, N7, PIXEL)\
294 ALPHA_BLEND_224_W(E[N8], PIXEL); \
295 ALPHA_BLEND_32_W(E[N5], PIXEL); \
296 ALPHA_BLEND_32_W(E[N7], PIXEL); \
298 #define FILTRO(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,r2y) \
299 ex = (PE!=PH && PE!=PF); \
302 e = (df(PE,PC,r2y)+df(PE,PG,r2y)+df(PI,H5,r2y)+df(PI,F4,r2y))+(df(PH,PF,r2y)<<2); \
303 i = (df(PH,PD,r2y)+df(PH,I5,r2y)+df(PF,I4,r2y)+df(PF,PB,r2y))+(df(PE,PI,r2y)<<2); \
304 if ((e<i) && ( !eq(PF,PB,r2y) && !eq(PF,PC,r2y) || !eq(PH,PD,r2y) && !eq(PH,PG,r2y) || eq(PE,PI,r2y) && (!eq(PF,F4,r2y) && !eq(PF,I4,r2y) || !eq(PH,H5,r2y) && !eq(PH,I5,r2y)) || eq(PE,PG,r2y) || eq(PE,PC,r2y)) )\
306 ke=df(PF,PG,r2y); ki=df(PH,PC,r2y); \
307 ex2 = (PE!=PC && PB!=PC); ex3 = (PE!=PG && PD!=PG); px = (df(PE,PF,r2y) <= df(PE,PH,r2y)) ? PF : PH; \
308 if ( ((ke<<1)<=ki) && ex3 && (ke>=(ki<<1)) && ex2 ) \
310 LEFT_UP_2_3X(N7, N5, N6, N2, N8, px)\
312 else if ( ((ke<<1)<=ki) && ex3 ) \
314 LEFT_2_3X(N7, N5, N6, N8, px);\
316 else if ( (ke>=(ki<<1)) && ex2 ) \
318 UP_2_3X(N5, N7, N2, N8, px);\
322 DIA_3X(N8, N5, N7, px);\
327 ALPHA_BLEND_128_W( E[N8], ((df(PE,PF,r2y) <= df(PE,PH,r2y)) ? PF : PH)); \
331 static void xbr3x(AVFrame *input, AVFrame *output, const uint32_t *r2y)
333 const int nl = output->linesize[0]>>2;
334 const int nl1 = nl + nl;
336 unsigned int e, i,px;
337 unsigned int ex, ex2, ex3;
345 for (y = 0; y < input->height; y++) {
347 uint32_t * E = (uint32_t *)(output->data[0] + y * output->linesize[0] * 3);
349 /* middle. Offset of -8 is given */
350 uint32_t * sa2 = (uint32_t *)(input->data[0] + y * input->linesize[0] - 8);
352 uint32_t * sa1 = sa2 - (input->linesize[0]>>2);
354 uint32_t * sa0 = sa1 - (input->linesize[0]>>2);
356 uint32_t * sa3 = sa2 + (input->linesize[0]>>2);
358 uint32_t * sa4 = sa3 + (input->linesize[0]>>2);
367 if (y >= input->height - 2){
369 if (y == input->height - 1){
376 for (x = 0; x < input->width; x++){
377 uint32_t B1 = sa0[2];
378 uint32_t PB = sa1[2];
379 uint32_t PE = sa2[2];
380 uint32_t PH = sa3[2];
381 uint32_t H5 = sa4[2];
383 uint32_t A1 = sa0[pprev];
384 uint32_t PA = sa1[pprev];
385 uint32_t PD = sa2[pprev];
386 uint32_t PG = sa3[pprev];
387 uint32_t G5 = sa4[pprev];
389 uint32_t A0 = sa1[pprev2];
390 uint32_t D0 = sa2[pprev2];
391 uint32_t G0 = sa3[pprev2];
403 if (x >= input->width - 2){
404 if (x == input->width - 1){
437 E[0] = E[1] = E[2] = PE;
438 E[nl] = E[nl+1] = E[nl+2] = PE; // 3, 4, 5
439 E[nl1] = E[nl1+1] = E[nl1+2] = PE; // 6, 7, 8
441 FILTRO(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,r2y);
442 FILTRO(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,r2y);
443 FILTRO(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,r2y);
444 FILTRO(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,r2y);
463 #define LEFT_UP_2(N15, N14, N11, N13, N12, N10, N7, N3, PIXEL)\
464 ALPHA_BLEND_192_W(E[N13], PIXEL); \
465 ALPHA_BLEND_64_W( E[N12], PIXEL); \
466 E[N15] = E[N14] = E[N11] = PIXEL; \
467 E[N10] = E[N3] = E[N12]; \
470 #define LEFT_2(N15, N14, N11, N13, N12, N10, PIXEL)\
471 ALPHA_BLEND_192_W(E[N11], PIXEL); \
472 ALPHA_BLEND_192_W(E[N13], PIXEL); \
473 ALPHA_BLEND_64_W( E[N10], PIXEL); \
474 ALPHA_BLEND_64_W( E[N12], PIXEL); \
478 #define UP_2(N15, N14, N11, N3, N7, N10, PIXEL)\
479 ALPHA_BLEND_192_W(E[N14], PIXEL); \
480 ALPHA_BLEND_192_W(E[N7 ], PIXEL); \
481 ALPHA_BLEND_64_W( E[N10], PIXEL); \
482 ALPHA_BLEND_64_W( E[N3 ], PIXEL); \
486 #define DIA(N15, N14, N11, PIXEL)\
487 ALPHA_BLEND_128_W(E[N11], PIXEL); \
488 ALPHA_BLEND_128_W(E[N14], PIXEL); \
491 #define FILTRO(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,r2y) \
492 ex = (PE!=PH && PE!=PF); \
495 e = (df(PE,PC,r2y)+df(PE,PG,r2y)+df(PI,H5,r2y)+df(PI,F4,r2y))+(df(PH,PF,r2y)<<2); \
496 i = (df(PH,PD,r2y)+df(PH,I5,r2y)+df(PF,I4,r2y)+df(PF,PB,r2y))+(df(PE,PI,r2y)<<2); \
497 if ((e<i) && ( !eq(PF,PB,r2y) && !eq(PH,PD,r2y) || eq(PE,PI,r2y) && (!eq(PF,I4,r2y) && !eq(PH,I5,r2y)) || eq(PE,PG,r2y) || eq(PE,PC,r2y)) )\
499 ke=df(PF,PG,r2y); ki=df(PH,PC,r2y); \
500 ex2 = (PE!=PC && PB!=PC); ex3 = (PE!=PG && PD!=PG); px = (df(PE,PF,r2y) <= df(PE,PH,r2y)) ? PF : PH; \
501 if ( ((ke<<1)<=ki) && ex3 && (ke>=(ki<<1)) && ex2 ) \
503 LEFT_UP_2(N15, N14, N11, N13, N12, N10, N7, N3, px)\
505 else if ( ((ke<<1)<=ki) && ex3 ) \
507 LEFT_2(N15, N14, N11, N13, N12, N10, px)\
509 else if ( (ke>=(ki<<1)) && ex2 ) \
511 UP_2(N15, N14, N11, N3, N7, N10, px)\
515 DIA(N15, N14, N11, px)\
520 ALPHA_BLEND_128_W( E[N15], ((df(PE,PF,r2y) <= df(PE,PH,r2y)) ? PF : PH)); \
524 static void xbr4x(AVFrame *input, AVFrame *output, const uint32_t *r2y)
527 const int nl = output->linesize[0]>>2;
528 const int nl1 = nl + nl;
529 const int nl2 = nl1 + nl;
531 unsigned int e, i, px;
532 unsigned int ex, ex2, ex3;
540 for (y = 0; y < input->height; y++) {
542 uint32_t * E = (uint32_t *)(output->data[0] + y * output->linesize[0] * 4);
544 /* middle. Offset of -8 is given */
545 uint32_t * sa2 = (uint32_t *)(input->data[0] + y * input->linesize[0] - 8);
547 uint32_t * sa1 = sa2 - (input->linesize[0]>>2);
549 uint32_t * sa0 = sa1 - (input->linesize[0]>>2);
551 uint32_t * sa3 = sa2 + (input->linesize[0]>>2);
553 uint32_t * sa4 = sa3 + (input->linesize[0]>>2);
562 if (y >= input->height - 2) {
564 if (y == input->height - 1) {
571 for (x = 0; x < input->width; x++) {
572 uint32_t B1 = sa0[2];
573 uint32_t PB = sa1[2];
574 uint32_t PE = sa2[2];
575 uint32_t PH = sa3[2];
576 uint32_t H5 = sa4[2];
578 uint32_t A1 = sa0[pprev];
579 uint32_t PA = sa1[pprev];
580 uint32_t PD = sa2[pprev];
581 uint32_t PG = sa3[pprev];
582 uint32_t G5 = sa4[pprev];
584 uint32_t A0 = sa1[pprev2];
585 uint32_t D0 = sa2[pprev2];
586 uint32_t G0 = sa3[pprev2];
598 if (x >= input->width - 2) {
599 if (x == input->width - 1) {
632 E[0] = E[1] = E[2] = E[3] = PE;
633 E[nl] = E[nl+1] = E[nl+2] = E[nl+3] = PE; // 4, 5, 6, 7
634 E[nl1] = E[nl1+1] = E[nl1+2] = E[nl1+3] = PE; // 8, 9, 10, 11
635 E[nl2] = E[nl2+1] = E[nl2+2] = E[nl2+3] = PE; // 12, 13, 14, 15
637 FILTRO(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,r2y);
638 FILTRO(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,r2y);
639 FILTRO(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,r2y);
640 FILTRO(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,r2y);
659 static int config_output(AVFilterLink *outlink)
661 AVFilterContext *ctx = outlink->src;
662 XBRContext *xbr = ctx->priv;
663 AVFilterLink *inlink = ctx->inputs[0];
665 outlink->w = inlink->w * xbr->n;
666 outlink->h = inlink->h * xbr->n;
670 static int query_formats(AVFilterContext *ctx)
672 static const enum AVPixelFormat pix_fmts[] = {
673 AV_PIX_FMT_0RGB32, AV_PIX_FMT_NONE,
676 ff_set_common_formats(ctx, ff_make_format_list(pix_fmts));
680 static int filter_frame(AVFilterLink *inlink, AVFrame *in)
682 AVFilterContext *ctx = inlink->dst;
683 AVFilterLink *outlink = ctx->outputs[0];
684 XBRContext *xbr = ctx->priv;
685 const uint32_t *r2y = xbr->rgbtoyuv;
687 AVFrame *out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
690 return AVERROR(ENOMEM);
693 av_frame_copy_props(out, in);
696 else if (xbr->n == 3)
701 out->width = outlink->w;
702 out->height = outlink->h;
705 return ff_filter_frame(outlink, out);
708 static int init(AVFilterContext *ctx)
710 XBRContext *xbr = ctx->priv;
714 for (bg = -255; bg < 256; bg++) {
715 for (rg = -255; rg < 256; rg++) {
716 const uint32_t u = (uint32_t)((-169*rg + 500*bg)/1000) + 128;
717 const uint32_t v = (uint32_t)(( 500*rg - 81*bg)/1000) + 128;
718 int startg = FFMAX3(-bg, -rg, 0);
719 int endg = FFMIN3(255-bg, 255-rg, 255);
720 uint32_t y = (uint32_t)(( 299*rg + 1000*startg + 114*bg)/1000);
721 c = bg + (rg<<16) + 0x010101 * startg;
722 for (g = startg; g <= endg; g++) {
723 xbr->rgbtoyuv[c] = ((y++) << 16) + (u << 8) + v;
732 static const AVFilterPad xbr_inputs[] = {
735 .type = AVMEDIA_TYPE_VIDEO,
736 .filter_frame = filter_frame,
741 static const AVFilterPad xbr_outputs[] = {
744 .type = AVMEDIA_TYPE_VIDEO,
745 .config_props = config_output,
750 AVFilter ff_vf_xbr = {
752 .description = NULL_IF_CONFIG_SMALL("Scale the input using xBR algorithm."),
753 .inputs = xbr_inputs,
754 .outputs = xbr_outputs,
755 .query_formats = query_formats,
756 .priv_size = sizeof(XBRContext),
757 .priv_class = &xbr_class,