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];
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) ||
393 const int dst_linesize =
out->linesize[0];
394 const int src_linesize = in->
linesize[0];
398 const int dst32_linesize = dst_linesize >> 2;
399 const int src32_linesize = src_linesize >> 2;
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) \
455static 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;
475 inlink->
w, inlink->
h, outlink->w, outlink->h);
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 .p.description =
NULL_IF_CONFIG_SMALL(
"Scale the input by 2, 3 or 4 using the hq*x magnification algorithm."),
550 .p.priv_class = &hqx_class,
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
static AVFormatContext * ctx
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert0(cond)
assert() equivalent, that is always enabled.
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 AV_LOG_VERBOSE
Detailed information.
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.
const char * av_get_pix_fmt_name(enum AVPixelFormat pix_fmt)
Return the short name for a pixel format, NULL in case pix_fmt is unknown.
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
int format
agreed upon media format
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...
uint32_t rgbtoyuv[1<< 24]
Used for passing data between threads.
const uint32_t * rgbtoyuv
static av_always_inline void hqx_filter(const ThreadData *td, int jobnr, int nb_jobs, int n)
static av_always_inline uint32_t rgb2yuv(const uint32_t *r2y, uint32_t c)
static av_always_inline void hq3x_interp_2x1(uint32_t *dst, int dst_linesize, const uint32_t *r2y, int k, const uint32_t *w, int pos00, int pos01, int p0, int p1, int p2, int p3, int p4, int p5, int p6, int p7, int p8, int rotate)
#define INTERP_BOOTSTRAP(rot)
static av_always_inline int yuv_diff(uint32_t yuv1, uint32_t yuv2)
static av_always_inline void hq4x_interp_2x2(uint32_t *dst, int dst_linesize, const uint32_t *r2y, int k, const uint32_t *w, int pos00, int pos01, int pos10, int pos11, int p0, int p1, int p2, int p3, int p4, int p5, int p6, int p7, int p8)
static const AVFilterPad hqx_outputs[]
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
static av_always_inline uint32_t interp_2px(uint32_t c1, int w1, uint32_t c2, int w2, int s)
static const AVFilterPad hqx_inputs[]
int(* hqxfunc_t)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
static av_always_inline uint32_t hq2x_interp_1x1(const uint32_t *r2y, int k, const uint32_t *w, int p0, int p1, int p2, int p3, int p4, int p5, int p6, int p7, int p8)
static const AVOption hqx_options[]
static av_always_inline uint32_t interp_3px(uint32_t c1, int w1, uint32_t c2, int w2, uint32_t c3, int w3, int s)
static void rotate(const float rot_quaternion[2][4], float *vec)
Rotate vector with given rotation quaternion.
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)