Statistics
| Branch: | Revision:

ffmpeg / libavfilter / libmpcodecs / vf_ow.c @ e4852fb3

History | View | Annotate | Download (10.1 KB)

1
/*
2
 * Copyright (C) 2007 Michael Niedermayer <michaelni@gmx.at>
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
/**
22
 * @todo try to change to int
23
 * @todo try lifting based implementation
24
 * @todo optimize optimize optimize
25
 * @todo hard tresholding
26
 * @todo use QP to decide filter strength
27
 * @todo wavelet normalization / least squares optimal signal vs. noise thresholds
28
 */
29

    
30
#include <stdio.h>
31
#include <string.h>
32
#include <inttypes.h>
33
#include <math.h>
34

    
35
#include "mp_msg.h"
36
#include "img_format.h"
37
#include "mp_image.h"
38
#include "vf.h"
39

    
40
//===========================================================================//
41
static const uint8_t  __attribute__((aligned(8))) dither[8][8]={
42
{  0,  48,  12,  60,   3,  51,  15,  63, },
43
{ 32,  16,  44,  28,  35,  19,  47,  31, },
44
{  8,  56,   4,  52,  11,  59,   7,  55, },
45
{ 40,  24,  36,  20,  43,  27,  39,  23, },
46
{  2,  50,  14,  62,   1,  49,  13,  61, },
47
{ 34,  18,  46,  30,  33,  17,  45,  29, },
48
{ 10,  58,   6,  54,   9,  57,   5,  53, },
49
{ 42,  26,  38,  22,  41,  25,  37,  21, },
50
};
51
//FIXME the above is duplicated in many filters
52

    
53
struct vf_priv_s {
54
    float strength[2];
55
    float delta;
56
    int mode;
57
    int depth;
58
    float *plane[16][4];
59
    int stride;
60
};
61

    
62
#define S 1.41421356237 //sqrt(2)
63

    
64
static const double coeff[2][5]={
65
    {
66
         0.6029490182363579  *S,
67
         0.2668641184428723  *S,
68
        -0.07822326652898785 *S,
69
        -0.01686411844287495 *S,
70
         0.02674875741080976 *S
71
    },{
72
         1.115087052456994   /S,
73
        -0.5912717631142470  /S,
74
        -0.05754352622849957 /S,
75
         0.09127176311424948 /S
76
    }
77
};
78

    
79
static const double icoeff[2][5]={
80
    {
81
         1.115087052456994   /S,
82
         0.5912717631142470  /S,
83
        -0.05754352622849957 /S,
84
        -0.09127176311424948 /S
85
    },{
86
         0.6029490182363579  *S,
87
        -0.2668641184428723  *S,
88
        -0.07822326652898785 *S,
89
         0.01686411844287495 *S,
90
         0.02674875741080976 *S
91
    }
92
};
93
#undef S
94

    
95
static inline int mirror(int x, int w){
96
    while((unsigned)x > (unsigned)w){
97
        x=-x;
98
        if(x<0) x+= 2*w;
99
    }
100
    return x;
101
}
102

    
103
static inline void decompose(float *dstL, float *dstH, float *src, int stride, int w){
104
    int x, i;
105
    for(x=0; x<w; x++){
106
        double sumL= src[x*stride] * coeff[0][0];
107
        double sumH= src[x*stride] * coeff[1][0];
108
        for(i=1; i<=4; i++){
109
            double s= (src[mirror(x-i, w-1)*stride] + src[mirror(x+i, w-1)*stride]);
110

    
111
            sumL+= coeff[0][i]*s;
112
            sumH+= coeff[1][i]*s;
113
        }
114
        dstL[x*stride]= sumL;
115
        dstH[x*stride]= sumH;
116
    }
117
}
118

    
119
static inline void compose(float *dst, float *srcL, float *srcH, int stride, int w){
120
    int x, i;
121
    for(x=0; x<w; x++){
122
        double sumL= srcL[x*stride] * icoeff[0][0];
123
        double sumH= srcH[x*stride] * icoeff[1][0];
124
        for(i=1; i<=4; i++){
125
            int x0= mirror(x-i, w-1)*stride;
126
            int x1= mirror(x+i, w-1)*stride;
127

    
128
            sumL+= icoeff[0][i]*(srcL[x0] + srcL[x1]);
129
            sumH+= icoeff[1][i]*(srcH[x0] + srcH[x1]);
130
        }
131
        dst[x*stride]= (sumL + sumH)*0.5;
132
    }
133
}
134

    
135
static inline void decompose2D(float *dstL, float *dstH, float *src, int xstride, int ystride, int step, int w, int h){
136
    int y, x;
137
    for(y=0; y<h; y++)
138
        for(x=0; x<step; x++)
139
            decompose(dstL + ystride*y + xstride*x, dstH + ystride*y + xstride*x, src + ystride*y + xstride*x, step*xstride, (w-x+step-1)/step);
140
}
141

    
142
static inline void compose2D(float *dst, float *srcL, float *srcH, int xstride, int ystride, int step, int w, int h){
143
    int y, x;
144
    for(y=0; y<h; y++)
145
        for(x=0; x<step; x++)
146
            compose(dst + ystride*y + xstride*x, srcL + ystride*y + xstride*x, srcH + ystride*y + xstride*x, step*xstride, (w-x+step-1)/step);
147
}
148

    
149
static void decompose2D2(float *dst[4], float *src, float *temp[2], int stride, int step, int w, int h){
150
    decompose2D(temp[0], temp[1], src    , 1, stride, step  , w, h);
151
    decompose2D( dst[0],  dst[1], temp[0], stride, 1, step  , h, w);
152
    decompose2D( dst[2],  dst[3], temp[1], stride, 1, step  , h, w);
153
}
154

    
155
static void compose2D2(float *dst, float *src[4], float *temp[2], int stride, int step, int w, int h){
156
    compose2D(temp[0],  src[0],  src[1], stride, 1, step  , h, w);
157
    compose2D(temp[1],  src[2],  src[3], stride, 1, step  , h, w);
158
    compose2D(dst    , temp[0], temp[1], 1, stride, step  , w, h);
159
}
160

    
161
static void filter(struct vf_priv_s *p, uint8_t *dst, uint8_t *src, int dst_stride, int src_stride, int width, int height, int is_luma){
162
    int x,y, i, j;
163
//    double sum=0;
164
    double s= p->strength[!is_luma];
165
    int depth= p->depth;
166

    
167
    while(1<<depth > width || 1<<depth > height)
168
        depth--;
169

    
170
    for(y=0; y<height; y++)
171
        for(x=0; x<width; x++)
172
            p->plane[0][0][x + y*p->stride]= src[x + y*src_stride];
173

    
174
    for(i=0; i<depth; i++){
175
        decompose2D2(p->plane[i+1], p->plane[i][0], p->plane[0]+1,p->stride, 1<<i, width, height);
176
    }
177
    for(i=0; i<depth; i++){
178
        for(j=1; j<4; j++){
179
            for(y=0; y<height; y++){
180
                for(x=0; x<width; x++){
181
                    double v= p->plane[i+1][j][x + y*p->stride];
182
                    if     (v> s) v-=s;
183
                    else if(v<-s) v+=s;
184
                    else          v =0;
185
                    p->plane[i+1][j][x + y*p->stride]= v;
186
                }
187
            }
188
        }
189
    }
190
    for(i=depth-1; i>=0; i--){
191
        compose2D2(p->plane[i][0], p->plane[i+1], p->plane[0]+1, p->stride, 1<<i, width, height);
192
    }
193

    
194
    for(y=0; y<height; y++)
195
        for(x=0; x<width; x++){
196
            i= p->plane[0][0][x + y*p->stride] + dither[x&7][y&7]*(1.0/64) + 1.0/128; //yes the rounding is insane but optimal :)
197
//            double e= i - src[x + y*src_stride];
198
//            sum += e*e;
199
            if((unsigned)i > 255U) i= ~(i>>31);
200
            dst[x + y*dst_stride]= i;
201
        }
202

    
203
//    printf("%f\n", sum/height/width);
204
}
205

    
206
static int config(struct vf_instance *vf, int width, int height, int d_width, int d_height, unsigned int flags, unsigned int outfmt){
207
    int h= (height+15)&(~15);
208
    int i,j;
209

    
210
    vf->priv->stride= (width+15)&(~15);
211
    for(j=0; j<4; j++){
212
        for(i=0; i<=vf->priv->depth; i++)
213
            vf->priv->plane[i][j]= malloc(vf->priv->stride*h*sizeof(vf->priv->plane[0][0][0]));
214
    }
215

    
216
    return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
217
}
218

    
219
static void get_image(struct vf_instance *vf, mp_image_t *mpi){
220
    if(mpi->flags&MP_IMGFLAG_PRESERVE) return; // don't change
221
    // ok, we can do pp in-place (or pp disabled):
222
    vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
223
        mpi->type, mpi->flags | MP_IMGFLAG_READABLE, mpi->width, mpi->height);
224
    mpi->planes[0]=vf->dmpi->planes[0];
225
    mpi->stride[0]=vf->dmpi->stride[0];
226
    mpi->width=vf->dmpi->width;
227
    if(mpi->flags&MP_IMGFLAG_PLANAR){
228
        mpi->planes[1]=vf->dmpi->planes[1];
229
        mpi->planes[2]=vf->dmpi->planes[2];
230
        mpi->stride[1]=vf->dmpi->stride[1];
231
        mpi->stride[2]=vf->dmpi->stride[2];
232
    }
233
    mpi->flags|=MP_IMGFLAG_DIRECT;
234
}
235

    
236
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
237
    mp_image_t *dmpi;
238

    
239
    if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
240
        // no DR, so get a new image! hope we'll get DR buffer:
241
        dmpi=vf_get_image(vf->next,mpi->imgfmt,
242
            MP_IMGTYPE_TEMP,
243
            MP_IMGFLAG_ACCEPT_STRIDE|MP_IMGFLAG_PREFER_ALIGNED_STRIDE,
244
            mpi->width,mpi->height);
245
        vf_clone_mpi_attributes(dmpi, mpi);
246
    }else{
247
        dmpi=vf->dmpi;
248
    }
249

    
250
    filter(vf->priv, dmpi->planes[0], mpi->planes[0], dmpi->stride[0], mpi->stride[0], mpi->w, mpi->h, 1);
251
    filter(vf->priv, dmpi->planes[1], mpi->planes[1], dmpi->stride[1], mpi->stride[1], mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, 0);
252
    filter(vf->priv, dmpi->planes[2], mpi->planes[2], dmpi->stride[2], mpi->stride[2], mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, 0);
253

    
254
    return vf_next_put_image(vf,dmpi, pts);
255
}
256

    
257
static void uninit(struct vf_instance *vf){
258
    int i,j;
259
    if(!vf->priv) return;
260

    
261
    for(j=0; j<4; j++){
262
        for(i=0; i<16; i++){
263
            free(vf->priv->plane[i][j]);
264
            vf->priv->plane[i][j]= NULL;
265
        }
266
    }
267

    
268
    free(vf->priv);
269
    vf->priv=NULL;
270
}
271

    
272
//===========================================================================//
273
static int query_format(struct vf_instance *vf, unsigned int fmt){
274
    switch(fmt){
275
        case IMGFMT_YVU9:
276
        case IMGFMT_IF09:
277
        case IMGFMT_YV12:
278
        case IMGFMT_I420:
279
        case IMGFMT_IYUV:
280
        case IMGFMT_CLPL:
281
        case IMGFMT_Y800:
282
        case IMGFMT_Y8:
283
        case IMGFMT_444P:
284
        case IMGFMT_422P:
285
        case IMGFMT_411P:
286
            return vf_next_query_format(vf,fmt);
287
    }
288
    return 0;
289
}
290

    
291

    
292
static int vf_open(vf_instance_t *vf, char *args){
293
    vf->config=config;
294
    vf->put_image=put_image;
295
    vf->get_image=get_image;
296
    vf->query_format=query_format;
297
    vf->uninit=uninit;
298
    vf->priv=malloc(sizeof(struct vf_priv_s));
299
    memset(vf->priv, 0, sizeof(struct vf_priv_s));
300

    
301
    vf->priv->depth= 8;
302
    vf->priv->strength[0]= 1.0;
303
    vf->priv->strength[1]= 1.0;
304
    vf->priv->delta= 1.0;
305

    
306
    if (args) sscanf(args, "%d:%f:%f:%d:%f", &vf->priv->depth,
307
                     &vf->priv->strength[0],
308
                     &vf->priv->strength[1],
309
                     &vf->priv->mode,
310
                     &vf->priv->delta);
311

    
312
    return 1;
313
}
314

    
315
const vf_info_t vf_info_ow = {
316
    "overcomplete wavelet denoiser",
317
    "ow",
318
    "Michael Niedermayer",
319
    "",
320
    vf_open,
321
    NULL
322
};