Statistics
| Branch: | Revision:

ffmpeg / libavfilter / libmpcodecs / vf_sab.c @ e4852fb3

History | View | Annotate | Download (9.14 KB)

1
/*
2
 * Copyright (C) 2002 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
#include <stdio.h>
22
#include <stdlib.h>
23
#include <string.h>
24
#include <inttypes.h>
25
#include <assert.h>
26

    
27
#include "config.h"
28
#include "mp_msg.h"
29

    
30
#if HAVE_MALLOC_H
31
#include <malloc.h>
32
#endif
33

    
34
#include "libavutil/avutil.h"
35
#include "img_format.h"
36
#include "mp_image.h"
37
#include "vf.h"
38
#include "libswscale/swscale.h"
39
#include "vf_scale.h"
40

    
41

    
42
//===========================================================================//
43

    
44
typedef struct FilterParam{
45
    float radius;
46
    float preFilterRadius;
47
    float strength;
48
    float quality;
49
    struct SwsContext *preFilterContext;
50
    uint8_t *preFilterBuf;
51
    int preFilterStride;
52
    int distWidth;
53
    int distStride;
54
    int *distCoeff;
55
    int colorDiffCoeff[512];
56
}FilterParam;
57

    
58
struct vf_priv_s {
59
    FilterParam luma;
60
    FilterParam chroma;
61
};
62

    
63

    
64
/***************************************************************************/
65

    
66
//FIXME stupid code duplication
67
static void getSubSampleFactors(int *h, int *v, int format){
68
    switch(format){
69
    case IMGFMT_YV12:
70
    case IMGFMT_I420:
71
        *h=1;
72
        *v=1;
73
        break;
74
    case IMGFMT_YVU9:
75
        *h=2;
76
        *v=2;
77
        break;
78
    case IMGFMT_444P:
79
        *h=0;
80
        *v=0;
81
        break;
82
    case IMGFMT_422P:
83
        *h=1;
84
        *v=0;
85
        break;
86
    case IMGFMT_411P:
87
        *h=2;
88
        *v=0;
89
        break;
90
    }
91
}
92

    
93
static int allocStuff(FilterParam *f, int width, int height){
94
    int stride= (width+7)&~7;
95
    SwsVector *vec;
96
    SwsFilter swsF;
97
    int i,x,y;
98
    f->preFilterBuf= (uint8_t*)memalign(8, stride*height);
99
    f->preFilterStride= stride;
100

    
101
    vec = sws_getGaussianVec(f->preFilterRadius, f->quality);
102
    swsF.lumH= swsF.lumV= vec;
103
    swsF.chrH= swsF.chrV= NULL;
104
    f->preFilterContext= sws_getContext(
105
        width, height, PIX_FMT_GRAY8, width, height, PIX_FMT_GRAY8, get_sws_cpuflags()|SWS_POINT, &swsF, NULL, NULL);
106

    
107
    sws_freeVec(vec);
108
    vec = sws_getGaussianVec(f->strength, 5.0);
109
    for(i=0; i<512; i++){
110
        double d;
111
        int index= i-256 + vec->length/2;
112

    
113
        if(index<0 || index>=vec->length)     d= 0.0;
114
        else                    d= vec->coeff[index];
115

    
116
        f->colorDiffCoeff[i]= (int)(d/vec->coeff[vec->length/2]*(1<<12) + 0.5);
117
    }
118
    sws_freeVec(vec);
119
    vec = sws_getGaussianVec(f->radius, f->quality);
120
    f->distWidth= vec->length;
121
    f->distStride= (vec->length+7)&~7;
122
    f->distCoeff= (int32_t*)memalign(8, f->distWidth*f->distStride*sizeof(int32_t));
123

    
124
    for(y=0; y<vec->length; y++){
125
        for(x=0; x<vec->length; x++){
126
            double d= vec->coeff[x] * vec->coeff[y];
127

    
128
            f->distCoeff[x + y*f->distStride]= (int)(d*(1<<10) + 0.5);
129
//            if(y==vec->length/2)
130
//                printf("%6d ", f->distCoeff[x + y*f->distStride]);
131
        }
132
    }
133
    sws_freeVec(vec);
134

    
135
    return 0;
136
}
137

    
138
static int config(struct vf_instance *vf,
139
    int width, int height, int d_width, int d_height,
140
    unsigned int flags, unsigned int outfmt){
141

    
142
    int sw, sh;
143
//__asm__ volatile("emms\n\t");
144
    allocStuff(&vf->priv->luma, width, height);
145

    
146
    getSubSampleFactors(&sw, &sh, outfmt);
147
    allocStuff(&vf->priv->chroma, width>>sw, height>>sh);
148

    
149
    return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
150
}
151

    
152
static void freeBuffers(FilterParam *f){
153
    if(f->preFilterContext) sws_freeContext(f->preFilterContext);
154
    f->preFilterContext=NULL;
155

    
156
    free(f->preFilterBuf);
157
    f->preFilterBuf=NULL;
158

    
159
    free(f->distCoeff);
160
    f->distCoeff=NULL;
161
}
162

    
163
static void uninit(struct vf_instance *vf){
164
    if(!vf->priv) return;
165

    
166
    freeBuffers(&vf->priv->luma);
167
    freeBuffers(&vf->priv->chroma);
168

    
169
    free(vf->priv);
170
    vf->priv=NULL;
171
}
172

    
173
static inline void blur(uint8_t *dst, uint8_t *src, int w, int h, int dstStride, int srcStride, FilterParam *fp){
174
    int x, y;
175
    FilterParam f= *fp;
176
    const int radius= f.distWidth/2;
177
    const uint8_t* const srcArray[MP_MAX_PLANES] = {src};
178
    uint8_t *dstArray[MP_MAX_PLANES]= {f.preFilterBuf};
179
    int srcStrideArray[MP_MAX_PLANES]= {srcStride};
180
    int dstStrideArray[MP_MAX_PLANES]= {f.preFilterStride};
181

    
182
//    f.preFilterContext->swScale(f.preFilterContext, srcArray, srcStrideArray, 0, h, dstArray, dstStrideArray);
183
    sws_scale(f.preFilterContext, srcArray, srcStrideArray, 0, h, dstArray, dstStrideArray);
184

    
185
    for(y=0; y<h; y++){
186
        for(x=0; x<w; x++){
187
            int sum=0;
188
            int div=0;
189
            int dy;
190
            const int preVal= f.preFilterBuf[x + y*f.preFilterStride];
191
#if 0
192
            const int srcVal= src[x + y*srcStride];
193
if((x/32)&1){
194
    dst[x + y*dstStride]= srcVal;
195
    if(y%32==0) dst[x + y*dstStride]= 0;
196
    continue;
197
}
198
#endif
199
            if(x >= radius && x < w - radius){
200
                for(dy=0; dy<radius*2+1; dy++){
201
                    int dx;
202
                    int iy= y+dy - radius;
203
                    if     (iy<0)  iy=  -iy;
204
                    else if(iy>=h) iy= h+h-iy-1;
205

    
206
                    for(dx=0; dx<radius*2+1; dx++){
207
                        const int ix= x+dx - radius;
208
                        int factor;
209

    
210
                        factor= f.colorDiffCoeff[256+preVal - f.preFilterBuf[ix + iy*f.preFilterStride] ]
211
                            *f.distCoeff[dx + dy*f.distStride];
212
                        sum+= src[ix + iy*srcStride] *factor;
213
                        div+= factor;
214
                    }
215
                }
216
            }else{
217
                for(dy=0; dy<radius*2+1; dy++){
218
                    int dx;
219
                    int iy= y+dy - radius;
220
                    if     (iy<0)  iy=  -iy;
221
                    else if(iy>=h) iy= h+h-iy-1;
222

    
223
                    for(dx=0; dx<radius*2+1; dx++){
224
                        int ix= x+dx - radius;
225
                        int factor;
226
                        if     (ix<0)  ix=  -ix;
227
                        else if(ix>=w) ix= w+w-ix-1;
228

    
229
                        factor= f.colorDiffCoeff[256+preVal - f.preFilterBuf[ix + iy*f.preFilterStride] ]
230
                            *f.distCoeff[dx + dy*f.distStride];
231
                        sum+= src[ix + iy*srcStride] *factor;
232
                        div+= factor;
233
                    }
234
                }
235
            }
236
            dst[x + y*dstStride]= (sum + div/2)/div;
237
        }
238
    }
239
}
240

    
241
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
242
    int cw= mpi->w >> mpi->chroma_x_shift;
243
    int ch= mpi->h >> mpi->chroma_y_shift;
244

    
245
    mp_image_t *dmpi=vf_get_image(vf->next,mpi->imgfmt,
246
        MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
247
        mpi->w,mpi->h);
248

    
249
    assert(mpi->flags&MP_IMGFLAG_PLANAR);
250

    
251
    blur(dmpi->planes[0], mpi->planes[0], mpi->w,mpi->h, dmpi->stride[0], mpi->stride[0], &vf->priv->luma);
252
    blur(dmpi->planes[1], mpi->planes[1], cw    , ch   , dmpi->stride[1], mpi->stride[1], &vf->priv->chroma);
253
    blur(dmpi->planes[2], mpi->planes[2], cw    , ch   , dmpi->stride[2], mpi->stride[2], &vf->priv->chroma);
254

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

    
258
//===========================================================================//
259

    
260
static int query_format(struct vf_instance *vf, unsigned int fmt){
261
    switch(fmt)
262
    {
263
    case IMGFMT_YV12:
264
    case IMGFMT_I420:
265
    case IMGFMT_IYUV:
266
    case IMGFMT_YVU9:
267
    case IMGFMT_444P:
268
    case IMGFMT_422P:
269
    case IMGFMT_411P:
270
        return vf_next_query_format(vf, fmt);
271
    }
272
    return 0;
273
}
274

    
275
static int vf_open(vf_instance_t *vf, char *args){
276
    int e;
277

    
278
    vf->config=config;
279
    vf->put_image=put_image;
280
//    vf->get_image=get_image;
281
    vf->query_format=query_format;
282
    vf->uninit=uninit;
283
    vf->priv=malloc(sizeof(struct vf_priv_s));
284
    memset(vf->priv, 0, sizeof(struct vf_priv_s));
285

    
286
    if(args==NULL) return 0;
287

    
288
    e=sscanf(args, "%f:%f:%f:%f:%f:%f",
289
        &vf->priv->luma.radius,
290
        &vf->priv->luma.preFilterRadius,
291
        &vf->priv->luma.strength,
292
        &vf->priv->chroma.radius,
293
        &vf->priv->chroma.preFilterRadius,
294
        &vf->priv->chroma.strength
295
        );
296

    
297
    vf->priv->luma.quality = vf->priv->chroma.quality= 3.0;
298

    
299
    if(e==3){
300
        vf->priv->chroma.radius= vf->priv->luma.radius;
301
        vf->priv->chroma.preFilterRadius = vf->priv->luma.preFilterRadius;
302
        vf->priv->chroma.strength= vf->priv->luma.strength;
303
    }else if(e!=6)
304
        return 0;
305

    
306
//    if(vf->priv->luma.radius < 0) return 0;
307
//    if(vf->priv->chroma.radius < 0) return 0;
308

    
309
    return 1;
310
}
311

    
312
const vf_info_t vf_info_sab = {
313
    "shape adaptive blur",
314
    "sab",
315
    "Michael Niedermayer",
316
    "",
317
    vf_open,
318
    NULL
319
};
320

    
321
//===========================================================================//