41 uint32_t rgbtoyuv[1<<24];
49 #define OFFSET(x) offsetof(HQXContext, x)
50 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
60 return r2y[c & 0xffffff];
65 #define YMASK 0xff0000
66 #define UMASK 0x00ff00
67 #define VMASK 0x0000ff
68 return abs((yuv1 &
YMASK) - (yuv2 & YMASK)) > (48 << 16) ||
69 abs((yuv1 &
UMASK) - (yuv2 & UMASK)) > ( 7 << 8) ||
70 abs((yuv1 &
VMASK) - (yuv2 & VMASK)) > ( 6 << 0);
76 return (((((c1 & 0xff00ff00) >> 8) * w1 + ((c2 & 0xff00ff00) >> 8) * w2) << (8 - s)) & 0xff00ff00) |
77 (((((c1 & 0x00ff00ff) ) * w1 + ((c2 & 0x00ff00ff) ) * w2) >> s ) & 0x00ff00ff);
83 return (((((c1 & 0xff00ff00) >> 8) * w1 + ((c2 & 0xff00ff00) >> 8) * w2 + ((c3 & 0xff00ff00) >> 8) * w3) << (8 - s)) & 0xff00ff00) |
84 (((((c1 & 0x00ff00ff) ) * w1 + ((c2 & 0x00ff00ff) ) * w2 + ((c3 & 0x00ff00ff) ) * w3) >> s ) & 0x00ff00ff);
90 #define P(m, r) ((k_shuffled & (m)) == (r))
94 #define DROP4(z) ((z) > 4 ? (z)-1 : (z))
97 #define SHF(x, rot, n) (((x) >> ((rot) ? 7-DROP4(n) : DROP4(n)) & 1) << DROP4(p##n))
100 #define WDIFF(c1, c2) yuv_diff(rgb2yuv(r2y, c1), rgb2yuv(r2y, c2))
105 #define INTERP_BOOTSTRAP(rot) \
106 const int k_shuffled = SHF(k,rot,0) | SHF(k,rot,1) | SHF(k,rot,2) \
107 | SHF(k,rot,3) | 0 | SHF(k,rot,5) \
108 | SHF(k,rot,6) | SHF(k,rot,7) | SHF(k,rot,8); \
110 const uint32_t w0 = w[p0], w1 = w[p1], \
111 w3 = w[p3], w4 = w[p4], w5 = w[p5], \
119 int p0,
int p1,
int p2,
120 int p3,
int p4,
int p5,
121 int p6,
int p7,
int p8)
125 if ((
P(0xbf,0x37) ||
P(0xdb,0x13)) &&
WDIFF(w1, w5))
127 if ((
P(0xdb,0x49) ||
P(0xef,0x6d)) &&
WDIFF(w7, w3))
129 if ((
P(0x0b,0x0b) ||
P(0xfe,0x4a) ||
P(0xfe,0x1a)) &&
WDIFF(w3, w1))
131 if ((
P(0x6f,0x2a) ||
P(0x5b,0x0a) ||
P(0xbf,0x3a) ||
P(0xdf,0x5a) ||
132 P(0x9f,0x8a) ||
P(0xcf,0x8a) ||
P(0xef,0x4e) ||
P(0x3f,0x0e) ||
133 P(0xfb,0x5a) ||
P(0xbb,0x8a) ||
P(0x7f,0x5a) ||
P(0xaf,0x8a) ||
134 P(0xeb,0x8a)) &&
WDIFF(w3, w1))
142 if (
P(0xbf,0x37) ||
P(0xdb,0x13))
144 if (
P(0xdb,0x49) ||
P(0xef,0x6d))
146 if (
P(0x1b,0x03) ||
P(0x4f,0x43) ||
P(0x8b,0x83) ||
P(0x6b,0x43))
148 if (
P(0x4b,0x09) ||
P(0x8b,0x89) ||
P(0x1f,0x19) ||
P(0x3b,0x19))
150 if (
P(0x7e,0x2a) ||
P(0xef,0xab) ||
P(0xbf,0x8f) ||
P(0x7e,0x0e))
152 if (
P(0xfb,0x6a) ||
P(0x6f,0x6e) ||
P(0x3f,0x3e) ||
P(0xfb,0xfa) ||
153 P(0xdf,0xde) ||
P(0xdf,0x1e))
155 if (
P(0x0a,0x00) ||
P(0x4f,0x4b) ||
P(0x9f,0x1b) ||
P(0x2f,0x0b) ||
156 P(0xbe,0x0a) ||
P(0xee,0x0a) ||
P(0x7e,0x0a) ||
P(0xeb,0x4b) ||
168 const uint32_t *r2y,
int k,
170 int pos00,
int pos01,
171 int p0,
int p1,
int p2,
172 int p3,
int p4,
int p5,
173 int p6,
int p7,
int p8,
178 uint32_t *dst00 = &dst[dst_linesize*(pos00>>1) + (pos00&1)];
179 uint32_t *dst01 = &dst[dst_linesize*(pos01>>1) + (pos01&1)];
181 if ((
P(0xdb,0x49) ||
P(0xef,0x6d)) &&
WDIFF(w7, w3))
183 else if ((
P(0xbf,0x37) ||
P(0xdb,0x13)) &&
WDIFF(w1, w5))
185 else if ((
P(0x0b,0x0b) ||
P(0xfe,0x4a) ||
P(0xfe,0x1a)) &&
WDIFF(w3, w1))
187 else if ((
P(0x6f,0x2a) ||
P(0x5b,0x0a) ||
P(0xbf,0x3a) ||
P(0xdf,0x5a) ||
188 P(0x9f,0x8a) ||
P(0xcf,0x8a) ||
P(0xef,0x4e) ||
P(0x3f,0x0e) ||
189 P(0xfb,0x5a) ||
P(0xbb,0x8a) ||
P(0x7f,0x5a) ||
P(0xaf,0x8a) ||
190 P(0xeb,0x8a)) &&
WDIFF(w3, w1))
192 else if (
P(0x4b,0x09) ||
P(0x8b,0x89) ||
P(0x1f,0x19) ||
P(0x3b,0x19))
194 else if (
P(0x1b,0x03) ||
P(0x4f,0x43) ||
P(0x8b,0x83) ||
P(0x6b,0x43))
196 else if (
P(0x7e,0x2a) ||
P(0xef,0xab) ||
P(0xbf,0x8f) ||
P(0x7e,0x0e))
198 else if (
P(0x4f,0x4b) ||
P(0x9f,0x1b) ||
P(0x2f,0x0b) ||
P(0xbe,0x0a) ||
199 P(0xee,0x0a) ||
P(0x7e,0x0a) ||
P(0xeb,0x4b) ||
P(0x3b,0x1b))
201 else if (
P(0x0b,0x08) ||
P(0xf9,0x68) ||
P(0xf3,0x62) ||
P(0x6d,0x6c) ||
202 P(0x67,0x66) ||
P(0x3d,0x3c) ||
P(0x37,0x36) ||
P(0xf9,0xf8) ||
203 P(0xdd,0xdc) ||
P(0xf3,0xf2) ||
P(0xd7,0xd6) ||
P(0xdd,0x1c) ||
204 P(0xd7,0x16) ||
P(0x0b,0x02))
209 if ((
P(0xfe,0xde) ||
P(0x9e,0x16) ||
P(0xda,0x12) ||
P(0x17,0x16) ||
210 P(0x5b,0x12) ||
P(0xbb,0x12)) &&
WDIFF(w1, w5))
212 else if ((
P(0x0f,0x0b) ||
P(0x5e,0x0a) ||
P(0xfb,0x7b) ||
P(0x3b,0x0b) ||
213 P(0xbe,0x0a) ||
P(0x7a,0x0a)) &&
WDIFF(w3, w1))
215 else if (
P(0xbf,0x8f) ||
P(0x7e,0x0e) ||
P(0xbf,0x37) ||
P(0xdb,0x13))
217 else if (
P(0x02,0x00) ||
P(0x7c,0x28) ||
P(0xed,0xa9) ||
P(0xf5,0xb4) ||
220 else if (
P(0x4f,0x4b) ||
P(0xfb,0x7b) ||
P(0xfe,0x7e) ||
P(0x9f,0x1b) ||
221 P(0x2f,0x0b) ||
P(0xbe,0x0a) ||
P(0x7e,0x0a) ||
P(0xfb,0x4b) ||
222 P(0xfb,0xdb) ||
P(0xfe,0xde) ||
P(0xfe,0x56) ||
P(0x57,0x56) ||
223 P(0x97,0x16) ||
P(0x3f,0x1e) ||
P(0xdb,0x12) ||
P(0xbb,0x12))
234 const uint32_t *r2y,
int k,
236 int pos00,
int pos01,
237 int pos10,
int pos11,
238 int p0,
int p1,
int p2,
239 int p3,
int p4,
int p5,
240 int p6,
int p7,
int p8)
244 uint32_t *dst00 = &dst[dst_linesize*(pos00>>1) + (pos00&1)];
245 uint32_t *dst01 = &dst[dst_linesize*(pos01>>1) + (pos01&1)];
246 uint32_t *dst10 = &dst[dst_linesize*(pos10>>1) + (pos10&1)];
247 uint32_t *dst11 = &dst[dst_linesize*(pos11>>1) + (pos11&1)];
249 const int cond00 = (
P(0xbf,0x37) ||
P(0xdb,0x13)) &&
WDIFF(w1, w5);
250 const int cond01 = (
P(0xdb,0x49) ||
P(0xef,0x6d)) &&
WDIFF(w7, w3);
251 const int cond02 = (
P(0x6f,0x2a) ||
P(0x5b,0x0a) ||
P(0xbf,0x3a) ||
252 P(0xdf,0x5a) ||
P(0x9f,0x8a) ||
P(0xcf,0x8a) ||
253 P(0xef,0x4e) ||
P(0x3f,0x0e) ||
P(0xfb,0x5a) ||
254 P(0xbb,0x8a) ||
P(0x7f,0x5a) ||
P(0xaf,0x8a) ||
255 P(0xeb,0x8a)) &&
WDIFF(w3, w1);
256 const int cond03 =
P(0xdb,0x49) ||
P(0xef,0x6d);
257 const int cond04 =
P(0xbf,0x37) ||
P(0xdb,0x13);
258 const int cond05 =
P(0x1b,0x03) ||
P(0x4f,0x43) ||
P(0x8b,0x83) ||
260 const int cond06 =
P(0x4b,0x09) ||
P(0x8b,0x89) ||
P(0x1f,0x19) ||
262 const int cond07 =
P(0x0b,0x08) ||
P(0xf9,0x68) ||
P(0xf3,0x62) ||
263 P(0x6d,0x6c) ||
P(0x67,0x66) ||
P(0x3d,0x3c) ||
264 P(0x37,0x36) ||
P(0xf9,0xf8) ||
P(0xdd,0xdc) ||
265 P(0xf3,0xf2) ||
P(0xd7,0xd6) ||
P(0xdd,0x1c) ||
266 P(0xd7,0x16) ||
P(0x0b,0x02);
267 const int cond08 = (
P(0x0f,0x0b) ||
P(0x2b,0x0b) ||
P(0xfe,0x4a) ||
268 P(0xfe,0x1a)) &&
WDIFF(w3, w1);
269 const int cond09 =
P(0x2f,0x2f);
270 const int cond10 =
P(0x0a,0x00);
271 const int cond11 =
P(0x0b,0x09);
272 const int cond12 =
P(0x7e,0x2a) ||
P(0xef,0xab);
273 const int cond13 =
P(0xbf,0x8f) ||
P(0x7e,0x0e);
274 const int cond14 =
P(0x4f,0x4b) ||
P(0x9f,0x1b) ||
P(0x2f,0x0b) ||
275 P(0xbe,0x0a) ||
P(0xee,0x0a) ||
P(0x7e,0x0a) ||
276 P(0xeb,0x4b) ||
P(0x3b,0x1b);
277 const int cond15 =
P(0x0b,0x03);
283 else if ((
P(0x0b,0x0b) ||
P(0xfe,0x4a) ||
P(0xfe,0x1a)) &&
WDIFF(w3, w1))
295 else if (
P(0x0f,0x0b) ||
P(0x5e,0x0a) ||
P(0x2b,0x0b) ||
P(0xbe,0x0a) ||
296 P(0x7a,0x0a) ||
P(0xee,0x0a))
313 else if (
P(0x0b,0x08))
325 else if (
P(0xf3,0x62) ||
P(0x67,0x66) ||
P(0x37,0x36) ||
P(0xf3,0xf2) ||
326 P(0xd7,0xd6) ||
P(0xd7,0x16) ||
P(0x0b,0x02))
343 else if (
P(0x0b,0x02))
355 else if (
P(0x0b,0x08) ||
P(0xf9,0x68) ||
P(0x6d,0x6c) ||
P(0x3d,0x3c) ||
356 P(0xf9,0xf8) ||
P(0xdd,0xdc) ||
P(0xdd,0x1c))
363 if ((
P(0x7f,0x2b) ||
P(0xef,0xab) ||
P(0xbf,0x8f) ||
P(0x7f,0x0f)) &&
372 else if (
P(0x0a,0x00) ||
P(0x7e,0x2a) ||
P(0xef,0xab) ||
P(0xbf,0x8f) ||
388 const int slice_start = (height * jobnr ) / nb_jobs;
389 const int slice_end = (height * (jobnr+1)) / nb_jobs;
390 const int dst_linesize =
out->linesize[0];
391 const int src_linesize = in->
linesize[0];
392 uint8_t *dst =
out->data[0] + slice_start * dst_linesize *
n;
395 const int dst32_linesize = dst_linesize >> 2;
396 const int src32_linesize = src_linesize >> 2;
398 for (y = slice_start; y <
slice_end; y++) {
399 const uint32_t *src32 = (
const uint32_t *)src;
400 uint32_t *dst32 = (uint32_t *)dst;
401 const int prevline = y > 0 ? -src32_linesize : 0;
402 const int nextline = y < height - 1 ? src32_linesize : 0;
404 for (x = 0; x <
width; x++) {
405 const int prevcol = x > 0 ? -1 : 0;
406 const int nextcol = x < width -1 ? 1 : 0;
407 const uint32_t w[3*3] = {
408 src32[prevcol + prevline], src32[prevline], src32[prevline + nextcol],
409 src32[prevcol ], src32[ 0], src32[ nextcol],
410 src32[prevcol + nextline], src32[nextline], src32[nextline + nextcol]
412 const uint32_t yuv1 =
rgb2yuv(r2y, w[4]);
413 const int pattern = (w[4] != w[0] ? (
yuv_diff(yuv1,
rgb2yuv(r2y, w[0]))) : 0)
423 dst32[dst32_linesize*0 + 0] =
hq2x_interp_1x1(r2y, pattern, w, 0,1,2,3,4,5,6,7,8);
424 dst32[dst32_linesize*0 + 1] =
hq2x_interp_1x1(r2y, pattern, w, 2,1,0,5,4,3,8,7,6);
425 dst32[dst32_linesize*1 + 0] =
hq2x_interp_1x1(r2y, pattern, w, 6,7,8,3,4,5,0,1,2);
426 dst32[dst32_linesize*1 + 1] =
hq2x_interp_1x1(r2y, pattern, w, 8,7,6,5,4,3,2,1,0);
428 hq3x_interp_2x1(dst32, dst32_linesize, r2y, pattern, w, 0,1, 0,1,2,3,4,5,6,7,8, 0);
429 hq3x_interp_2x1(dst32 + 1, dst32_linesize, r2y, pattern, w, 1,3, 2,5,8,1,4,7,0,3,6, 1);
430 hq3x_interp_2x1(dst32 + 1*dst32_linesize, dst32_linesize, r2y, pattern, w, 2,0, 6,3,0,7,4,1,8,5,2, 1);
431 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);
432 dst32[dst32_linesize + 1] = w[4];
434 hq4x_interp_2x2(dst32, dst32_linesize, r2y, pattern, w, 0,1,2,3, 0,1,2,3,4,5,6,7,8);
435 hq4x_interp_2x2(dst32 + 2, dst32_linesize, r2y, pattern, w, 1,0,3,2, 2,1,0,5,4,3,8,7,6);
436 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);
437 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);
447 dst += dst_linesize *
n;
451 #define HQX_FUNC(size) \
452 static int hq##size##x(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \
454 hqx_filter(arg, jobnr, nb_jobs, size); \
475 outlink->
w = inlink->
w * hqx->
n;
476 outlink->
h = inlink->
h * hqx->
n;
479 inlink->
w, inlink->
h, outlink->
w, outlink->
h);
510 static const hqxfunc_t hqxfuncs[] = {hq2x, hq3x, hq4x};
515 for (bg=-255; bg<256; bg++) {
516 for (rg=-255; rg<256; rg++) {
517 const uint32_t
u = (uint32_t)((-169*rg + 500*bg)/1000) + 128;
518 const uint32_t
v = (uint32_t)(( 500*rg - 81*bg)/1000) + 128;
519 int startg =
FFMAX3(-bg, -rg, 0);
520 int endg =
FFMIN3(255-bg, 255-rg, 255);
521 uint32_t
y = (uint32_t)(( 299*rg + 1000*startg + 114*bg)/1000);
522 c = bg + (rg<<16) + 0x010101 * startg;
523 for (g = startg; g <= endg; g++) {
524 hqx->
rgbtoyuv[
c] = ((y++) << 16) + (u << 8) + v;
530 hqx->
func = hqxfuncs[hqx->
n - 2];
554 .description =
NULL_IF_CONFIG_SMALL(
"Scale the input by 2, 3 or 4 using the hq*x magnification algorithm."),
560 .priv_class = &hqx_class,