FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
vf_hqx.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014 Clément Bœsch
3  *
4  * This file is part of FFmpeg.
5  *
6  * Permission to use, copy, modify, and/or distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /**
20  * @file
21  * hqx magnification filters (hq2x, hq3x, hq4x)
22  *
23  * Originally designed by Maxim Stephin.
24  *
25  * @see http://en.wikipedia.org/wiki/Hqx
26  * @see http://web.archive.org/web/20131114143602/http://www.hiend3d.com/hq3x.html
27  * @see http://blog.pkh.me/p/19-butchering-hqx-scaling-filters.html
28  */
29 
30 #include "libavutil/opt.h"
31 #include "libavutil/avassert.h"
32 #include "libavutil/pixdesc.h"
33 #include "internal.h"
34 
35 typedef int (*hqxfunc_t)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs);
36 
37 typedef struct {
38  const AVClass *class;
39  int n;
41  uint32_t rgbtoyuv[1<<24];
42 } HQXContext;
43 
44 typedef struct ThreadData {
45  AVFrame *in, *out;
46  const uint32_t *rgbtoyuv;
47 } ThreadData;
48 
49 #define OFFSET(x) offsetof(HQXContext, x)
50 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
51 static const AVOption hqx_options[] = {
52  { "n", "set scale factor", OFFSET(n), AV_OPT_TYPE_INT, {.i64 = 3}, 2, 4, .flags = FLAGS },
53  { NULL }
54 };
55 
57 
58 static av_always_inline uint32_t rgb2yuv(const uint32_t *r2y, uint32_t c)
59 {
60  return r2y[c & 0xffffff];
61 }
62 
63 static av_always_inline int yuv_diff(uint32_t yuv1, uint32_t yuv2)
64 {
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);
71 }
72 
73 /* (c1*w1 + c2*w2) >> s */
74 static av_always_inline uint32_t interp_2px(uint32_t c1, int w1, uint32_t c2, int w2, int s)
75 {
76  return (((((c1 & 0xff00ff00) >> 8) * w1 + ((c2 & 0xff00ff00) >> 8) * w2) << (8 - s)) & 0xff00ff00) |
77  (((((c1 & 0x00ff00ff) ) * w1 + ((c2 & 0x00ff00ff) ) * w2) >> s ) & 0x00ff00ff);
78 }
79 
80 /* (c1*w1 + c2*w2 + c3*w3) >> s */
81 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)
82 {
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);
85 }
86 
87 /* m is the mask of diff with the center pixel that matters in the pattern, and
88  * r is the expected result (bit set to 1 if there is difference with the
89  * center, 0 otherwise) */
90 #define P(m, r) ((k_shuffled & (m)) == (r))
91 
92 /* adjust 012345678 to 01235678: the mask doesn't contain the (null) diff
93  * between the center/current pixel and itself */
94 #define DROP4(z) ((z) > 4 ? (z)-1 : (z))
95 
96 /* shuffle the input mask: move bit n (4-adjusted) to position stored in p<n> */
97 #define SHF(x, rot, n) (((x) >> ((rot) ? 7-DROP4(n) : DROP4(n)) & 1) << DROP4(p##n))
98 
99 /* used to check if there is YUV difference between 2 pixels */
100 #define WDIFF(c1, c2) yuv_diff(rgb2yuv(r2y, c1), rgb2yuv(r2y, c2))
101 
102 /* bootstrap template for every interpolation code. It defines the shuffled
103  * masks and surrounding pixels. The rot flag is used to indicate if it's a
104  * rotation; its basic effect is to shuffle k using p8..p0 instead of p0..p8 */
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); \
109  \
110  const uint32_t w0 = w[p0], w1 = w[p1], \
111  w3 = w[p3], w4 = w[p4], w5 = w[p5], \
112  w7 = w[p7]
113 
114 /* Assuming p0..p8 is mapped to pixels 0..8, this function interpolates the
115  * top-left pixel in the total of the 2x2 pixels to interpolates. The function
116  * is also used for the 3 other pixels */
117 static av_always_inline uint32_t hq2x_interp_1x1(const uint32_t *r2y, int k,
118  const uint32_t *w,
119  int p0, int p1, int p2,
120  int p3, int p4, int p5,
121  int p6, int p7, int p8)
122 {
123  INTERP_BOOTSTRAP(0);
124 
125  if ((P(0xbf,0x37) || P(0xdb,0x13)) && WDIFF(w1, w5))
126  return interp_2px(w4, 3, w3, 1, 2);
127  if ((P(0xdb,0x49) || P(0xef,0x6d)) && WDIFF(w7, w3))
128  return interp_2px(w4, 3, w1, 1, 2);
129  if ((P(0x0b,0x0b) || P(0xfe,0x4a) || P(0xfe,0x1a)) && WDIFF(w3, w1))
130  return w4;
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))
135  return interp_2px(w4, 3, w0, 1, 2);
136  if (P(0x0b,0x08))
137  return interp_3px(w4, 2, w0, 1, w1, 1, 2);
138  if (P(0x0b,0x02))
139  return interp_3px(w4, 2, w0, 1, w3, 1, 2);
140  if (P(0x2f,0x2f))
141  return interp_3px(w4, 14, w3, 1, w1, 1, 4);
142  if (P(0xbf,0x37) || P(0xdb,0x13))
143  return interp_3px(w4, 5, w1, 2, w3, 1, 3);
144  if (P(0xdb,0x49) || P(0xef,0x6d))
145  return interp_3px(w4, 5, w3, 2, w1, 1, 3);
146  if (P(0x1b,0x03) || P(0x4f,0x43) || P(0x8b,0x83) || P(0x6b,0x43))
147  return interp_2px(w4, 3, w3, 1, 2);
148  if (P(0x4b,0x09) || P(0x8b,0x89) || P(0x1f,0x19) || P(0x3b,0x19))
149  return interp_2px(w4, 3, w1, 1, 2);
150  if (P(0x7e,0x2a) || P(0xef,0xab) || P(0xbf,0x8f) || P(0x7e,0x0e))
151  return interp_3px(w4, 2, w3, 3, w1, 3, 3);
152  if (P(0xfb,0x6a) || P(0x6f,0x6e) || P(0x3f,0x3e) || P(0xfb,0xfa) ||
153  P(0xdf,0xde) || P(0xdf,0x1e))
154  return interp_2px(w4, 3, w0, 1, 2);
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) ||
157  P(0x3b,0x1b))
158  return interp_3px(w4, 2, w3, 1, w1, 1, 2);
159  return interp_3px(w4, 6, w3, 1, w1, 1, 3);
160 }
161 
162 /* Assuming p0..p8 is mapped to pixels 0..8, this function interpolates the
163  * top-left and top-center pixel in the total of the 3x3 pixels to
164  * interpolates. The function is also used for the 3 other couples of pixels
165  * defining the outline. The center pixel is not defined through this function,
166  * since it's just the same as the original value. */
167 static av_always_inline void hq3x_interp_2x1(uint32_t *dst, int dst_linesize,
168  const uint32_t *r2y, int k,
169  const uint32_t *w,
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,
174  int rotate)
175 {
176  INTERP_BOOTSTRAP(rotate);
177 
178  uint32_t *dst00 = &dst[dst_linesize*(pos00>>1) + (pos00&1)];
179  uint32_t *dst01 = &dst[dst_linesize*(pos01>>1) + (pos01&1)];
180 
181  if ((P(0xdb,0x49) || P(0xef,0x6d)) && WDIFF(w7, w3))
182  *dst00 = interp_2px(w4, 3, w1, 1, 2);
183  else if ((P(0xbf,0x37) || P(0xdb,0x13)) && WDIFF(w1, w5))
184  *dst00 = interp_2px(w4, 3, w3, 1, 2);
185  else if ((P(0x0b,0x0b) || P(0xfe,0x4a) || P(0xfe,0x1a)) && WDIFF(w3, w1))
186  *dst00 = w4;
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))
191  *dst00 = interp_2px(w4, 3, w0, 1, 2);
192  else if (P(0x4b,0x09) || P(0x8b,0x89) || P(0x1f,0x19) || P(0x3b,0x19))
193  *dst00 = interp_2px(w4, 3, w1, 1, 2);
194  else if (P(0x1b,0x03) || P(0x4f,0x43) || P(0x8b,0x83) || P(0x6b,0x43))
195  *dst00 = interp_2px(w4, 3, w3, 1, 2);
196  else if (P(0x7e,0x2a) || P(0xef,0xab) || P(0xbf,0x8f) || P(0x7e,0x0e))
197  *dst00 = interp_2px(w3, 1, w1, 1, 1);
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))
200  *dst00 = interp_3px(w4, 2, w3, 7, w1, 7, 4);
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))
205  *dst00 = interp_2px(w4, 3, w0, 1, 2);
206  else
207  *dst00 = interp_3px(w4, 2, w3, 1, w1, 1, 2);
208 
209  if ((P(0xfe,0xde) || P(0x9e,0x16) || P(0xda,0x12) || P(0x17,0x16) ||
210  P(0x5b,0x12) || P(0xbb,0x12)) && WDIFF(w1, w5))
211  *dst01 = w4;
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))
214  *dst01 = w4;
215  else if (P(0xbf,0x8f) || P(0x7e,0x0e) || P(0xbf,0x37) || P(0xdb,0x13))
216  *dst01 = interp_2px(w1, 3, w4, 1, 2);
217  else if (P(0x02,0x00) || P(0x7c,0x28) || P(0xed,0xa9) || P(0xf5,0xb4) ||
218  P(0xd9,0x90))
219  *dst01 = interp_2px(w4, 3, w1, 1, 2);
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))
224  *dst01 = interp_2px(w4, 7, w1, 1, 3);
225  else
226  *dst01 = w4;
227 }
228 
229 /* Assuming p0..p8 is mapped to pixels 0..8, this function interpolates the
230  * top-left block of 2x2 pixels in the total of the 4x4 pixels (or 4 blocks) to
231  * interpolates. The function is also used for the 3 other blocks of 2x2
232  * pixels. */
233 static av_always_inline void hq4x_interp_2x2(uint32_t *dst, int dst_linesize,
234  const uint32_t *r2y, int k,
235  const uint32_t *w,
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)
241 {
242  INTERP_BOOTSTRAP(0);
243 
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)];
248 
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) ||
259  P(0x6b,0x43);
260  const int cond06 = P(0x4b,0x09) || P(0x8b,0x89) || P(0x1f,0x19) ||
261  P(0x3b,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);
278 
279  if (cond00)
280  *dst00 = interp_2px(w4, 5, w3, 3, 3);
281  else if (cond01)
282  *dst00 = interp_2px(w4, 5, w1, 3, 3);
283  else if ((P(0x0b,0x0b) || P(0xfe,0x4a) || P(0xfe,0x1a)) && WDIFF(w3, w1))
284  *dst00 = w4;
285  else if (cond02)
286  *dst00 = interp_2px(w4, 5, w0, 3, 3);
287  else if (cond03)
288  *dst00 = interp_2px(w4, 3, w3, 1, 2);
289  else if (cond04)
290  *dst00 = interp_2px(w4, 3, w1, 1, 2);
291  else if (cond05)
292  *dst00 = interp_2px(w4, 5, w3, 3, 3);
293  else if (cond06)
294  *dst00 = interp_2px(w4, 5, w1, 3, 3);
295  else if (P(0x0f,0x0b) || P(0x5e,0x0a) || P(0x2b,0x0b) || P(0xbe,0x0a) ||
296  P(0x7a,0x0a) || P(0xee,0x0a))
297  *dst00 = interp_2px(w1, 1, w3, 1, 1);
298  else if (cond07)
299  *dst00 = interp_2px(w4, 5, w0, 3, 3);
300  else
301  *dst00 = interp_3px(w4, 2, w1, 1, w3, 1, 2);
302 
303  if (cond00)
304  *dst01 = interp_2px(w4, 7, w3, 1, 3);
305  else if (cond08)
306  *dst01 = w4;
307  else if (cond02)
308  *dst01 = interp_2px(w4, 3, w0, 1, 2);
309  else if (cond09)
310  *dst01 = w4;
311  else if (cond10)
312  *dst01 = interp_3px(w4, 5, w1, 2, w3, 1, 3);
313  else if (P(0x0b,0x08))
314  *dst01 = interp_3px(w4, 5, w1, 2, w0, 1, 3);
315  else if (cond11)
316  *dst01 = interp_2px(w4, 5, w1, 3, 3);
317  else if (cond04)
318  *dst01 = interp_2px(w1, 3, w4, 1, 2);
319  else if (cond12)
320  *dst01 = interp_3px(w1, 2, w4, 1, w3, 1, 2);
321  else if (cond13)
322  *dst01 = interp_2px(w1, 5, w3, 3, 3);
323  else if (cond05)
324  *dst01 = interp_2px(w4, 7, w3, 1, 3);
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))
327  *dst01 = interp_2px(w4, 3, w0, 1, 2);
328  else if (cond14)
329  *dst01 = interp_2px(w1, 1, w4, 1, 1);
330  else
331  *dst01 = interp_2px(w4, 3, w1, 1, 2);
332 
333  if (cond01)
334  *dst10 = interp_2px(w4, 7, w1, 1, 3);
335  else if (cond08)
336  *dst10 = w4;
337  else if (cond02)
338  *dst10 = interp_2px(w4, 3, w0, 1, 2);
339  else if (cond09)
340  *dst10 = w4;
341  else if (cond10)
342  *dst10 = interp_3px(w4, 5, w3, 2, w1, 1, 3);
343  else if (P(0x0b,0x02))
344  *dst10 = interp_3px(w4, 5, w3, 2, w0, 1, 3);
345  else if (cond15)
346  *dst10 = interp_2px(w4, 5, w3, 3, 3);
347  else if (cond03)
348  *dst10 = interp_2px(w3, 3, w4, 1, 2);
349  else if (cond13)
350  *dst10 = interp_3px(w3, 2, w4, 1, w1, 1, 2);
351  else if (cond12)
352  *dst10 = interp_2px(w3, 5, w1, 3, 3);
353  else if (cond06)
354  *dst10 = interp_2px(w4, 7, w1, 1, 3);
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))
357  *dst10 = interp_2px(w4, 3, w0, 1, 2);
358  else if (cond14)
359  *dst10 = interp_2px(w3, 1, w4, 1, 1);
360  else
361  *dst10 = interp_2px(w4, 3, w3, 1, 2);
362 
363  if ((P(0x7f,0x2b) || P(0xef,0xab) || P(0xbf,0x8f) || P(0x7f,0x0f)) &&
364  WDIFF(w3, w1))
365  *dst11 = w4;
366  else if (cond02)
367  *dst11 = interp_2px(w4, 7, w0, 1, 3);
368  else if (cond15)
369  *dst11 = interp_2px(w4, 7, w3, 1, 3);
370  else if (cond11)
371  *dst11 = interp_2px(w4, 7, w1, 1, 3);
372  else if (P(0x0a,0x00) || P(0x7e,0x2a) || P(0xef,0xab) || P(0xbf,0x8f) ||
373  P(0x7e,0x0e))
374  *dst11 = interp_3px(w4, 6, w3, 1, w1, 1, 3);
375  else if (cond07)
376  *dst11 = interp_2px(w4, 7, w0, 1, 3);
377  else
378  *dst11 = w4;
379 }
380 
381 static av_always_inline void hqx_filter(const ThreadData *td, int jobnr, int nb_jobs, int n)
382 {
383  int x, y;
384  AVFrame *in = td->in, *out = td->out;
385  const uint32_t *r2y = td->rgbtoyuv;
386  const int height = in->height;
387  const int width = in->width;
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;
393  const uint8_t *src = in->data[0] + slice_start * src_linesize;
394 
395  const int dst32_linesize = dst_linesize >> 2;
396  const int src32_linesize = src_linesize >> 2;
397 
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;
403 
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]
411  };
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)
414  | (w[4] != w[1] ? (yuv_diff(yuv1, rgb2yuv(r2y, w[1]))) : 0) << 1
415  | (w[4] != w[2] ? (yuv_diff(yuv1, rgb2yuv(r2y, w[2]))) : 0) << 2
416  | (w[4] != w[3] ? (yuv_diff(yuv1, rgb2yuv(r2y, w[3]))) : 0) << 3
417  | (w[4] != w[5] ? (yuv_diff(yuv1, rgb2yuv(r2y, w[5]))) : 0) << 4
418  | (w[4] != w[6] ? (yuv_diff(yuv1, rgb2yuv(r2y, w[6]))) : 0) << 5
419  | (w[4] != w[7] ? (yuv_diff(yuv1, rgb2yuv(r2y, w[7]))) : 0) << 6
420  | (w[4] != w[8] ? (yuv_diff(yuv1, rgb2yuv(r2y, w[8]))) : 0) << 7;
421 
422  if (n == 2) {
423  dst32[dst32_linesize*0 + 0] = hq2x_interp_1x1(r2y, pattern, w, 0,1,2,3,4,5,6,7,8); // 00
424  dst32[dst32_linesize*0 + 1] = hq2x_interp_1x1(r2y, pattern, w, 2,1,0,5,4,3,8,7,6); // 01 (vert mirrored)
425  dst32[dst32_linesize*1 + 0] = hq2x_interp_1x1(r2y, pattern, w, 6,7,8,3,4,5,0,1,2); // 10 (horiz mirrored)
426  dst32[dst32_linesize*1 + 1] = hq2x_interp_1x1(r2y, pattern, w, 8,7,6,5,4,3,2,1,0); // 11 (center mirrored)
427  } else if (n == 3) {
428  hq3x_interp_2x1(dst32, dst32_linesize, r2y, pattern, w, 0,1, 0,1,2,3,4,5,6,7,8, 0); // 00 01
429  hq3x_interp_2x1(dst32 + 1, dst32_linesize, r2y, pattern, w, 1,3, 2,5,8,1,4,7,0,3,6, 1); // 02 12 (rotated to the right)
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); // 20 10 (rotated to the left)
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); // 22 21 (center mirrored)
432  dst32[dst32_linesize + 1] = w[4]; // 11
433  } else if (n == 4) {
434  hq4x_interp_2x2(dst32, dst32_linesize, r2y, pattern, w, 0,1,2,3, 0,1,2,3,4,5,6,7,8); // 00 01 10 11
435  hq4x_interp_2x2(dst32 + 2, dst32_linesize, r2y, pattern, w, 1,0,3,2, 2,1,0,5,4,3,8,7,6); // 02 03 12 13 (vert mirrored)
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); // 20 21 30 31 (horiz mirrored)
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); // 22 23 32 33 (center mirrored)
438  } else {
439  av_assert0(0);
440  }
441 
442  src32 += 1;
443  dst32 += n;
444  }
445 
446  src += src_linesize;
447  dst += dst_linesize * n;
448  }
449 }
450 
451 #define HQX_FUNC(size) \
452 static int hq##size##x(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \
453 { \
454  hqx_filter(arg, jobnr, nb_jobs, size); \
455  return 0; \
456 }
457 
458 HQX_FUNC(2)
459 HQX_FUNC(3)
460 HQX_FUNC(4)
461 
463 {
464  static const enum AVPixelFormat pix_fmts[] = {AV_PIX_FMT_RGB32, AV_PIX_FMT_NONE};
465  AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts);
466  if (!fmts_list)
467  return AVERROR(ENOMEM);
468  return ff_set_common_formats(ctx, fmts_list);
469 }
470 
471 static int config_output(AVFilterLink *outlink)
472 {
473  AVFilterContext *ctx = outlink->src;
474  HQXContext *hqx = ctx->priv;
475  AVFilterLink *inlink = ctx->inputs[0];
476 
477  outlink->w = inlink->w * hqx->n;
478  outlink->h = inlink->h * hqx->n;
479  av_log(inlink->dst, AV_LOG_VERBOSE, "fmt:%s size:%dx%d -> size:%dx%d\n",
480  av_get_pix_fmt_name(inlink->format),
481  inlink->w, inlink->h, outlink->w, outlink->h);
482  return 0;
483 }
484 
485 static int filter_frame(AVFilterLink *inlink, AVFrame *in)
486 {
487  AVFilterContext *ctx = inlink->dst;
488  AVFilterLink *outlink = ctx->outputs[0];
489  HQXContext *hqx = ctx->priv;
490  ThreadData td;
491  AVFrame *out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
492  if (!out) {
493  av_frame_free(&in);
494  return AVERROR(ENOMEM);
495  }
496  av_frame_copy_props(out, in);
497  out->width = outlink->w;
498  out->height = outlink->h;
499 
500  td.in = in;
501  td.out = out;
502  td.rgbtoyuv = hqx->rgbtoyuv;
503  ctx->internal->execute(ctx, hqx->func, &td, NULL, FFMIN(inlink->h, ctx->graph->nb_threads));
504 
505  av_frame_free(&in);
506  return ff_filter_frame(outlink, out);
507 }
508 
509 static av_cold int init(AVFilterContext *ctx)
510 {
511  HQXContext *hqx = ctx->priv;
512  static const hqxfunc_t hqxfuncs[] = {hq2x, hq3x, hq4x};
513 
514  uint32_t c;
515  int bg, rg, g;
516 
517  for (bg=-255; bg<256; bg++) {
518  for (rg=-255; rg<256; rg++) {
519  const uint32_t u = (uint32_t)((-169*rg + 500*bg)/1000) + 128;
520  const uint32_t v = (uint32_t)(( 500*rg - 81*bg)/1000) + 128;
521  int startg = FFMAX3(-bg, -rg, 0);
522  int endg = FFMIN3(255-bg, 255-rg, 255);
523  uint32_t y = (uint32_t)(( 299*rg + 1000*startg + 114*bg)/1000);
524  c = bg + (rg<<16) + 0x010101 * startg;
525  for (g = startg; g <= endg; g++) {
526  hqx->rgbtoyuv[c] = ((y++) << 16) + (u << 8) + v;
527  c+= 0x010101;
528  }
529  }
530  }
531 
532  hqx->func = hqxfuncs[hqx->n - 2];
533  return 0;
534 }
535 
536 static const AVFilterPad hqx_inputs[] = {
537  {
538  .name = "default",
539  .type = AVMEDIA_TYPE_VIDEO,
540  .filter_frame = filter_frame,
541  },
542  { NULL }
543 };
544 
545 static const AVFilterPad hqx_outputs[] = {
546  {
547  .name = "default",
548  .type = AVMEDIA_TYPE_VIDEO,
549  .config_props = config_output,
550  },
551  { NULL }
552 };
553 
555  .name = "hqx",
556  .description = NULL_IF_CONFIG_SMALL("Scale the input by 2, 3 or 4 using the hq*x magnification algorithm."),
557  .priv_size = sizeof(HQXContext),
558  .init = init,
560  .inputs = hqx_inputs,
561  .outputs = hqx_outputs,
562  .priv_class = &hqx_class,
564 };
#define P(m, r)
Definition: vf_hqx.c:90
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
Definition: vf_hqx.c:485
#define NULL
Definition: coverity.c:32
float v
const char * s
Definition: avisynth_c.h:631
AVFrame * out
Definition: vf_curves.c:73
This structure describes decoded (raw) audio or video data.
Definition: frame.h:171
AVOption.
Definition: opt.h:255
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)
Definition: vf_hqx.c:81
#define UMASK
static const AVFilterPad outputs[]
Definition: af_ashowinfo.c:248
const char * g
Definition: vf_curves.c:108
int n
Definition: vf_hqx.c:39
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition: video.c:109
#define WDIFF(c1, c2)
Definition: vf_hqx.c:100
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:283
struct AVFilterGraph * graph
filtergraph this filter belongs to
Definition: avfilter.h:656
const char * name
Pad name.
Definition: internal.h:67
static av_cold int init(AVFilterContext *ctx)
Definition: vf_hqx.c:509
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:641
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1145
AVFrame * in
Definition: vf_curves.c:73
uint8_t
#define av_cold
Definition: attributes.h:74
AVFilter ff_vf_hqx
Definition: vf_hqx.c:554
AVOptions.
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)
Definition: vf_hqx.c:167
hqxfunc_t func
Definition: vf_hqx.c:40
int nb_threads
Maximum number of threads used by filters in this graph.
Definition: avfilter.h:1203
#define FFMIN3(a, b, c)
Definition: common.h:67
static const uint64_t c1
Definition: murmur3.c:49
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:192
#define VMASK
#define av_log(a,...)
A filter pad used for either input or output.
Definition: internal.h:61
static av_always_inline int yuv_diff(uint32_t yuv1, uint32_t yuv2)
Definition: vf_hqx.c:63
int width
width and height of the video frame
Definition: frame.h:220
int ff_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats)
A helper for query_formats() which sets all links to the same list of formats.
Definition: formats.c:542
#define td
Definition: regdef.h:70
static int query_formats(AVFilterContext *ctx)
Definition: vf_hqx.c:462
#define AVERROR(e)
Definition: error.h:43
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:148
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:175
void * priv
private data for use by the filter
Definition: avfilter.h:654
#define AVFILTER_FLAG_SLICE_THREADS
The filter supports multithreading by splitting frames into multiple parts and processing them concur...
Definition: avfilter.h:442
const char * arg
Definition: jacosubdec.c:66
simple assert() macros that are a bit more flexible than ISO C assert().
static av_always_inline void hqx_filter(const ThreadData *td, int jobnr, int nb_jobs, int n)
Definition: vf_hqx.c:381
Definition: hqx.h:62
#define FFMIN(a, b)
Definition: common.h:66
float y
AVFILTER_DEFINE_CLASS(hqx)
static const AVFilterPad hqx_outputs[]
Definition: vf_hqx.c:545
float u
int n
Definition: avisynth_c.h:547
static const AVFilterPad hqx_inputs[]
Definition: vf_hqx.c:536
static av_always_inline uint32_t interp_2px(uint32_t c1, int w1, uint32_t c2, int w2, int s)
Definition: vf_hqx.c:74
static int config_output(AVFilterLink *outlink)
Definition: vf_hqx.c:471
#define INTERP_BOOTSTRAP(rot)
Definition: vf_hqx.c:105
#define OFFSET(x)
Definition: vf_hqx.c:49
#define HQX_FUNC(size)
Definition: vf_hqx.c:451
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)
Definition: vf_hqx.c:233
AVS_Value src
Definition: avisynth_c.h:482
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:199
#define AV_PIX_FMT_RGB32
Definition: pixfmt.h:341
const uint32_t * rgbtoyuv
Definition: vf_hqx.c:46
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(constuint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(constuint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(constint16_t *) pi >>8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t,*(constint16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t,*(constint16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(constint32_t *) pi >>24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t,*(constint32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t,*(constint32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(constfloat *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(constfloat *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(constfloat *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(constdouble *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(constdouble *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(constdouble *) pi *(1U<< 31))))#defineSET_CONV_FUNC_GROUP(ofmt, ifmt) staticvoidset_generic_function(AudioConvert *ac){}voidff_audio_convert_free(AudioConvert **ac){if(!*ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);}AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enumAVSampleFormatout_fmt, enumAVSampleFormatin_fmt, intchannels, intsample_rate, intapply_map){AudioConvert *ac;intin_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) returnNULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method!=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt)>2){ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc){av_free(ac);returnNULL;}returnac;}in_planar=ff_sample_fmt_is_planar(in_fmt, channels);out_planar=ff_sample_fmt_is_planar(out_fmt, channels);if(in_planar==out_planar){ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar?ac->channels:1;}elseif(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;elseac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_AARCH64) ff_audio_convert_init_aarch64(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);returnac;}intff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in){intuse_generic=1;intlen=in->nb_samples;intp;if(ac->dc){av_log(ac->avr, AV_LOG_TRACE,"%dsamples-audio_convert:%sto%s(dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));returnff_convert_dither(ac-> in
BYTE int const BYTE int int int height
Definition: avisynth_c.h:676
Describe the class of an AVClass context structure.
Definition: log.h:67
Filter definition.
Definition: avfilter.h:470
static const AVFilterPad inputs[]
Definition: af_ashowinfo.c:239
const char * name
Filter name.
Definition: avfilter.h:474
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:648
#define YMASK
AVFilterInternal * internal
An opaque struct for libavfilter internal use.
Definition: avfilter.h:679
static int flags
Definition: cpu.c:47
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:182
static double c[64]
static const AVOption hqx_options[]
Definition: vf_hqx.c:51
static const uint64_t c2
Definition: murmur3.c:50
avfilter_execute_func * execute
Definition: internal.h:162
static int slice_end(AVCodecContext *avctx, AVFrame *pict)
Handle slice ends.
Definition: mpeg12dec.c:2073
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)
Definition: vf_hqx.c:117
A list of supported formats for one end of a filter link.
Definition: formats.h:64
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(constuint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(constuint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(constint16_t *) pi >>8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t,*(constint16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t,*(constint16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(constint32_t *) pi >>24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t,*(constint32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t,*(constint32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(constfloat *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(constfloat *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(constfloat *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(constdouble *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(constdouble *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(constdouble *) pi *(1U<< 31))))#defineSET_CONV_FUNC_GROUP(ofmt, ifmt) staticvoidset_generic_function(AudioConvert *ac){}voidff_audio_convert_free(AudioConvert **ac){if(!*ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);}AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enumAVSampleFormatout_fmt, enumAVSampleFormatin_fmt, intchannels, intsample_rate, intapply_map){AudioConvert *ac;intin_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) returnNULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method!=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt)>2){ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc){av_free(ac);returnNULL;}returnac;}in_planar=ff_sample_fmt_is_planar(in_fmt, channels);out_planar=ff_sample_fmt_is_planar(out_fmt, channels);if(in_planar==out_planar){ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar?ac->channels:1;}elseif(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;elseac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_AARCH64) ff_audio_convert_init_aarch64(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);returnac;}intff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in){intuse_generic=1;intlen=in->nb_samples;intp;if(ac->dc){av_log(ac->avr, AV_LOG_TRACE,"%dsamples-audio_convert:%sto%s(dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));returnff_convert_dither(ac-> out
An instance of a filter.
Definition: avfilter.h:633
int height
Definition: frame.h:220
#define av_always_inline
Definition: attributes.h:37
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.
Definition: pixdesc.c:2011
internal API functions
AVPixelFormat
Pixel format.
Definition: pixfmt.h:61
static av_always_inline uint32_t rgb2yuv(const uint32_t *r2y, uint32_t c)
Definition: vf_hqx.c:58
uint32_t rgbtoyuv[1<< 24]
Definition: vf_hqx.c:41
int(* hqxfunc_t)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_hqx.c:35
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:548
#define FFMAX3(a, b, c)
Definition: common.h:65
#define FLAGS
Definition: vf_hqx.c:50
static int width