~ubuntu-branches/debian/sid/ffmpeg/sid

« back to all changes in this revision

Viewing changes to libavfilter/vf_deband.c

  • Committer: Package Import Robot
  • Author(s): Andreas Cadhalpun, Fabian Greffrath, Andreas Cadhalpun
  • Date: 2015-09-22 15:15:20 UTC
  • mfrom: (0.1.29)
  • Revision ID: package-import@ubuntu.com-20150922151520-hhmd3in9ykigjvs9
Tags: 7:2.8-1
[ Fabian Greffrath ]
* Pass the --dbg-package=ffmpeg-dbg parameter only to dh_strip.
* Add alternative Depends: libavcodec-ffmpeg-extra56 to libavcodec-dev and
  ffmpeg-dbg to allow for building and debugging with this library installed.

[ Andreas Cadhalpun ]
* Import new major upstream release 2.8.
* Remove the transitional lib*-ffmpeg-dev packages.
* Drop old Breaks on kodi-bin.
* Drop workaround for sparc, which is no Debian architecture anymore.
* Re-enable x265 on alpha, as it's available again.
* Disable unavailable frei0r, opencv and x264 on mips64el.
* Disable libopenjpeg (#787275) and libschroedinger (#787957) decoders.
  (Closes: #786670)
* Disable libdc1394 on sparc64, because it links against the broken due to
  #790560 libudev1.
* Enable libsnappy support.
* Add new symbols.
* Update debian/copyright.
* Update debian/tests/encdec_list.txt.
* Add hls-only-seek-if-there-is-an-offset.patch. (Closes: #798189)
* Add 'Breaks: libavutil-ffmpeg54 (>= 8:0)' to the libraries.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2015 Niklas Haas
 
3
 * Copyright (c) 2015 Paul B Mahol
 
4
 *
 
5
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 
6
 * of this software and associated documentation files (the "Software"), to deal
 
7
 * in the Software without restriction, including without limitation the rights
 
8
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
9
 * copies of the Software, and to permit persons to whom the Software is
 
10
 * furnished to do so, subject to the following conditions:
 
11
 *
 
12
 * The above copyright notice and this permission notice shall be included in
 
13
 * all copies or substantial portions of the Software.
 
14
 *
 
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
16
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
17
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 
18
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
19
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
20
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 
21
 * SOFTWARE.
 
22
 */
 
23
 
 
24
#include "libavutil/opt.h"
 
25
#include "libavutil/pixdesc.h"
 
26
#include "avfilter.h"
 
27
#include "internal.h"
 
28
#include "video.h"
 
29
 
 
30
typedef struct DebandContext {
 
31
    const AVClass *class;
 
32
 
 
33
    float threshold[4];
 
34
    int range;
 
35
    int blur;
 
36
    float direction;
 
37
 
 
38
    int nb_components;
 
39
    int planewidth[4];
 
40
    int planeheight[4];
 
41
    int thr[4];
 
42
 
 
43
    int *x_pos;
 
44
    int *y_pos;
 
45
 
 
46
    int (*deband)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs);
 
47
} DebandContext;
 
48
 
 
49
#define OFFSET(x) offsetof(DebandContext, x)
 
50
#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
 
51
 
 
52
static const AVOption deband_options[] = {
 
53
    { "1thr",      "set 1st plane threshold", OFFSET(threshold[0]), AV_OPT_TYPE_FLOAT, {.dbl=0.02},  0.00003,     0.5, FLAGS },
 
54
    { "2thr",      "set 2nd plane threshold", OFFSET(threshold[1]), AV_OPT_TYPE_FLOAT, {.dbl=0.02},  0.00003,     0.5, FLAGS },
 
55
    { "3thr",      "set 3rd plane threshold", OFFSET(threshold[2]), AV_OPT_TYPE_FLOAT, {.dbl=0.02},  0.00003,     0.5, FLAGS },
 
56
    { "4thr",      "set 4th plane threshold", OFFSET(threshold[3]), AV_OPT_TYPE_FLOAT, {.dbl=0.02},  0.00003,     0.5, FLAGS },
 
57
    { "range",     "set range",               OFFSET(range),        AV_OPT_TYPE_INT,   {.i64=16},    INT_MIN, INT_MAX, FLAGS },
 
58
    { "r",         "set range",               OFFSET(range),        AV_OPT_TYPE_INT,   {.i64=16},    INT_MIN, INT_MAX, FLAGS },
 
59
    { "direction", "set direction",           OFFSET(direction),    AV_OPT_TYPE_FLOAT, {.dbl=2*M_PI},-2*M_PI,  2*M_PI, FLAGS },
 
60
    { "d",         "set direction",           OFFSET(direction),    AV_OPT_TYPE_FLOAT, {.dbl=2*M_PI},-2*M_PI,  2*M_PI, FLAGS },
 
61
    { "blur",      "enable blur",             OFFSET(blur),         AV_OPT_TYPE_INT,   {.i64=1},           0,       1, FLAGS },
 
62
    { NULL }
 
63
};
 
64
 
 
65
AVFILTER_DEFINE_CLASS(deband);
 
66
 
 
67
static int query_formats(AVFilterContext *ctx)
 
68
{
 
69
    static const enum AVPixelFormat pix_fmts[] = {
 
70
        AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY16,
 
71
        AV_PIX_FMT_YUV444P,  AV_PIX_FMT_YUV422P,  AV_PIX_FMT_YUV420P,
 
72
        AV_PIX_FMT_YUV411P,  AV_PIX_FMT_YUV410P,  AV_PIX_FMT_YUV440P,
 
73
        AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ420P,
 
74
        AV_PIX_FMT_YUVJ411P, AV_PIX_FMT_YUVJ440P,
 
75
        AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P,
 
76
        AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9,
 
77
        AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA444P9,
 
78
        AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA444P10,
 
79
        AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV444P12,
 
80
        AV_PIX_FMT_YUV420P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV444P14,
 
81
        AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP,
 
82
        AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10,
 
83
        AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14,
 
84
        AV_PIX_FMT_GBRP16, AV_PIX_FMT_GBRAP16,
 
85
        AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16,
 
86
        AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA444P16,
 
87
        AV_PIX_FMT_NONE
 
88
    };
 
89
    AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts);
 
90
    if (!fmts_list)
 
91
        return AVERROR(ENOMEM);
 
92
 
 
93
    return ff_set_common_formats(ctx, fmts_list);
 
94
}
 
95
 
 
96
static float frand(int x, int y)
 
97
{
 
98
    const float r = sinf(x * 12.9898 + y * 78.233) * 43758.545;
 
99
 
 
100
    return r - floorf(r);
 
101
}
 
102
 
 
103
static int inline get_avg(int ref0, int ref1, int ref2, int ref3)
 
104
{
 
105
    return (ref0 + ref1 + ref2 + ref3) / 4;
 
106
}
 
107
 
 
108
typedef struct ThreadData {
 
109
    AVFrame *in, *out;
 
110
} ThreadData;
 
111
 
 
112
static int deband_8_c(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
 
113
{
 
114
    DebandContext *s = ctx->priv;
 
115
    ThreadData *td = arg;
 
116
    AVFrame *in = td->in;
 
117
    AVFrame *out = td->out;
 
118
    int x, y, p;
 
119
 
 
120
    for (p = 0; p < s->nb_components; p++) {
 
121
        const uint8_t *src_ptr = (const uint8_t *)in->data[p];
 
122
        uint8_t *dst_ptr = (uint8_t *)out->data[p];
 
123
        const int dst_linesize = out->linesize[p];
 
124
        const int src_linesize = in->linesize[p];
 
125
        const int thr = s->thr[p];
 
126
        const int start = (s->planeheight[p] *  jobnr   ) / nb_jobs;
 
127
        const int end   = (s->planeheight[p] * (jobnr+1)) / nb_jobs;
 
128
        const int w = s->planewidth[p] - 1;
 
129
        const int h = s->planeheight[p] - 1;
 
130
 
 
131
        for (y = start; y < end; y++) {
 
132
            const int pos = y * s->planeheight[0];
 
133
 
 
134
            for (x = 0; x < s->planewidth[p]; x++) {
 
135
                const int x_pos = s->x_pos[pos + x];
 
136
                const int y_pos = s->y_pos[pos + x];
 
137
                const int ref0 = src_ptr[av_clip(y +  y_pos, 0, h) * src_linesize + av_clip(x +  x_pos, 0, w)];
 
138
                const int ref1 = src_ptr[av_clip(y + -y_pos, 0, h) * src_linesize + av_clip(x +  x_pos, 0, w)];
 
139
                const int ref2 = src_ptr[av_clip(y + -y_pos, 0, h) * src_linesize + av_clip(x + -x_pos, 0, w)];
 
140
                const int ref3 = src_ptr[av_clip(y +  y_pos, 0, h) * src_linesize + av_clip(x + -x_pos, 0, w)];
 
141
                const int src0 = src_ptr[y * src_linesize + x];
 
142
 
 
143
                if (s->blur) {
 
144
                    const int avg = get_avg(ref0, ref1, ref2, ref3);
 
145
                    const int diff = FFABS(src0 - avg);
 
146
 
 
147
                    dst_ptr[y * dst_linesize + x] = diff < thr ? avg : src0;
 
148
                } else {
 
149
                    dst_ptr[y * dst_linesize + x] = (FFABS(src0 - ref0) < thr) &&
 
150
                                                    (FFABS(src0 - ref1) < thr) &&
 
151
                                                    (FFABS(src0 - ref2) < thr) &&
 
152
                                                    (FFABS(src0 - ref3) < thr) ? get_avg(ref0, ref1, ref2, ref3) : src0;
 
153
                }
 
154
            }
 
155
        }
 
156
    }
 
157
 
 
158
    return 0;
 
159
}
 
160
 
 
161
static int deband_16_c(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
 
162
{
 
163
    DebandContext *s = ctx->priv;
 
164
    ThreadData *td = arg;
 
165
    AVFrame *in = td->in;
 
166
    AVFrame *out = td->out;
 
167
    int x, y, p;
 
168
 
 
169
    for (p = 0; p < s->nb_components; p++) {
 
170
        const uint16_t *src_ptr = (const uint16_t *)in->data[p];
 
171
        uint16_t *dst_ptr = (uint16_t *)out->data[p];
 
172
        const int dst_linesize = out->linesize[p] / 2;
 
173
        const int src_linesize = in->linesize[p] / 2;
 
174
        const int thr = s->thr[p];
 
175
        const int start = (s->planeheight[p] *  jobnr   ) / nb_jobs;
 
176
        const int end   = (s->planeheight[p] * (jobnr+1)) / nb_jobs;
 
177
        const int w = s->planewidth[p] - 1;
 
178
        const int h = s->planeheight[p] - 1;
 
179
 
 
180
        for (y = start; y < end; y++) {
 
181
            const int pos = y * s->planeheight[0];
 
182
 
 
183
            for (x = 0; x < s->planewidth[p]; x++) {
 
184
                const int x_pos = s->x_pos[pos + x];
 
185
                const int y_pos = s->y_pos[pos + x];
 
186
                const int ref0 = src_ptr[av_clip(y +  y_pos, 0, h) * src_linesize + av_clip(x +  x_pos, 0, w)];
 
187
                const int ref1 = src_ptr[av_clip(y + -y_pos, 0, h) * src_linesize + av_clip(x +  x_pos, 0, w)];
 
188
                const int ref2 = src_ptr[av_clip(y + -y_pos, 0, h) * src_linesize + av_clip(x + -x_pos, 0, w)];
 
189
                const int ref3 = src_ptr[av_clip(y +  y_pos, 0, h) * src_linesize + av_clip(x + -x_pos, 0, w)];
 
190
                const int src0 = src_ptr[y * src_linesize + x];
 
191
 
 
192
                if (s->blur) {
 
193
                    const int avg = get_avg(ref0, ref1, ref2, ref3);
 
194
                    const int diff = FFABS(src0 - avg);
 
195
 
 
196
                    dst_ptr[y * dst_linesize + x] = diff < thr ? avg : src0;
 
197
                } else {
 
198
                    dst_ptr[y * dst_linesize + x] = (FFABS(src0 - ref0) < thr) &&
 
199
                                                    (FFABS(src0 - ref1) < thr) &&
 
200
                                                    (FFABS(src0 - ref2) < thr) &&
 
201
                                                    (FFABS(src0 - ref3) < thr) ? get_avg(ref0, ref1, ref2, ref3) : src0;
 
202
                }
 
203
            }
 
204
        }
 
205
    }
 
206
 
 
207
    return 0;
 
208
}
 
209
 
 
210
static int config_input(AVFilterLink *inlink)
 
211
{
 
212
    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
 
213
    AVFilterContext *ctx = inlink->dst;
 
214
    DebandContext *s = ctx->priv;
 
215
    const float direction = s->direction;
 
216
    const int range = s->range;
 
217
    int x, y;
 
218
 
 
219
    s->nb_components = desc->nb_components;
 
220
 
 
221
    s->planeheight[1] = s->planeheight[2] = FF_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h);
 
222
    s->planeheight[0] = s->planeheight[3] = inlink->h;
 
223
    s->planewidth[1]  = s->planewidth[2]  = FF_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w);
 
224
    s->planewidth[0]  = s->planewidth[3]  = inlink->w;
 
225
 
 
226
    s->deband = desc->comp[0].depth_minus1 > 7 ? deband_16_c : deband_8_c;
 
227
 
 
228
    s->thr[0] = ((1 << (desc->comp[0].depth_minus1 + 1)) - 1) * s->threshold[0];
 
229
    s->thr[1] = ((1 << (desc->comp[1].depth_minus1 + 1)) - 1) * s->threshold[1];
 
230
    s->thr[2] = ((1 << (desc->comp[2].depth_minus1 + 1)) - 1) * s->threshold[2];
 
231
    s->thr[3] = ((1 << (desc->comp[3].depth_minus1 + 1)) - 1) * s->threshold[3];
 
232
 
 
233
    s->x_pos = av_malloc(s->planewidth[0] * s->planeheight[0] * sizeof(*s->x_pos));
 
234
    s->y_pos = av_malloc(s->planewidth[0] * s->planeheight[0] * sizeof(*s->y_pos));
 
235
    if (!s->x_pos || !s->y_pos)
 
236
        return AVERROR(ENOMEM);
 
237
 
 
238
    for (y = 0; y < s->planeheight[0]; y++) {
 
239
        for (x = 0; x < s->planewidth[0]; x++) {
 
240
            const float r = frand(x, y);
 
241
            const float dir = direction < 0 ? -direction : r * direction;
 
242
            const int dist = range < 0 ? -range : r * range;
 
243
 
 
244
            s->x_pos[y * s->planeheight[0] + x] = cosf(dir) * dist;
 
245
            s->y_pos[y * s->planeheight[0] + x] = sinf(dir) * dist;
 
246
        }
 
247
    }
 
248
 
 
249
    return 0;
 
250
}
 
251
 
 
252
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
 
253
{
 
254
    AVFilterContext *ctx = inlink->dst;
 
255
    AVFilterLink *outlink = ctx->outputs[0];
 
256
    DebandContext *s = ctx->priv;
 
257
    AVFrame *out;
 
258
    ThreadData td;
 
259
 
 
260
    out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
 
261
    if (!out) {
 
262
        av_frame_free(&in);
 
263
        return AVERROR(ENOMEM);
 
264
    }
 
265
    av_frame_copy_props(out, in);
 
266
 
 
267
    td.in = in; td.out = out;
 
268
    ctx->internal->execute(ctx, s->deband, &td, NULL, FFMIN3(s->planeheight[1],
 
269
                                                             s->planeheight[2],
 
270
                                                             ctx->graph->nb_threads));
 
271
 
 
272
    av_frame_free(&in);
 
273
    return ff_filter_frame(outlink, out);
 
274
}
 
275
 
 
276
static av_cold void uninit(AVFilterContext *ctx)
 
277
{
 
278
    DebandContext *s = ctx->priv;
 
279
 
 
280
    av_freep(&s->x_pos);
 
281
    av_freep(&s->y_pos);
 
282
}
 
283
 
 
284
static const AVFilterPad avfilter_vf_deband_inputs[] = {
 
285
    {
 
286
        .name         = "default",
 
287
        .type         = AVMEDIA_TYPE_VIDEO,
 
288
        .config_props = config_input,
 
289
        .filter_frame = filter_frame,
 
290
    },
 
291
    { NULL }
 
292
};
 
293
 
 
294
static const AVFilterPad avfilter_vf_deband_outputs[] = {
 
295
    {
 
296
        .name = "default",
 
297
        .type = AVMEDIA_TYPE_VIDEO,
 
298
    },
 
299
    { NULL }
 
300
};
 
301
 
 
302
AVFilter ff_vf_deband = {
 
303
    .name          = "deband",
 
304
    .description   = NULL_IF_CONFIG_SMALL("Debands video."),
 
305
    .priv_size     = sizeof(DebandContext),
 
306
    .priv_class    = &deband_class,
 
307
    .uninit        = uninit,
 
308
    .query_formats = query_formats,
 
309
    .inputs        = avfilter_vf_deband_inputs,
 
310
    .outputs       = avfilter_vf_deband_outputs,
 
311
    .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
 
312
};