FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
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 http://www.libretro.com/forums/viewtopic.php?f=6&t=134
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 
36 #define LB_MASK 0x00FEFEFE
37 #define RED_BLUE_MASK 0x00FF00FF
38 #define GREEN_MASK 0x0000FF00
39 
40 typedef int (*xbrfunc_t)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs);
41 
42 typedef struct {
43  const AVClass *class;
44  int n;
46  uint32_t rgbtoyuv[1<<24];
47 } XBRContext;
48 
49 typedef struct ThreadData {
50  AVFrame *in, *out;
51  const uint32_t *rgbtoyuv;
52 } ThreadData;
53 
54 #define OFFSET(x) offsetof(XBRContext, x)
55 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
56 static const AVOption xbr_options[] = {
57  { "n", "set scale factor", OFFSET(n), AV_OPT_TYPE_INT, {.i64 = 3}, 2, 4, .flags = FLAGS },
58  { NULL }
59 };
60 
62 
63 static uint32_t pixel_diff(uint32_t x, uint32_t y, const uint32_t *r2y)
64 {
65 #define YMASK 0xff0000
66 #define UMASK 0x00ff00
67 #define VMASK 0x0000ff
68 
69  uint32_t yuv1 = r2y[x & 0xffffff];
70  uint32_t yuv2 = r2y[y & 0xffffff];
71 
72  return (abs((yuv1 & YMASK) - (yuv2 & YMASK)) >> 16) +
73  (abs((yuv1 & UMASK) - (yuv2 & UMASK)) >> 8) +
74  abs((yuv1 & VMASK) - (yuv2 & VMASK));
75 }
76 
77 #define ALPHA_BLEND_128_W(a, b) ((((a) & LB_MASK) >> 1) + (((b) & LB_MASK) >> 1))
78 #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)))) \
79  | (GREEN_MASK & (((a) & GREEN_MASK) + (((((b) & GREEN_MASK) - ((a) & GREEN_MASK)) * (m)) >> (s)))))
80 #define ALPHA_BLEND_32_W(a, b) ALPHA_BLEND_BASE(a, b, 1, 3)
81 #define ALPHA_BLEND_64_W(a, b) ALPHA_BLEND_BASE(a, b, 1, 2)
82 #define ALPHA_BLEND_192_W(a, b) ALPHA_BLEND_BASE(a, b, 3, 2)
83 #define ALPHA_BLEND_224_W(a, b) ALPHA_BLEND_BASE(a, b, 7, 3)
84 
85 #define df(A, B) pixel_diff(A, B, r2y)
86 #define eq(A, B) (df(A, B) < 155)
87 
88 #define FILT2(PE, PI, PH, PF, PG, PC, PD, PB, PA, G5, C4, G0, D0, C1, B1, F4, I4, H5, I5, A0, A1, \
89  N0, N1, N2, N3) do { \
90  if (PE != PH && PE != PF) { \
91  const unsigned e = df(PE,PC) + df(PE,PG) + df(PI,H5) + df(PI,F4) + (df(PH,PF)<<2); \
92  const unsigned i = df(PH,PD) + df(PH,I5) + df(PF,I4) + df(PF,PB) + (df(PE,PI)<<2); \
93  if (e <= i) { \
94  const unsigned px = df(PE,PF) <= df(PE,PH) ? PF : PH; \
95  if (e < i && (!eq(PF,PB) && !eq(PH,PD) || eq(PE,PI) \
96  && (!eq(PF,I4) && !eq(PH,I5)) \
97  || eq(PE,PG) || eq(PE,PC))) { \
98  const unsigned ke = df(PF,PG); \
99  const unsigned ki = df(PH,PC); \
100  const int left = ke<<1 <= ki && PE != PG && PD != PG; \
101  const int up = ke >= ki<<1 && PE != PC && PB != PC; \
102  if (left && up) { \
103  E[N3] = ALPHA_BLEND_224_W(E[N3], px); \
104  E[N2] = ALPHA_BLEND_64_W( E[N2], px); \
105  E[N1] = E[N2]; \
106  } else if (left) { \
107  E[N3] = ALPHA_BLEND_192_W(E[N3], px); \
108  E[N2] = ALPHA_BLEND_64_W( E[N2], px); \
109  } else if (up) { \
110  E[N3] = ALPHA_BLEND_192_W(E[N3], px); \
111  E[N1] = ALPHA_BLEND_64_W( E[N1], px); \
112  } else { /* diagonal */ \
113  E[N3] = ALPHA_BLEND_128_W(E[N3], px); \
114  } \
115  } else { \
116  E[N3] = ALPHA_BLEND_128_W(E[N3], px); \
117  } \
118  } \
119  } \
120 } while (0)
121 
122 #define FILT3(PE, PI, PH, PF, PG, PC, PD, PB, PA, G5, C4, G0, D0, C1, B1, F4, I4, H5, I5, A0, A1, \
123  N0, N1, N2, N3, N4, N5, N6, N7, N8) do { \
124  if (PE != PH && PE != PF) { \
125  const unsigned e = df(PE,PC) + df(PE,PG) + df(PI,H5) + df(PI,F4) + (df(PH,PF)<<2); \
126  const unsigned i = df(PH,PD) + df(PH,I5) + df(PF,I4) + df(PF,PB) + (df(PE,PI)<<2); \
127  if (e <= i) { \
128  const unsigned px = df(PE,PF) <= df(PE,PH) ? PF : PH; \
129  if (e < i && (!eq(PF,PB) && !eq(PF,PC) || !eq(PH,PD) && !eq(PH,PG) || eq(PE,PI) \
130  && (!eq(PF,F4) && !eq(PF,I4) || !eq(PH,H5) && !eq(PH,I5)) \
131  || eq(PE,PG) || eq(PE,PC))) { \
132  const unsigned ke = df(PF,PG); \
133  const unsigned ki = df(PH,PC); \
134  const int left = ke<<1 <= ki && PE != PG && PD != PG; \
135  const int up = ke >= ki<<1 && PE != PC && PB != PC; \
136  if (left && up) { \
137  E[N7] = ALPHA_BLEND_192_W(E[N7], px); \
138  E[N6] = ALPHA_BLEND_64_W( E[N6], px); \
139  E[N5] = E[N7]; \
140  E[N2] = E[N6]; \
141  E[N8] = px; \
142  } else if (left) { \
143  E[N7] = ALPHA_BLEND_192_W(E[N7], px); \
144  E[N5] = ALPHA_BLEND_64_W( E[N5], px); \
145  E[N6] = ALPHA_BLEND_64_W( E[N6], px); \
146  E[N8] = px; \
147  } else if (up) { \
148  E[N5] = ALPHA_BLEND_192_W(E[N5], px); \
149  E[N7] = ALPHA_BLEND_64_W( E[N7], px); \
150  E[N2] = ALPHA_BLEND_64_W( E[N2], px); \
151  E[N8] = px; \
152  } else { /* diagonal */ \
153  E[N8] = ALPHA_BLEND_224_W(E[N8], px); \
154  E[N5] = ALPHA_BLEND_32_W( E[N5], px); \
155  E[N7] = ALPHA_BLEND_32_W( E[N7], px); \
156  } \
157  } else { \
158  E[N8] = ALPHA_BLEND_128_W(E[N8], px); \
159  } \
160  } \
161  } \
162 } while (0)
163 
164 #define FILT4(PE, PI, PH, PF, PG, PC, PD, PB, PA, G5, C4, G0, D0, C1, B1, F4, I4, H5, I5, A0, A1, \
165  N15, N14, N11, N3, N7, N10, N13, N12, N9, N6, N2, N1, N5, N8, N4, N0) do { \
166  if (PE != PH && PE != PF) { \
167  const unsigned e = df(PE,PC) + df(PE,PG) + df(PI,H5) + df(PI,F4) + (df(PH,PF)<<2); \
168  const unsigned i = df(PH,PD) + df(PH,I5) + df(PF,I4) + df(PF,PB) + (df(PE,PI)<<2); \
169  if (e <= i) { \
170  const unsigned px = df(PE,PF) <= df(PE,PH) ? PF : PH; \
171  if (e < i && (!eq(PF,PB) && !eq(PH,PD) || eq(PE,PI) \
172  && (!eq(PF,I4) && !eq(PH,I5)) \
173  || eq(PE,PG) || eq(PE,PC))) { \
174  const unsigned ke = df(PF,PG); \
175  const unsigned ki = df(PH,PC); \
176  const int left = ke<<1 <= ki && PE != PG && PD != PG; \
177  const int up = ke >= ki<<1 && PE != PC && PB != PC; \
178  if (left && up) { \
179  E[N13] = ALPHA_BLEND_192_W(E[N13], px); \
180  E[N12] = ALPHA_BLEND_64_W( E[N12], px); \
181  E[N15] = E[N14] = E[N11] = px; \
182  E[N10] = E[N3] = E[N12]; \
183  E[N7] = E[N13]; \
184  } else if (left) { \
185  E[N11] = ALPHA_BLEND_192_W(E[N11], px); \
186  E[N13] = ALPHA_BLEND_192_W(E[N13], px); \
187  E[N10] = ALPHA_BLEND_64_W( E[N10], px); \
188  E[N12] = ALPHA_BLEND_64_W( E[N12], px); \
189  E[N14] = px; \
190  E[N15] = px; \
191  } else if (up) { \
192  E[N14] = ALPHA_BLEND_192_W(E[N14], px); \
193  E[N7 ] = ALPHA_BLEND_192_W(E[N7 ], px); \
194  E[N10] = ALPHA_BLEND_64_W( E[N10], px); \
195  E[N3 ] = ALPHA_BLEND_64_W( E[N3 ], px); \
196  E[N11] = px; \
197  E[N15] = px; \
198  } else { /* diagonal */ \
199  E[N11] = ALPHA_BLEND_128_W(E[N11], px); \
200  E[N14] = ALPHA_BLEND_128_W(E[N14], px); \
201  E[N15] = px; \
202  } \
203  } else { \
204  E[N15] = ALPHA_BLEND_128_W(E[N15], px); \
205  } \
206  } \
207  } \
208 } while (0)
209 
210 static av_always_inline void xbr_filter(const ThreadData *td, int jobnr, int nb_jobs, int n)
211 {
212  int x, y;
213  const AVFrame *input = td->in;
214  AVFrame *output = td->out;
215  const uint32_t *r2y = td->rgbtoyuv;
216  const int slice_start = (input->height * jobnr ) / nb_jobs;
217  const int slice_end = (input->height * (jobnr+1)) / nb_jobs;
218  const int nl = output->linesize[0] >> 2;
219  const int nl1 = nl + nl;
220  const int nl2 = nl1 + nl;
221 
222  for (y = slice_start; y < slice_end; y++) {
223 
224  uint32_t *E = (uint32_t *)(output->data[0] + y * output->linesize[0] * n);
225  const uint32_t *sa2 = (uint32_t *)(input->data[0] + y * input->linesize[0] - 8); /* center */
226  const uint32_t *sa1 = sa2 - (input->linesize[0]>>2); /* up x1 */
227  const uint32_t *sa0 = sa1 - (input->linesize[0]>>2); /* up x2 */
228  const uint32_t *sa3 = sa2 + (input->linesize[0]>>2); /* down x1 */
229  const uint32_t *sa4 = sa3 + (input->linesize[0]>>2); /* down x2 */
230 
231  if (y <= 1) {
232  sa0 = sa1;
233  if (y == 0) {
234  sa0 = sa1 = sa2;
235  }
236  }
237 
238  if (y >= input->height - 2) {
239  sa4 = sa3;
240  if (y == input->height - 1) {
241  sa4 = sa3 = sa2;
242  }
243  }
244 
245  for (x = 0; x < input->width; x++) {
246  const uint32_t B1 = sa0[2];
247  const uint32_t PB = sa1[2];
248  const uint32_t PE = sa2[2];
249  const uint32_t PH = sa3[2];
250  const uint32_t H5 = sa4[2];
251 
252  const int pprev = 2 - (x > 0);
253  const uint32_t A1 = sa0[pprev];
254  const uint32_t PA = sa1[pprev];
255  const uint32_t PD = sa2[pprev];
256  const uint32_t PG = sa3[pprev];
257  const uint32_t G5 = sa4[pprev];
258 
259  const int pprev2 = pprev - (x > 1);
260  const uint32_t A0 = sa1[pprev2];
261  const uint32_t D0 = sa2[pprev2];
262  const uint32_t G0 = sa3[pprev2];
263 
264  const int pnext = 3 - (x == input->width - 1);
265  const uint32_t C1 = sa0[pnext];
266  const uint32_t PC = sa1[pnext];
267  const uint32_t PF = sa2[pnext];
268  const uint32_t PI = sa3[pnext];
269  const uint32_t I5 = sa4[pnext];
270 
271  const int pnext2 = pnext + 1 - (x >= input->width - 2);
272  const uint32_t C4 = sa1[pnext2];
273  const uint32_t F4 = sa2[pnext2];
274  const uint32_t I4 = sa3[pnext2];
275 
276  if (n == 2) {
277  E[0] = E[1] = // 0, 1
278  E[nl] = E[nl + 1] = PE; // 2, 3
279 
280  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);
281  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);
282  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);
283  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);
284  } else if (n == 3) {
285  E[0] = E[1] = E[2] = // 0, 1, 2
286  E[nl] = E[nl+1] = E[nl+2] = // 3, 4, 5
287  E[nl1] = E[nl1+1] = E[nl1+2] = PE; // 6, 7, 8
288 
289  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);
290  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);
291  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);
292  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);
293  } else if (n == 4) {
294  E[0] = E[1] = E[2] = E[3] = // 0, 1, 2, 3
295  E[nl] = E[nl+1] = E[nl+2] = E[nl+3] = // 4, 5, 6, 7
296  E[nl1] = E[nl1+1] = E[nl1+2] = E[nl1+3] = // 8, 9, 10, 11
297  E[nl2] = E[nl2+1] = E[nl2+2] = E[nl2+3] = PE; // 12, 13, 14, 15
298 
299  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);
300  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);
301  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);
302  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);
303  }
304 
305  sa0 += 1;
306  sa1 += 1;
307  sa2 += 1;
308  sa3 += 1;
309  sa4 += 1;
310 
311  E += n;
312  }
313  }
314 }
315 
316 #define XBR_FUNC(size) \
317 static int xbr##size##x(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \
318 { \
319  xbr_filter(arg, jobnr, nb_jobs, size); \
320  return 0; \
321 }
322 
323 XBR_FUNC(2)
324 XBR_FUNC(3)
325 XBR_FUNC(4)
326 
327 
328 static int config_output(AVFilterLink *outlink)
329 {
330  AVFilterContext *ctx = outlink->src;
331  XBRContext *xbr = ctx->priv;
332  AVFilterLink *inlink = ctx->inputs[0];
333 
334  outlink->w = inlink->w * xbr->n;
335  outlink->h = inlink->h * xbr->n;
336  return 0;
337 }
338 
340 {
341  static const enum AVPixelFormat pix_fmts[] = {
343  };
344 
345  AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts);
346  if (!fmts_list)
347  return AVERROR(ENOMEM);
348  return ff_set_common_formats(ctx, fmts_list);
349 }
350 
351 static int filter_frame(AVFilterLink *inlink, AVFrame *in)
352 {
353  AVFilterContext *ctx = inlink->dst;
354  AVFilterLink *outlink = ctx->outputs[0];
355  XBRContext *xbr = ctx->priv;
356  ThreadData td;
357 
358  AVFrame *out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
359  if (!out) {
360  av_frame_free(&in);
361  return AVERROR(ENOMEM);
362  }
363 
364  av_frame_copy_props(out, in);
365 
366  td.in = in;
367  td.out = out;
368  td.rgbtoyuv = xbr->rgbtoyuv;
369  ctx->internal->execute(ctx, xbr->func, &td, NULL, FFMIN(inlink->h, ctx->graph->nb_threads));
370 
371  out->width = outlink->w;
372  out->height = outlink->h;
373 
374  av_frame_free(&in);
375  return ff_filter_frame(outlink, out);
376 }
377 
378 static int init(AVFilterContext *ctx)
379 {
380  XBRContext *xbr = ctx->priv;
381  static const xbrfunc_t xbrfuncs[] = {xbr2x, xbr3x, xbr4x};
382 
383  uint32_t c;
384  int bg, rg, g;
385 
386  for (bg = -255; bg < 256; bg++) {
387  for (rg = -255; rg < 256; rg++) {
388  const uint32_t u = (uint32_t)((-169*rg + 500*bg)/1000) + 128;
389  const uint32_t v = (uint32_t)(( 500*rg - 81*bg)/1000) + 128;
390  int startg = FFMAX3(-bg, -rg, 0);
391  int endg = FFMIN3(255-bg, 255-rg, 255);
392  uint32_t y = (uint32_t)(( 299*rg + 1000*startg + 114*bg)/1000);
393  c = bg + (rg<<16) + 0x010101 * startg;
394  for (g = startg; g <= endg; g++) {
395  xbr->rgbtoyuv[c] = ((y++) << 16) + (u << 8) + v;
396  c+= 0x010101;
397  }
398  }
399  }
400 
401  xbr->func = xbrfuncs[xbr->n - 2];
402  return 0;
403 }
404 
405 static const AVFilterPad xbr_inputs[] = {
406  {
407  .name = "default",
408  .type = AVMEDIA_TYPE_VIDEO,
409  .filter_frame = filter_frame,
410  },
411  { NULL }
412 };
413 
414 static const AVFilterPad xbr_outputs[] = {
415  {
416  .name = "default",
417  .type = AVMEDIA_TYPE_VIDEO,
418  .config_props = config_output,
419  },
420  { NULL }
421 };
422 
424  .name = "xbr",
425  .description = NULL_IF_CONFIG_SMALL("Scale the input using xBR algorithm."),
426  .inputs = xbr_inputs,
427  .outputs = xbr_outputs,
428  .query_formats = query_formats,
429  .priv_size = sizeof(XBRContext),
430  .priv_class = &xbr_class,
431  .init = init,
433 };
#define NULL
Definition: coverity.c:32
float v
AVFrame * out
Definition: vf_curves.c:73
#define VMASK
This structure describes decoded (raw) audio or video data.
Definition: frame.h:171
AVOption.
Definition: opt.h:255
#define A1
Definition: binkdsp.c:31
static const AVOption xbr_options[]
Definition: vf_xbr.c:56
xbrfunc_t func
Definition: vf_xbr.c:45
const char * g
Definition: vf_curves.c:108
#define OFFSET(x)
Definition: vf_xbr.c:54
static const AVFilterPad xbr_inputs[]
Definition: vf_xbr.c:405
#define PF(suf)
#define C1
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
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:283
#define B1
Definition: faandct.c:41
struct AVFilterGraph * graph
filtergraph this filter belongs to
Definition: avfilter.h:656
const char * name
Pad name.
Definition: internal.h:67
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:641
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
AVOptions.
int(* xbrfunc_t)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: vf_xbr.c:40
#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:122
#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:88
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
A filter pad used for either input or output.
Definition: internal.h:61
int n
Definition: vf_xbr.c:44
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
#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
static int config_output(AVFilterLink *outlink)
Definition: vf_xbr.c:328
simple assert() macros that are a bit more flexible than ISO C assert().
AVFilter ff_vf_xbr
Definition: vf_xbr.c:423
static int query_formats(AVFilterContext *ctx)
Definition: vf_xbr.c:339
#define YMASK
static av_always_inline void xbr_filter(const ThreadData *td, int jobnr, int nb_jobs, int n)
Definition: vf_xbr.c:210
#define E
Definition: avdct.c:32
#define C4
#define FFMIN(a, b)
Definition: common.h:66
float y
#define FLAGS
Definition: vf_xbr.c:55
#define UMASK
float u
int n
Definition: avisynth_c.h:547
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:199
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
Describe the class of an AVClass context structure.
Definition: log.h:67
Filter definition.
Definition: avfilter.h:470
#define XBR_FUNC(size)
Definition: vf_xbr.c:316
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
Definition: vf_xbr.c:351
static uint32_t pixel_diff(uint32_t x, uint32_t y, const uint32_t *r2y)
Definition: vf_xbr.c:63
const char * name
Filter name.
Definition: avfilter.h:474
#define PD(a, b)
Pack two delta values (a,b) into one 16bit word according with endianness of the host machine...
Definition: indeo3data.h:290
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:648
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]
avfilter_execute_func * execute
Definition: internal.h:162
static int slice_end(AVCodecContext *avctx, AVFrame *pict)
Handle slice ends.
Definition: mpeg12dec.c:2073
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
#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:164
int height
Definition: frame.h:220
#define av_always_inline
Definition: attributes.h:37
internal API functions
static const AVFilterPad xbr_outputs[]
Definition: vf_xbr.c:414
static int init(AVFilterContext *ctx)
Definition: vf_xbr.c:378
AVPixelFormat
Pixel format.
Definition: pixfmt.h:61
AVFILTER_DEFINE_CLASS(xbr)
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
uint32_t rgbtoyuv[1<< 24]
Definition: vf_xbr.c:46
#define AV_PIX_FMT_0RGB32
Definition: pixfmt.h:345