Revision a4dc7aa5

View differences:

Changelog
61 61
- IEC 61937 demuxer
62 62
- Mobotix .mxg demuxer
63 63
- frei0r source added
64
- hqdn3d filter added
64 65

  
65 66

  
66 67
version 0.6:
configure
1407 1407
cropdetect_filter_deps="gpl"
1408 1408
frei0r_filter_deps="frei0r dlopen strtok_r"
1409 1409
frei0r_src_filter_deps="frei0r dlopen strtok_r"
1410
hqdn3d_filter_deps="gpl"
1410 1411
ocv_smooth_filter_deps="libopencv"
1411 1412
yadif_filter_deps="gpl"
1412 1413

  
doc/filters.texi
344 344
ffmpeg -i in.avi -vf "hflip" out.avi
345 345
@end example
346 346

  
347
@section hqdn3d
348

  
349
High precision/quality 3d denoise filter. This filter aims to reduce
350
image noise producing smooth images and making still images really
351
still. It should enhance compressibility.
352

  
353
It accepts the following optional parameters:
354
@var{luma_spatial}:@var{chroma_spatial}:@var{luma_tmp}:@var{chroma_tmp}
355

  
356
@table @option
357
@item luma_spatial
358
a non-negative float number which specifies spatial luma strength,
359
defaults to 4.0
360

  
361
@item chroma_spatial
362
a non-negative float number which specifies spatial chroma strength,
363
defaults to 3.0*@var{luma_spatial}/4.0
364

  
365
@item luma_tmp
366
a float number which specifies luma temporal strength, defaults to
367
6.0*@var{luma_spatial}/4.0
368

  
369
@item chroma_tmp
370
a float number which specifies chroma temporal strength, defaults to
371
@var{luma_tmp}*@var{chroma_spatial}/@var{luma_spatial}
372
@end table
373

  
347 374
@section noformat
348 375

  
349 376
Force libavfilter not to use any of the specified pixel formats for the
libavfilter/Makefile
27 27
OBJS-$(CONFIG_FORMAT_FILTER)                 += vf_format.o
28 28
OBJS-$(CONFIG_FREI0R_FILTER)                 += vf_frei0r.o
29 29
OBJS-$(CONFIG_HFLIP_FILTER)                  += vf_hflip.o
30
OBJS-$(CONFIG_HQDN3D_FILTER)                 += vf_hqdn3d.o
30 31
OBJS-$(CONFIG_NOFORMAT_FILTER)               += vf_format.o
31 32
OBJS-$(CONFIG_NULL_FILTER)                   += vf_null.o
32 33
OBJS-$(CONFIG_OCV_SMOOTH_FILTER)             += vf_libopencv.o
libavfilter/allfilters.c
48 48
    REGISTER_FILTER (FORMAT,      format,      vf);
49 49
    REGISTER_FILTER (FREI0R,      frei0r,      vf);
50 50
    REGISTER_FILTER (HFLIP,       hflip,       vf);
51
    REGISTER_FILTER (HQDN3D,      hqdn3d,      vf);
51 52
    REGISTER_FILTER (NOFORMAT,    noformat,    vf);
52 53
    REGISTER_FILTER (NULL,        null,        vf);
53 54
    REGISTER_FILTER (OCV_SMOOTH,  ocv_smooth,  vf);
libavfilter/avfilter.h
25 25
#include "libavutil/avutil.h"
26 26

  
27 27
#define LIBAVFILTER_VERSION_MAJOR  1
28
#define LIBAVFILTER_VERSION_MINOR 67
29
#define LIBAVFILTER_VERSION_MICRO  1
28
#define LIBAVFILTER_VERSION_MINOR 68
29
#define LIBAVFILTER_VERSION_MICRO  0
30 30

  
31 31
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
32 32
                                               LIBAVFILTER_VERSION_MINOR, \
libavfilter/vf_hqdn3d.c
1
/*
2
 * Copyright (c) 2003 Daniel Moreno <comac AT comac DOT darktech DOT org>
3
 * Copyright (c) 2010 Baptiste Coudurier
4
 *
5
 * This file is part of FFmpeg, ported from MPlayer.
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
 * high quality 3d video denoiser, ported from MPlayer
25
 * libmpcodecs/vf_hqdn3d.c.
26
 */
27

  
28
#include "libavutil/pixdesc.h"
29
#include "avfilter.h"
30

  
31
typedef struct {
32
    int Coefs[4][512*16];
33
    unsigned int *Line;
34
    unsigned short *Frame[3];
35
    int hsub, vsub;
36
} HQDN3DContext;
37

  
38
static inline unsigned int LowPassMul(unsigned int PrevMul, unsigned int CurrMul, int *Coef)
39
{
40
    //    int dMul= (PrevMul&0xFFFFFF)-(CurrMul&0xFFFFFF);
41
    int dMul= PrevMul-CurrMul;
42
    unsigned int d=((dMul+0x10007FF)>>12);
43
    return CurrMul + Coef[d];
44
}
45

  
46
static void deNoiseTemporal(unsigned char *FrameSrc,
47
                            unsigned char *FrameDest,
48
                            unsigned short *FrameAnt,
49
                            int W, int H, int sStride, int dStride,
50
                            int *Temporal)
51
{
52
    long X, Y;
53
    unsigned int PixelDst;
54

  
55
    for (Y = 0; Y < H; Y++) {
56
        for (X = 0; X < W; X++) {
57
            PixelDst = LowPassMul(FrameAnt[X]<<8, FrameSrc[X]<<16, Temporal);
58
            FrameAnt[X] = ((PixelDst+0x1000007F)>>8);
59
            FrameDest[X]= ((PixelDst+0x10007FFF)>>16);
60
        }
61
        FrameSrc  += sStride;
62
        FrameDest += dStride;
63
        FrameAnt += W;
64
    }
65
}
66

  
67
static void deNoiseSpacial(unsigned char *Frame,
68
                           unsigned char *FrameDest,
69
                           unsigned int *LineAnt,
70
                           int W, int H, int sStride, int dStride,
71
                           int *Horizontal, int *Vertical)
72
{
73
    long X, Y;
74
    long sLineOffs = 0, dLineOffs = 0;
75
    unsigned int PixelAnt;
76
    unsigned int PixelDst;
77

  
78
    /* First pixel has no left nor top neighbor. */
79
    PixelDst = LineAnt[0] = PixelAnt = Frame[0]<<16;
80
    FrameDest[0]= ((PixelDst+0x10007FFF)>>16);
81

  
82
    /* First line has no top neighbor, only left. */
83
    for (X = 1; X < W; X++) {
84
        PixelDst = LineAnt[X] = LowPassMul(PixelAnt, Frame[X]<<16, Horizontal);
85
        FrameDest[X]= ((PixelDst+0x10007FFF)>>16);
86
    }
87

  
88
    for (Y = 1; Y < H; Y++) {
89
        unsigned int PixelAnt;
90
        sLineOffs += sStride, dLineOffs += dStride;
91
        /* First pixel on each line doesn't have previous pixel */
92
        PixelAnt = Frame[sLineOffs]<<16;
93
        PixelDst = LineAnt[0] = LowPassMul(LineAnt[0], PixelAnt, Vertical);
94
        FrameDest[dLineOffs]= ((PixelDst+0x10007FFF)>>16);
95

  
96
        for (X = 1; X < W; X++) {
97
            unsigned int PixelDst;
98
            /* The rest are normal */
99
            PixelAnt = LowPassMul(PixelAnt, Frame[sLineOffs+X]<<16, Horizontal);
100
            PixelDst = LineAnt[X] = LowPassMul(LineAnt[X], PixelAnt, Vertical);
101
            FrameDest[dLineOffs+X]= ((PixelDst+0x10007FFF)>>16);
102
        }
103
    }
104
}
105

  
106
static void deNoise(unsigned char *Frame,
107
                    unsigned char *FrameDest,
108
                    unsigned int *LineAnt,
109
                    unsigned short **FrameAntPtr,
110
                    int W, int H, int sStride, int dStride,
111
                    int *Horizontal, int *Vertical, int *Temporal)
112
{
113
    long X, Y;
114
    long sLineOffs = 0, dLineOffs = 0;
115
    unsigned int PixelAnt;
116
    unsigned int PixelDst;
117
    unsigned short* FrameAnt=(*FrameAntPtr);
118

  
119
    if (!FrameAnt) {
120
        (*FrameAntPtr) = FrameAnt = av_malloc(W*H*sizeof(unsigned short));
121
        for (Y = 0; Y < H; Y++) {
122
            unsigned short* dst=&FrameAnt[Y*W];
123
            unsigned char* src=Frame+Y*sStride;
124
            for (X = 0; X < W; X++) dst[X]=src[X]<<8;
125
        }
126
    }
127

  
128
    if (!Horizontal[0] && !Vertical[0]) {
129
        deNoiseTemporal(Frame, FrameDest, FrameAnt,
130
                        W, H, sStride, dStride, Temporal);
131
        return;
132
    }
133
    if (!Temporal[0]) {
134
        deNoiseSpacial(Frame, FrameDest, LineAnt,
135
                       W, H, sStride, dStride, Horizontal, Vertical);
136
        return;
137
    }
138

  
139
    /* First pixel has no left nor top neighbor. Only previous frame */
140
    LineAnt[0] = PixelAnt = Frame[0]<<16;
141
    PixelDst = LowPassMul(FrameAnt[0]<<8, PixelAnt, Temporal);
142
    FrameAnt[0] = ((PixelDst+0x1000007F)>>8);
143
    FrameDest[0]= ((PixelDst+0x10007FFF)>>16);
144

  
145
    /* First line has no top neighbor. Only left one for each pixel and
146
     * last frame */
147
    for (X = 1; X < W; X++) {
148
        LineAnt[X] = PixelAnt = LowPassMul(PixelAnt, Frame[X]<<16, Horizontal);
149
        PixelDst = LowPassMul(FrameAnt[X]<<8, PixelAnt, Temporal);
150
        FrameAnt[X] = ((PixelDst+0x1000007F)>>8);
151
        FrameDest[X]= ((PixelDst+0x10007FFF)>>16);
152
    }
153

  
154
    for (Y = 1; Y < H; Y++) {
155
        unsigned int PixelAnt;
156
        unsigned short* LinePrev=&FrameAnt[Y*W];
157
        sLineOffs += sStride, dLineOffs += dStride;
158
        /* First pixel on each line doesn't have previous pixel */
159
        PixelAnt = Frame[sLineOffs]<<16;
160
        LineAnt[0] = LowPassMul(LineAnt[0], PixelAnt, Vertical);
161
        PixelDst = LowPassMul(LinePrev[0]<<8, LineAnt[0], Temporal);
162
        LinePrev[0] = ((PixelDst+0x1000007F)>>8);
163
        FrameDest[dLineOffs]= ((PixelDst+0x10007FFF)>>16);
164

  
165
        for (X = 1; X < W; X++) {
166
            unsigned int PixelDst;
167
            /* The rest are normal */
168
            PixelAnt = LowPassMul(PixelAnt, Frame[sLineOffs+X]<<16, Horizontal);
169
            LineAnt[X] = LowPassMul(LineAnt[X], PixelAnt, Vertical);
170
            PixelDst = LowPassMul(LinePrev[X]<<8, LineAnt[X], Temporal);
171
            LinePrev[X] = ((PixelDst+0x1000007F)>>8);
172
            FrameDest[dLineOffs+X]= ((PixelDst+0x10007FFF)>>16);
173
        }
174
    }
175
}
176

  
177
static void PrecalcCoefs(int *Ct, double Dist25)
178
{
179
    int i;
180
    double Gamma, Simil, C;
181

  
182
    Gamma = log(0.25) / log(1.0 - Dist25/255.0 - 0.00001);
183

  
184
    for (i = -255*16; i <= 255*16; i++) {
185
        Simil = 1.0 - FFABS(i) / (16*255.0);
186
        C = pow(Simil, Gamma) * 65536.0 * i / 16.0;
187
        Ct[16*256+i] = lrint(C);
188
    }
189

  
190
    Ct[0] = !!Dist25;
191
}
192

  
193
#define PARAM1_DEFAULT 4.0
194
#define PARAM2_DEFAULT 3.0
195
#define PARAM3_DEFAULT 6.0
196

  
197
static int init(AVFilterContext *ctx, const char *args, void *opaque)
198
{
199
    HQDN3DContext *hqdn3d = ctx->priv;
200
    double LumSpac, LumTmp, ChromSpac, ChromTmp;
201
    double Param1, Param2, Param3, Param4;
202

  
203
    LumSpac   = PARAM1_DEFAULT;
204
    ChromSpac = PARAM2_DEFAULT;
205
    LumTmp    = PARAM3_DEFAULT;
206
    ChromTmp  = LumTmp * ChromSpac / LumSpac;
207

  
208
    if (args) {
209
        switch (sscanf(args, "%lf:%lf:%lf:%lf",
210
                       &Param1, &Param2, &Param3, &Param4)) {
211
        case 1:
212
            LumSpac   = Param1;
213
            ChromSpac = PARAM2_DEFAULT * Param1 / PARAM1_DEFAULT;
214
            LumTmp    = PARAM3_DEFAULT * Param1 / PARAM1_DEFAULT;
215
            ChromTmp  = LumTmp * ChromSpac / LumSpac;
216
            break;
217
        case 2:
218
            LumSpac   = Param1;
219
            ChromSpac = Param2;
220
            LumTmp    = PARAM3_DEFAULT * Param1 / PARAM1_DEFAULT;
221
            ChromTmp  = LumTmp * ChromSpac / LumSpac;
222
            break;
223
        case 3:
224
            LumSpac   = Param1;
225
            ChromSpac = Param2;
226
            LumTmp    = Param3;
227
            ChromTmp  = LumTmp * ChromSpac / LumSpac;
228
            break;
229
        case 4:
230
            LumSpac   = Param1;
231
            ChromSpac = Param2;
232
            LumTmp    = Param3;
233
            ChromTmp  = Param4;
234
            break;
235
        }
236
    }
237

  
238
    av_log(ctx, AV_LOG_INFO, "ls:%lf cs:%lf lt:%lf ct:%lf\n",
239
           LumSpac, ChromSpac, LumTmp, ChromTmp);
240
    if (LumSpac < 0 || ChromSpac < 0 || isnan(ChromTmp)) {
241
        av_log(ctx, AV_LOG_ERROR,
242
               "Invalid negative value for luma or chroma spatial strength, "
243
               "or resulting value for chroma temporal strength is nan.\n");
244
        return AVERROR(EINVAL);
245
    }
246

  
247
    PrecalcCoefs(hqdn3d->Coefs[0], LumSpac);
248
    PrecalcCoefs(hqdn3d->Coefs[1], LumTmp);
249
    PrecalcCoefs(hqdn3d->Coefs[2], ChromSpac);
250
    PrecalcCoefs(hqdn3d->Coefs[3], ChromTmp);
251

  
252
    return 0;
253
}
254

  
255
static void uninit(AVFilterContext *ctx)
256
{
257
    HQDN3DContext *hqdn3d = ctx->priv;
258

  
259
    av_freep(&hqdn3d->Line);
260
    av_freep(&hqdn3d->Frame[0]);
261
    av_freep(&hqdn3d->Frame[1]);
262
    av_freep(&hqdn3d->Frame[2]);
263
}
264

  
265
static int query_formats(AVFilterContext *ctx)
266
{
267
    static const enum PixelFormat pix_fmts[] = {
268
        PIX_FMT_YUV420P, PIX_FMT_YUV422P, PIX_FMT_YUV411P, PIX_FMT_NONE
269
    };
270

  
271
    avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts));
272

  
273
    return 0;
274
}
275

  
276
static int config_input(AVFilterLink *inlink)
277
{
278
    HQDN3DContext *hqdn3d = inlink->dst->priv;
279

  
280
    hqdn3d->hsub = av_pix_fmt_descriptors[inlink->format].log2_chroma_w;
281
    hqdn3d->vsub = av_pix_fmt_descriptors[inlink->format].log2_chroma_h;
282

  
283
    hqdn3d->Line = av_malloc(inlink->w * sizeof(*hqdn3d->Line));
284
    if (!hqdn3d->Line)
285
        return AVERROR(ENOMEM);
286

  
287
    return 0;
288
}
289

  
290
static void null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) { }
291

  
292
static void end_frame(AVFilterLink *inlink)
293
{
294
    HQDN3DContext *hqdn3d = inlink->dst->priv;
295
    AVFilterLink *outlink = inlink->dst->outputs[0];
296
    AVFilterBufferRef *inpic  = inlink ->cur_buf;
297
    AVFilterBufferRef *outpic = outlink->out_buf;
298
    int cw = inpic->video->w >> hqdn3d->hsub;
299
    int ch = inpic->video->h >> hqdn3d->vsub;
300

  
301
    deNoise(inpic->data[0], outpic->data[0],
302
            hqdn3d->Line, &hqdn3d->Frame[0], inpic->video->w, inpic->video->h,
303
            inpic->linesize[0], outpic->linesize[0],
304
            hqdn3d->Coefs[0],
305
            hqdn3d->Coefs[0],
306
            hqdn3d->Coefs[1]);
307
    deNoise(inpic->data[1], outpic->data[1],
308
            hqdn3d->Line, &hqdn3d->Frame[1], cw, ch,
309
            inpic->linesize[1], outpic->linesize[1],
310
            hqdn3d->Coefs[2],
311
            hqdn3d->Coefs[2],
312
            hqdn3d->Coefs[3]);
313
    deNoise(inpic->data[2], outpic->data[2],
314
            hqdn3d->Line, &hqdn3d->Frame[2], cw, ch,
315
            inpic->linesize[2], outpic->linesize[2],
316
            hqdn3d->Coefs[2],
317
            hqdn3d->Coefs[2],
318
            hqdn3d->Coefs[3]);
319

  
320
    avfilter_draw_slice(outlink, 0, inpic->video->h, 1);
321
    avfilter_end_frame(outlink);
322
    avfilter_unref_buffer(inpic);
323
    avfilter_unref_buffer(outpic);
324
}
325

  
326
AVFilter avfilter_vf_hqdn3d = {
327
    .name          = "hqdn3d",
328
    .description   = NULL_IF_CONFIG_SMALL("Apply a High Quality 3D Denoiser."),
329

  
330
    .priv_size     = sizeof(HQDN3DContext),
331
    .init          = init,
332
    .uninit        = uninit,
333
    .query_formats = query_formats,
334

  
335
    .inputs    = (AVFilterPad[]) {{ .name             = "default",
336
                                    .type             = AVMEDIA_TYPE_VIDEO,
337
                                    .draw_slice       = null_draw_slice,
338
                                    .config_props     = config_input,
339
                                    .end_frame        = end_frame },
340
                                  { .name = NULL}},
341

  
342
    .outputs   = (AVFilterPad[]) {{ .name             = "default",
343
                                    .type             = AVMEDIA_TYPE_VIDEO },
344
                                  { .name = NULL}},
345
};

Also available in: Unified diff