Statistics
| Branch: | Revision:

ffmpeg / libavfilter / libmpcodecs / vf_denoise3d.c @ e4852fb3

History | View | Annotate | Download (8.16 KB)

1
/*
2
 * Copyright (C) 2003 Daniel Moreno <comac@comac.darktech.org>
3
 *
4
 * This file is part of MPlayer.
5
 *
6
 * MPlayer is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 2 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * MPlayer is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License along
17
 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
18
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
 */
20

    
21
#include <stdio.h>
22
#include <stdlib.h>
23
#include <string.h>
24
#include <inttypes.h>
25
#include <math.h>
26

    
27
#include "mp_msg.h"
28
#include "img_format.h"
29
#include "mp_image.h"
30
#include "vf.h"
31

    
32
#define PARAM1_DEFAULT 4.0
33
#define PARAM2_DEFAULT 3.0
34
#define PARAM3_DEFAULT 6.0
35

    
36
//===========================================================================//
37

    
38
struct vf_priv_s {
39
        int Coefs[4][512];
40
        unsigned char *Line;
41
        mp_image_t *pmpi;
42
};
43

    
44

    
45
/***************************************************************************/
46

    
47

    
48
static int config(struct vf_instance *vf,
49
        int width, int height, int d_width, int d_height,
50
        unsigned int flags, unsigned int outfmt){
51

    
52
        free(vf->priv->Line);
53
        vf->priv->Line = malloc(width);
54
        vf->priv->pmpi=NULL;
55
//        vf->default_caps &= !VFCAP_ACCEPT_STRIDE;
56

    
57
        return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
58
}
59

    
60

    
61
static void uninit(struct vf_instance *vf)
62
{
63
    free(vf->priv->Line);
64
}
65

    
66
#define LowPass(Prev, Curr, Coef) (Curr + Coef[Prev - Curr])
67

    
68
static void deNoise(unsigned char *Frame,        // mpi->planes[x]
69
                    unsigned char *FramePrev,    // pmpi->planes[x]
70
                    unsigned char *FrameDest,    // dmpi->planes[x]
71
                    unsigned char *LineAnt,      // vf->priv->Line (width bytes)
72
                    int W, int H, int sStride, int pStride, int dStride,
73
                    int *Horizontal, int *Vertical, int *Temporal)
74
{
75
    int X, Y;
76
    int sLineOffs = 0, pLineOffs = 0, dLineOffs = 0;
77
    unsigned char PixelAnt;
78

    
79
    /* First pixel has no left nor top neighbor. Only previous frame */
80
    LineAnt[0] = PixelAnt = Frame[0];
81
    FrameDest[0] = LowPass(FramePrev[0], LineAnt[0], Temporal);
82

    
83
    /* Fist line has no top neighbor. Only left one for each pixel and
84
     * last frame */
85
    for (X = 1; X < W; X++)
86
    {
87
        PixelAnt = LowPass(PixelAnt, Frame[X], Horizontal);
88
        LineAnt[X] = PixelAnt;
89
        FrameDest[X] = LowPass(FramePrev[X], LineAnt[X], Temporal);
90
    }
91

    
92
    for (Y = 1; Y < H; Y++)
93
    {
94
        sLineOffs += sStride, pLineOffs += pStride, dLineOffs += dStride;
95
        /* First pixel on each line doesn't have previous pixel */
96
        PixelAnt = Frame[sLineOffs];
97
        LineAnt[0] = LowPass(LineAnt[0], PixelAnt, Vertical);
98
        FrameDest[dLineOffs] = LowPass(FramePrev[pLineOffs], LineAnt[0], Temporal);
99

    
100
        for (X = 1; X < W; X++)
101
        {
102
            /* The rest are normal */
103
            PixelAnt = LowPass(PixelAnt, Frame[sLineOffs+X], Horizontal);
104
            LineAnt[X] = LowPass(LineAnt[X], PixelAnt, Vertical);
105
            FrameDest[dLineOffs+X] = LowPass(FramePrev[pLineOffs+X], LineAnt[X], Temporal);
106
        }
107
    }
108
}
109

    
110

    
111

    
112
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
113
        int cw= mpi->w >> mpi->chroma_x_shift;
114
        int ch= mpi->h >> mpi->chroma_y_shift;
115
        int W = mpi->w, H = mpi->h;
116

    
117
        mp_image_t *dmpi=vf_get_image(vf->next,mpi->imgfmt,
118
                MP_IMGTYPE_IP, MP_IMGFLAG_ACCEPT_STRIDE |
119
                MP_IMGFLAG_PRESERVE | MP_IMGFLAG_READABLE,
120
                mpi->w,mpi->h);
121

    
122
        if(!dmpi) return 0;
123
        if (!vf->priv->pmpi) vf->priv->pmpi=mpi;
124

    
125
        deNoise(mpi->planes[0], vf->priv->pmpi->planes[0], dmpi->planes[0],
126
                vf->priv->Line, W, H,
127
                mpi->stride[0], vf->priv->pmpi->stride[0], dmpi->stride[0],
128
                vf->priv->Coefs[0] + 256,
129
                vf->priv->Coefs[0] + 256,
130
                vf->priv->Coefs[1] + 256);
131
        deNoise(mpi->planes[1], vf->priv->pmpi->planes[1], dmpi->planes[1],
132
                vf->priv->Line, cw, ch,
133
                mpi->stride[1], vf->priv->pmpi->stride[1], dmpi->stride[1],
134
                vf->priv->Coefs[2] + 256,
135
                vf->priv->Coefs[2] + 256,
136
                vf->priv->Coefs[3] + 256);
137
        deNoise(mpi->planes[2], vf->priv->pmpi->planes[2], dmpi->planes[2],
138
                vf->priv->Line, cw, ch,
139
                mpi->stride[2], vf->priv->pmpi->stride[2], dmpi->stride[2],
140
                vf->priv->Coefs[2] + 256,
141
                vf->priv->Coefs[2] + 256,
142
                vf->priv->Coefs[3] + 256);
143

    
144
        vf->priv->pmpi=dmpi; // save reference image
145
        return vf_next_put_image(vf,dmpi, pts);
146
}
147

    
148
//===========================================================================//
149

    
150
static int query_format(struct vf_instance *vf, unsigned int fmt){
151
        switch(fmt)
152
        {
153
        case IMGFMT_YV12:
154
        case IMGFMT_I420:
155
        case IMGFMT_IYUV:
156
        case IMGFMT_YVU9:
157
        case IMGFMT_444P:
158
        case IMGFMT_422P:
159
        case IMGFMT_411P:
160
                return vf_next_query_format(vf, fmt);
161
        }
162
        return 0;
163
}
164

    
165

    
166
#define ABS(A) ( (A) > 0 ? (A) : -(A) )
167

    
168
static void PrecalcCoefs(int *Ct, double Dist25)
169
{
170
    int i;
171
    double Gamma, Simil, C;
172

    
173
    Gamma = log(0.25) / log(1.0 - Dist25/255.0);
174

    
175
    for (i = -256; i <= 255; i++)
176
    {
177
        Simil = 1.0 - ABS(i) / 255.0;
178
//        Ct[256+i] = lround(pow(Simil, Gamma) * (double)i);
179
        C = pow(Simil, Gamma) * (double)i;
180
        Ct[256+i] = (C<0) ? (C-0.5) : (C+0.5);
181
    }
182
}
183

    
184

    
185
static int vf_open(vf_instance_t *vf, char *args){
186
        double LumSpac, LumTmp, ChromSpac, ChromTmp;
187
        double Param1, Param2, Param3;
188

    
189
        vf->config=config;
190
        vf->put_image=put_image;
191
        vf->query_format=query_format;
192
        vf->uninit=uninit;
193
        vf->priv=malloc(sizeof(struct vf_priv_s));
194
        memset(vf->priv, 0, sizeof(struct vf_priv_s));
195

    
196
        if (args)
197
        {
198
            switch(sscanf(args, "%lf:%lf:%lf",
199
                          &Param1, &Param2, &Param3
200
                         ))
201
            {
202
            case 0:
203
                LumSpac = PARAM1_DEFAULT;
204
                LumTmp = PARAM3_DEFAULT;
205

    
206
                ChromSpac = PARAM2_DEFAULT;
207
                ChromTmp = LumTmp * ChromSpac / LumSpac;
208
                break;
209

    
210
            case 1:
211
                LumSpac = Param1;
212
                LumTmp = PARAM3_DEFAULT * Param1 / PARAM1_DEFAULT;
213

    
214
                ChromSpac = PARAM2_DEFAULT * Param1 / PARAM1_DEFAULT;
215
                ChromTmp = LumTmp * ChromSpac / LumSpac;
216
                break;
217

    
218
            case 2:
219
                LumSpac = Param1;
220
                LumTmp = PARAM3_DEFAULT * Param1 / PARAM1_DEFAULT;
221

    
222
                ChromSpac = Param2;
223
                ChromTmp = LumTmp * ChromSpac / LumSpac;
224
                break;
225

    
226
            case 3:
227
                LumSpac = Param1;
228
                LumTmp = Param3;
229

    
230
                ChromSpac = Param2;
231
                ChromTmp = LumTmp * ChromSpac / LumSpac;
232
                break;
233

    
234
            default:
235
                LumSpac = PARAM1_DEFAULT;
236
                LumTmp = PARAM3_DEFAULT;
237

    
238
                ChromSpac = PARAM2_DEFAULT;
239
                ChromTmp = LumTmp * ChromSpac / LumSpac;
240
            }
241
        }
242
        else
243
        {
244
            LumSpac = PARAM1_DEFAULT;
245
            LumTmp = PARAM3_DEFAULT;
246

    
247
            ChromSpac = PARAM2_DEFAULT;
248
            ChromTmp = LumTmp * ChromSpac / LumSpac;
249
        }
250

    
251
        PrecalcCoefs(vf->priv->Coefs[0], LumSpac);
252
        PrecalcCoefs(vf->priv->Coefs[1], LumTmp);
253
        PrecalcCoefs(vf->priv->Coefs[2], ChromSpac);
254
        PrecalcCoefs(vf->priv->Coefs[3], ChromTmp);
255

    
256
        return 1;
257
}
258

    
259
const vf_info_t vf_info_denoise3d = {
260
    "3D Denoiser (variable lowpass filter)",
261
    "denoise3d",
262
    "Daniel Moreno",
263
    "",
264
    vf_open,
265
    NULL
266
};
267

    
268
//===========================================================================//