FFmpeg
Loading...
Searching...
No Matches
vf_pp7.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2005 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 * Postprocessing filter - 7
25 *
26 * Originally written by Michael Niedermayer for the MPlayer
27 * project, and ported by Arwa Arif for FFmpeg.
28 */
29
30#include "libavutil/imgutils.h"
31#include "libavutil/mem.h"
33#include "libavutil/opt.h"
34#include "libavutil/pixdesc.h"
36
37#include "avfilter.h"
38#include "filters.h"
39#include "qp_table.h"
40#include "vf_pp7dsp.h"
41#include "video.h"
42
48
49typedef struct PP7Context {
50 const AVClass *class;
51 int thres2[99][16];
52
53 int qp;
54 int mode;
56 int hsub;
57 int vsub;
59 uint8_t *src;
60
61 int (*requantize)(const struct PP7Context *p, const int16_t *src, int qp);
62
65
66#define OFFSET(x) offsetof(PP7Context, x)
67#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
68static const AVOption pp7_options[] = {
69 { "qp", "force a constant quantizer parameter", OFFSET(qp), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 64, FLAGS },
70 { "mode", "set thresholding mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64 = MODE_MEDIUM}, 0, 2, FLAGS, .unit = "mode" },
71 { "hard", "hard thresholding", 0, AV_OPT_TYPE_CONST, {.i64 = MODE_HARD}, INT_MIN, INT_MAX, FLAGS, .unit = "mode" },
72 { "soft", "soft thresholding", 0, AV_OPT_TYPE_CONST, {.i64 = MODE_SOFT}, INT_MIN, INT_MAX, FLAGS, .unit = "mode" },
73 { "medium", "medium thresholding", 0, AV_OPT_TYPE_CONST, {.i64 = MODE_MEDIUM}, INT_MIN, INT_MAX, FLAGS, .unit = "mode" },
74 { NULL }
75};
76
78
79DECLARE_ALIGNED(8, static const uint8_t, dither)[8][8] = {
80 { 0, 48, 12, 60, 3, 51, 15, 63, },
81 { 32, 16, 44, 28, 35, 19, 47, 31, },
82 { 8, 56, 4, 52, 11, 59, 7, 55, },
83 { 40, 24, 36, 20, 43, 27, 39, 23, },
84 { 2, 50, 14, 62, 1, 49, 13, 61, },
85 { 34, 18, 46, 30, 33, 17, 45, 29, },
86 { 10, 58, 6, 54, 9, 57, 5, 53, },
87 { 42, 26, 38, 22, 41, 25, 37, 21, },
88};
89
90#define N0 4
91#define N1 5
92#define N2 10
93#define SN0 2
94#define SN1 2.2360679775
95#define SN2 3.16227766017
96#define N (1 << 16)
97
98static const int factor[16] = {
99 N / (N0 * N0), N / (N0 * N1), N / (N0 * N0), N / (N0 * N2),
100 N / (N1 * N0), N / (N1 * N1), N / (N1 * N0), N / (N1 * N2),
101 N / (N0 * N0), N / (N0 * N1), N / (N0 * N0), N / (N0 * N2),
102 N / (N2 * N0), N / (N2 * N1), N / (N2 * N0), N / (N2 * N2),
103};
104
105static void init_thres2(PP7Context *p)
106{
107 int qp, i;
108 int bias = 0; //FIXME
109
110 for (qp = 0; qp < 99; qp++) {
111 for (i = 0; i < 16; i++) {
112 p->thres2[qp][i] = ((i&1) ? SN2 : SN0) * ((i&4) ? SN2 : SN0) * FFMAX(1, qp) * (1<<2) - 1 - bias;
113 }
114 }
115}
116
117static inline void dctA_c(int16_t *dst, const uint8_t *src, int stride)
118{
119 int i;
120
121 for (i = 0; i < 4; i++) {
122 int s0 = src[0 * stride] + src[6 * stride];
123 int s1 = src[1 * stride] + src[5 * stride];
124 int s2 = src[2 * stride] + src[4 * stride];
125 int s3 = src[3 * stride];
126 int s = s3 + s3;
127 s3 = s - s0;
128 s0 = s + s0;
129 s = s2 + s1;
130 s2 = s2 - s1;
131 dst[0] = s0 + s;
132 dst[2] = s0 - s;
133 dst[1] = 2 * s3 + s2;
134 dst[3] = s3 - 2 * s2;
135 src++;
136 dst += 4;
137 }
138}
139
140static int hardthresh_c(const PP7Context *p, const int16_t *src, int qp)
141{
142 int i;
143 int a;
144
145 a = src[0] * factor[0];
146 for (i = 1; i < 16; i++) {
147 unsigned int threshold1 = p->thres2[qp][i];
148 unsigned int threshold2 = threshold1 << 1;
149 int level = src[i];
150 if (((unsigned)(level + threshold1)) > threshold2)
151 a += level * factor[i];
152 }
153 return (a + (1 << 11)) >> 12;
154}
155
156static int mediumthresh_c(const PP7Context *p, const int16_t *src, int qp)
157{
158 int i;
159 int a;
160
161 a = src[0] * factor[0];
162 for (i = 1; i < 16; i++) {
163 unsigned int threshold1 = p->thres2[qp][i];
164 unsigned int threshold2 = threshold1 << 1;
165 int level = src[i];
166 if (((unsigned)(level + threshold1)) > threshold2) {
167 if (((unsigned)(level + 2 * threshold1)) > 2 * threshold2)
168 a += level * factor[i];
169 else {
170 if (level > 0)
171 a += 2 * (level - (int)threshold1) * factor[i];
172 else
173 a += 2 * (level + (int)threshold1) * factor[i];
174 }
175 }
176 }
177 return (a + (1 << 11)) >> 12;
178}
179
180static int softthresh_c(const PP7Context *p, const int16_t *src, int qp)
181{
182 int i;
183 int a;
184
185 a = src[0] * factor[0];
186 for (i = 1; i < 16; i++) {
187 unsigned int threshold1 = p->thres2[qp][i];
188 unsigned int threshold2 = threshold1 << 1;
189 int level = src[i];
190 if (((unsigned)(level + threshold1)) > threshold2) {
191 if (level > 0)
192 a += (level - (int)threshold1) * factor[i];
193 else
194 a += (level + (int)threshold1) * factor[i];
195 }
196 }
197 return (a + (1 << 11)) >> 12;
198}
199
200static void filter(PP7Context *p, uint8_t *dst, const uint8_t *src,
201 int dst_stride, int src_stride,
202 int width, int height,
203 const uint8_t *qp_store, int qp_stride, int is_luma)
204{
205 int x, y;
206 const int stride = is_luma ? p->temp_stride : ((width + 16 + 15) & (~15));
207 uint8_t *p_src = p->src + 8 * stride;
208 int16_t *block = (int16_t *)p->src;
209 int16_t *temp = (int16_t *)(p->src + 32);
210
211 if (!src || !dst) return;
212 for (y = 0; y < height; y++) {
213 int index = 8 + 8 * stride + y * stride;
214 memcpy(p_src + index, src + y * src_stride, width);
215 for (x = 0; x < 8; x++) {
216 p_src[index - x - 1]= p_src[index + x ];
217 p_src[index + width + x ]= p_src[index + width - x - 1];
218 }
219 }
220 for (y = 0; y < 8; y++) {
221 memcpy(p_src + ( 7 - y ) * stride, p_src + ( y + 8 ) * stride, stride);
222 memcpy(p_src + (height + 8 + y) * stride, p_src + (height - y + 7) * stride, stride);
223 }
224 //FIXME (try edge emu)
225
226 for (y = 0; y < height; y++) {
227 for (x = -8; x < 0; x += 4) {
228 const int index = x + y * stride + (8 - 3) * (1 + stride) + 8; //FIXME silly offset
229 int16_t *tp = temp + 4 * x;
230
231 dctA_c(tp + 4 * 8, p_src + index, stride);
232 }
233 for (x = 0; x < width; ) {
234 const int qps = 3 + is_luma;
235 int qp;
236 int end = FFMIN(x + 8, width);
237
238 if (p->qp)
239 qp = p->qp;
240 else {
241 qp = qp_store[ (FFMIN(x, width - 1) >> qps) + (FFMIN(y, height - 1) >> qps) * qp_stride];
242 qp = ff_norm_qscale(qp, p->qscale_type);
243 }
244 for (; x < end; x++) {
245 const int index = x + y * stride + (8 - 3) * (1 + stride) + 8; //FIXME silly offset
246 int16_t *tp = temp + 4 * x;
247 int v;
248
249 if ((x & 3) == 0)
250 dctA_c(tp + 4 * 8, p_src + index, stride);
251
252 p->pp7dsp.dctB(block, tp);
253
254 v = p->requantize(p, block, qp);
255 v = (v + dither[y & 7][x & 7]) >> 6;
256 if ((unsigned)v > 255)
257 v = (-v) >> 31;
258 dst[x + y * dst_stride] = v;
259 }
260 }
261 }
262}
263
273
274static int config_input(AVFilterLink *inlink)
275{
276 AVFilterContext *ctx = inlink->dst;
277 PP7Context *pp7 = ctx->priv;
278 const int h = FFALIGN(inlink->h + 16, 16);
280
281 pp7->hsub = desc->log2_chroma_w;
282 pp7->vsub = desc->log2_chroma_h;
283
284 pp7->temp_stride = FFALIGN(inlink->w + 16, 16);
285 pp7->src = av_malloc_array(pp7->temp_stride, (h + 8) * sizeof(uint8_t));
286
287 if (!pp7->src)
288 return AVERROR(ENOMEM);
289
290 init_thres2(pp7);
291
292 switch (pp7->mode) {
293 case 0: pp7->requantize = hardthresh_c; break;
294 case 1: pp7->requantize = softthresh_c; break;
295 default:
296 case 2: pp7->requantize = mediumthresh_c; break;
297 }
298
299 ff_pp7dsp_init(&pp7->pp7dsp);
300
301 return 0;
302}
303
304static int filter_frame(AVFilterLink *inlink, AVFrame *in)
305{
306 AVFilterContext *ctx = inlink->dst;
307 PP7Context *pp7 = ctx->priv;
308 AVFilterLink *outlink = ctx->outputs[0];
309 AVFrame *out = in;
310
311 int qp_stride = 0;
312 int8_t *qp_table = NULL;
313
314 if (!pp7->qp) {
315 int ret = ff_qp_table_extract(in, &qp_table, &qp_stride, NULL, &pp7->qscale_type);
316 if (ret < 0) {
317 av_frame_free(&in);
318 return ret;
319 }
320 }
321
322 if (!ctx->is_disabled) {
323 const int cw = AV_CEIL_RSHIFT(inlink->w, pp7->hsub);
324 const int ch = AV_CEIL_RSHIFT(inlink->h, pp7->vsub);
325
326 /* get a new frame if in-place is not possible or if the dimensions
327 * are not multiple of 8 */
328 if (!av_frame_is_writable(in) || (inlink->w & 7) || (inlink->h & 7)) {
329 const int aligned_w = FFALIGN(inlink->w, 8);
330 const int aligned_h = FFALIGN(inlink->h, 8);
331
332 out = ff_get_video_buffer(outlink, aligned_w, aligned_h);
333 if (!out) {
334 av_frame_free(&in);
335 av_freep(&qp_table);
336 return AVERROR(ENOMEM);
337 }
339 out->width = in->width;
340 out->height = in->height;
341 }
342
343 if (qp_table || pp7->qp) {
344
345 filter(pp7, out->data[0], in->data[0], out->linesize[0], in->linesize[0],
346 inlink->w, inlink->h, qp_table, qp_stride, 1);
347 filter(pp7, out->data[1], in->data[1], out->linesize[1], in->linesize[1],
348 cw, ch, qp_table, qp_stride, 0);
349 filter(pp7, out->data[2], in->data[2], out->linesize[2], in->linesize[2],
350 cw, ch, qp_table, qp_stride, 0);
351 }
352 }
353
354 if (in != out) {
355 if (in->data[3])
356 av_image_copy_plane(out->data[3], out->linesize[3],
357 in ->data[3], in ->linesize[3],
358 inlink->w, inlink->h);
359 av_frame_free(&in);
360 }
361 av_freep(&qp_table);
362 return ff_filter_frame(outlink, out);
363}
364
366{
367 PP7Context *pp7 = ctx->priv;
368 av_freep(&pp7->src);
369}
370
371static const AVFilterPad pp7_inputs[] = {
372 {
373 .name = "default",
374 .type = AVMEDIA_TYPE_VIDEO,
375 .config_props = config_input,
376 .filter_frame = filter_frame,
377 },
378};
379
381 .p.name = "pp7",
382 .p.description = NULL_IF_CONFIG_SMALL("Apply Postprocessing 7 filter."),
383 .p.priv_class = &pp7_class,
385 .priv_size = sizeof(PP7Context),
386 .uninit = uninit,
390};
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition dsp.h:87
static int config_input(AVFilterLink *inlink)
#define N
Definition af_mcompand.c:54
const FFFilter ff_vf_pp7
Definition vf_pp7.c:380
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition avfilter.c:1068
Main libavfilter public API header.
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define s(width, name)
Definition cbs_vp9.c:198
#define FLAGS
Definition cmdutils.c:598
#define AV_CEIL_RSHIFT(a, b)
Definition common.h:60
#define NULL
Definition coverity.c:32
static int16_t block[64]
Definition dct.c:125
static int filter_frame(DBEDecodeContext *s, AVFrame *frame)
Definition dolby_e.c:1067
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
Definition opt.h:298
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition opt.h:258
#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:204
#define AVERROR(e)
Definition error.h:45
int av_frame_is_writable(AVFrame *frame)
Check if the frame data is writable.
Definition frame.c:535
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition frame.c:64
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition frame.c:599
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
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
int index
Definition gxfenc.c:90
int a
misc image utilities
static av_cold void uninit(AVBitStreamFilterContext *ctx)
#define FILTER_INPUTS(array)
Definition filters.h:264
#define FILTER_OUTPUTS(array)
Definition filters.h:265
#define FILTER_PIXFMTS_ARRAY(array)
Definition filters.h:244
#define AVFILTER_DEFINE_CLASS(fname)
Definition filters.h:478
@ MODE_HARD
Definition vf_pp7.c:44
@ MODE_SOFT
Definition vf_pp7.c:45
#define N0
Definition vf_pp7.c:90
static const AVOption pp7_options[]
Definition vf_pp7.c:68
static int softthresh_c(const PP7Context *p, const int16_t *src, int qp)
Definition vf_pp7.c:180
static int mediumthresh_c(const PP7Context *p, const int16_t *src, int qp)
Definition vf_pp7.c:156
static const int factor[16]
Definition vf_pp7.c:98
#define SN0
Definition vf_pp7.c:93
static int config_input(AVFilterLink *inlink)
Definition vf_pp7.c:274
static int hardthresh_c(const PP7Context *p, const int16_t *src, int qp)
Definition vf_pp7.c:140
static void init_thres2(PP7Context *p)
Definition vf_pp7.c:105
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
Definition vf_pp7.c:304
static av_cold void uninit(AVFilterContext *ctx)
Definition vf_pp7.c:365
#define N1
Definition vf_pp7.c:91
static const AVFilterPad pp7_inputs[]
Definition vf_pp7.c:371
#define N2
Definition vf_pp7.c:92
#define OFFSET(x)
Definition vf_pp7.c:66
#define SN2
Definition vf_pp7.c:95
static void dctA_c(int16_t *dst, const uint8_t *src, int stride)
Definition vf_pp7.c:117
#define av_cold
Definition attributes.h:117
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition internal.h:88
static enum AVPixelFormat pix_fmts[]
Definition libkvazaar.c:296
const char * desc
Definition libsvtav1.c:83
#define FFMIN(a, b)
Definition macros.h:49
#define FFMAX(a, b)
Definition macros.h:47
#define FFALIGN(x, a)
Definition macros.h:78
Memory handling functions.
#define DECLARE_ALIGNED(n, t, v)
Declare a variable that is aligned in memory.
AVOptions.
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3460
AVPixelFormat
Pixel format.
Definition pixfmt.h:71
@ AV_PIX_FMT_NONE
Definition pixfmt.h:72
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition pixfmt.h:73
@ AV_PIX_FMT_YUV440P
planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
Definition pixfmt.h:106
@ AV_PIX_FMT_YUV422P
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition pixfmt.h:77
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
Definition pixfmt.h:81
@ 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:107
@ AV_PIX_FMT_YUV410P
planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples)
Definition pixfmt.h:79
@ AV_PIX_FMT_YUV411P
planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
Definition pixfmt.h:80
@ AV_PIX_FMT_YUV444P
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition pixfmt.h:78
@ 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:86
@ AV_PIX_FMT_GBRP
planar GBR 4:4:4 24bpp
Definition pixfmt.h:165
@ 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
@ 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
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
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
Describe the class of an AVClass context structure.
Definition log.h:76
An instance of a filter.
Definition avfilter.h:273
A filter pad used for either input or output.
Definition filters.h:40
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition frame.h:493
int width
Definition frame.h:544
int height
Definition frame.h:544
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:517
AVOption.
Definition opt.h:428
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition pixdesc.h:69
int thres2[99][16]
Definition vf_pp7.c:51
int temp_stride
Definition vf_pp7.c:58
int vsub
Definition vf_pp7.c:57
enum AVVideoEncParamsType qscale_type
Definition vf_pp7.c:55
int mode
Definition vf_pp7.c:54
int(* requantize)(const struct PP7Context *p, const int16_t *src, int qp)
Definition vf_pp7.c:61
int qp
Definition vf_pp7.c:53
int hsub
Definition vf_pp7.c:56
PP7DSPContext pp7dsp
Definition vf_pp7.c:63
uint8_t * src
Definition vf_pp7.c:59
Definition swscale.c:71
uint8_t level
Definition svq3.c:208
#define stride
#define av_malloc_array(a, b)
#define av_freep(p)
void(* filter)(uint8_t *src, ptrdiff_t stride, int qscale)
Definition h263dsp.c:29
#define src
Definition vp8dsp.c:248
static FILE * out
Definition movenc.c:55
static AVFormatContext * ctx
Definition movenc.c:49
#define height
Definition dsp.h:89
#define width
Definition dsp.h:89
static const uint16_t dither[8][8]
Definition vf_gradfun.c:46
else temp
Definition vf_mcdeint.c:275
@ MODE_MEDIUM
Definition vf_mcdeint.c:62
static void ff_pp7dsp_init(PP7DSPContext *pp7dsp)
Definition vf_pp7dsp.h:56
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
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition video.c:89
AVVideoEncParamsType
static int bias(int x, int c)
Definition vqcdec.c:115