FFmpeg
vf_uspp.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>
3  * Copyright (c) 2014 Arwa Arif <arwaarif1994@gmail.com>
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (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
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with FFmpeg; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21 
22 /**
23  * @file
24  * Ultra Slow/Simple Post-processing filter.
25  *
26  * Originally written by Michael Niedermayer for the MPlayer project, and
27  * ported by Arwa Arif for FFmpeg.
28  */
29 
30 #include "libavutil/avassert.h"
31 #include "libavutil/imgutils.h"
32 #include "libavutil/mem.h"
33 #include "libavutil/mem_internal.h"
34 #include "libavutil/opt.h"
35 #include "libavutil/pixdesc.h"
37 #include "libavcodec/avcodec.h"
38 
39 #include "filters.h"
40 #include "qp_table.h"
41 #include "avfilter.h"
42 #include "video.h"
43 
44 #define MAX_LEVEL 8 /* quality levels */
45 #define BLOCK 16
46 
47 typedef struct USPPContext {
48  const AVClass *av_class;
50  int count;
51  int hsub, vsub;
52  int qp;
53  char *codec_name;
55  int temp_stride[3];
56  uint8_t *src[3];
57  uint16_t *temp[3];
59  uint8_t *outbuf;
65  int8_t *non_b_qp_table;
68  int quality;
69 } USPPContext;
70 
71 #define OFFSET(x) offsetof(USPPContext, x)
72 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
73 static const AVOption uspp_options[] = {
74  { "quality", "set quality", OFFSET(log2_count), AV_OPT_TYPE_INT, {.i64 = 3}, 0, MAX_LEVEL, FLAGS },
75  { "qp", "force a constant quantizer parameter", OFFSET(qp), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 63, FLAGS },
76  { "use_bframe_qp", "use B-frames' QP", OFFSET(use_bframe_qp), AV_OPT_TYPE_BOOL,{.i64 = 0}, 0, 1, FLAGS },
77  { "codec", "Codec name", OFFSET(codec_name), AV_OPT_TYPE_STRING, {.str = "snow"}, 0, 0, FLAGS },
78  { NULL }
79 };
80 
82 
83 DECLARE_ALIGNED(8, static const uint8_t, dither)[8][8] = {
84  { 0*4, 48*4, 12*4, 60*4, 3*4, 51*4, 15*4, 63*4, },
85  { 32*4, 16*4, 44*4, 28*4, 35*4, 19*4, 47*4, 31*4, },
86  { 8*4, 56*4, 4*4, 52*4, 11*4, 59*4, 7*4, 55*4, },
87  { 40*4, 24*4, 36*4, 20*4, 43*4, 27*4, 39*4, 23*4, },
88  { 2*4, 50*4, 14*4, 62*4, 1*4, 49*4, 13*4, 61*4, },
89  { 34*4, 18*4, 46*4, 30*4, 33*4, 17*4, 45*4, 29*4, },
90  { 10*4, 58*4, 6*4, 54*4, 9*4, 57*4, 5*4, 53*4, },
91  { 42*4, 26*4, 38*4, 22*4, 41*4, 25*4, 37*4, 21*4, },
92 };
93 
94 static const uint8_t offset[511][2] = {
95  { 0, 0},
96  { 0, 0}, { 8, 8}, // quality 1
97  { 0, 0}, { 4, 4}, {12, 8}, { 8,12}, // quality 2
98  { 0, 0}, {10, 2}, { 4, 4}, {14, 6}, { 8, 8}, { 2,10}, {12,12}, { 6,14}, // quality 3
99 
100  { 0, 0}, {10, 2}, { 4, 4}, {14, 6}, { 8, 8}, { 2,10}, {12,12}, { 6,14},
101  { 5, 1}, {15, 3}, { 9, 5}, { 3, 7}, {13, 9}, { 7,11}, { 1,13}, {11,15}, // quality 4
102 
103  { 0, 0}, { 8, 0}, { 0, 8}, { 8, 8}, { 5, 1}, {13, 1}, { 5, 9}, {13, 9},
104  { 2, 2}, {10, 2}, { 2,10}, {10,10}, { 7, 3}, {15, 3}, { 7,11}, {15,11},
105  { 4, 4}, {12, 4}, { 4,12}, {12,12}, { 1, 5}, { 9, 5}, { 1,13}, { 9,13},
106  { 6, 6}, {14, 6}, { 6,14}, {14,14}, { 3, 7}, {11, 7}, { 3,15}, {11,15}, // quality 5
107 
108  { 0, 0}, { 8, 0}, { 0, 8}, { 8, 8}, { 4, 0}, {12, 0}, { 4, 8}, {12, 8},
109  { 1, 1}, { 9, 1}, { 1, 9}, { 9, 9}, { 5, 1}, {13, 1}, { 5, 9}, {13, 9},
110  { 3, 2}, {11, 2}, { 3,10}, {11,10}, { 7, 2}, {15, 2}, { 7,10}, {15,10},
111  { 2, 3}, {10, 3}, { 2,11}, {10,11}, { 6, 3}, {14, 3}, { 6,11}, {14,11},
112  { 0, 4}, { 8, 4}, { 0,12}, { 8,12}, { 4, 4}, {12, 4}, { 4,12}, {12,12},
113  { 1, 5}, { 9, 5}, { 1,13}, { 9,13}, { 5, 5}, {13, 5}, { 5,13}, {13,13},
114  { 3, 6}, {11, 6}, { 3,14}, {11,14}, { 7, 6}, {15, 6}, { 7,14}, {15,14},
115  { 2, 7}, {10, 7}, { 2,15}, {10,15}, { 6, 7}, {14, 7}, { 6,15}, {14,15}, // quality 6
116 
117  { 0, 0}, { 8, 0}, { 0, 8}, { 8, 8}, { 0, 2}, { 8, 2}, { 0,10}, { 8,10},
118  { 0, 4}, { 8, 4}, { 0,12}, { 8,12}, { 0, 6}, { 8, 6}, { 0,14}, { 8,14},
119  { 1, 1}, { 9, 1}, { 1, 9}, { 9, 9}, { 1, 3}, { 9, 3}, { 1,11}, { 9,11},
120  { 1, 5}, { 9, 5}, { 1,13}, { 9,13}, { 1, 7}, { 9, 7}, { 1,15}, { 9,15},
121  { 2, 0}, {10, 0}, { 2, 8}, {10, 8}, { 2, 2}, {10, 2}, { 2,10}, {10,10},
122  { 2, 4}, {10, 4}, { 2,12}, {10,12}, { 2, 6}, {10, 6}, { 2,14}, {10,14},
123  { 3, 1}, {11, 1}, { 3, 9}, {11, 9}, { 3, 3}, {11, 3}, { 3,11}, {11,11},
124  { 3, 5}, {11, 5}, { 3,13}, {11,13}, { 3, 7}, {11, 7}, { 3,15}, {11,15},
125  { 4, 0}, {12, 0}, { 4, 8}, {12, 8}, { 4, 2}, {12, 2}, { 4,10}, {12,10},
126  { 4, 4}, {12, 4}, { 4,12}, {12,12}, { 4, 6}, {12, 6}, { 4,14}, {12,14},
127  { 5, 1}, {13, 1}, { 5, 9}, {13, 9}, { 5, 3}, {13, 3}, { 5,11}, {13,11},
128  { 5, 5}, {13, 5}, { 5,13}, {13,13}, { 5, 7}, {13, 7}, { 5,15}, {13,15},
129  { 6, 0}, {14, 0}, { 6, 8}, {14, 8}, { 6, 2}, {14, 2}, { 6,10}, {14,10},
130  { 6, 4}, {14, 4}, { 6,12}, {14,12}, { 6, 6}, {14, 6}, { 6,14}, {14,14},
131  { 7, 1}, {15, 1}, { 7, 9}, {15, 9}, { 7, 3}, {15, 3}, { 7,11}, {15,11},
132  { 7, 5}, {15, 5}, { 7,13}, {15,13}, { 7, 7}, {15, 7}, { 7,15}, {15,15}, // quality 7
133 
134  { 0, 0}, { 8, 0}, { 0, 8}, { 8, 8}, { 4, 4}, {12, 4}, { 4,12}, {12,12},
135  { 0, 4}, { 8, 4}, { 0,12}, { 8,12}, { 4, 0}, {12, 0}, { 4, 8}, {12, 8},
136  { 2, 2}, {10, 2}, { 2,10}, {10,10}, { 6, 6}, {14, 6}, { 6,14}, {14,14},
137  { 2, 6}, {10, 6}, { 2,14}, {10,14}, { 6, 2}, {14, 2}, { 6,10}, {14,10},
138  { 0, 2}, { 8, 2}, { 0,10}, { 8,10}, { 4, 6}, {12, 6}, { 4,14}, {12,14},
139  { 0, 6}, { 8, 6}, { 0,14}, { 8,14}, { 4, 2}, {12, 2}, { 4,10}, {12,10},
140  { 2, 0}, {10, 0}, { 2, 8}, {10, 8}, { 6, 4}, {14, 4}, { 6,12}, {14,12},
141  { 2, 4}, {10, 4}, { 2,12}, {10,12}, { 6, 0}, {14, 0}, { 6, 8}, {14, 8},
142  { 1, 1}, { 9, 1}, { 1, 9}, { 9, 9}, { 5, 5}, {13, 5}, { 5,13}, {13,13},
143  { 1, 5}, { 9, 5}, { 1,13}, { 9,13}, { 5, 1}, {13, 1}, { 5, 9}, {13, 9},
144  { 3, 3}, {11, 3}, { 3,11}, {11,11}, { 7, 7}, {15, 7}, { 7,15}, {15,15},
145  { 3, 7}, {11, 7}, { 3,15}, {11,15}, { 7, 3}, {15, 3}, { 7,11}, {15,11},
146  { 1, 3}, { 9, 3}, { 1,11}, { 9,11}, { 5, 7}, {13, 7}, { 5,15}, {13,15},
147  { 1, 7}, { 9, 7}, { 1,15}, { 9,15}, { 5, 3}, {13, 3}, { 5,11}, {13,11}, // quality 8
148  { 3, 1}, {11, 1}, { 3, 9}, {11, 9}, { 7, 5}, {15, 5}, { 7,13}, {15,13},
149  { 3, 5}, {11, 5}, { 3,13}, {11,13}, { 7, 1}, {15, 1}, { 7, 9}, {15, 9},
150  { 0, 1}, { 8, 1}, { 0, 9}, { 8, 9}, { 4, 5}, {12, 5}, { 4,13}, {12,13},
151  { 0, 5}, { 8, 5}, { 0,13}, { 8,13}, { 4, 1}, {12, 1}, { 4, 9}, {12, 9},
152  { 2, 3}, {10, 3}, { 2,11}, {10,11}, { 6, 7}, {14, 7}, { 6,15}, {14,15},
153  { 2, 7}, {10, 7}, { 2,15}, {10,15}, { 6, 3}, {14, 3}, { 6,11}, {14,11},
154  { 0, 3}, { 8, 3}, { 0,11}, { 8,11}, { 4, 7}, {12, 7}, { 4,15}, {12,15},
155  { 0, 7}, { 8, 7}, { 0,15}, { 8,15}, { 4, 3}, {12, 3}, { 4,11}, {12,11},
156  { 2, 1}, {10, 1}, { 2, 9}, {10, 9}, { 6, 5}, {14, 5}, { 6,13}, {14,13},
157  { 2, 5}, {10, 5}, { 2,13}, {10,13}, { 6, 1}, {14, 1}, { 6, 9}, {14, 9},
158  { 1, 0}, { 9, 0}, { 1, 8}, { 9, 8}, { 5, 4}, {13, 4}, { 5,12}, {13,12},
159  { 1, 4}, { 9, 4}, { 1,12}, { 9,12}, { 5, 0}, {13, 0}, { 5, 8}, {13, 8},
160  { 3, 2}, {11, 2}, { 3,10}, {11,10}, { 7, 6}, {15, 6}, { 7,14}, {15,14},
161  { 3, 6}, {11, 6}, { 3,14}, {11,14}, { 7, 2}, {15, 2}, { 7,10}, {15,10},
162  { 1, 2}, { 9, 2}, { 1,10}, { 9,10}, { 5, 6}, {13, 6}, { 5,14}, {13,14},
163  { 1, 6}, { 9, 6}, { 1,14}, { 9,14}, { 5, 2}, {13, 2}, { 5,10}, {13,10},
164  { 3, 0}, {11, 0}, { 3, 8}, {11, 8}, { 7, 4}, {15, 4}, { 7,12}, {15,12},
165  { 3, 4}, {11, 4}, { 3,12}, {11,12}, { 7, 0}, {15, 0}, { 7, 8}, {15, 8},
166 };
167 
168 static void store_slice_c(uint8_t *dst, const uint16_t *src,
169  int dst_stride, int src_stride,
170  int width, int height, int log2_scale)
171 {
172  int y, x;
173 
174 #define STORE(pos) do { \
175  temp = ((src[x + y * src_stride + pos] << log2_scale) + d[pos]) >> 8; \
176  if (temp & 0x100) temp = ~(temp >> 31); \
177  dst[x + y * dst_stride + pos] = temp; \
178 } while (0)
179 
180  for (y = 0; y < height; y++) {
181  const uint8_t *d = dither[y&7];
182  for (x = 0; x < width; x += 8) {
183  int temp;
184  STORE(0);
185  STORE(1);
186  STORE(2);
187  STORE(3);
188  STORE(4);
189  STORE(5);
190  STORE(6);
191  STORE(7);
192  }
193  }
194 }
195 
196 static int filter_1phase(AVFilterContext *ctx, void *arg, int i, int nb_jobs)
197 {
198  USPPContext *p = ctx->priv;
199  int ret, x, y;
200  int width = ctx->inputs[0]->w;
201  int height = ctx->inputs[0]->h;
202 
203  const int x1 = offset[i+nb_jobs-1][0];
204  const int y1 = offset[i+nb_jobs-1][1];
205  const int x1c = x1 >> p->hsub;
206  const int y1c = y1 >> p->vsub;
207  const int BLOCKc = BLOCK >> p->hsub;
208  int offset;
209  AVPacket *pkt = p->pkt[i];
210 
212  pkt->data = p->outbuf;
213  pkt->size = p->outbuf_size;
214 
215  p->frame[i]->linesize[0] = p->temp_stride[0];
216  p->frame[i]->linesize[1] = p->temp_stride[1];
217  p->frame[i]->linesize[2] = p->temp_stride[2];
218  p->frame[i]->height = height + BLOCK;
219  p->frame[i]->width = width + BLOCK;
220  p->frame[i]->data[0] = p->src[0] + x1 + y1 * p->frame[i]->linesize[0];
221  p->frame[i]->data[1] = p->src[1] + x1c + y1c * p->frame[i]->linesize[1];
222  p->frame[i]->data[2] = p->src[2] + x1c + y1c * p->frame[i]->linesize[2];
223  p->frame[i]->format = p->avctx_enc[i]->pix_fmt;
224  p->frame[i]->quality = p->quality;
225 
226  ret = avcodec_send_frame(p->avctx_enc[i], p->frame[i]);
227  if (ret < 0) {
228  av_log(p->avctx_enc[i], AV_LOG_ERROR, "Error sending a frame for encoding\n");
229  return ret;
230  }
232  if (ret < 0) {
233  av_log(p->avctx_enc[i], AV_LOG_ERROR, "Error receiving a packet from encoding\n");
234  return ret;
235  }
236 
240  if (ret < 0) {
241  av_log(p->avctx_dec[i], AV_LOG_ERROR, "Error receiving a frame from encoding\n");
242  return ret;
243  }
244  } else {
247  if (ret < 0) {
248  av_log(p->avctx_dec[i], AV_LOG_ERROR, "Error sending a packet for decoding\n");
249  return ret;
250  }
252  if (ret < 0) {
253  av_log(p->avctx_dec[i], AV_LOG_ERROR, "Error receiving a frame from decoding\n");
254  return ret;
255  }
256  }
257 
258  offset = (BLOCK-x1) + (BLOCK-y1) * p->frame_dec[i]->linesize[0];
259 
260  for (y = 0; y < height; y++)
261  for (x = 0; x < width; x++)
262  p->temp[0][x + y * p->temp_stride[0]] += p->frame_dec[i]->data[0][x + y * p->frame_dec[i]->linesize[0] + offset];
263 
264 
265  if (!p->frame_dec[i]->data[2] || !p->temp[2])
266  return 0;
267 
268  offset = (BLOCKc-x1c) + (BLOCKc-y1c) * p->frame_dec[i]->linesize[1];
269 
270  for (y = 0; y < AV_CEIL_RSHIFT(height, p->vsub); y++) {
271  for (x = 0; x < AV_CEIL_RSHIFT(width, p->hsub); x++) {
272  p->temp[1][x + y * p->temp_stride[1]] += p->frame_dec[i]->data[1][x + y * p->frame_dec[i]->linesize[1] + offset];
273  p->temp[2][x + y * p->temp_stride[2]] += p->frame_dec[i]->data[2][x + y * p->frame_dec[i]->linesize[2] + offset];
274  }
275  }
276 
277  return 0;
278 }
279 
280 static void filter(AVFilterContext *ctx, uint8_t *dst[3], uint8_t *src[3],
281  int dst_stride[3], int src_stride[3], int width,
282  int height, uint8_t *qp_store, int qp_stride)
283 {
284  USPPContext *p = ctx->priv;
285  int x, y, i, j;
286 
287  for (i = 0; i < 3; i++) {
288  int is_chroma = !!i;
289  int w = AV_CEIL_RSHIFT(width, is_chroma ? p->hsub : 0);
290  int h = AV_CEIL_RSHIFT(height, is_chroma ? p->vsub : 0);
291  int stride = p->temp_stride[i];
292  int block = BLOCK >> (is_chroma ? p->hsub : 0);
293 
294  if (!src[i] || !dst[i])
295  continue;
296  for (y = 0; y < h; y++) {
297  int index = block + block * stride + y * stride;
298 
299  memcpy(p->src[i] + index, src[i] + y * src_stride[i], w );
300  for (x = 0; x < block; x++) {
301  p->src[i][index - x - 1] = p->src[i][index + x ];
302  p->src[i][index + w + x ] = p->src[i][index + w - x - 1];
303  }
304  }
305  for (y = 0; y < block; y++) {
306  memcpy(p->src[i] + ( block-1-y) * stride, p->src[i] + ( y+block ) * stride, stride);
307  memcpy(p->src[i] + (h+block +y) * stride, p->src[i] + (h-y+block-1) * stride, stride);
308  }
309 
310  memset(p->temp[i], 0, (h + 2 * block) * stride * sizeof(int16_t));
311  }
312 
313  if (p->qp)
314  p->quality = p->qp * FF_QP2LAMBDA;
315  else {
316  int qpsum=0;
317  int qpcount = (height>>4) * (height>>4);
318 
319  for (y = 0; y < (height>>4); y++) {
320  for (x = 0; x < (width>>4); x++)
321  qpsum += qp_store[x + y * qp_stride];
322  }
323  p->quality = ff_norm_qscale((qpsum + qpcount/2) / qpcount, p->qscale_type) * FF_QP2LAMBDA;
324  }
325 // init per MB qscale stuff FIXME
326 
328 
329  for (j = 0; j < 3; j++) {
330  int is_chroma = !!j;
331  if (!dst[j])
332  continue;
333  store_slice_c(dst[j], p->temp[j], dst_stride[j], p->temp_stride[j],
334  AV_CEIL_RSHIFT(width, is_chroma ? p->hsub : 0),
335  AV_CEIL_RSHIFT(height, is_chroma ? p->vsub : 0),
336  8-p->log2_count);
337  }
338 }
339 
340 static const enum AVPixelFormat pix_fmts[] = {
348 };
349 
351 {
352 
353  AVFilterContext *ctx = inlink->dst;
354  USPPContext *uspp = ctx->priv;
355  const int height = inlink->h;
356  const int width = inlink->w;
358  int i;
359  const AVCodec *enc = avcodec_find_encoder_by_name(uspp->codec_name);
360  const AVCodec *dec = avcodec_find_decoder_by_name(uspp->codec_name);
361  if (!enc) {
362  av_log(ctx, AV_LOG_ERROR, "encoder %s not found.\n", uspp->codec_name);
363  return AVERROR(EINVAL);
364  }
365  if (!dec) {
366  av_log(ctx, AV_LOG_ERROR, "decoder %s not found.\n", uspp->codec_name);
367  return AVERROR(EINVAL);
368  }
369 
370  uspp->hsub = desc->log2_chroma_w;
371  uspp->vsub = desc->log2_chroma_h;
372  uspp->count = 1<<uspp->log2_count;
373 
374  for (i = 0; i < 3; i++) {
375  int is_chroma = !!i;
376  int w = (width + 4 * BLOCK-1) & (~(2 * BLOCK-1));
377  int h = (height + 4 * BLOCK-1) & (~(2 * BLOCK-1));
378 
379  if (is_chroma) {
380  w = AV_CEIL_RSHIFT(w, uspp->hsub);
381  h = AV_CEIL_RSHIFT(h, uspp->vsub);
382  }
383 
384  uspp->temp_stride[i] = w;
385  if (!(uspp->temp[i] = av_malloc_array(uspp->temp_stride[i], h * sizeof(int16_t))))
386  return AVERROR(ENOMEM);
387  if (!(uspp->src [i] = av_malloc_array(uspp->temp_stride[i], h * sizeof(uint8_t))))
388  return AVERROR(ENOMEM);
389  }
390 
391  for (i = 0; i < uspp->count; i++) {
392  AVCodecContext *avctx_enc, *avctx_dec;
394  int ret;
395 
396  if (!(uspp->avctx_enc[i] = avcodec_alloc_context3(NULL)))
397  return AVERROR(ENOMEM);
398 
399  avctx_enc = uspp->avctx_enc[i];
400  avctx_enc->width = width + BLOCK;
401  avctx_enc->height = height + BLOCK;
402  avctx_enc->time_base = (AVRational){1,25}; // meaningless
403  avctx_enc->gop_size = INT_MAX;
404  avctx_enc->max_b_frames = 0;
405  avctx_enc->pix_fmt = inlink->format;
408  avctx_enc->flags |= AV_CODEC_FLAG_RECON_FRAME;
409  av_dict_set(&opts, "no_bitstream", "1", 0);
410  }
412  avctx_enc->global_quality = 123;
413  avctx_enc->thread_count = 1; // We do threading in the filter with muiltiple codecs
414  ret = avcodec_open2(avctx_enc, enc, &opts);
415  av_dict_free(&opts);
416  if (ret < 0)
417  return ret;
418  av_assert0(avctx_enc->codec);
419 
420 
422  if (!(uspp->avctx_dec[i] = avcodec_alloc_context3(NULL)))
423  return AVERROR(ENOMEM);
424  avctx_dec = uspp->avctx_dec[i];
425  avctx_dec->width = avctx_enc->width;
426  avctx_dec->height = avctx_enc->height;
427  avctx_dec->thread_count = 1;
428  ret = avcodec_open2(avctx_dec, dec, NULL);
429  if (ret < 0)
430  return ret;
431  }
432 
433  if (!(uspp->frame[i] = av_frame_alloc()))
434  return AVERROR(ENOMEM);
435  if (!(uspp->frame_dec[i] = av_frame_alloc()))
436  return AVERROR(ENOMEM);
437  if (!(uspp->pkt[i] = av_packet_alloc()))
438  return AVERROR(ENOMEM);
439  }
440 
441  uspp->outbuf_size = (width + BLOCK) * (height + BLOCK) * 10;
442  if (!(uspp->outbuf = av_malloc(uspp->outbuf_size)))
443  return AVERROR(ENOMEM);
444 
445  return 0;
446 }
447 
449 {
450  AVFilterContext *ctx = inlink->dst;
451  USPPContext *uspp = ctx->priv;
452  AVFilterLink *outlink = ctx->outputs[0];
453  AVFrame *out = in;
454 
455  int qp_stride = 0;
456  int8_t *qp_table = NULL;
457  int ret = 0;
458 
459  /* if we are not in a constant user quantizer mode and we don't want to use
460  * the quantizers from the B-frames (B-frames often have a higher QP), we
461  * need to save the qp table from the last non B-frame; this is what the
462  * following code block does */
463  if (!uspp->qp && (uspp->use_bframe_qp || in->pict_type != AV_PICTURE_TYPE_B)) {
464  ret = ff_qp_table_extract(in, &qp_table, &qp_stride, NULL, &uspp->qscale_type);
465  if (ret < 0) {
466  av_frame_free(&in);
467  return ret;
468  }
469 
470  if (!uspp->use_bframe_qp && in->pict_type != AV_PICTURE_TYPE_B) {
471  av_freep(&uspp->non_b_qp_table);
472  uspp->non_b_qp_table = qp_table;
473  uspp->non_b_qp_stride = qp_stride;
474  }
475  }
476 
477  if (uspp->log2_count && !ctx->is_disabled) {
478  if (!uspp->use_bframe_qp && uspp->non_b_qp_table) {
479  qp_table = uspp->non_b_qp_table;
480  qp_stride = uspp->non_b_qp_stride;
481  }
482 
483  if (qp_table || uspp->qp) {
484 
485  /* get a new frame if in-place is not possible or if the dimensions
486  * are not multiple of 8 */
487  if (!av_frame_is_writable(in) || (inlink->w & 7) || (inlink->h & 7)) {
488  const int aligned_w = FFALIGN(inlink->w, 8);
489  const int aligned_h = FFALIGN(inlink->h, 8);
490 
491  out = ff_get_video_buffer(outlink, aligned_w, aligned_h);
492  if (!out) {
493  av_frame_free(&in);
494  if (qp_table != uspp->non_b_qp_table)
495  av_free(qp_table);
496  return AVERROR(ENOMEM);
497  }
499  out->width = in->width;
500  out->height = in->height;
501  }
502 
503  filter(ctx, out->data, in->data, out->linesize, in->linesize,
504  inlink->w, inlink->h, qp_table, qp_stride);
505  }
506  }
507 
508  if (in != out) {
509  if (in->data[3])
510  av_image_copy_plane(out->data[3], out->linesize[3],
511  in ->data[3], in ->linesize[3],
512  inlink->w, inlink->h);
513  av_frame_free(&in);
514  }
515  ret = ff_filter_frame(outlink, out);
516  if (qp_table != uspp->non_b_qp_table)
517  av_freep(&qp_table);
518  return ret;
519 }
520 
522 {
523  USPPContext *uspp = ctx->priv;
524  int i;
525 
526  for (i = 0; i < 3; i++) {
527  av_freep(&uspp->temp[i]);
528  av_freep(&uspp->src[i]);
529  }
530 
531  for (i = 0; i < uspp->count; i++) {
534  av_frame_free(&uspp->frame[i]);
535  av_frame_free(&uspp->frame_dec[i]);
536  av_packet_free(&uspp->pkt[i]);
537  }
538 
539  av_freep(&uspp->non_b_qp_table);
540  av_freep(&uspp->outbuf);
541 }
542 
543 static const AVFilterPad uspp_inputs[] = {
544  {
545  .name = "default",
546  .type = AVMEDIA_TYPE_VIDEO,
547  .config_props = config_input,
548  .filter_frame = filter_frame,
549  },
550 };
551 
553  .name = "uspp",
554  .description = NULL_IF_CONFIG_SMALL("Apply Ultra Simple / Slow Post-processing filter."),
555  .priv_size = sizeof(USPPContext),
556  .uninit = uninit,
560  .priv_class = &uspp_class,
562 };
STORE
#define STORE(pos)
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:116
uninit
static av_cold void uninit(AVFilterContext *ctx)
Definition: vf_uspp.c:521
USPPContext::src
uint8_t * src[3]
Definition: vf_uspp.c:56
USPPContext::qp
int qp
Definition: vf_uspp.c:52
av_packet_unref
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: packet.c:429
AVCodec
AVCodec.
Definition: codec.h:187
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:71
filter_frame
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
Definition: vf_uspp.c:448
USPPContext::avctx_enc
AVCodecContext * avctx_enc[BLOCK *BLOCK]
Definition: vf_uspp.c:60
qp_table.h
avcodec_receive_packet
int avcodec_receive_packet(AVCodecContext *avctx, AVPacket *avpkt)
Read encoded data from the encoder.
Definition: encode.c:541
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
mem_internal.h
FILTER_PIXFMTS_ARRAY
#define FILTER_PIXFMTS_ARRAY(array)
Definition: filters.h:242
out
FILE * out
Definition: movenc.c:55
ff_filter_frame
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1061
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:3170
AV_CODEC_FLAG_QSCALE
#define AV_CODEC_FLAG_QSCALE
Use fixed qscale.
Definition: avcodec.h:224
USPPContext::temp
uint16_t * temp[3]
Definition: vf_uspp.c:57
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
AV_CODEC_CAP_ENCODER_RECON_FRAME
#define AV_CODEC_CAP_ENCODER_RECON_FRAME
The encoder is able to output reconstructed frame data, i.e.
Definition: codec.h:174
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:162
FILTER_INPUTS
#define FILTER_INPUTS(array)
Definition: filters.h:262
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:389
pixdesc.h
AVFrame::width
int width
Definition: frame.h:461
AVCodec::capabilities
int capabilities
Codec capabilities.
Definition: codec.h:206
w
uint8_t w
Definition: llviddspenc.c:38
AVPacket::data
uint8_t * data
Definition: packet.h:539
AVOption
AVOption.
Definition: opt.h:429
BLOCK
#define BLOCK
Definition: vf_uspp.c:45
USPPContext::frame
AVFrame * frame[BLOCK *BLOCK]
Definition: vf_uspp.c:63
offset
static const uint8_t offset[511][2]
Definition: vf_uspp.c:94
FF_COMPLIANCE_EXPERIMENTAL
#define FF_COMPLIANCE_EXPERIMENTAL
Allow nonstandardized experimental things.
Definition: defs.h:62
AVDictionary
Definition: dict.c:34
config_input
static int config_input(AVFilterLink *inlink)
Definition: vf_uspp.c:350
AVFilter::name
const char * name
Filter name.
Definition: avfilter.h:205
USPPContext::codec_name
char * codec_name
Definition: vf_uspp.c:53
ff_norm_qscale
static int ff_norm_qscale(int qscale, enum AVVideoEncParamsType type)
Normalize the qscale factor FIXME Add support for other values of enum AVVideoEncParamsType besides A...
Definition: qp_table.h:39
video.h
USPPContext::vsub
int vsub
Definition: vf_uspp.c:51
av_packet_free
void av_packet_free(AVPacket **pkt)
Free the packet, if the packet is reference counted, it will be unreferenced first.
Definition: packet.c:74
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:410
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:30
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:374
USPPContext::use_bframe_qp
int use_bframe_qp
Definition: vf_uspp.c:67
AVCodecContext::codec
const struct AVCodec * codec
Definition: avcodec.h:460
AVCodecContext::thread_count
int thread_count
thread count is used to decide how many independent tasks should be passed to execute()
Definition: avcodec.h:1593
AVCodecContext::flags
int flags
AV_CODEC_FLAG_*.
Definition: avcodec.h:508
AV_CODEC_FLAG_LOW_DELAY
#define AV_CODEC_FLAG_LOW_DELAY
Force low delay.
Definition: avcodec.h:334
USPPContext::avctx_dec
AVCodecContext * avctx_dec[BLOCK *BLOCK]
Definition: vf_uspp.c:61
AVFilterPad
A filter pad used for either input or output.
Definition: filters.h:38
av_frame_alloc
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:150
avassert.h
pkt
AVPacket * pkt
Definition: movenc.c:60
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:209
av_cold
#define av_cold
Definition: attributes.h:90
store_slice_c
static void store_slice_c(uint8_t *dst, const uint16_t *src, int dst_stride, int src_stride, int width, int height, int log2_scale)
Definition: vf_uspp.c:168
AVVideoEncParamsType
AVVideoEncParamsType
Definition: video_enc_params.h:28
ff_video_default_filterpad
const AVFilterPad ff_video_default_filterpad[1]
An AVFilterPad array whose only entry has name "default" and is of type AVMEDIA_TYPE_VIDEO.
Definition: video.c:37
avcodec_alloc_context3
AVCodecContext * avcodec_alloc_context3(const AVCodec *codec)
Allocate an AVCodecContext and set its fields to default values.
Definition: options.c:149
AVCodecContext::global_quality
int global_quality
Global quality for codecs which cannot change it per frame.
Definition: avcodec.h:1249
AV_CEIL_RSHIFT
#define AV_CEIL_RSHIFT(a, b)
Definition: common.h:60
avcodec_receive_frame
int attribute_align_arg avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame)
Return decoded output data from a decoder or encoder (when the AV_CODEC_FLAG_RECON_FRAME flag is used...
Definition: avcodec.c:713
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:40
filters.h
ctx
AVFormatContext * ctx
Definition: movenc.c:49
USPPContext::non_b_qp_stride
int non_b_qp_stride
Definition: vf_uspp.c:66
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:73
FILTER_OUTPUTS
#define FILTER_OUTPUTS(array)
Definition: filters.h:263
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:87
arg
const char * arg
Definition: jacosubdec.c:67
if
if(ret)
Definition: filter_design.txt:179
opts
AVDictionary * opts
Definition: movenc.c:51
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:75
NULL
#define NULL
Definition: coverity.c:32
avcodec_find_decoder_by_name
const AVCodec * avcodec_find_decoder_by_name(const char *name)
Find a registered decoder with the specified name.
Definition: allcodecs.c:1040
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:725
AVFILTER_DEFINE_CLASS
AVFILTER_DEFINE_CLASS(uspp)
avcodec_free_context
void avcodec_free_context(AVCodecContext **avctx)
Free the codec context and everything associated with it and write NULL to the provided pointer.
Definition: options.c:164
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
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:85
USPPContext::log2_count
int log2_count
Definition: vf_uspp.c:49
USPPContext::quality
int quality
Definition: vf_uspp.c:68
avcodec_open2
int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options)
Initialize the AVCodecContext to use the given AVCodec.
Definition: avcodec.c:143
dither
static const uint8_t dither[8][8]
Definition: vf_uspp.c:83
USPPContext::frame_dec
AVFrame * frame_dec[BLOCK *BLOCK]
Definition: vf_uspp.c:64
AV_PIX_FMT_GRAY8
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
Definition: pixfmt.h:81
index
int index
Definition: gxfenc.c:90
AVCodecContext::time_base
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented.
Definition: avcodec.h:550
USPPContext::outbuf
uint8_t * outbuf
Definition: vf_uspp.c:59
AVFrame::pict_type
enum AVPictureType pict_type
Picture type of the frame.
Definition: frame.h:491
filter
static void filter(AVFilterContext *ctx, uint8_t *dst[3], uint8_t *src[3], int dst_stride[3], int src_stride[3], int width, int height, uint8_t *qp_store, int qp_stride)
Definition: vf_uspp.c:280
AVPacket::size
int size
Definition: packet.h:540
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:94
AVCodecContext::gop_size
int gop_size
the number of pictures in a group of pictures, or 0 for intra_only
Definition: avcodec.h:1037
height
#define height
Definition: dsp.h:85
USPPContext::av_class
const AVClass * av_class
Definition: vf_uspp.c:48
DECLARE_ALIGNED
#define DECLARE_ALIGNED(n, t, v)
Definition: mem_internal.h:102
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:83
AVFrame::quality
int quality
quality (between 1 (good) and FF_LAMBDA_MAX (bad))
Definition: frame.h:521
av_frame_is_writable
int av_frame_is_writable(AVFrame *frame)
Check if the frame data is writable.
Definition: frame.c:661
AVFrame::format
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames,...
Definition: frame.h:476
av_packet_alloc
AVPacket * av_packet_alloc(void)
Allocate an AVPacket and set its fields to default values.
Definition: packet.c:63
av_dict_free
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
Definition: dict.c:223
USPPContext::count
int count
Definition: vf_uspp.c:50
avcodec_send_packet
int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt)
Supply raw packet data as input to a decoder.
Definition: decode.c:728
AV_CODEC_FLAG_RECON_FRAME
#define AV_CODEC_FLAG_RECON_FRAME
Request the encoder to output reconstructed frames, i.e. frames that would be produced by decoding th...
Definition: avcodec.h:264
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
MAX_LEVEL
#define MAX_LEVEL
Definition: vf_uspp.c:44
av_malloc_array
#define av_malloc_array(a, b)
Definition: tableprint_vlc.h:31
AVFilterPad::name
const char * name
Pad name.
Definition: filters.h:44
AVCodecContext::height
int height
Definition: avcodec.h:624
avcodec_send_frame
int avcodec_send_frame(AVCodecContext *avctx, const AVFrame *frame)
Supply a raw video or audio frame to the encoder.
Definition: encode.c:508
AVCodecContext::pix_fmt
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:663
USPPContext::pkt
AVPacket * pkt[BLOCK *BLOCK]
Definition: vf_uspp.c:62
avcodec.h
USPPContext
Definition: vf_uspp.c:47
stride
#define stride
Definition: h264pred_template.c:537
AVFilter
Filter definition.
Definition: avfilter.h:201
ret
ret
Definition: filter_design.txt:187
pix_fmts
static enum AVPixelFormat pix_fmts[]
Definition: vf_uspp.c:340
ff_qp_table_extract
int ff_qp_table_extract(AVFrame *frame, int8_t **table, int *table_w, int *table_h, enum AVVideoEncParamsType *qscale_type)
Extract a libpostproc-compatible QP table - an 8-bit QP value per 16x16 macroblock,...
Definition: qp_table.c:27
AVCodecContext::strict_std_compliance
int strict_std_compliance
strictly follow the standard (MPEG-4, ...).
Definition: avcodec.h:1389
uspp_options
static const AVOption uspp_options[]
Definition: vf_uspp.c:73
AVCodecContext
main external API structure.
Definition: avcodec.h:451
AVFrame::height
int height
Definition: frame.h:461
uspp_inputs
static const AVFilterPad uspp_inputs[]
Definition: vf_uspp.c:543
ff_filter_execute
int ff_filter_execute(AVFilterContext *ctx, avfilter_action_func *func, void *arg, int *ret, int nb_jobs)
Definition: avfilter.c:1666
AV_PICTURE_TYPE_B
@ AV_PICTURE_TYPE_B
Bi-dir predicted.
Definition: avutil.h:281
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:72
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition: opt.h:259
avfilter.h
temp
else temp
Definition: vf_mcdeint.c:263
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:78
AVFilterContext
An instance of a filter.
Definition: avfilter.h:457
USPPContext::non_b_qp_table
int8_t * non_b_qp_table
Definition: vf_uspp.c:65
AVFILTER_FLAG_SLICE_THREADS
#define AVFILTER_FLAG_SLICE_THREADS
The filter supports multithreading by splitting frames into multiple parts and processing them concur...
Definition: avfilter.h:152
desc
const char * desc
Definition: libsvtav1.c:79
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
filter_1phase
static int filter_1phase(AVFilterContext *ctx, void *arg, int i, int nb_jobs)
Definition: vf_uspp.c:196
mem.h
AVCodecContext::max_b_frames
int max_b_frames
maximum number of B-frames between non-B-frames Note: The output will be delayed by max_b_frames+1 re...
Definition: avcodec.h:801
FLAGS
#define FLAGS
Definition: vf_uspp.c:72
USPPContext::qscale_type
enum AVVideoEncParamsType qscale_type
Definition: vf_uspp.c:54
AVPixFmtDescriptor
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:69
av_free
#define av_free(p)
Definition: tableprint_vlc.h:33
FFALIGN
#define FFALIGN(x, a)
Definition: macros.h:78
AVPacket
This structure stores compressed data.
Definition: packet.h:516
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Underlying C type is int.
Definition: opt.h:327
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
av_dict_set
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
Definition: dict.c:88
USPPContext::outbuf_size
int outbuf_size
Definition: vf_uspp.c:58
AVCodecContext::width
int width
picture width / height.
Definition: avcodec.h:624
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:190
imgutils.h
AVFrame::linesize
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
Definition: frame.h:434
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:79
block
The exact code depends on how similar the blocks are and how related they are to the block
Definition: filter_design.txt:207
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
h
h
Definition: vp9dsp_template.c:2070
OFFSET
#define OFFSET(x)
Definition: vf_uspp.c:71
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
Definition: opt.h:276
width
#define width
Definition: dsp.h:85
FF_QP2LAMBDA
#define FF_QP2LAMBDA
factor to convert from H.263 QP to lambda
Definition: avutil.h:227
ff_vf_uspp
const AVFilter ff_vf_uspp
Definition: vf_uspp.c:552
src
#define src
Definition: vp8dsp.c:248
video_enc_params.h
USPPContext::hsub
int hsub
Definition: vf_uspp.c:51
avcodec_find_encoder_by_name
const AVCodec * avcodec_find_encoder_by_name(const char *name)
Find a registered encoder with the specified name.
Definition: allcodecs.c:1035
USPPContext::temp_stride
int temp_stride[3]
Definition: vf_uspp.c:55