~ubuntu-dev/mplayer/ubuntu-feisty

« back to all changes in this revision

Viewing changes to libmpcodecs/vf_hqdn3d.c

  • Committer: Reinhard Tartler
  • Date: 2006-07-08 08:45:33 UTC
  • Revision ID: siretart@tauware.de-20060708084533-dbc155bde7122e78
imported mplayer_0.99+1.0pre7try2+cvs20060117

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    Copyright (C) 2003 Daniel Moreno <comac@comac.darktech.org>
 
3
 
 
4
    This program is free software; you can redistribute it and/or modify
 
5
    it under the terms of the GNU General Public License as published by
 
6
    the Free Software Foundation; either version 2 of the License, or
 
7
    (at your option) any later version.
 
8
 
 
9
    This program is distributed in the hope that it will be useful,
 
10
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
    GNU General Public License for more details.
 
13
 
 
14
    You should have received a copy of the GNU General Public License
 
15
    along with this program; if not, write to the Free Software
 
16
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 
17
*/
 
18
 
 
19
#include <stdio.h>
 
20
#include <stdlib.h>
 
21
#include <string.h>
 
22
#include <inttypes.h>
 
23
#include <math.h>
 
24
 
 
25
#include "config.h"
 
26
#include "mp_msg.h"
 
27
 
 
28
#ifdef HAVE_MALLOC_H
 
29
#include <malloc.h>
 
30
#endif
 
31
 
 
32
#include "img_format.h"
 
33
#include "mp_image.h"
 
34
#include "vf.h"
 
35
#include "libvo/fastmemcpy.h"
 
36
 
 
37
#define PARAM1_DEFAULT 4.0
 
38
#define PARAM2_DEFAULT 3.0
 
39
#define PARAM3_DEFAULT 6.0
 
40
 
 
41
//===========================================================================//
 
42
 
 
43
struct vf_priv_s {
 
44
        int Coefs[4][512*16];
 
45
        unsigned int *Line;
 
46
        unsigned short *Frame[3];
 
47
};
 
48
 
 
49
 
 
50
/***************************************************************************/
 
51
 
 
52
static void uninit(struct vf_instance_s* vf){
 
53
        if(vf->priv->Line){free(vf->priv->Line);vf->priv->Line=NULL;}
 
54
        if(vf->priv->Frame[0]){free(vf->priv->Frame[0]);vf->priv->Frame[0]=NULL;}
 
55
        if(vf->priv->Frame[1]){free(vf->priv->Frame[1]);vf->priv->Frame[1]=NULL;}
 
56
        if(vf->priv->Frame[2]){free(vf->priv->Frame[2]);vf->priv->Frame[2]=NULL;}
 
57
}
 
58
 
 
59
static int config(struct vf_instance_s* vf,
 
60
        int width, int height, int d_width, int d_height,
 
61
        unsigned int flags, unsigned int outfmt){
 
62
 
 
63
        uninit(vf);
 
64
        vf->priv->Line = malloc(width*sizeof(int));
 
65
 
 
66
        return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
 
67
}
 
68
 
 
69
static inline unsigned int LowPassMul(unsigned int PrevMul, unsigned int CurrMul, int* Coef){
 
70
//    int dMul= (PrevMul&0xFFFFFF)-(CurrMul&0xFFFFFF);
 
71
    int dMul= PrevMul-CurrMul;
 
72
    int d=((dMul+0x10007FF)/(65536/16));
 
73
    return CurrMul + Coef[d];
 
74
}
 
75
 
 
76
static void deNoiseTemporal(
 
77
                    unsigned char *Frame,        // mpi->planes[x]
 
78
                    unsigned char *FrameDest,    // dmpi->planes[x]
 
79
                    unsigned short *FrameAnt,
 
80
                    int W, int H, int sStride, int dStride,
 
81
                    int *Temporal)
 
82
{
 
83
    int X, Y;
 
84
    int PixelDst;
 
85
 
 
86
    for (Y = 0; Y < H; Y++){
 
87
        for (X = 0; X < W; X++){
 
88
            PixelDst = LowPassMul(FrameAnt[X]<<8, Frame[X]<<16, Temporal);
 
89
            FrameAnt[X] = ((PixelDst+0x1000007F)/256);
 
90
            FrameDest[X]= ((PixelDst+0x10007FFF)/65536);
 
91
        }
 
92
        Frame += sStride;
 
93
        FrameDest += dStride;
 
94
        FrameAnt += W;
 
95
    }
 
96
}
 
97
 
 
98
static void deNoiseSpacial(
 
99
                    unsigned char *Frame,        // mpi->planes[x]
 
100
                    unsigned char *FrameDest,    // dmpi->planes[x]
 
101
                    unsigned int *LineAnt,       // vf->priv->Line (width bytes)
 
102
                    int W, int H, int sStride, int dStride,
 
103
                    int *Horizontal, int *Vertical)
 
104
{
 
105
    int X, Y;
 
106
    int sLineOffs = 0, dLineOffs = 0;
 
107
    unsigned int PixelAnt;
 
108
    int PixelDst;
 
109
    
 
110
    /* First pixel has no left nor top neighbor. */
 
111
    PixelDst = LineAnt[0] = PixelAnt = Frame[0]<<16;
 
112
    FrameDest[0]= ((PixelDst+0x10007FFF)/65536);
 
113
 
 
114
    /* First line has no top neighbor, only left. */
 
115
    for (X = 1; X < W; X++){
 
116
        PixelDst = LineAnt[X] = LowPassMul(PixelAnt, Frame[X]<<16, Horizontal);
 
117
        FrameDest[X]= ((PixelDst+0x10007FFF)/65536);
 
118
    }
 
119
 
 
120
    for (Y = 1; Y < H; Y++){
 
121
        unsigned int PixelAnt;
 
122
        sLineOffs += sStride, dLineOffs += dStride;
 
123
        /* First pixel on each line doesn't have previous pixel */
 
124
        PixelAnt = Frame[sLineOffs]<<16;
 
125
        PixelDst = LineAnt[0] = LowPassMul(LineAnt[0], PixelAnt, Vertical);
 
126
        FrameDest[dLineOffs]= ((PixelDst+0x10007FFF)/65536);
 
127
 
 
128
        for (X = 1; X < W; X++){
 
129
            int PixelDst;
 
130
            /* The rest are normal */
 
131
            PixelAnt = LowPassMul(PixelAnt, Frame[sLineOffs+X]<<16, Horizontal);
 
132
            PixelDst = LineAnt[X] = LowPassMul(LineAnt[X], PixelAnt, Vertical);
 
133
            FrameDest[dLineOffs+X]= ((PixelDst+0x10007FFF)/65536);
 
134
        }
 
135
    }
 
136
}
 
137
 
 
138
static void deNoise(unsigned char *Frame,        // mpi->planes[x]
 
139
                    unsigned char *FrameDest,    // dmpi->planes[x]
 
140
                    unsigned int *LineAnt,      // vf->priv->Line (width bytes)
 
141
                    unsigned short **FrameAntPtr,
 
142
                    int W, int H, int sStride, int dStride,
 
143
                    int *Horizontal, int *Vertical, int *Temporal)
 
144
{
 
145
    int X, Y;
 
146
    int sLineOffs = 0, dLineOffs = 0;
 
147
    unsigned int PixelAnt;
 
148
    int PixelDst;
 
149
    unsigned short* FrameAnt=(*FrameAntPtr);
 
150
    
 
151
    if(!FrameAnt){
 
152
        (*FrameAntPtr)=FrameAnt=malloc(W*H*sizeof(unsigned short));
 
153
        for (Y = 0; Y < H; Y++){
 
154
            unsigned short* dst=&FrameAnt[Y*W];
 
155
            unsigned char* src=Frame+Y*sStride;
 
156
            for (X = 0; X < W; X++) dst[X]=src[X]<<8;
 
157
        }
 
158
    }
 
159
 
 
160
    if(!Horizontal[0] && !Vertical[0]){
 
161
        deNoiseTemporal(Frame, FrameDest, FrameAnt,
 
162
                        W, H, sStride, dStride, Temporal);
 
163
        return;
 
164
    }
 
165
    if(!Temporal[0]){
 
166
        deNoiseSpacial(Frame, FrameDest, LineAnt,
 
167
                       W, H, sStride, dStride, Horizontal, Vertical);
 
168
        return;
 
169
    }
 
170
 
 
171
    /* First pixel has no left nor top neighbor. Only previous frame */
 
172
    LineAnt[0] = PixelAnt = Frame[0]<<16;
 
173
    PixelDst = LowPassMul(FrameAnt[0]<<8, PixelAnt, Temporal);
 
174
    FrameAnt[0] = ((PixelDst+0x1000007F)/256);
 
175
    FrameDest[0]= ((PixelDst+0x10007FFF)/65536);
 
176
 
 
177
    /* First line has no top neighbor. Only left one for each pixel and
 
178
     * last frame */
 
179
    for (X = 1; X < W; X++){
 
180
        LineAnt[X] = PixelAnt = LowPassMul(PixelAnt, Frame[X]<<16, Horizontal);
 
181
        PixelDst = LowPassMul(FrameAnt[X]<<8, PixelAnt, Temporal);
 
182
        FrameAnt[X] = ((PixelDst+0x1000007F)/256);
 
183
        FrameDest[X]= ((PixelDst+0x10007FFF)/65536);
 
184
    }
 
185
 
 
186
    for (Y = 1; Y < H; Y++){
 
187
        unsigned int PixelAnt;
 
188
        unsigned short* LinePrev=&FrameAnt[Y*W];
 
189
        sLineOffs += sStride, dLineOffs += dStride;
 
190
        /* First pixel on each line doesn't have previous pixel */
 
191
        PixelAnt = Frame[sLineOffs]<<16;
 
192
        LineAnt[0] = LowPassMul(LineAnt[0], PixelAnt, Vertical);
 
193
        PixelDst = LowPassMul(LinePrev[0]<<8, LineAnt[0], Temporal);
 
194
        LinePrev[0] = ((PixelDst+0x1000007F)/256);
 
195
        FrameDest[dLineOffs]= ((PixelDst+0x10007FFF)/65536);
 
196
 
 
197
        for (X = 1; X < W; X++){
 
198
            int PixelDst;
 
199
            /* The rest are normal */
 
200
            PixelAnt = LowPassMul(PixelAnt, Frame[sLineOffs+X]<<16, Horizontal);
 
201
            LineAnt[X] = LowPassMul(LineAnt[X], PixelAnt, Vertical);
 
202
            PixelDst = LowPassMul(LinePrev[X]<<8, LineAnt[X], Temporal);
 
203
            LinePrev[X] = ((PixelDst+0x1000007F)/256);
 
204
            FrameDest[dLineOffs+X]= ((PixelDst+0x10007FFF)/65536);
 
205
        }
 
206
    }
 
207
}
 
208
 
 
209
 
 
210
static int put_image(struct vf_instance_s* vf, mp_image_t *mpi){
 
211
        int cw= mpi->w >> mpi->chroma_x_shift;
 
212
        int ch= mpi->h >> mpi->chroma_y_shift;
 
213
        int W = mpi->w, H = mpi->h;
 
214
 
 
215
        mp_image_t *dmpi=vf_get_image(vf->next,mpi->imgfmt,
 
216
                MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
 
217
                mpi->w,mpi->h);
 
218
 
 
219
        if(!dmpi) return 0;
 
220
 
 
221
        deNoise(mpi->planes[0], dmpi->planes[0],
 
222
                vf->priv->Line, &vf->priv->Frame[0], W, H,
 
223
                mpi->stride[0], dmpi->stride[0],
 
224
                vf->priv->Coefs[0],
 
225
                vf->priv->Coefs[0],
 
226
                vf->priv->Coefs[1]);
 
227
        deNoise(mpi->planes[1], dmpi->planes[1],
 
228
                vf->priv->Line, &vf->priv->Frame[1], cw, ch,
 
229
                mpi->stride[1], dmpi->stride[1],
 
230
                vf->priv->Coefs[2],
 
231
                vf->priv->Coefs[2],
 
232
                vf->priv->Coefs[3]);
 
233
        deNoise(mpi->planes[2], dmpi->planes[2],
 
234
                vf->priv->Line, &vf->priv->Frame[2], cw, ch,
 
235
                mpi->stride[2], dmpi->stride[2],
 
236
                vf->priv->Coefs[2],
 
237
                vf->priv->Coefs[2],
 
238
                vf->priv->Coefs[3]);
 
239
 
 
240
        return vf_next_put_image(vf,dmpi);
 
241
}
 
242
 
 
243
//===========================================================================//
 
244
 
 
245
static int query_format(struct vf_instance_s* vf, unsigned int fmt){
 
246
        switch(fmt)
 
247
        {
 
248
        case IMGFMT_YV12:
 
249
        case IMGFMT_I420:
 
250
        case IMGFMT_IYUV:
 
251
        case IMGFMT_YVU9:
 
252
        case IMGFMT_444P:
 
253
        case IMGFMT_422P:
 
254
        case IMGFMT_411P:
 
255
                return vf_next_query_format(vf, fmt);
 
256
        }
 
257
        return 0;
 
258
}
 
259
 
 
260
 
 
261
#define ABS(A) ( (A) > 0 ? (A) : -(A) )
 
262
 
 
263
static void PrecalcCoefs(int *Ct, double Dist25)
 
264
{
 
265
    int i;
 
266
    double Gamma, Simil, C;
 
267
 
 
268
    Gamma = log(0.25) / log(1.0 - Dist25/255.0 - 0.00001);
 
269
 
 
270
    for (i = -255*16; i <= 255*16; i++)
 
271
    {
 
272
        Simil = 1.0 - ABS(i) / (16*255.0);
 
273
        C = pow(Simil, Gamma) * 65536.0 * (double)i / 16.0;
 
274
        Ct[16*256+i] = (C<0) ? (C-0.5) : (C+0.5);
 
275
    }
 
276
 
 
277
    Ct[0] = (Dist25 != 0);
 
278
}
 
279
 
 
280
 
 
281
static int open(vf_instance_t *vf, char* args){
 
282
        double LumSpac, LumTmp, ChromSpac, ChromTmp;
 
283
        double Param1, Param2, Param3, Param4;
 
284
 
 
285
        vf->config=config;
 
286
        vf->put_image=put_image;
 
287
        vf->query_format=query_format;
 
288
        vf->uninit=uninit;
 
289
        vf->priv=malloc(sizeof(struct vf_priv_s));
 
290
        memset(vf->priv, 0, sizeof(struct vf_priv_s));
 
291
 
 
292
        if (args)
 
293
        {
 
294
            switch(sscanf(args, "%lf:%lf:%lf:%lf",
 
295
                          &Param1, &Param2, &Param3, &Param4
 
296
                         ))
 
297
            {
 
298
            case 0:
 
299
                LumSpac = PARAM1_DEFAULT;
 
300
                LumTmp = PARAM3_DEFAULT;
 
301
 
 
302
                ChromSpac = PARAM2_DEFAULT;
 
303
                ChromTmp = LumTmp * ChromSpac / LumSpac;
 
304
                break;
 
305
 
 
306
            case 1:
 
307
                LumSpac = Param1;
 
308
                LumTmp = PARAM3_DEFAULT * Param1 / PARAM1_DEFAULT;
 
309
 
 
310
                ChromSpac = PARAM2_DEFAULT * Param1 / PARAM1_DEFAULT;
 
311
                ChromTmp = LumTmp * ChromSpac / LumSpac;
 
312
                break;
 
313
 
 
314
            case 2:
 
315
                LumSpac = Param1;
 
316
                LumTmp = PARAM3_DEFAULT * Param1 / PARAM1_DEFAULT;
 
317
 
 
318
                ChromSpac = Param2;
 
319
                ChromTmp = LumTmp * ChromSpac / LumSpac;
 
320
                break;
 
321
 
 
322
            case 3:
 
323
                LumSpac = Param1;
 
324
                LumTmp = Param3;
 
325
 
 
326
                ChromSpac = Param2;
 
327
                ChromTmp = LumTmp * ChromSpac / LumSpac;
 
328
                break;
 
329
 
 
330
            case 4:
 
331
                LumSpac = Param1;
 
332
                LumTmp = Param3;
 
333
 
 
334
                ChromSpac = Param2;
 
335
                ChromTmp = Param4;
 
336
                break;
 
337
 
 
338
            default:
 
339
                LumSpac = PARAM1_DEFAULT;
 
340
                LumTmp = PARAM3_DEFAULT;
 
341
 
 
342
                ChromSpac = PARAM2_DEFAULT;
 
343
                ChromTmp = LumTmp * ChromSpac / LumSpac;
 
344
            }
 
345
        }
 
346
        else
 
347
        {
 
348
            LumSpac = PARAM1_DEFAULT;
 
349
            LumTmp = PARAM3_DEFAULT;
 
350
 
 
351
            ChromSpac = PARAM2_DEFAULT;
 
352
            ChromTmp = LumTmp * ChromSpac / LumSpac;
 
353
        }
 
354
 
 
355
        PrecalcCoefs(vf->priv->Coefs[0], LumSpac);
 
356
        PrecalcCoefs(vf->priv->Coefs[1], LumTmp);
 
357
        PrecalcCoefs(vf->priv->Coefs[2], ChromSpac);
 
358
        PrecalcCoefs(vf->priv->Coefs[3], ChromTmp);
 
359
 
 
360
        return 1;
 
361
}
 
362
 
 
363
vf_info_t vf_info_hqdn3d = {
 
364
    "High Quality 3D Denoiser",
 
365
    "hqdn3d",
 
366
    "Daniel Moreno & A'rpi",
 
367
    "",
 
368
    open,
 
369
    NULL
 
370
};
 
371
 
 
372
//===========================================================================//