Statistics
| Branch: | Revision:

ffmpeg / libavfilter / libmpcodecs / vf_unsharp.c @ e4852fb3

History | View | Annotate | Download (9.79 KB)

1
/*
2
 * Copyright (C) 2002 Remi Guyomarch <rguyom@pobox.com>
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 "config.h"
28
#include "mp_msg.h"
29
#include "cpudetect.h"
30

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

    
35
#include "img_format.h"
36
#include "mp_image.h"
37
#include "vf.h"
38
#include "libvo/fastmemcpy.h"
39
#include "libavutil/common.h"
40

    
41
//===========================================================================//
42

    
43
#define MIN_MATRIX_SIZE 3
44
#define MAX_MATRIX_SIZE 63
45

    
46
typedef struct FilterParam {
47
    int msizeX, msizeY;
48
    double amount;
49
    uint32_t *SC[MAX_MATRIX_SIZE-1];
50
} FilterParam;
51

    
52
struct vf_priv_s {
53
    FilterParam lumaParam;
54
    FilterParam chromaParam;
55
    unsigned int outfmt;
56
};
57

    
58

    
59
//===========================================================================//
60

    
61
/* This code is based on :
62

63
An Efficient algorithm for Gaussian blur using finite-state machines
64
Frederick M. Waltz and John W. V. Miller
65

66
SPIE Conf. on Machine Vision Systems for Inspection and Metrology VII
67
Originally published Boston, Nov 98
68

69
*/
70

    
71
static void unsharp( uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int width, int height, FilterParam *fp ) {
72

    
73
    uint32_t **SC = fp->SC;
74
    uint32_t SR[MAX_MATRIX_SIZE-1], Tmp1, Tmp2;
75
    uint8_t* src2 = src; // avoid gcc warning
76

    
77
    int32_t res;
78
    int x, y, z;
79
    int amount = fp->amount * 65536.0;
80
    int stepsX = fp->msizeX/2;
81
    int stepsY = fp->msizeY/2;
82
    int scalebits = (stepsX+stepsY)*2;
83
    int32_t halfscale = 1 << ((stepsX+stepsY)*2-1);
84

    
85
    if( !fp->amount ) {
86
        if( src == dst )
87
            return;
88
        if( dstStride == srcStride )
89
            fast_memcpy( dst, src, srcStride*height );
90
        else
91
            for( y=0; y<height; y++, dst+=dstStride, src+=srcStride )
92
                fast_memcpy( dst, src, width );
93
        return;
94
    }
95

    
96
    for( y=0; y<2*stepsY; y++ )
97
        memset( SC[y], 0, sizeof(SC[y][0]) * (width+2*stepsX) );
98

    
99
    for( y=-stepsY; y<height+stepsY; y++ ) {
100
        if( y < height ) src2 = src;
101
        memset( SR, 0, sizeof(SR[0]) * (2*stepsX-1) );
102
        for( x=-stepsX; x<width+stepsX; x++ ) {
103
            Tmp1 = x<=0 ? src2[0] : x>=width ? src2[width-1] : src2[x];
104
            for( z=0; z<stepsX*2; z+=2 ) {
105
                Tmp2 = SR[z+0] + Tmp1; SR[z+0] = Tmp1;
106
                Tmp1 = SR[z+1] + Tmp2; SR[z+1] = Tmp2;
107
            }
108
            for( z=0; z<stepsY*2; z+=2 ) {
109
                Tmp2 = SC[z+0][x+stepsX] + Tmp1; SC[z+0][x+stepsX] = Tmp1;
110
                Tmp1 = SC[z+1][x+stepsX] + Tmp2; SC[z+1][x+stepsX] = Tmp2;
111
            }
112
            if( x>=stepsX && y>=stepsY ) {
113
                uint8_t* srx = src - stepsY*srcStride + x - stepsX;
114
                uint8_t* dsx = dst - stepsY*dstStride + x - stepsX;
115

    
116
                res = (int32_t)*srx + ( ( ( (int32_t)*srx - (int32_t)((Tmp1+halfscale) >> scalebits) ) * amount ) >> 16 );
117
                *dsx = res>255 ? 255 : res<0 ? 0 : (uint8_t)res;
118
            }
119
        }
120
        if( y >= 0 ) {
121
            dst += dstStride;
122
            src += srcStride;
123
        }
124
    }
125
}
126

    
127
//===========================================================================//
128

    
129
static int config( struct vf_instance *vf,
130
                   int width, int height, int d_width, int d_height,
131
                   unsigned int flags, unsigned int outfmt ) {
132

    
133
    int z, stepsX, stepsY;
134
    FilterParam *fp;
135
    char *effect;
136

    
137
    // allocate buffers
138

    
139
    fp = &vf->priv->lumaParam;
140
    effect = fp->amount == 0 ? "don't touch" : fp->amount < 0 ? "blur" : "sharpen";
141
    mp_msg( MSGT_VFILTER, MSGL_INFO, "unsharp: %dx%d:%0.2f (%s luma) \n", fp->msizeX, fp->msizeY, fp->amount, effect );
142
    memset( fp->SC, 0, sizeof( fp->SC ) );
143
    stepsX = fp->msizeX/2;
144
    stepsY = fp->msizeY/2;
145
    for( z=0; z<2*stepsY; z++ )
146
        fp->SC[z] = av_malloc(sizeof(*(fp->SC[z])) * (width+2*stepsX));
147

    
148
    fp = &vf->priv->chromaParam;
149
    effect = fp->amount == 0 ? "don't touch" : fp->amount < 0 ? "blur" : "sharpen";
150
    mp_msg( MSGT_VFILTER, MSGL_INFO, "unsharp: %dx%d:%0.2f (%s chroma)\n", fp->msizeX, fp->msizeY, fp->amount, effect );
151
    memset( fp->SC, 0, sizeof( fp->SC ) );
152
    stepsX = fp->msizeX/2;
153
    stepsY = fp->msizeY/2;
154
    for( z=0; z<2*stepsY; z++ )
155
        fp->SC[z] = av_malloc(sizeof(*(fp->SC[z])) * (width+2*stepsX));
156

    
157
    return vf_next_config( vf, width, height, d_width, d_height, flags, outfmt );
158
}
159

    
160
//===========================================================================//
161

    
162
static void get_image( struct vf_instance *vf, mp_image_t *mpi ) {
163
    if( mpi->flags & MP_IMGFLAG_PRESERVE )
164
        return; // don't change
165
    if( mpi->imgfmt!=vf->priv->outfmt )
166
        return; // colorspace differ
167

    
168
    vf->dmpi = vf_get_image( vf->next, mpi->imgfmt, mpi->type, mpi->flags, mpi->w, mpi->h );
169
    mpi->planes[0] = vf->dmpi->planes[0];
170
    mpi->stride[0] = vf->dmpi->stride[0];
171
    mpi->width = vf->dmpi->width;
172
    if( mpi->flags & MP_IMGFLAG_PLANAR ) {
173
        mpi->planes[1] = vf->dmpi->planes[1];
174
        mpi->planes[2] = vf->dmpi->planes[2];
175
        mpi->stride[1] = vf->dmpi->stride[1];
176
        mpi->stride[2] = vf->dmpi->stride[2];
177
    }
178
    mpi->flags |= MP_IMGFLAG_DIRECT;
179
}
180

    
181
static int put_image( struct vf_instance *vf, mp_image_t *mpi, double pts) {
182
    mp_image_t *dmpi;
183

    
184
    if( !(mpi->flags & MP_IMGFLAG_DIRECT) )
185
        // no DR, so get a new image! hope we'll get DR buffer:
186
        vf->dmpi = vf_get_image( vf->next,vf->priv->outfmt, MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE, mpi->w, mpi->h);
187
    dmpi= vf->dmpi;
188

    
189
    unsharp( dmpi->planes[0], mpi->planes[0], dmpi->stride[0], mpi->stride[0], mpi->w,   mpi->h,   &vf->priv->lumaParam );
190
    unsharp( dmpi->planes[1], mpi->planes[1], dmpi->stride[1], mpi->stride[1], mpi->w/2, mpi->h/2, &vf->priv->chromaParam );
191
    unsharp( dmpi->planes[2], mpi->planes[2], dmpi->stride[2], mpi->stride[2], mpi->w/2, mpi->h/2, &vf->priv->chromaParam );
192

    
193
    vf_clone_mpi_attributes(dmpi, mpi);
194

    
195
#if HAVE_MMX
196
    if(gCpuCaps.hasMMX)
197
        __asm__ volatile ("emms\n\t");
198
#endif
199
#if HAVE_MMX2
200
    if(gCpuCaps.hasMMX2)
201
        __asm__ volatile ("sfence\n\t");
202
#endif
203

    
204
    return vf_next_put_image( vf, dmpi, pts);
205
}
206

    
207
static void uninit( struct vf_instance *vf ) {
208
    unsigned int z;
209
    FilterParam *fp;
210

    
211
    if( !vf->priv ) return;
212

    
213
    fp = &vf->priv->lumaParam;
214
    for( z=0; z<sizeof(fp->SC)/sizeof(fp->SC[0]); z++ ) {
215
        av_free( fp->SC[z] );
216
        fp->SC[z] = NULL;
217
    }
218
    fp = &vf->priv->chromaParam;
219
    for( z=0; z<sizeof(fp->SC)/sizeof(fp->SC[0]); z++ ) {
220
        av_free( fp->SC[z] );
221
        fp->SC[z] = NULL;
222
    }
223

    
224
    free( vf->priv );
225
    vf->priv = NULL;
226
}
227

    
228
//===========================================================================//
229

    
230
static int query_format( struct vf_instance *vf, unsigned int fmt ) {
231
    switch(fmt) {
232
    case IMGFMT_YV12:
233
    case IMGFMT_I420:
234
    case IMGFMT_IYUV:
235
        return vf_next_query_format( vf, vf->priv->outfmt );
236
    }
237
    return 0;
238
}
239

    
240
//===========================================================================//
241

    
242
static void parse( FilterParam *fp, char* args ) {
243

    
244
    // l7x5:0.8:c3x3:-0.2
245

    
246
    char *z;
247
    char *pos = args;
248
    char *max = args + strlen(args);
249

    
250
    // parse matrix sizes
251
    fp->msizeX = ( pos && pos+1<max ) ? atoi( pos+1 ) : 0;
252
    z = strchr( pos+1, 'x' );
253
    fp->msizeY = ( z && z+1<max ) ? atoi( pos=z+1 ) : fp->msizeX;
254

    
255
    // min/max & odd
256
    fp->msizeX = 1 | av_clip(fp->msizeX, MIN_MATRIX_SIZE, MAX_MATRIX_SIZE);
257
    fp->msizeY = 1 | av_clip(fp->msizeY, MIN_MATRIX_SIZE, MAX_MATRIX_SIZE);
258

    
259
    // parse amount
260
    pos = strchr( pos+1, ':' );
261
    fp->amount = ( pos && pos+1<max ) ? atof( pos+1 ) : 0;
262
}
263

    
264
//===========================================================================//
265

    
266
static const unsigned int fmt_list[] = {
267
    IMGFMT_YV12,
268
    IMGFMT_I420,
269
    IMGFMT_IYUV,
270
    0
271
};
272

    
273
static int vf_open( vf_instance_t *vf, char *args ) {
274
    vf->config       = config;
275
    vf->put_image    = put_image;
276
    vf->get_image    = get_image;
277
    vf->query_format = query_format;
278
    vf->uninit       = uninit;
279
    vf->priv         = malloc( sizeof(struct vf_priv_s) );
280
    memset( vf->priv, 0, sizeof(struct vf_priv_s) );
281

    
282
    if( args ) {
283
        char *args2 = strchr( args, 'l' );
284
        if( args2 )
285
            parse( &vf->priv->lumaParam, args2 );
286
        else {
287
            vf->priv->lumaParam.amount =
288
            vf->priv->lumaParam.msizeX =
289
            vf->priv->lumaParam.msizeY = 0;
290
        }
291

    
292
        args2 = strchr( args, 'c' );
293
        if( args2 )
294
            parse( &vf->priv->chromaParam, args2 );
295
        else {
296
            vf->priv->chromaParam.amount =
297
            vf->priv->chromaParam.msizeX =
298
            vf->priv->chromaParam.msizeY = 0;
299
        }
300

    
301
        if( !vf->priv->lumaParam.msizeX && !vf->priv->chromaParam.msizeX )
302
            return 0; // nothing to do
303
    }
304

    
305
    // check csp:
306
    vf->priv->outfmt = vf_match_csp( &vf->next, fmt_list, IMGFMT_YV12 );
307
    if( !vf->priv->outfmt ) {
308
        uninit( vf );
309
        return 0; // no csp match :(
310
    }
311

    
312
    return 1;
313
}
314

    
315
const vf_info_t vf_info_unsharp = {
316
    "unsharp mask & gaussian blur",
317
    "unsharp",
318
    "Remi Guyomarch",
319
    "",
320
    vf_open,
321
    NULL
322
};
323

    
324
//===========================================================================//