50 #define OFFSET(x) offsetof(HQXContext, x)
51 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
61 return r2y[
c & 0xffffff];
66 #define YMASK 0xff0000
67 #define UMASK 0x00ff00
68 #define VMASK 0x0000ff
69 #define ABSDIFF(a,b) (abs((int)(a)-(int)(b)))
79 return (((((
c1 & 0xff00ff00) >> 8) * w1 + ((
c2 & 0xff00ff00) >> 8) * w2) << (8 -
s)) & 0xff00ff00) |
80 (((((
c1 & 0x00ff00ff) ) * w1 + ((
c2 & 0x00ff00ff) ) * w2) >>
s ) & 0x00ff00ff);
86 return (((((
c1 & 0xff00ff00) >> 8) * w1 + ((
c2 & 0xff00ff00) >> 8) * w2 + ((c3 & 0xff00ff00) >> 8) * w3) << (8 -
s)) & 0xff00ff00) |
87 (((((
c1 & 0x00ff00ff) ) * w1 + ((
c2 & 0x00ff00ff) ) * w2 + ((c3 & 0x00ff00ff) ) * w3) >>
s ) & 0x00ff00ff);
93 #define P(m, r) ((k_shuffled & (m)) == (r))
97 #define DROP4(z) ((z) > 4 ? (z)-1 : (z))
100 #define SHF(x, rot, n) (((x) >> ((rot) ? 7-DROP4(n) : DROP4(n)) & 1) << DROP4(p##n))
103 #define WDIFF(c1, c2) yuv_diff(rgb2yuv(r2y, c1), rgb2yuv(r2y, c2))
108 #define INTERP_BOOTSTRAP(rot) \
109 const int k_shuffled = SHF(k,rot,0) | SHF(k,rot,1) | SHF(k,rot,2) \
110 | SHF(k,rot,3) | 0 | SHF(k,rot,5) \
111 | SHF(k,rot,6) | SHF(k,rot,7) | SHF(k,rot,8); \
113 const uint32_t w0 = w[p0], w1 = w[p1], \
114 w3 = w[p3], w4 = w[p4], w5 = w[p5], \
122 int p0,
int p1,
int p2,
123 int p3,
int p4,
int p5,
124 int p6,
int p7,
int p8)
128 if ((
P(0xbf,0x37) ||
P(0xdb,0x13)) &&
WDIFF(w1, w5))
130 if ((
P(0xdb,0x49) ||
P(0xef,0x6d)) &&
WDIFF(w7, w3))
132 if ((
P(0x0b,0x0b) ||
P(0xfe,0x4a) ||
P(0xfe,0x1a)) &&
WDIFF(w3, w1))
134 if ((
P(0x6f,0x2a) ||
P(0x5b,0x0a) ||
P(0xbf,0x3a) ||
P(0xdf,0x5a) ||
135 P(0x9f,0x8a) ||
P(0xcf,0x8a) ||
P(0xef,0x4e) ||
P(0x3f,0x0e) ||
136 P(0xfb,0x5a) ||
P(0xbb,0x8a) ||
P(0x7f,0x5a) ||
P(0xaf,0x8a) ||
137 P(0xeb,0x8a)) &&
WDIFF(w3, w1))
145 if (
P(0xbf,0x37) ||
P(0xdb,0x13))
147 if (
P(0xdb,0x49) ||
P(0xef,0x6d))
149 if (
P(0x1b,0x03) ||
P(0x4f,0x43) ||
P(0x8b,0x83) ||
P(0x6b,0x43))
151 if (
P(0x4b,0x09) ||
P(0x8b,0x89) ||
P(0x1f,0x19) ||
P(0x3b,0x19))
153 if (
P(0x7e,0x2a) ||
P(0xef,0xab) ||
P(0xbf,0x8f) ||
P(0x7e,0x0e))
155 if (
P(0xfb,0x6a) ||
P(0x6f,0x6e) ||
P(0x3f,0x3e) ||
P(0xfb,0xfa) ||
156 P(0xdf,0xde) ||
P(0xdf,0x1e))
158 if (
P(0x0a,0x00) ||
P(0x4f,0x4b) ||
P(0x9f,0x1b) ||
P(0x2f,0x0b) ||
159 P(0xbe,0x0a) ||
P(0xee,0x0a) ||
P(0x7e,0x0a) ||
P(0xeb,0x4b) ||
171 const uint32_t *r2y,
int k,
173 int pos00,
int pos01,
174 int p0,
int p1,
int p2,
175 int p3,
int p4,
int p5,
176 int p6,
int p7,
int p8,
181 uint32_t *dst00 = &dst[dst_linesize*(pos00>>1) + (pos00&1)];
182 uint32_t *dst01 = &dst[dst_linesize*(pos01>>1) + (pos01&1)];
184 if ((
P(0xdb,0x49) ||
P(0xef,0x6d)) &&
WDIFF(w7, w3))
186 else if ((
P(0xbf,0x37) ||
P(0xdb,0x13)) &&
WDIFF(w1, w5))
188 else if ((
P(0x0b,0x0b) ||
P(0xfe,0x4a) ||
P(0xfe,0x1a)) &&
WDIFF(w3, w1))
190 else if ((
P(0x6f,0x2a) ||
P(0x5b,0x0a) ||
P(0xbf,0x3a) ||
P(0xdf,0x5a) ||
191 P(0x9f,0x8a) ||
P(0xcf,0x8a) ||
P(0xef,0x4e) ||
P(0x3f,0x0e) ||
192 P(0xfb,0x5a) ||
P(0xbb,0x8a) ||
P(0x7f,0x5a) ||
P(0xaf,0x8a) ||
193 P(0xeb,0x8a)) &&
WDIFF(w3, w1))
195 else if (
P(0x4b,0x09) ||
P(0x8b,0x89) ||
P(0x1f,0x19) ||
P(0x3b,0x19))
197 else if (
P(0x1b,0x03) ||
P(0x4f,0x43) ||
P(0x8b,0x83) ||
P(0x6b,0x43))
199 else if (
P(0x7e,0x2a) ||
P(0xef,0xab) ||
P(0xbf,0x8f) ||
P(0x7e,0x0e))
201 else if (
P(0x4f,0x4b) ||
P(0x9f,0x1b) ||
P(0x2f,0x0b) ||
P(0xbe,0x0a) ||
202 P(0xee,0x0a) ||
P(0x7e,0x0a) ||
P(0xeb,0x4b) ||
P(0x3b,0x1b))
204 else if (
P(0x0b,0x08) ||
P(0xf9,0x68) ||
P(0xf3,0x62) ||
P(0x6d,0x6c) ||
205 P(0x67,0x66) ||
P(0x3d,0x3c) ||
P(0x37,0x36) ||
P(0xf9,0xf8) ||
206 P(0xdd,0xdc) ||
P(0xf3,0xf2) ||
P(0xd7,0xd6) ||
P(0xdd,0x1c) ||
207 P(0xd7,0x16) ||
P(0x0b,0x02))
212 if ((
P(0xfe,0xde) ||
P(0x9e,0x16) ||
P(0xda,0x12) ||
P(0x17,0x16) ||
213 P(0x5b,0x12) ||
P(0xbb,0x12)) &&
WDIFF(w1, w5))
215 else if ((
P(0x0f,0x0b) ||
P(0x5e,0x0a) ||
P(0xfb,0x7b) ||
P(0x3b,0x0b) ||
216 P(0xbe,0x0a) ||
P(0x7a,0x0a)) &&
WDIFF(w3, w1))
218 else if (
P(0xbf,0x8f) ||
P(0x7e,0x0e) ||
P(0xbf,0x37) ||
P(0xdb,0x13))
220 else if (
P(0x02,0x00) ||
P(0x7c,0x28) ||
P(0xed,0xa9) ||
P(0xf5,0xb4) ||
223 else if (
P(0x4f,0x4b) ||
P(0xfb,0x7b) ||
P(0xfe,0x7e) ||
P(0x9f,0x1b) ||
224 P(0x2f,0x0b) ||
P(0xbe,0x0a) ||
P(0x7e,0x0a) ||
P(0xfb,0x4b) ||
225 P(0xfb,0xdb) ||
P(0xfe,0xde) ||
P(0xfe,0x56) ||
P(0x57,0x56) ||
226 P(0x97,0x16) ||
P(0x3f,0x1e) ||
P(0xdb,0x12) ||
P(0xbb,0x12))
237 const uint32_t *r2y,
int k,
239 int pos00,
int pos01,
240 int pos10,
int pos11,
241 int p0,
int p1,
int p2,
242 int p3,
int p4,
int p5,
243 int p6,
int p7,
int p8)
247 uint32_t *dst00 = &dst[dst_linesize*(pos00>>1) + (pos00&1)];
248 uint32_t *dst01 = &dst[dst_linesize*(pos01>>1) + (pos01&1)];
249 uint32_t *dst10 = &dst[dst_linesize*(pos10>>1) + (pos10&1)];
250 uint32_t *dst11 = &dst[dst_linesize*(pos11>>1) + (pos11&1)];
252 const int cond00 = (
P(0xbf,0x37) ||
P(0xdb,0x13)) &&
WDIFF(w1, w5);
253 const int cond01 = (
P(0xdb,0x49) ||
P(0xef,0x6d)) &&
WDIFF(w7, w3);
254 const int cond02 = (
P(0x6f,0x2a) ||
P(0x5b,0x0a) ||
P(0xbf,0x3a) ||
255 P(0xdf,0x5a) ||
P(0x9f,0x8a) ||
P(0xcf,0x8a) ||
256 P(0xef,0x4e) ||
P(0x3f,0x0e) ||
P(0xfb,0x5a) ||
257 P(0xbb,0x8a) ||
P(0x7f,0x5a) ||
P(0xaf,0x8a) ||
258 P(0xeb,0x8a)) &&
WDIFF(w3, w1);
259 const int cond03 =
P(0xdb,0x49) ||
P(0xef,0x6d);
260 const int cond04 =
P(0xbf,0x37) ||
P(0xdb,0x13);
261 const int cond05 =
P(0x1b,0x03) ||
P(0x4f,0x43) ||
P(0x8b,0x83) ||
263 const int cond06 =
P(0x4b,0x09) ||
P(0x8b,0x89) ||
P(0x1f,0x19) ||
265 const int cond07 =
P(0x0b,0x08) ||
P(0xf9,0x68) ||
P(0xf3,0x62) ||
266 P(0x6d,0x6c) ||
P(0x67,0x66) ||
P(0x3d,0x3c) ||
267 P(0x37,0x36) ||
P(0xf9,0xf8) ||
P(0xdd,0xdc) ||
268 P(0xf3,0xf2) ||
P(0xd7,0xd6) ||
P(0xdd,0x1c) ||
269 P(0xd7,0x16) ||
P(0x0b,0x02);
270 const int cond08 = (
P(0x0f,0x0b) ||
P(0x2b,0x0b) ||
P(0xfe,0x4a) ||
271 P(0xfe,0x1a)) &&
WDIFF(w3, w1);
272 const int cond09 =
P(0x2f,0x2f);
273 const int cond10 =
P(0x0a,0x00);
274 const int cond11 =
P(0x0b,0x09);
275 const int cond12 =
P(0x7e,0x2a) ||
P(0xef,0xab);
276 const int cond13 =
P(0xbf,0x8f) ||
P(0x7e,0x0e);
277 const int cond14 =
P(0x4f,0x4b) ||
P(0x9f,0x1b) ||
P(0x2f,0x0b) ||
278 P(0xbe,0x0a) ||
P(0xee,0x0a) ||
P(0x7e,0x0a) ||
279 P(0xeb,0x4b) ||
P(0x3b,0x1b);
280 const int cond15 =
P(0x0b,0x03);
286 else if ((
P(0x0b,0x0b) ||
P(0xfe,0x4a) ||
P(0xfe,0x1a)) &&
WDIFF(w3, w1))
298 else if (
P(0x0f,0x0b) ||
P(0x5e,0x0a) ||
P(0x2b,0x0b) ||
P(0xbe,0x0a) ||
299 P(0x7a,0x0a) ||
P(0xee,0x0a))
316 else if (
P(0x0b,0x08))
328 else if (
P(0xf3,0x62) ||
P(0x67,0x66) ||
P(0x37,0x36) ||
P(0xf3,0xf2) ||
329 P(0xd7,0xd6) ||
P(0xd7,0x16) ||
P(0x0b,0x02))
346 else if (
P(0x0b,0x02))
358 else if (
P(0x0b,0x08) ||
P(0xf9,0x68) ||
P(0x6d,0x6c) ||
P(0x3d,0x3c) ||
359 P(0xf9,0xf8) ||
P(0xdd,0xdc) ||
P(0xdd,0x1c))
366 if ((
P(0x7f,0x2b) ||
P(0xef,0xab) ||
P(0xbf,0x8f) ||
P(0x7f,0x0f)) &&
375 else if (
P(0x0a,0x00) ||
P(0x7e,0x2a) ||
P(0xef,0xab) ||
P(0xbf,0x8f) ||
388 const uint32_t *r2y =
td->rgbtoyuv;
391 const int slice_start = (
height * jobnr ) / nb_jobs;
393 const int dst_linesize =
out->linesize[0];
394 const int src_linesize = in->
linesize[0];
395 uint8_t *dst =
out->data[0] + slice_start * dst_linesize * n;
396 const uint8_t *
src = in->
data[0] + slice_start * src_linesize;
398 const int dst32_linesize = dst_linesize >> 2;
399 const int src32_linesize = src_linesize >> 2;
401 for (y = slice_start; y <
slice_end; y++) {
402 const uint32_t *src32 = (
const uint32_t *)
src;
403 uint32_t *dst32 = (uint32_t *)dst;
404 const int prevline = y > 0 ? -src32_linesize : 0;
405 const int nextline = y <
height - 1 ? src32_linesize : 0;
407 for (x = 0; x <
width; x++) {
408 const int prevcol = x > 0 ? -1 : 0;
409 const int nextcol = x <
width -1 ? 1 : 0;
410 const uint32_t
w[3*3] = {
411 src32[prevcol + prevline], src32[prevline], src32[prevline + nextcol],
412 src32[prevcol ], src32[ 0], src32[ nextcol],
413 src32[prevcol + nextline], src32[nextline], src32[nextline + nextcol]
415 const uint32_t yuv1 =
rgb2yuv(r2y,
w[4]);
426 dst32[dst32_linesize*0 + 0] =
hq2x_interp_1x1(r2y, pattern,
w, 0,1,2,3,4,5,6,7,8);
427 dst32[dst32_linesize*0 + 1] =
hq2x_interp_1x1(r2y, pattern,
w, 2,1,0,5,4,3,8,7,6);
428 dst32[dst32_linesize*1 + 0] =
hq2x_interp_1x1(r2y, pattern,
w, 6,7,8,3,4,5,0,1,2);
429 dst32[dst32_linesize*1 + 1] =
hq2x_interp_1x1(r2y, pattern,
w, 8,7,6,5,4,3,2,1,0);
431 hq3x_interp_2x1(dst32, dst32_linesize, r2y, pattern,
w, 0,1, 0,1,2,3,4,5,6,7,8, 0);
432 hq3x_interp_2x1(dst32 + 1, dst32_linesize, r2y, pattern,
w, 1,3, 2,5,8,1,4,7,0,3,6, 1);
433 hq3x_interp_2x1(dst32 + 1*dst32_linesize, dst32_linesize, r2y, pattern,
w, 2,0, 6,3,0,7,4,1,8,5,2, 1);
434 hq3x_interp_2x1(dst32 + 1*dst32_linesize + 1, dst32_linesize, r2y, pattern,
w, 3,2, 8,7,6,5,4,3,2,1,0, 0);
435 dst32[dst32_linesize + 1] =
w[4];
437 hq4x_interp_2x2(dst32, dst32_linesize, r2y, pattern,
w, 0,1,2,3, 0,1,2,3,4,5,6,7,8);
438 hq4x_interp_2x2(dst32 + 2, dst32_linesize, r2y, pattern,
w, 1,0,3,2, 2,1,0,5,4,3,8,7,6);
439 hq4x_interp_2x2(dst32 + 2*dst32_linesize, dst32_linesize, r2y, pattern,
w, 2,3,0,1, 6,7,8,3,4,5,0,1,2);
440 hq4x_interp_2x2(dst32 + 2*dst32_linesize + 2, dst32_linesize, r2y, pattern,
w, 3,2,1,0, 8,7,6,5,4,3,2,1,0);
450 dst += dst_linesize * n;
454 #define HQX_FUNC(size) \
455 static int hq##size##x(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \
457 hqx_filter(arg, jobnr, nb_jobs, size); \
471 outlink->w =
inlink->w * hqx->
n;
472 outlink->h =
inlink->h * hqx->
n;
491 out->width = outlink->
w;
492 out->height = outlink->
h;
507 static const hqxfunc_t hqxfuncs[] = {hq2x, hq3x, hq4x};
512 for (bg=-255; bg<256; bg++) {
513 for (rg=-255; rg<256; rg++) {
514 const uint32_t
u = (uint32_t)((-169*rg + 500*bg)/1000) + 128;
515 const uint32_t v = (uint32_t)(( 500*rg - 81*bg)/1000) + 128;
516 int startg =
FFMAX3(-bg, -rg, 0);
517 int endg =
FFMIN3(255-bg, 255-rg, 255);
518 uint32_t y = (uint32_t)(( 299*rg + 1000*startg + 114*bg)/1000);
519 c = bg + rg * (1 << 16) + 0x010101 * startg;
520 for (
g = startg;
g <= endg;
g++) {
521 hqx->
rgbtoyuv[
c] = ((y++) << 16) + (
u << 8) + v;
527 hqx->
func = hqxfuncs[hqx->
n - 2];
549 .description =
NULL_IF_CONFIG_SMALL(
"Scale the input by 2, 3 or 4 using the hq*x magnification algorithm."),
555 .priv_class = &hqx_class,