FFmpeg  4.4.8
vf_xbr.c
Go to the documentation of this file.
1 /*
2  * This file is part of FFmpeg.
3  *
4  * Copyright (c) 2011, 2012 Hyllian/Jararaca <sergiogdb@gmail.com>
5  * Copyright (c) 2014 Arwa Arif <arwaarif1994@gmail.com>
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 /**
23  * @file
24  * XBR Filter is used for depixelization of image.
25  * This is based on Hyllian's xBR shader.
26  *
27  * @see https://forums.libretro.com/t/xbr-algorithm-tutorial/123
28  * @see https://github.com/yoyofr/iFBA/blob/master/fba_src/src/intf/video/scalers/xbr.cpp
29  */
30 
31 #include "libavutil/opt.h"
32 #include "libavutil/avassert.h"
33 #include "libavutil/pixdesc.h"
34 #include "internal.h"
35 #include "filters.h"
36 
37 #define LB_MASK 0x00FEFEFE
38 #define RED_BLUE_MASK 0x00FF00FF
39 #define GREEN_MASK 0x0000FF00
40 
41 #ifdef PI
42 #undef PI
43 #endif
44 
45 typedef int (*xbrfunc_t)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs);
46 
47 typedef struct XBRContext {
48  const AVClass *class;
49  int n;
51  uint32_t rgbtoyuv[1<<24];
52 } XBRContext;
53 
54 typedef struct ThreadData {
55  AVFrame *in, *out;
56  const uint32_t *rgbtoyuv;
57 } ThreadData;
58 
59 #define OFFSET(x) offsetof(XBRContext, x)
60 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
61 static const AVOption xbr_options[] = {
62  { "n", "set scale factor", OFFSET(n), AV_OPT_TYPE_INT, {.i64 = 3}, 2, 4, .flags = FLAGS },
63  { NULL }
64 };
65 
67 
68 static uint32_t pixel_diff(uint32_t x, uint32_t y, const uint32_t *r2y)
69 {
70 #define YMASK 0xff0000
71 #define UMASK 0x00ff00
72 #define VMASK 0x0000ff
73 #define ABSDIFF(a,b) (abs((int)(a)-(int)(b)))
74 
75  uint32_t yuv1 = r2y[x & 0xffffff];
76  uint32_t yuv2 = r2y[y & 0xffffff];
77 
78  return (ABSDIFF(yuv1 & YMASK, yuv2 & YMASK) >> 16) +
79  (ABSDIFF(yuv1 & UMASK, yuv2 & UMASK) >> 8) +
80  ABSDIFF(yuv1 & VMASK, yuv2 & VMASK);
81 }
82 
83 #define ALPHA_BLEND_128_W(a, b) ((((a) & LB_MASK) >> 1) + (((b) & LB_MASK) >> 1))
84 #define ALPHA_BLEND_BASE(a, b, m, s) ( (RED_BLUE_MASK & (((a) & RED_BLUE_MASK) + (((((b) & RED_BLUE_MASK) - ((a) & RED_BLUE_MASK)) * (m)) >> (s)))) \
85  | (GREEN_MASK & (((a) & GREEN_MASK) + (((((b) & GREEN_MASK) - ((a) & GREEN_MASK)) * (m)) >> (s)))))
86 #define ALPHA_BLEND_32_W(a, b) ALPHA_BLEND_BASE(a, b, 1, 3)
87 #define ALPHA_BLEND_64_W(a, b) ALPHA_BLEND_BASE(a, b, 1, 2)
88 #define ALPHA_BLEND_192_W(a, b) ALPHA_BLEND_BASE(a, b, 3, 2)
89 #define ALPHA_BLEND_224_W(a, b) ALPHA_BLEND_BASE(a, b, 7, 3)
90 
91 #define df(A, B) pixel_diff(A, B, r2y)
92 #define eq(A, B) (df(A, B) < 155)
93 
94 #define FILT2(PE, PI, PH, PF, PG, PC, PD, PB, PA, G5, C4, G0, D0, C1, B1, F4, I4, H5, I5, A0, A1, \
95  N0, N1, N2, N3) do { \
96  if (PE != PH && PE != PF) { \
97  const unsigned e = df(PE,PC) + df(PE,PG) + df(PI,H5) + df(PI,F4) + (df(PH,PF)<<2); \
98  const unsigned i = df(PH,PD) + df(PH,I5) + df(PF,I4) + df(PF,PB) + (df(PE,PI)<<2); \
99  if (e <= i) { \
100  const unsigned px = df(PE,PF) <= df(PE,PH) ? PF : PH; \
101  if (e < i && (!eq(PF,PB) && !eq(PH,PD) || eq(PE,PI) \
102  && (!eq(PF,I4) && !eq(PH,I5)) \
103  || eq(PE,PG) || eq(PE,PC))) { \
104  const unsigned ke = df(PF,PG); \
105  const unsigned ki = df(PH,PC); \
106  const int left = ke<<1 <= ki && PE != PG && PD != PG; \
107  const int up = ke >= ki<<1 && PE != PC && PB != PC; \
108  if (left && up) { \
109  E[N3] = ALPHA_BLEND_224_W(E[N3], px); \
110  E[N2] = ALPHA_BLEND_64_W( E[N2], px); \
111  E[N1] = E[N2]; \
112  } else if (left) { \
113  E[N3] = ALPHA_BLEND_192_W(E[N3], px); \
114  E[N2] = ALPHA_BLEND_64_W( E[N2], px); \
115  } else if (up) { \
116  E[N3] = ALPHA_BLEND_192_W(E[N3], px); \
117  E[N1] = ALPHA_BLEND_64_W( E[N1], px); \
118  } else { /* diagonal */ \
119  E[N3] = ALPHA_BLEND_128_W(E[N3], px); \
120  } \
121  } else { \
122  E[N3] = ALPHA_BLEND_128_W(E[N3], px); \
123  } \
124  } \
125  } \
126 } while (0)
127 
128 #define FILT3(PE, PI, PH, PF, PG, PC, PD, PB, PA, G5, C4, G0, D0, C1, B1, F4, I4, H5, I5, A0, A1, \
129  N0, N1, N2, N3, N4, N5, N6, N7, N8) do { \
130  if (PE != PH && PE != PF) { \
131  const unsigned e = df(PE,PC) + df(PE,PG) + df(PI,H5) + df(PI,F4) + (df(PH,PF)<<2); \
132  const unsigned i = df(PH,PD) + df(PH,I5) + df(PF,I4) + df(PF,PB) + (df(PE,PI)<<2); \
133  if (e <= i) { \
134  const unsigned px = df(PE,PF) <= df(PE,PH) ? PF : PH; \
135  if (e < i && (!eq(PF,PB) && !eq(PF,PC) || !eq(PH,PD) && !eq(PH,PG) || eq(PE,PI) \
136  && (!eq(PF,F4) && !eq(PF,I4) || !eq(PH,H5) && !eq(PH,I5)) \
137  || eq(PE,PG) || eq(PE,PC))) { \
138  const unsigned ke = df(PF,PG); \
139  const unsigned ki = df(PH,PC); \
140  const int left = ke<<1 <= ki && PE != PG && PD != PG; \
141  const int up = ke >= ki<<1 && PE != PC && PB != PC; \
142  if (left && up) { \
143  E[N7] = ALPHA_BLEND_192_W(E[N7], px); \
144  E[N6] = ALPHA_BLEND_64_W( E[N6], px); \
145  E[N5] = E[N7]; \
146  E[N2] = E[N6]; \
147  E[N8] = px; \
148  } else if (left) { \
149  E[N7] = ALPHA_BLEND_192_W(E[N7], px); \
150  E[N5] = ALPHA_BLEND_64_W( E[N5], px); \
151  E[N6] = ALPHA_BLEND_64_W( E[N6], px); \
152  E[N8] = px; \
153  } else if (up) { \
154  E[N5] = ALPHA_BLEND_192_W(E[N5], px); \
155  E[N7] = ALPHA_BLEND_64_W( E[N7], px); \
156  E[N2] = ALPHA_BLEND_64_W( E[N2], px); \
157  E[N8] = px; \
158  } else { /* diagonal */ \
159  E[N8] = ALPHA_BLEND_224_W(E[N8], px); \
160  E[N5] = ALPHA_BLEND_32_W( E[N5], px); \
161  E[N7] = ALPHA_BLEND_32_W( E[N7], px); \
162  } \
163  } else { \
164  E[N8] = ALPHA_BLEND_128_W(E[N8], px); \
165  } \
166  } \
167  } \
168 } while (0)
169 
170 #define FILT4(PE, PI, PH, PF, PG, PC, PD, PB, PA, G5, C4, G0, D0, C1, B1, F4, I4, H5, I5, A0, A1, \
171  N15, N14, N11, N3, N7, N10, N13, N12, N9, N6, N2, N1, N5, N8, N4, N0) do { \
172  if (PE != PH && PE != PF) { \
173  const unsigned e = df(PE,PC) + df(PE,PG) + df(PI,H5) + df(PI,F4) + (df(PH,PF)<<2); \
174  const unsigned i = df(PH,PD) + df(PH,I5) + df(PF,I4) + df(PF,PB) + (df(PE,PI)<<2); \
175  if (e <= i) { \
176  const unsigned px = df(PE,PF) <= df(PE,PH) ? PF : PH; \
177  if (e < i && (!eq(PF,PB) && !eq(PH,PD) || eq(PE,PI) \
178  && (!eq(PF,I4) && !eq(PH,I5)) \
179  || eq(PE,PG) || eq(PE,PC))) { \
180  const unsigned ke = df(PF,PG); \
181  const unsigned ki = df(PH,PC); \
182  const int left = ke<<1 <= ki && PE != PG && PD != PG; \
183  const int up = ke >= ki<<1 && PE != PC && PB != PC; \
184  if (left && up) { \
185  E[N13] = ALPHA_BLEND_192_W(E[N13], px); \
186  E[N12] = ALPHA_BLEND_64_W( E[N12], px); \
187  E[N15] = E[N14] = E[N11] = px; \
188  E[N10] = E[N3] = E[N12]; \
189  E[N7] = E[N13]; \
190  } else if (left) { \
191  E[N11] = ALPHA_BLEND_192_W(E[N11], px); \
192  E[N13] = ALPHA_BLEND_192_W(E[N13], px); \
193  E[N10] = ALPHA_BLEND_64_W( E[N10], px); \
194  E[N12] = ALPHA_BLEND_64_W( E[N12], px); \
195  E[N14] = px; \
196  E[N15] = px; \
197  } else if (up) { \
198  E[N14] = ALPHA_BLEND_192_W(E[N14], px); \
199  E[N7 ] = ALPHA_BLEND_192_W(E[N7 ], px); \
200  E[N10] = ALPHA_BLEND_64_W( E[N10], px); \
201  E[N3 ] = ALPHA_BLEND_64_W( E[N3 ], px); \
202  E[N11] = px; \
203  E[N15] = px; \
204  } else { /* diagonal */ \
205  E[N11] = ALPHA_BLEND_128_W(E[N11], px); \
206  E[N14] = ALPHA_BLEND_128_W(E[N14], px); \
207  E[N15] = px; \
208  } \
209  } else { \
210  E[N15] = ALPHA_BLEND_128_W(E[N15], px); \
211  } \
212  } \
213  } \
214 } while (0)
215 
216 static av_always_inline void xbr_filter(const ThreadData *td, int jobnr, int nb_jobs, int n)
217 {
218  int x, y;
219  const AVFrame *input = td->in;
220  AVFrame *output = td->out;
221  const uint32_t *r2y = td->rgbtoyuv;
222  const int slice_start = ff_slice_pos(input->height, jobnr, nb_jobs);
223  const int slice_end = ff_slice_pos(input->height, jobnr + 1, nb_jobs);
224  const int nl = output->linesize[0] >> 2;
225  const int nl1 = nl + nl;
226  const int nl2 = nl1 + nl;
227 
228  for (y = slice_start; y < slice_end; y++) {
229 
230  uint32_t *E = (uint32_t *)(output->data[0] + y * output->linesize[0] * n);
231  const uint32_t *sa2 = (uint32_t *)(input->data[0] + y * input->linesize[0] - 8); /* center */
232  const uint32_t *sa1 = sa2 - (input->linesize[0]>>2); /* up x1 */
233  const uint32_t *sa0 = sa1 - (input->linesize[0]>>2); /* up x2 */
234  const uint32_t *sa3 = sa2 + (input->linesize[0]>>2); /* down x1 */
235  const uint32_t *sa4 = sa3 + (input->linesize[0]>>2); /* down x2 */
236 
237  if (y <= 1) {
238  sa0 = sa1;
239  if (y == 0) {
240  sa0 = sa1 = sa2;
241  }
242  }
243 
244  if (y >= input->height - 2) {
245  sa4 = sa3;
246  if (y == input->height - 1) {
247  sa4 = sa3 = sa2;
248  }
249  }
250 
251  for (x = 0; x < input->width; x++) {
252  const uint32_t B1 = sa0[2];
253  const uint32_t PB = sa1[2];
254  const uint32_t PE = sa2[2];
255  const uint32_t PH = sa3[2];
256  const uint32_t H5 = sa4[2];
257 
258  const int pprev = 2 - (x > 0);
259  const uint32_t A1 = sa0[pprev];
260  const uint32_t PA = sa1[pprev];
261  const uint32_t PD = sa2[pprev];
262  const uint32_t PG = sa3[pprev];
263  const uint32_t G5 = sa4[pprev];
264 
265  const int pprev2 = pprev - (x > 1);
266  const uint32_t A0 = sa1[pprev2];
267  const uint32_t D0 = sa2[pprev2];
268  const uint32_t G0 = sa3[pprev2];
269 
270  const int pnext = 3 - (x == input->width - 1);
271  const uint32_t C1 = sa0[pnext];
272  const uint32_t PC = sa1[pnext];
273  const uint32_t PF = sa2[pnext];
274  const uint32_t PI = sa3[pnext];
275  const uint32_t I5 = sa4[pnext];
276 
277  const int pnext2 = pnext + 1 - (x >= input->width - 2);
278  const uint32_t C4 = sa1[pnext2];
279  const uint32_t F4 = sa2[pnext2];
280  const uint32_t I4 = sa3[pnext2];
281 
282  if (n == 2) {
283  E[0] = E[1] = // 0, 1
284  E[nl] = E[nl + 1] = PE; // 2, 3
285 
286  FILT2(PE, PI, PH, PF, PG, PC, PD, PB, PA, G5, C4, G0, D0, C1, B1, F4, I4, H5, I5, A0, A1, 0, 1, nl, nl+1);
287  FILT2(PE, PC, PF, PB, PI, PA, PH, PD, PG, I4, A1, I5, H5, A0, D0, B1, C1, F4, C4, G5, G0, nl, 0, nl+1, 1);
288  FILT2(PE, PA, PB, PD, PC, PG, PF, PH, PI, C1, G0, C4, F4, G5, H5, D0, A0, B1, A1, I4, I5, nl+1, nl, 1, 0);
289  FILT2(PE, PG, PD, PH, PA, PI, PB, PF, PC, A0, I5, A1, B1, I4, F4, H5, G5, D0, G0, C1, C4, 1, nl+1, 0, nl);
290  } else if (n == 3) {
291  E[0] = E[1] = E[2] = // 0, 1, 2
292  E[nl] = E[nl+1] = E[nl+2] = // 3, 4, 5
293  E[nl1] = E[nl1+1] = E[nl1+2] = PE; // 6, 7, 8
294 
295  FILT3(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);
296  FILT3(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);
297  FILT3(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);
298  FILT3(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);
299  } else if (n == 4) {
300  E[0] = E[1] = E[2] = E[3] = // 0, 1, 2, 3
301  E[nl] = E[nl+1] = E[nl+2] = E[nl+3] = // 4, 5, 6, 7
302  E[nl1] = E[nl1+1] = E[nl1+2] = E[nl1+3] = // 8, 9, 10, 11
303  E[nl2] = E[nl2+1] = E[nl2+2] = E[nl2+3] = PE; // 12, 13, 14, 15
304 
305  FILT4(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);
306  FILT4(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);
307  FILT4(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);
308  FILT4(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);
309  }
310 
311  sa0 += 1;
312  sa1 += 1;
313  sa2 += 1;
314  sa3 += 1;
315  sa4 += 1;
316 
317  E += n;
318  }
319  }
320 }
321 
322 #define XBR_FUNC(size) \
323 static int xbr##size##x(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \
324 { \
325  xbr_filter(arg, jobnr, nb_jobs, size); \
326  return 0; \
327 }
328 
329 XBR_FUNC(2)
330 XBR_FUNC(3)
331 XBR_FUNC(4)
332 
333 
334 static int config_output(AVFilterLink *outlink)
335 {
336  AVFilterContext *ctx = outlink->src;
337  XBRContext *s = ctx->priv;
338  AVFilterLink *inlink = ctx->inputs[0];
339 
340  outlink->w = inlink->w * s->n;
341  outlink->h = inlink->h * s->n;
342  return 0;
343 }
344 
346 {
347  static const enum AVPixelFormat pix_fmts[] = {
349  };
350 
352  if (!fmts_list)
353  return AVERROR(ENOMEM);
354  return ff_set_common_formats(ctx, fmts_list);
355 }
356 
357 static int filter_frame(AVFilterLink *inlink, AVFrame *in)
358 {
359  AVFilterContext *ctx = inlink->dst;
360  AVFilterLink *outlink = ctx->outputs[0];
361  XBRContext *s = ctx->priv;
362  ThreadData td;
363 
364  AVFrame *out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
365  if (!out) {
366  av_frame_free(&in);
367  return AVERROR(ENOMEM);
368  }
369 
371 
372  td.in = in;
373  td.out = out;
374  td.rgbtoyuv = s->rgbtoyuv;
375  ctx->internal->execute(ctx, s->func, &td, NULL, FFMIN(inlink->h, ff_filter_get_nb_threads(ctx)));
376 
377  out->width = outlink->w;
378  out->height = outlink->h;
379 
380  av_frame_free(&in);
381  return ff_filter_frame(outlink, out);
382 }
383 
385 {
386  XBRContext *s = ctx->priv;
387  static const xbrfunc_t xbrfuncs[] = {xbr2x, xbr3x, xbr4x};
388 
389  uint32_t c;
390  int bg, rg, g;
391 
392  for (bg = -255; bg < 256; bg++) {
393  for (rg = -255; rg < 256; rg++) {
394  const uint32_t u = (uint32_t)((-169*rg + 500*bg)/1000) + 128;
395  const uint32_t v = (uint32_t)(( 500*rg - 81*bg)/1000) + 128;
396  int startg = FFMAX3(-bg, -rg, 0);
397  int endg = FFMIN3(255-bg, 255-rg, 255);
398  uint32_t y = (uint32_t)(( 299*rg + 1000*startg + 114*bg)/1000);
399  c = bg + rg * (1 << 16) + 0x010101 * startg;
400  for (g = startg; g <= endg; g++) {
401  s->rgbtoyuv[c] = ((y++) << 16) + (u << 8) + v;
402  c+= 0x010101;
403  }
404  }
405  }
406 
407  s->func = xbrfuncs[s->n - 2];
408  return 0;
409 }
410 
411 static const AVFilterPad xbr_inputs[] = {
412  {
413  .name = "default",
414  .type = AVMEDIA_TYPE_VIDEO,
415  .filter_frame = filter_frame,
416  },
417  { NULL }
418 };
419 
420 static const AVFilterPad xbr_outputs[] = {
421  {
422  .name = "default",
423  .type = AVMEDIA_TYPE_VIDEO,
424  .config_props = config_output,
425  },
426  { NULL }
427 };
428 
430  .name = "xbr",
431  .description = NULL_IF_CONFIG_SMALL("Scale the input using xBR algorithm."),
432  .inputs = xbr_inputs,
433  .outputs = xbr_outputs,
434  .query_formats = query_formats,
435  .priv_size = sizeof(XBRContext),
436  .priv_class = &xbr_class,
437  .init = init,
439 };
#define av_always_inline
Definition: attributes.h:45
#define av_cold
Definition: attributes.h:88
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi - 0x80) *(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi - 0x80) *(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(const int16_t *) pi >> 8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(const int32_t *) pi >> 24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31)))) #define SET_CONV_FUNC_GROUP(ofmt, ifmt) static void set_generic_function(AudioConvert *ac) { } void ff_audio_convert_free(AudioConvert **ac) { if(! *ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);} AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, int sample_rate, int apply_map) { AudioConvert *ac;int in_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) return NULL;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);return NULL;} return ac;} 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;} else if(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;else ac->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);return ac;} int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in) { int use_generic=1;int len=in->nb_samples;int p;if(ac->dc) { av_log(ac->avr, AV_LOG_TRACE, "%d samples - audio_convert: %s to %s (dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));return ff_convert_dither(ac-> in
simple assert() macros that are a bit more flexible than ISO C assert().
#define E
Definition: avdct.c:32
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1096
int ff_filter_get_nb_threads(AVFilterContext *ctx)
Get number of threads for current filter instance.
Definition: avfilter.c:802
#define A1
Definition: binkdsp.c:31
#define flags(name, subs,...)
Definition: cbs_av1.c:572
#define u(width, name, range_min, range_max)
Definition: cbs_h2645.c:264
#define s(width, name)
Definition: cbs_vp9.c:257
#define FFMAX3(a, b, c)
Definition: common.h:104
#define FFMIN(a, b)
Definition: common.h:105
#define FFMIN3(a, b, c)
Definition: common.h:106
#define NULL
Definition: coverity.c:32
#define B1
Definition: faandct.c:41
int
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.
Definition: filters.h:271
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:587
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:286
@ AV_OPT_TYPE_INT
Definition: opt.h:225
#define AVFILTER_FLAG_SLICE_THREADS
The filter supports multithreading by splitting frames into multiple parts and processing them concur...
Definition: avfilter.h:117
#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:203
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:658
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
#define PD(a, b)
Pack two delta values (a,b) into one 16-bit word according with endianness of the host machine.
Definition: indeo3data.h:290
const char * arg
Definition: jacosubdec.c:66
common internal API header
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:117
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:309
static int slice_end(AVCodecContext *avctx, AVFrame *pict)
Handle slice ends.
Definition: mpeg12dec.c:2033
#define C4
#define C1
AVOptions.
#define AV_PIX_FMT_0RGB32
Definition: pixfmt.h:376
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:65
#define td
Definition: regdef.h:70
Describe the class of an AVClass context structure.
Definition: log.h:67
An instance of a filter.
Definition: avfilter.h:341
A list of supported formats for one end of a filter link.
Definition: formats.h:65
A filter pad used for either input or output.
Definition: internal.h:54
const char * name
Pad name.
Definition: internal.h:60
Filter definition.
Definition: avfilter.h:145
const char * name
Filter name.
Definition: avfilter.h:149
AVFormatInternal * internal
An opaque field for libavformat internal usage.
Definition: avformat.h:1699
This structure describes decoded (raw) audio or video data.
Definition: frame.h:318
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:332
int width
Definition: frame.h:376
int height
Definition: frame.h:376
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:349
AVOption.
Definition: opt.h:248
Used for passing data between threads.
Definition: dsddec.c:67
const uint32_t * rgbtoyuv
Definition: vf_hqx.c:47
AVFrame * out
Definition: af_adeclick.c:502
AVFrame * in
Definition: af_adenorm.c:223
uint32_t rgbtoyuv[1<< 24]
Definition: vf_xbr.c:51
xbrfunc_t func
Definition: vf_xbr.c:50
int n
Definition: vf_xbr.c:49
FILE * out
Definition: movenc.c:54
AVFormatContext * ctx
Definition: movenc.c:48
const char * g
Definition: vf_curves.c:118
#define PF(suf)
static uint32_t pixel_diff(uint32_t x, uint32_t y, const uint32_t *r2y)
Definition: vf_xbr.c:68
#define ABSDIFF(a, b)
static int query_formats(AVFilterContext *ctx)
Definition: vf_xbr.c:345
#define FILT3(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)
Definition: vf_xbr.c:128
#define YMASK
#define FLAGS
Definition: vf_xbr.c:60
AVFilter ff_vf_xbr
Definition: vf_xbr.c:429
#define XBR_FUNC(size)
Definition: vf_xbr.c:322
static const AVOption xbr_options[]
Definition: vf_xbr.c:61
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
Definition: vf_xbr.c:357
#define VMASK
#define FILT4(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)
Definition: vf_xbr.c:170
static const AVFilterPad xbr_outputs[]
Definition: vf_xbr.c:420
static av_cold int init(AVFilterContext *ctx)
Definition: vf_xbr.c:384
static av_always_inline void xbr_filter(const ThreadData *td, int jobnr, int nb_jobs, int n)
Definition: vf_xbr.c:216
#define UMASK
static const AVFilterPad xbr_inputs[]
Definition: vf_xbr.c:411
#define OFFSET(x)
Definition: vf_xbr.c:59
AVFILTER_DEFINE_CLASS(xbr)
static int config_output(AVFilterLink *outlink)
Definition: vf_xbr.c:334
int(* xbrfunc_t)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_xbr.c:45
#define FILT2(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)
Definition: vf_xbr.c:94
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition: video.c:104
static double c[64]