FFmpeg
vf_fspp.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>
3  * Copyright (C) 2005 Nikolaj Poroshin <porosh3@psu.ru>
4  * Copyright (c) 2014 Arwa Arif <arwaarif1994@gmail.com>
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with FFmpeg; if not, write to the Free Software Foundation, Inc.,
20  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  */
22 
23 /**
24  * @file
25  * Fast Simple Post-processing filter
26  * This implementation is based on an algorithm described in
27  * "Aria Nosratinia Embedded Post-Processing for
28  * Enhancement of Compressed Images (1999)"
29  * (http://www.utdallas.edu/~aria/papers/vlsisp99.pdf)
30  * Further, with splitting (I)DCT into horizontal/vertical passes, one of
31  * them can be performed once per block, not per pixel. This allows for much
32  * higher speed.
33  *
34  * Originally written by Michael Niedermayer and Nikolaj for the MPlayer
35  * project, and ported by Arwa Arif for FFmpeg.
36  */
37 
38 #include "libavutil/avassert.h"
39 #include "libavutil/imgutils.h"
40 #include "libavutil/opt.h"
41 #include "libavutil/pixdesc.h"
42 #include "internal.h"
43 #include "vf_fspp.h"
44 
45 #define OFFSET(x) offsetof(FSPPContext, x)
46 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
47 static const AVOption fspp_options[] = {
48  { "quality", "set quality", OFFSET(log2_count), AV_OPT_TYPE_INT, {.i64 = 4}, 4, MAX_LEVEL, FLAGS },
49  { "qp", "force a constant quantizer parameter", OFFSET(qp), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 64, FLAGS },
50  { "strength", "set filter strength", OFFSET(strength), AV_OPT_TYPE_INT, {.i64 = 0}, -15, 32, FLAGS },
51  { "use_bframe_qp", "use B-frames' QP", OFFSET(use_bframe_qp), AV_OPT_TYPE_BOOL,{.i64 = 0}, 0, 1, FLAGS },
52  { NULL }
53 };
54 
56 
57 DECLARE_ALIGNED(32, static const uint8_t, dither)[8][8] = {
58  { 0, 48, 12, 60, 3, 51, 15, 63, },
59  { 32, 16, 44, 28, 35, 19, 47, 31, },
60  { 8, 56, 4, 52, 11, 59, 7, 55, },
61  { 40, 24, 36, 20, 43, 27, 39, 23, },
62  { 2, 50, 14, 62, 1, 49, 13, 61, },
63  { 34, 18, 46, 30, 33, 17, 45, 29, },
64  { 10, 58, 6, 54, 9, 57, 5, 53, },
65  { 42, 26, 38, 22, 41, 25, 37, 21, },
66 };
67 
68 static const short custom_threshold[64] = {
69 // values (296) can't be too high
70 // -it causes too big quant dependence
71 // or maybe overflow(check), which results in some flashing
72  71, 296, 295, 237, 71, 40, 38, 19,
73  245, 193, 185, 121, 102, 73, 53, 27,
74  158, 129, 141, 107, 97, 73, 50, 26,
75  102, 116, 109, 98, 82, 66, 45, 23,
76  71, 94, 95, 81, 70, 56, 38, 20,
77  56, 77, 74, 66, 56, 44, 30, 15,
78  38, 53, 50, 45, 38, 30, 21, 11,
79  20, 27, 26, 23, 20, 15, 11, 5
80 };
81 
82 //This func reads from 1 slice, 1 and clears 0 & 1
83 static void store_slice_c(uint8_t *dst, int16_t *src,
84  ptrdiff_t dst_stride, ptrdiff_t src_stride,
85  ptrdiff_t width, ptrdiff_t height, ptrdiff_t log2_scale)
86 {
87  int y, x;
88 #define STORE(pos) \
89  temp = (src[x + pos] + (d[pos] >> log2_scale)) >> (6 - log2_scale); \
90  src[x + pos] = src[x + pos - 8 * src_stride] = 0; \
91  if (temp & 0x100) temp = ~(temp >> 31); \
92  dst[x + pos] = temp;
93 
94  for (y = 0; y < height; y++) {
95  const uint8_t *d = dither[y];
96  for (x = 0; x < width; x += 8) {
97  int temp;
98  STORE(0);
99  STORE(1);
100  STORE(2);
101  STORE(3);
102  STORE(4);
103  STORE(5);
104  STORE(6);
105  STORE(7);
106  }
107  src += src_stride;
108  dst += dst_stride;
109  }
110 }
111 
112 //This func reads from 2 slices, 0 & 2 and clears 2-nd
113 static void store_slice2_c(uint8_t *dst, int16_t *src,
114  ptrdiff_t dst_stride, ptrdiff_t src_stride,
115  ptrdiff_t width, ptrdiff_t height, ptrdiff_t log2_scale)
116 {
117  int y, x;
118 #define STORE2(pos) \
119  temp = (src[x + pos] + src[x + pos + 16 * src_stride] + (d[pos] >> log2_scale)) >> (6 - log2_scale); \
120  src[x + pos + 16 * src_stride] = 0; \
121  if (temp & 0x100) temp = ~(temp >> 31); \
122  dst[x + pos] = temp;
123 
124  for (y = 0; y < height; y++) {
125  const uint8_t *d = dither[y];
126  for (x = 0; x < width; x += 8) {
127  int temp;
128  STORE2(0);
129  STORE2(1);
130  STORE2(2);
131  STORE2(3);
132  STORE2(4);
133  STORE2(5);
134  STORE2(6);
135  STORE2(7);
136  }
137  src += src_stride;
138  dst += dst_stride;
139  }
140 }
141 
142 static void mul_thrmat_c(int16_t *thr_adr_noq, int16_t *thr_adr, int q)
143 {
144  int a;
145  for (a = 0; a < 64; a++)
146  thr_adr[a] = q * thr_adr_noq[a];
147 }
148 
149 static void filter(FSPPContext *p, uint8_t *dst, uint8_t *src,
150  int dst_stride, int src_stride,
151  int width, int height,
152  uint8_t *qp_store, int qp_stride, int is_luma)
153 {
154  int x, x0, y, es, qy, t;
155 
156  const int stride = is_luma ? p->temp_stride : (width + 16);
157  const int step = 6 - p->log2_count;
158  const int qpsh = 4 - p->hsub * !is_luma;
159  const int qpsv = 4 - p->vsub * !is_luma;
160 
161  DECLARE_ALIGNED(32, int32_t, block_align)[4 * 8 * BLOCKSZ + 4 * 8 * BLOCKSZ];
162  int16_t *block = (int16_t *)block_align;
163  int16_t *block3 = (int16_t *)(block_align + 4 * 8 * BLOCKSZ);
164 
165  memset(block3, 0, 4 * 8 * BLOCKSZ);
166 
167  if (!src || !dst) return;
168 
169  for (y = 0; y < height; y++) {
170  int index = 8 + 8 * stride + y * stride;
171  memcpy(p->src + index, src + y * src_stride, width);
172  for (x = 0; x < 8; x++) {
173  p->src[index - x - 1] = p->src[index + x ];
174  p->src[index + width + x ] = p->src[index + width - x - 1];
175  }
176  }
177 
178  for (y = 0; y < 8; y++) {
179  memcpy(p->src + ( 7 - y ) * stride, p->src + ( y + 8 ) * stride, stride);
180  memcpy(p->src + (height + 8 + y) * stride, p->src + (height - y + 7) * stride, stride);
181  }
182  //FIXME (try edge emu)
183 
184  for (y = 8; y < 24; y++)
185  memset(p->temp + 8 + y * stride, 0, width * sizeof(int16_t));
186 
187  for (y = step; y < height + 8; y += step) { //step= 1,2
188  const int y1 = y - 8 + step; //l5-7 l4-6;
189  qy = y - 4;
190 
191  if (qy > height - 1) qy = height - 1;
192  if (qy < 0) qy = 0;
193 
194  qy = (qy >> qpsv) * qp_stride;
195  p->row_fdct(block, p->src + y * stride + 2 - (y&1), stride, 2);
196 
197  for (x0 = 0; x0 < width + 8 - 8 * (BLOCKSZ - 1); x0 += 8 * (BLOCKSZ - 1)) {
198  p->row_fdct(block + 8 * 8, p->src + y * stride + 8 + x0 + 2 - (y&1), stride, 2 * (BLOCKSZ - 1));
199 
200  if (p->qp)
201  p->column_fidct((int16_t *)(&p->threshold_mtx[0]), block + 0 * 8, block3 + 0 * 8, 8 * (BLOCKSZ - 1)); //yes, this is a HOTSPOT
202  else
203  for (x = 0; x < 8 * (BLOCKSZ - 1); x += 8) {
204  t = x + x0 - 2; //correct t=x+x0-2-(y&1), but its the same
205 
206  if (t < 0) t = 0; //t always < width-2
207 
208  t = qp_store[qy + (t >> qpsh)];
209  t = ff_norm_qscale(t, p->qscale_type);
210 
211  if (t != p->prev_q) p->prev_q = t, p->mul_thrmat((int16_t *)(&p->threshold_mtx_noq[0]), (int16_t *)(&p->threshold_mtx[0]), t);
212  p->column_fidct((int16_t *)(&p->threshold_mtx[0]), block + x * 8, block3 + x * 8, 8); //yes, this is a HOTSPOT
213  }
214  p->row_idct(block3 + 0 * 8, p->temp + (y & 15) * stride + x0 + 2 - (y & 1), stride, 2 * (BLOCKSZ - 1));
215  memmove(block, block + (BLOCKSZ - 1) * 64, 8 * 8 * sizeof(int16_t)); //cycling
216  memmove(block3, block3 + (BLOCKSZ - 1) * 64, 6 * 8 * sizeof(int16_t));
217  }
218 
219  es = width + 8 - x0; // 8, ...
220  if (es > 8)
221  p->row_fdct(block + 8 * 8, p->src + y * stride + 8 + x0 + 2 - (y & 1), stride, (es - 4) >> 2);
222 
223  p->column_fidct((int16_t *)(&p->threshold_mtx[0]), block, block3, es&(~1));
224  if (es > 3)
225  p->row_idct(block3 + 0 * 8, p->temp + (y & 15) * stride + x0 + 2 - (y & 1), stride, es >> 2);
226 
227  if (!(y1 & 7) && y1) {
228  if (y1 & 8)
229  p->store_slice(dst + (y1 - 8) * dst_stride, p->temp + 8 + 8 * stride,
230  dst_stride, stride, width, 8, 5 - p->log2_count);
231  else
232  p->store_slice2(dst + (y1 - 8) * dst_stride, p->temp + 8 + 0 * stride,
233  dst_stride, stride, width, 8, 5 - p->log2_count);
234  }
235  }
236 
237  if (y & 7) { // height % 8 != 0
238  if (y & 8)
239  p->store_slice(dst + ((y - 8) & ~7) * dst_stride, p->temp + 8 + 8 * stride,
240  dst_stride, stride, width, y&7, 5 - p->log2_count);
241  else
242  p->store_slice2(dst + ((y - 8) & ~7) * dst_stride, p->temp + 8 + 0 * stride,
243  dst_stride, stride, width, y&7, 5 - p->log2_count);
244  }
245 }
246 
247 static void column_fidct_c(int16_t *thr_adr, int16_t *data, int16_t *output, int cnt)
248 {
249  int_simd16_t tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
250  int_simd16_t tmp10, tmp11, tmp12, tmp13;
251  int_simd16_t z1,z2,z3,z4,z5, z10, z11, z12, z13;
252  int_simd16_t d0, d1, d2, d3, d4, d5, d6, d7;
253 
254  int16_t *dataptr;
255  int16_t *wsptr;
256  int16_t *threshold;
257  int ctr;
258 
259  dataptr = data;
260  wsptr = output;
261 
262  for (; cnt > 0; cnt -= 2) { //start positions
263  threshold = (int16_t *)thr_adr;//threshold_mtx
264  for (ctr = DCTSIZE; ctr > 0; ctr--) {
265  // Process columns from input, add to output.
266  tmp0 = dataptr[DCTSIZE * 0] + dataptr[DCTSIZE * 7];
267  tmp7 = dataptr[DCTSIZE * 0] - dataptr[DCTSIZE * 7];
268 
269  tmp1 = dataptr[DCTSIZE * 1] + dataptr[DCTSIZE * 6];
270  tmp6 = dataptr[DCTSIZE * 1] - dataptr[DCTSIZE * 6];
271 
272  tmp2 = dataptr[DCTSIZE * 2] + dataptr[DCTSIZE * 5];
273  tmp5 = dataptr[DCTSIZE * 2] - dataptr[DCTSIZE * 5];
274 
275  tmp3 = dataptr[DCTSIZE * 3] + dataptr[DCTSIZE * 4];
276  tmp4 = dataptr[DCTSIZE * 3] - dataptr[DCTSIZE * 4];
277 
278  // Even part of FDCT
279 
280  tmp10 = tmp0 + tmp3;
281  tmp13 = tmp0 - tmp3;
282  tmp11 = tmp1 + tmp2;
283  tmp12 = tmp1 - tmp2;
284 
285  d0 = tmp10 + tmp11;
286  d4 = tmp10 - tmp11;
287 
288  z1 = MULTIPLY16H((tmp12 + tmp13) << 2, FIX_0_707106781);
289  d2 = tmp13 + z1;
290  d6 = tmp13 - z1;
291 
292  // Even part of IDCT
293 
294  THRESHOLD(tmp0, d0, threshold[0 * 8]);
295  THRESHOLD(tmp1, d2, threshold[2 * 8]);
296  THRESHOLD(tmp2, d4, threshold[4 * 8]);
297  THRESHOLD(tmp3, d6, threshold[6 * 8]);
298  tmp0 += 2;
299  tmp10 = (tmp0 + tmp2) >> 2;
300  tmp11 = (tmp0 - tmp2) >> 2;
301 
302  tmp13 = (tmp1 + tmp3) >>2; //+2 ! (psnr decides)
303  tmp12 = MULTIPLY16H((tmp1 - tmp3), FIX_1_414213562_A) - tmp13; //<<2
304 
305  tmp0 = tmp10 + tmp13; //->temps
306  tmp3 = tmp10 - tmp13; //->temps
307  tmp1 = tmp11 + tmp12; //->temps
308  tmp2 = tmp11 - tmp12; //->temps
309 
310  // Odd part of FDCT
311 
312  tmp10 = tmp4 + tmp5;
313  tmp11 = tmp5 + tmp6;
314  tmp12 = tmp6 + tmp7;
315 
316  z5 = MULTIPLY16H((tmp10 - tmp12) << 2, FIX_0_382683433);
317  z2 = MULTIPLY16H(tmp10 << 2, FIX_0_541196100) + z5;
318  z4 = MULTIPLY16H(tmp12 << 2, FIX_1_306562965) + z5;
319  z3 = MULTIPLY16H(tmp11 << 2, FIX_0_707106781);
320 
321  z11 = tmp7 + z3;
322  z13 = tmp7 - z3;
323 
324  d5 = z13 + z2;
325  d3 = z13 - z2;
326  d1 = z11 + z4;
327  d7 = z11 - z4;
328 
329  // Odd part of IDCT
330 
331  THRESHOLD(tmp4, d1, threshold[1 * 8]);
332  THRESHOLD(tmp5, d3, threshold[3 * 8]);
333  THRESHOLD(tmp6, d5, threshold[5 * 8]);
334  THRESHOLD(tmp7, d7, threshold[7 * 8]);
335 
336  //Simd version uses here a shortcut for the tmp5,tmp6,tmp7 == 0
337  z13 = tmp6 + tmp5;
338  z10 = (tmp6 - tmp5) << 1;
339  z11 = tmp4 + tmp7;
340  z12 = (tmp4 - tmp7) << 1;
341 
342  tmp7 = (z11 + z13) >> 2; //+2 !
343  tmp11 = MULTIPLY16H((z11 - z13) << 1, FIX_1_414213562);
344  z5 = MULTIPLY16H(z10 + z12, FIX_1_847759065);
345  tmp10 = MULTIPLY16H(z12, FIX_1_082392200) - z5;
346  tmp12 = MULTIPLY16H(z10, FIX_2_613125930) + z5; // - !!
347 
348  tmp6 = tmp12 - tmp7;
349  tmp5 = tmp11 - tmp6;
350  tmp4 = tmp10 + tmp5;
351 
352  wsptr[DCTSIZE * 0] += (tmp0 + tmp7);
353  wsptr[DCTSIZE * 1] += (tmp1 + tmp6);
354  wsptr[DCTSIZE * 2] += (tmp2 + tmp5);
355  wsptr[DCTSIZE * 3] += (tmp3 - tmp4);
356  wsptr[DCTSIZE * 4] += (tmp3 + tmp4);
357  wsptr[DCTSIZE * 5] += (tmp2 - tmp5);
358  wsptr[DCTSIZE * 6] = (tmp1 - tmp6);
359  wsptr[DCTSIZE * 7] = (tmp0 - tmp7);
360  //
361  dataptr++; //next column
362  wsptr++;
363  threshold++;
364  }
365  dataptr += 8; //skip each second start pos
366  wsptr += 8;
367  }
368 }
369 
370 static void row_idct_c(int16_t *workspace, int16_t *output_adr, ptrdiff_t output_stride, int cnt)
371 {
372  int_simd16_t tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
373  int_simd16_t tmp10, tmp11, tmp12, tmp13;
374  int_simd16_t z5, z10, z11, z12, z13;
375  int16_t *outptr;
376  int16_t *wsptr;
377 
378  cnt *= 4;
379  wsptr = workspace;
380  outptr = output_adr;
381  for (; cnt > 0; cnt--) {
382  // Even part
383  //Simd version reads 4x4 block and transposes it
384  tmp10 = wsptr[2] + wsptr[3];
385  tmp11 = wsptr[2] - wsptr[3];
386 
387  tmp13 = wsptr[0] + wsptr[1];
388  tmp12 = (MULTIPLY16H(wsptr[0] - wsptr[1], FIX_1_414213562_A) << 2) - tmp13;//this shift order to avoid overflow
389 
390  tmp0 = tmp10 + tmp13; //->temps
391  tmp3 = tmp10 - tmp13; //->temps
392  tmp1 = tmp11 + tmp12;
393  tmp2 = tmp11 - tmp12;
394 
395  // Odd part
396  //Also transpose, with previous:
397  // ---- ---- ||||
398  // ---- ---- idct ||||
399  // ---- ---- ---> ||||
400  // ---- ---- ||||
401  z13 = wsptr[4] + wsptr[5];
402  z10 = wsptr[4] - wsptr[5];
403  z11 = wsptr[6] + wsptr[7];
404  z12 = wsptr[6] - wsptr[7];
405 
406  tmp7 = z11 + z13;
407  tmp11 = MULTIPLY16H(z11 - z13, FIX_1_414213562);
408 
409  z5 = MULTIPLY16H(z10 + z12, FIX_1_847759065);
410  tmp10 = MULTIPLY16H(z12, FIX_1_082392200) - z5;
411  tmp12 = MULTIPLY16H(z10, FIX_2_613125930) + z5; // - FIX_
412 
413  tmp6 = (tmp12 << 3) - tmp7;
414  tmp5 = (tmp11 << 3) - tmp6;
415  tmp4 = (tmp10 << 3) + tmp5;
416 
417  // Final output stage: descale and write column
418  outptr[0 * output_stride] += DESCALE(tmp0 + tmp7, 3);
419  outptr[1 * output_stride] += DESCALE(tmp1 + tmp6, 3);
420  outptr[2 * output_stride] += DESCALE(tmp2 + tmp5, 3);
421  outptr[3 * output_stride] += DESCALE(tmp3 - tmp4, 3);
422  outptr[4 * output_stride] += DESCALE(tmp3 + tmp4, 3);
423  outptr[5 * output_stride] += DESCALE(tmp2 - tmp5, 3);
424  outptr[6 * output_stride] += DESCALE(tmp1 - tmp6, 3); //no += ?
425  outptr[7 * output_stride] += DESCALE(tmp0 - tmp7, 3); //no += ?
426  outptr++;
427 
428  wsptr += DCTSIZE; // advance pointer to next row
429  }
430 }
431 
432 static void row_fdct_c(int16_t *data, const uint8_t *pixels, ptrdiff_t line_size, int cnt)
433 {
434  int_simd16_t tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
435  int_simd16_t tmp10, tmp11, tmp12, tmp13;
436  int_simd16_t z1, z2, z3, z4, z5, z11, z13;
437  int16_t *dataptr;
438 
439  cnt *= 4;
440  // Pass 1: process rows.
441 
442  dataptr = data;
443  for (; cnt > 0; cnt--) {
444  tmp0 = pixels[line_size * 0] + pixels[line_size * 7];
445  tmp7 = pixels[line_size * 0] - pixels[line_size * 7];
446  tmp1 = pixels[line_size * 1] + pixels[line_size * 6];
447  tmp6 = pixels[line_size * 1] - pixels[line_size * 6];
448  tmp2 = pixels[line_size * 2] + pixels[line_size * 5];
449  tmp5 = pixels[line_size * 2] - pixels[line_size * 5];
450  tmp3 = pixels[line_size * 3] + pixels[line_size * 4];
451  tmp4 = pixels[line_size * 3] - pixels[line_size * 4];
452 
453  // Even part
454 
455  tmp10 = tmp0 + tmp3;
456  tmp13 = tmp0 - tmp3;
457  tmp11 = tmp1 + tmp2;
458  tmp12 = tmp1 - tmp2;
459  //Even columns are written first, this leads to different order of columns
460  //in column_fidct(), but they are processed independently, so all ok.
461  //Later in the row_idct() columns readed at the same order.
462  dataptr[2] = tmp10 + tmp11;
463  dataptr[3] = tmp10 - tmp11;
464 
465  z1 = MULTIPLY16H((tmp12 + tmp13) << 2, FIX_0_707106781);
466  dataptr[0] = tmp13 + z1;
467  dataptr[1] = tmp13 - z1;
468 
469  // Odd part
470 
471  tmp10 = (tmp4 + tmp5) << 2;
472  tmp11 = (tmp5 + tmp6) << 2;
473  tmp12 = (tmp6 + tmp7) << 2;
474 
475  z5 = MULTIPLY16H(tmp10 - tmp12, FIX_0_382683433);
476  z2 = MULTIPLY16H(tmp10, FIX_0_541196100) + z5;
477  z4 = MULTIPLY16H(tmp12, FIX_1_306562965) + z5;
478  z3 = MULTIPLY16H(tmp11, FIX_0_707106781);
479 
480  z11 = tmp7 + z3;
481  z13 = tmp7 - z3;
482 
483  dataptr[4] = z13 + z2;
484  dataptr[5] = z13 - z2;
485  dataptr[6] = z11 + z4;
486  dataptr[7] = z11 - z4;
487 
488  pixels++; // advance pointer to next column
489  dataptr += DCTSIZE;
490  }
491 }
492 
494 {
495  static const enum AVPixelFormat pix_fmts[] = {
503  };
504 
506  if (!fmts_list)
507  return AVERROR(ENOMEM);
508  return ff_set_common_formats(ctx, fmts_list);
509 }
510 
512 {
513  AVFilterContext *ctx = inlink->dst;
514  FSPPContext *fspp = ctx->priv;
515  const int h = FFALIGN(inlink->h + 16, 16);
517 
518  fspp->hsub = desc->log2_chroma_w;
519  fspp->vsub = desc->log2_chroma_h;
520 
521  fspp->temp_stride = FFALIGN(inlink->w + 16, 16);
522  fspp->temp = av_malloc_array(fspp->temp_stride, h * sizeof(*fspp->temp));
523  fspp->src = av_malloc_array(fspp->temp_stride, h * sizeof(*fspp->src));
524 
525  if (!fspp->temp || !fspp->src)
526  return AVERROR(ENOMEM);
527 
528  if (!fspp->use_bframe_qp && !fspp->qp) {
530  fspp->non_b_qp_table = av_calloc(fspp->non_b_qp_alloc_size, sizeof(*fspp->non_b_qp_table));
531  if (!fspp->non_b_qp_table)
532  return AVERROR(ENOMEM);
533  }
534 
535  fspp->store_slice = store_slice_c;
537  fspp->mul_thrmat = mul_thrmat_c;
539  fspp->row_idct = row_idct_c;
540  fspp->row_fdct = row_fdct_c;
541 
542  if (ARCH_X86)
543  ff_fspp_init_x86(fspp);
544 
545  return 0;
546 }
547 
549 {
550  AVFilterContext *ctx = inlink->dst;
551  FSPPContext *fspp = ctx->priv;
552  AVFilterLink *outlink = ctx->outputs[0];
553  AVFrame *out = in;
554 
555  int qp_stride = 0;
556  uint8_t *qp_table = NULL;
557  int i, bias;
558  int custom_threshold_m[64];
559 
560  bias = (1 << 4) + fspp->strength;
561 
562  for (i = 0; i < 64; i++) //FIXME: tune custom_threshold[] and remove this !
563  custom_threshold_m[i] = (int)(custom_threshold[i] * (bias / 71.0) + 0.5);
564 
565  for (i = 0; i < 8; i++) {
566  fspp->threshold_mtx_noq[2 * i] = (uint64_t)custom_threshold_m[i * 8 + 2]
567  |(((uint64_t)custom_threshold_m[i * 8 + 6]) << 16)
568  |(((uint64_t)custom_threshold_m[i * 8 + 0]) << 32)
569  |(((uint64_t)custom_threshold_m[i * 8 + 4]) << 48);
570 
571  fspp->threshold_mtx_noq[2 * i + 1] = (uint64_t)custom_threshold_m[i * 8 + 5]
572  |(((uint64_t)custom_threshold_m[i * 8 + 3]) << 16)
573  |(((uint64_t)custom_threshold_m[i * 8 + 1]) << 32)
574  |(((uint64_t)custom_threshold_m[i * 8 + 7]) << 48);
575  }
576 
577  if (fspp->qp)
578  fspp->prev_q = fspp->qp, fspp->mul_thrmat((int16_t *)(&fspp->threshold_mtx_noq[0]), (int16_t *)(&fspp->threshold_mtx[0]), fspp->qp);
579 
580  /* if we are not in a constant user quantizer mode and we don't want to use
581  * the quantizers from the B-frames (B-frames often have a higher QP), we
582  * need to save the qp table from the last non B-frame; this is what the
583  * following code block does */
584  if (!fspp->qp) {
585  qp_table = av_frame_get_qp_table(in, &qp_stride, &fspp->qscale_type);
586 
587  if (qp_table && !fspp->use_bframe_qp && in->pict_type != AV_PICTURE_TYPE_B) {
588  int w, h;
589 
590  /* if the qp stride is not set, it means the QP are only defined on
591  * a line basis */
592  if (!qp_stride) {
593  w = AV_CEIL_RSHIFT(inlink->w, 4);
594  h = 1;
595  } else {
596  w = qp_stride;
597  h = AV_CEIL_RSHIFT(inlink->h, 4);
598  }
599  if (w * h > fspp->non_b_qp_alloc_size) {
600  int ret = av_reallocp_array(&fspp->non_b_qp_table, w, h);
601  if (ret < 0) {
602  fspp->non_b_qp_alloc_size = 0;
603  return ret;
604  }
605  fspp->non_b_qp_alloc_size = w * h;
606  }
607 
608  av_assert0(w * h <= fspp->non_b_qp_alloc_size);
609  memcpy(fspp->non_b_qp_table, qp_table, w * h);
610  }
611  }
612 
613  if (fspp->log2_count && !ctx->is_disabled) {
614  if (!fspp->use_bframe_qp && fspp->non_b_qp_table)
615  qp_table = fspp->non_b_qp_table;
616 
617  if (qp_table || fspp->qp) {
618  const int cw = AV_CEIL_RSHIFT(inlink->w, fspp->hsub);
619  const int ch = AV_CEIL_RSHIFT(inlink->h, fspp->vsub);
620 
621  /* get a new frame if in-place is not possible or if the dimensions
622  * are not multiple of 8 */
623  if (!av_frame_is_writable(in) || (inlink->w & 7) || (inlink->h & 7)) {
624  const int aligned_w = FFALIGN(inlink->w, 8);
625  const int aligned_h = FFALIGN(inlink->h, 8);
626 
627  out = ff_get_video_buffer(outlink, aligned_w, aligned_h);
628  if (!out) {
629  av_frame_free(&in);
630  return AVERROR(ENOMEM);
631  }
633  out->width = in->width;
634  out->height = in->height;
635  }
636 
637  filter(fspp, out->data[0], in->data[0], out->linesize[0], in->linesize[0],
638  inlink->w, inlink->h, qp_table, qp_stride, 1);
639  filter(fspp, out->data[1], in->data[1], out->linesize[1], in->linesize[1],
640  cw, ch, qp_table, qp_stride, 0);
641  filter(fspp, out->data[2], in->data[2], out->linesize[2], in->linesize[2],
642  cw, ch, qp_table, qp_stride, 0);
643  emms_c();
644  }
645  }
646 
647  if (in != out) {
648  if (in->data[3])
649  av_image_copy_plane(out->data[3], out->linesize[3],
650  in ->data[3], in ->linesize[3],
651  inlink->w, inlink->h);
652  av_frame_free(&in);
653  }
654  return ff_filter_frame(outlink, out);
655 }
656 
658 {
659  FSPPContext *fspp = ctx->priv;
660  av_freep(&fspp->temp);
661  av_freep(&fspp->src);
662  av_freep(&fspp->non_b_qp_table);
663 }
664 
665 static const AVFilterPad fspp_inputs[] = {
666  {
667  .name = "default",
668  .type = AVMEDIA_TYPE_VIDEO,
669  .config_props = config_input,
670  .filter_frame = filter_frame,
671  },
672  { NULL }
673 };
674 
675 static const AVFilterPad fspp_outputs[] = {
676  {
677  .name = "default",
678  .type = AVMEDIA_TYPE_VIDEO,
679  },
680  { NULL }
681 };
682 
684  .name = "fspp",
685  .description = NULL_IF_CONFIG_SMALL("Apply Fast Simple Post-processing filter."),
686  .priv_size = sizeof(FSPPContext),
687  .uninit = uninit,
689  .inputs = fspp_inputs,
691  .priv_class = &fspp_class,
693 };
ff_get_video_buffer
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition: video.c:99
MULTIPLY16H
#define MULTIPLY16H(x, k)
Definition: vf_fspp.h:36
stride
int stride
Definition: mace.c:144
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
FIX_0_707106781
#define FIX_0_707106781
Definition: jfdctfst.c:118
FIX_0_541196100
#define FIX_0_541196100
Definition: jfdctfst.c:117
FSPPContext::column_fidct
void(* column_fidct)(int16_t *thr_adr, int16_t *data, int16_t *output, int cnt)
Definition: vf_fspp.h:82
store_slice2_c
static void store_slice2_c(uint8_t *dst, int16_t *src, ptrdiff_t dst_stride, ptrdiff_t src_stride, ptrdiff_t width, ptrdiff_t height, ptrdiff_t log2_scale)
Definition: vf_fspp.c:113
vf_fspp.h
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
opt.h
FSPPContext::hsub
int hsub
Definition: vf_fspp.h:60
STORE
#define STORE(pos)
ff_make_format_list
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:283
out
FILE * out
Definition: movenc.c:54
FSPPContext::threshold_mtx_noq
uint64_t threshold_mtx_noq[8 *2]
Definition: vf_fspp.h:55
ff_filter_frame
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1080
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2522
ch
uint8_t pi<< 24) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_U8,(uint64_t)((*(const uint8_t *) pi - 0x80U))<< 56) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8,(*(const uint8_t *) pi - 0x80) *(1.0f/(1<< 7))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8,(*(const uint8_t *) pi - 0x80) *(1.0/(1<< 7))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16,(*(const int16_t *) pi >>8)+0x80) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_S16,(uint64_t)(*(const int16_t *) pi)<< 48) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, *(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, *(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32,(*(const int32_t *) pi >>24)+0x80) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_S32,(uint64_t)(*(const int32_t *) pi)<< 32) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, *(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, *(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S64,(*(const int64_t *) pi >>56)+0x80) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S64, *(const int64_t *) pi *(1.0f/(INT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S64, *(const int64_t *) pi *(1.0/(INT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_FLT, llrintf(*(const float *) pi *(INT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31)))) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_DBL, llrint(*(const double *) pi *(INT64_C(1)<< 63))) #define FMT_PAIR_FUNC(out, in) static conv_func_type *const fmt_pair_to_conv_functions[AV_SAMPLE_FMT_NB *AV_SAMPLE_FMT_NB]={ FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S64), };static void cpy1(uint8_t **dst, const uint8_t **src, int len){ memcpy(*dst, *src, len);} static void cpy2(uint8_t **dst, const uint8_t **src, int len){ memcpy(*dst, *src, 2 *len);} static void cpy4(uint8_t **dst, const uint8_t **src, int len){ memcpy(*dst, *src, 4 *len);} static void cpy8(uint8_t **dst, const uint8_t **src, int len){ memcpy(*dst, *src, 8 *len);} AudioConvert *swri_audio_convert_alloc(enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, const int *ch_map, int flags) { AudioConvert *ctx;conv_func_type *f=fmt_pair_to_conv_functions[av_get_packed_sample_fmt(out_fmt)+AV_SAMPLE_FMT_NB *av_get_packed_sample_fmt(in_fmt)];if(!f) return NULL;ctx=av_mallocz(sizeof(*ctx));if(!ctx) return NULL;if(channels==1){ in_fmt=av_get_planar_sample_fmt(in_fmt);out_fmt=av_get_planar_sample_fmt(out_fmt);} ctx->channels=channels;ctx->conv_f=f;ctx->ch_map=ch_map;if(in_fmt==AV_SAMPLE_FMT_U8||in_fmt==AV_SAMPLE_FMT_U8P) memset(ctx->silence, 0x80, sizeof(ctx->silence));if(out_fmt==in_fmt &&!ch_map) { switch(av_get_bytes_per_sample(in_fmt)){ case 1:ctx->simd_f=cpy1;break;case 2:ctx->simd_f=cpy2;break;case 4:ctx->simd_f=cpy4;break;case 8:ctx->simd_f=cpy8;break;} } if(HAVE_X86ASM &&1) swri_audio_convert_init_x86(ctx, out_fmt, in_fmt, channels);if(ARCH_ARM) swri_audio_convert_init_arm(ctx, out_fmt, in_fmt, channels);if(ARCH_AARCH64) swri_audio_convert_init_aarch64(ctx, out_fmt, in_fmt, channels);return ctx;} void swri_audio_convert_free(AudioConvert **ctx) { av_freep(ctx);} int swri_audio_convert(AudioConvert *ctx, AudioData *out, AudioData *in, int len) { int ch;int off=0;const int os=(out->planar ? 1 :out->ch_count) *out->bps;unsigned misaligned=0;av_assert0(ctx->channels==out->ch_count);if(ctx->in_simd_align_mask) { int planes=in->planar ? in->ch_count :1;unsigned m=0;for(ch=0;ch< planes;ch++) m|=(intptr_t) in->ch[ch];misaligned|=m &ctx->in_simd_align_mask;} if(ctx->out_simd_align_mask) { int planes=out->planar ? out->ch_count :1;unsigned m=0;for(ch=0;ch< planes;ch++) m|=(intptr_t) out->ch[ch];misaligned|=m &ctx->out_simd_align_mask;} if(ctx->simd_f &&!ctx->ch_map &&!misaligned){ off=len &~15;av_assert1(off >=0);av_assert1(off<=len);av_assert2(ctx->channels==SWR_CH_MAX||!in->ch[ctx->channels]);if(off >0){ if(out->planar==in->planar){ int planes=out->planar ? out->ch_count :1;for(ch=0;ch< planes;ch++){ ctx->simd_f(out-> ch ch
Definition: audioconvert.c:56
output
filter_frame For filters that do not use the this method is called when a frame is pushed to the filter s input It can be called at any time except in a reentrant way If the input frame is enough to produce output
Definition: filter_design.txt:225
inlink
The exact code depends on how similar the blocks are and how related they are to the and needs to apply these operations to the correct inlink or outlink if there are several Macros are available to factor that when no extra processing is inlink
Definition: filter_design.txt:212
FLAGS
#define FLAGS
Definition: vf_fspp.c:46
FSPPContext::store_slice
void(* store_slice)(uint8_t *dst, int16_t *src, ptrdiff_t dst_stride, ptrdiff_t src_stride, ptrdiff_t width, ptrdiff_t height, ptrdiff_t log2_scale)
Definition: vf_fspp.h:72
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:202
FSPPContext::vsub
int vsub
Definition: vf_fspp.h:61
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:295
pixdesc.h
step
trying all byte sequences megabyte in length and selecting the best looking sequence will yield cases to try But a word about which is also called distortion Distortion can be quantified by almost any quality measurement one chooses the sum of squared differences is used but more complex methods that consider psychovisual effects can be used as well It makes no difference in this discussion First step
Definition: rate_distortion.txt:58
w
uint8_t w
Definition: llviddspenc.c:38
pixels
int pixels
Definition: avisynth_c.h:390
AVOption
AVOption.
Definition: opt.h:246
data
const char data[16]
Definition: mxf.c:91
AV_PIX_FMT_YUV440P
@ AV_PIX_FMT_YUV440P
planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
Definition: pixfmt.h:99
FSPPContext::src
uint8_t * src
Definition: vf_fspp.h:66
AVFilter::name
const char * name
Filter name.
Definition: avfilter.h:148
FIX_1_082392200
#define FIX_1_082392200
Definition: 4xm.c:156
FSPPContext::row_idct
void(* row_idct)(int16_t *workspace, int16_t *output_adr, ptrdiff_t output_stride, int cnt)
Definition: vf_fspp.h:85
FSPPContext::non_b_qp_alloc_size
int non_b_qp_alloc_size
Definition: vf_fspp.h:69
av_image_copy_plane
void av_image_copy_plane(uint8_t *dst, int dst_linesize, const uint8_t *src, int src_linesize, int bytewidth, int height)
Copy image plane from src to dst.
Definition: imgutils.c:338
FIX_2_613125930
#define FIX_2_613125930
Definition: 4xm.c:159
AVFilterFormats
A list of supported formats for one end of a filter link.
Definition: formats.h:64
av_frame_get_qp_table
int8_t * av_frame_get_qp_table(AVFrame *f, int *stride, int *type)
Definition: frame.c:90
row_fdct_c
static void row_fdct_c(int16_t *data, const uint8_t *pixels, ptrdiff_t line_size, int cnt)
Definition: vf_fspp.c:432
BLOCKSZ
#define BLOCKSZ
Definition: vf_fspp.h:28
FIX_0_382683433
#define FIX_0_382683433
Definition: jfdctfst.c:116
fspp_inputs
static const AVFilterPad fspp_inputs[]
Definition: vf_fspp.c:665
custom_threshold
static const short custom_threshold[64]
Definition: vf_fspp.c:68
mul_thrmat_c
static void mul_thrmat_c(int16_t *thr_adr_noq, int16_t *thr_adr, int q)
Definition: vf_fspp.c:142
src
#define src
Definition: vp8dsp.c:254
AVFilterPad
A filter pad used for either input or output.
Definition: internal.h:54
avassert.h
av_cold
#define av_cold
Definition: attributes.h:84
ff_set_common_formats
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:568
column_fidct_c
static void column_fidct_c(int16_t *thr_adr, int16_t *data, int16_t *output, int cnt)
Definition: vf_fspp.c:247
AV_PIX_FMT_YUVJ422P
@ AV_PIX_FMT_YUVJ422P
planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV422P and setting col...
Definition: pixfmt.h:79
width
#define width
AV_CEIL_RSHIFT
#define AV_CEIL_RSHIFT(a, b)
Definition: common.h:58
FSPPContext::row_fdct
void(* row_fdct)(int16_t *data, const uint8_t *pixels, ptrdiff_t line_size, int cnt)
Definition: vf_fspp.h:88
DCTSIZE
#define DCTSIZE
Definition: jfdctfst.c:74
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
outputs
static const AVFilterPad outputs[]
Definition: af_acontrast.c:203
pix_fmts
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:275
ctx
AVFormatContext * ctx
Definition: movenc.c:48
config_input
static int config_input(AVFilterLink *inlink)
Definition: vf_fspp.c:511
store_slice_c
static void store_slice_c(uint8_t *dst, int16_t *src, ptrdiff_t dst_stride, ptrdiff_t src_stride, ptrdiff_t width, ptrdiff_t height, ptrdiff_t log2_scale)
Definition: vf_fspp.c:83
AV_PIX_FMT_YUV420P
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:66
FSPPContext::log2_count
int log2_count
Definition: vf_fspp.h:58
AV_PIX_FMT_YUVJ444P
@ AV_PIX_FMT_YUVJ444P
planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV444P and setting col...
Definition: pixfmt.h:80
int32_t
int32_t
Definition: audio_convert.c:194
NULL
#define NULL
Definition: coverity.c:32
av_frame_copy_props
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:654
FSPPContext::qp
int qp
Definition: vf_fspp.h:63
AV_PIX_FMT_YUVJ420P
@ AV_PIX_FMT_YUVJ420P
planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV420P and setting col...
Definition: pixfmt.h:78
FIX_1_306562965
#define FIX_1_306562965
Definition: jfdctfst.c:119
STORE2
#define STORE2(pos)
ff_vf_fspp
AVFilter ff_vf_fspp
Definition: vf_fspp.c:683
inputs
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several inputs
Definition: filter_design.txt:243
AV_PIX_FMT_GRAY8
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
Definition: pixfmt.h:74
query_formats
static int query_formats(AVFilterContext *ctx)
Definition: vf_fspp.c:493
index
int index
Definition: gxfenc.c:89
for
for(j=16;j >0;--j)
Definition: h264pred_template.c:469
MAX_LEVEL
#define MAX_LEVEL
Definition: rl.h:36
desc
const char * desc
Definition: nvenc.c:68
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:188
FSPPContext::strength
int strength
Definition: vf_fspp.h:59
uninit
static av_cold void uninit(AVFilterContext *ctx)
Definition: vf_fspp.c:657
av_frame_is_writable
int av_frame_is_writable(AVFrame *frame)
Check if the frame data is writable.
Definition: frame.c:594
ff_norm_qscale
static int ff_norm_qscale(int qscale, int type)
Normalize the qscale factor FIXME the H264 qscale is a log based scale, mpeg1/2 is not,...
Definition: internal.h:397
OFFSET
#define OFFSET(x)
Definition: vf_fspp.c:45
height
#define height
a
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
Definition: undefined.txt:41
av_reallocp_array
int av_reallocp_array(void *ptr, size_t nmemb, size_t size)
Allocate, reallocate, or free an array through a pointer to a pointer.
Definition: mem.c:205
fspp_options
static const AVOption fspp_options[]
Definition: vf_fspp.c:47
row_idct_c
static void row_idct_c(int16_t *workspace, int16_t *output_adr, ptrdiff_t output_stride, int cnt)
Definition: vf_fspp.c:370
FSPPContext::threshold_mtx
uint64_t threshold_mtx[8 *2]
Definition: vf_fspp.h:56
FIX_1_847759065
#define FIX_1_847759065
Definition: 4xm.c:158
internal.h
DECLARE_ALIGNED
#define DECLARE_ALIGNED(n, t, v)
Definition: mem.h:112
FSPPContext::temp_stride
int temp_stride
Definition: vf_fspp.h:62
in
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
Definition: audio_convert.c:326
FSPPContext::use_bframe_qp
int use_bframe_qp
Definition: vf_fspp.h:70
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
av_malloc_array
#define av_malloc_array(a, b)
Definition: tableprint_vlc.h:32
AV_PIX_FMT_YUVJ440P
@ AV_PIX_FMT_YUVJ440P
planar YUV 4:4:0 full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV440P and setting color_range
Definition: pixfmt.h:100
uint8_t
uint8_t
Definition: audio_convert.c:194
FIX_1_414213562
#define FIX_1_414213562
Definition: 4xm.c:157
AVFilterPad::name
const char * name
Pad name.
Definition: internal.h:60
DESCALE
#define DESCALE(x, n)
Definition: jfdctfst.c:135
AVFilter
Filter definition.
Definition: avfilter.h:144
ret
ret
Definition: filter_design.txt:187
fspp_outputs
static const AVFilterPad fspp_outputs[]
Definition: vf_fspp.c:675
FSPPContext
Definition: vf_fspp.h:53
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Non-inlined equivalent of av_mallocz_array().
Definition: mem.c:244
ff_fspp_init_x86
void ff_fspp_init_x86(FSPPContext *fspp)
Definition: vf_fspp_init.c:37
FIX_1_414213562_A
static const int16_t FIX_1_414213562_A
Definition: vf_fspp.h:47
AV_PICTURE_TYPE_B
@ AV_PICTURE_TYPE_B
Bi-dir predicted.
Definition: avutil.h:276
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:65
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:223
filter
static void filter(FSPPContext *p, uint8_t *dst, uint8_t *src, int dst_stride, int src_stride, int width, int height, uint8_t *qp_store, int qp_stride, int is_luma)
Definition: vf_fspp.c:149
FSPPContext::mul_thrmat
void(* mul_thrmat)(int16_t *thr_adr_noq, int16_t *thr_adr, int q)
Definition: vf_fspp.h:80
temp
else temp
Definition: vf_mcdeint.c:256
AV_PIX_FMT_YUV444P
@ AV_PIX_FMT_YUV444P
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition: pixfmt.h:71
AVFilterContext
An instance of a filter.
Definition: avfilter.h:338
FSPPContext::store_slice2
void(* store_slice2)(uint8_t *dst, int16_t *src, ptrdiff_t dst_stride, ptrdiff_t src_stride, ptrdiff_t width, ptrdiff_t height, ptrdiff_t log2_scale)
Definition: vf_fspp.h:76
AV_PIX_FMT_GBRP
@ AV_PIX_FMT_GBRP
planar GBR 4:4:4 24bpp
Definition: pixfmt.h:168
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
AV_PIX_FMT_YUV422P
@ AV_PIX_FMT_YUV422P
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition: pixfmt.h:70
AVPixFmtDescriptor
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:81
FSPPContext::temp
int16_t * temp
Definition: vf_fspp.h:67
filter_frame
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
Definition: vf_fspp.c:548
FFALIGN
#define FFALIGN(x, a)
Definition: macros.h:48
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Definition: opt.h:240
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
AV_PIX_FMT_YUV411P
@ AV_PIX_FMT_YUV411P
planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
Definition: pixfmt.h:73
FSPPContext::prev_q
int prev_q
Definition: vf_fspp.h:65
AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL
#define AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL
Same as AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, except that the filter will have its filter_frame() c...
Definition: avfilter.h:133
imgutils.h
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:565
AV_PIX_FMT_YUV410P
@ AV_PIX_FMT_YUV410P
planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples)
Definition: pixfmt.h:72
block
The exact code depends on how similar the blocks are and how related they are to the block
Definition: filter_design.txt:207
FSPPContext::qscale_type
int qscale_type
Definition: vf_fspp.h:64
h
h
Definition: vp9dsp_template.c:2038
AVFILTER_DEFINE_CLASS
AVFILTER_DEFINE_CLASS(fspp)
int_simd16_t
int32_t int_simd16_t
Definition: vf_fspp.h:42
FSPPContext::non_b_qp_table
uint8_t * non_b_qp_table
Definition: vf_fspp.h:68
THRESHOLD
#define THRESHOLD(r, x, t)
Definition: vf_fspp.h:37
dither
static const uint8_t dither[8][8]
Definition: vf_fspp.c:57