Use proper length specifiers in mp_msg calls, fixes the warnings:
[mplayer/greg.git] / libmpcodecs / vf_unsharp.c
blobe8126c566016ccc93a77381ace695056fbcf541c
1 /*
2 Copyright (C) 2002 Remi Guyomarch <rguyom@pobox.com>
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.
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.
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
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <inttypes.h>
24 #include <math.h>
26 #include "config.h"
27 #include "mp_msg.h"
28 #include "cpudetect.h"
30 #ifdef HAVE_MALLOC_H
31 #include <malloc.h>
32 #endif
34 #include "img_format.h"
35 #include "mp_image.h"
36 #include "vf.h"
37 #include "libvo/fastmemcpy.h"
38 #include "libavutil/common.h"
40 //===========================================================================//
42 #define MIN_MATRIX_SIZE 3
43 #define MAX_MATRIX_SIZE 63
45 typedef struct FilterParam {
46 int msizeX, msizeY;
47 double amount;
48 uint32_t *SC[MAX_MATRIX_SIZE-1];
49 } FilterParam;
51 struct vf_priv_s {
52 FilterParam lumaParam;
53 FilterParam chromaParam;
54 unsigned int outfmt;
58 //===========================================================================//
60 /* This code is based on :
62 An Efficient algorithm for Gaussian blur using finite-state machines
63 Frederick M. Waltz and John W. V. Miller
65 SPIE Conf. on Machine Vision Systems for Inspection and Metrology VII
66 Originally published Boston, Nov 98
70 static void unsharp( uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int width, int height, FilterParam *fp ) {
72 uint32_t **SC = fp->SC;
73 uint32_t SR[MAX_MATRIX_SIZE-1], Tmp1, Tmp2;
74 uint8_t* src2 = src; // avoid gcc warning
76 int32_t res;
77 int x, y, z;
78 int amount = fp->amount * 65536.0;
79 int stepsX = fp->msizeX/2;
80 int stepsY = fp->msizeY/2;
81 int scalebits = (stepsX+stepsY)*2;
82 int32_t halfscale = 1 << ((stepsX+stepsY)*2-1);
84 if( !fp->amount ) {
85 if( src == dst )
86 return;
87 if( dstStride == srcStride )
88 fast_memcpy( dst, src, srcStride*height );
89 else
90 for( y=0; y<height; y++, dst+=dstStride, src+=srcStride )
91 fast_memcpy( dst, src, width );
92 return;
95 for( y=0; y<2*stepsY; y++ )
96 memset( SC[y], 0, sizeof(SC[y][0]) * (width+2*stepsX) );
98 for( y=-stepsY; y<height+stepsY; y++ ) {
99 if( y < height ) src2 = src;
100 memset( SR, 0, sizeof(SR[0]) * (2*stepsX-1) );
101 for( x=-stepsX; x<width+stepsX; x++ ) {
102 Tmp1 = x<=0 ? src2[0] : x>=width ? src2[width-1] : src2[x];
103 for( z=0; z<stepsX*2; z+=2 ) {
104 Tmp2 = SR[z+0] + Tmp1; SR[z+0] = Tmp1;
105 Tmp1 = SR[z+1] + Tmp2; SR[z+1] = Tmp2;
107 for( z=0; z<stepsY*2; z+=2 ) {
108 Tmp2 = SC[z+0][x+stepsX] + Tmp1; SC[z+0][x+stepsX] = Tmp1;
109 Tmp1 = SC[z+1][x+stepsX] + Tmp2; SC[z+1][x+stepsX] = Tmp2;
111 if( x>=stepsX && y>=stepsY ) {
112 uint8_t* srx = src - stepsY*srcStride + x - stepsX;
113 uint8_t* dsx = dst - stepsY*dstStride + x - stepsX;
115 res = (int32_t)*srx + ( ( ( (int32_t)*srx - (int32_t)((Tmp1+halfscale) >> scalebits) ) * amount ) >> 16 );
116 *dsx = res>255 ? 255 : res<0 ? 0 : (uint8_t)res;
119 if( y >= 0 ) {
120 dst += dstStride;
121 src += srcStride;
126 //===========================================================================//
128 static int config( struct vf_instance_s* vf,
129 int width, int height, int d_width, int d_height,
130 unsigned int flags, unsigned int outfmt ) {
132 int z, stepsX, stepsY;
133 FilterParam *fp;
134 char *effect;
136 // allocate buffers
138 fp = &vf->priv->lumaParam;
139 effect = fp->amount == 0 ? "don't touch" : fp->amount < 0 ? "blur" : "sharpen";
140 mp_msg( MSGT_VFILTER, MSGL_INFO, "unsharp: %dx%d:%0.2f (%s luma) \n", fp->msizeX, fp->msizeY, fp->amount, effect );
141 memset( fp->SC, 0, sizeof( fp->SC ) );
142 stepsX = fp->msizeX/2;
143 stepsY = fp->msizeY/2;
144 for( z=0; z<2*stepsY; z++ )
145 fp->SC[z] = memalign( 16, sizeof(*(fp->SC[z])) * (width+2*stepsX) );
147 fp = &vf->priv->chromaParam;
148 effect = fp->amount == 0 ? "don't touch" : fp->amount < 0 ? "blur" : "sharpen";
149 mp_msg( MSGT_VFILTER, MSGL_INFO, "unsharp: %dx%d:%0.2f (%s chroma)\n", fp->msizeX, fp->msizeY, fp->amount, effect );
150 memset( fp->SC, 0, sizeof( fp->SC ) );
151 stepsX = fp->msizeX/2;
152 stepsY = fp->msizeY/2;
153 for( z=0; z<2*stepsY; z++ )
154 fp->SC[z] = memalign( 16, sizeof(*(fp->SC[z])) * (width+2*stepsX) );
156 return vf_next_config( vf, width, height, d_width, d_height, flags, outfmt );
159 //===========================================================================//
161 static void get_image( struct vf_instance_s* vf, mp_image_t *mpi ) {
162 if( mpi->flags & MP_IMGFLAG_PRESERVE )
163 return; // don't change
164 if( mpi->imgfmt!=vf->priv->outfmt )
165 return; // colorspace differ
167 vf->dmpi = vf_get_image( vf->next, mpi->imgfmt, mpi->type, mpi->flags, mpi->w, mpi->h );
168 mpi->planes[0] = vf->dmpi->planes[0];
169 mpi->stride[0] = vf->dmpi->stride[0];
170 mpi->width = vf->dmpi->width;
171 if( mpi->flags & MP_IMGFLAG_PLANAR ) {
172 mpi->planes[1] = vf->dmpi->planes[1];
173 mpi->planes[2] = vf->dmpi->planes[2];
174 mpi->stride[1] = vf->dmpi->stride[1];
175 mpi->stride[2] = vf->dmpi->stride[2];
177 mpi->flags |= MP_IMGFLAG_DIRECT;
180 static int put_image( struct vf_instance_s* vf, mp_image_t *mpi, double pts) {
181 mp_image_t *dmpi;
183 if( !(mpi->flags & MP_IMGFLAG_DIRECT) )
184 // no DR, so get a new image! hope we'll get DR buffer:
185 vf->dmpi = vf_get_image( vf->next,vf->priv->outfmt, MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE, mpi->w, mpi->h);
186 dmpi= vf->dmpi;
188 unsharp( dmpi->planes[0], mpi->planes[0], dmpi->stride[0], mpi->stride[0], mpi->w, mpi->h, &vf->priv->lumaParam );
189 unsharp( dmpi->planes[1], mpi->planes[1], dmpi->stride[1], mpi->stride[1], mpi->w/2, mpi->h/2, &vf->priv->chromaParam );
190 unsharp( dmpi->planes[2], mpi->planes[2], dmpi->stride[2], mpi->stride[2], mpi->w/2, mpi->h/2, &vf->priv->chromaParam );
192 vf_clone_mpi_attributes(dmpi, mpi);
194 #ifdef HAVE_MMX
195 if(gCpuCaps.hasMMX)
196 asm volatile ("emms\n\t");
197 #endif
198 #ifdef HAVE_MMX2
199 if(gCpuCaps.hasMMX2)
200 asm volatile ("sfence\n\t");
201 #endif
203 return vf_next_put_image( vf, dmpi, pts);
206 static void uninit( struct vf_instance_s* vf ) {
207 unsigned int z;
208 FilterParam *fp;
210 if( !vf->priv ) return;
212 fp = &vf->priv->lumaParam;
213 for( z=0; z<sizeof(fp->SC)/sizeof(fp->SC[0]); z++ ) {
214 if( fp->SC[z] ) free( fp->SC[z] );
215 fp->SC[z] = NULL;
217 fp = &vf->priv->chromaParam;
218 for( z=0; z<sizeof(fp->SC)/sizeof(fp->SC[0]); z++ ) {
219 if( fp->SC[z] ) free( fp->SC[z] );
220 fp->SC[z] = NULL;
223 free( vf->priv );
224 vf->priv = NULL;
227 //===========================================================================//
229 static int query_format( struct vf_instance_s* vf, unsigned int fmt ) {
230 switch(fmt) {
231 case IMGFMT_YV12:
232 case IMGFMT_I420:
233 case IMGFMT_IYUV:
234 return vf_next_query_format( vf, vf->priv->outfmt );
236 return 0;
239 //===========================================================================//
241 static void parse( FilterParam *fp, char* args ) {
243 // l7x5:0.8:c3x3:-0.2
245 char *z;
246 char *pos = args;
247 char *max = args + strlen(args);
249 // parse matrix sizes
250 fp->msizeX = ( pos && pos+1<max ) ? atoi( pos+1 ) : 0;
251 z = strchr( pos+1, 'x' );
252 fp->msizeY = ( z && z+1<max ) ? atoi( pos=z+1 ) : fp->msizeX;
254 // min/max & odd
255 fp->msizeX = 1 | av_clip(fp->msizeX, MIN_MATRIX_SIZE, MAX_MATRIX_SIZE);
256 fp->msizeY = 1 | av_clip(fp->msizeY, MIN_MATRIX_SIZE, MAX_MATRIX_SIZE);
258 // parse amount
259 pos = strchr( pos+1, ':' );
260 fp->amount = ( pos && pos+1<max ) ? atof( pos+1 ) : 0;
263 //===========================================================================//
265 static unsigned int fmt_list[] = {
266 IMGFMT_YV12,
267 IMGFMT_I420,
268 IMGFMT_IYUV,
272 static int open( vf_instance_t *vf, char* args ) {
273 vf->config = config;
274 vf->put_image = put_image;
275 vf->get_image = get_image;
276 vf->query_format = query_format;
277 vf->uninit = uninit;
278 vf->priv = malloc( sizeof(struct vf_priv_s) );
279 memset( vf->priv, 0, sizeof(struct vf_priv_s) );
281 if( args ) {
282 char *args2 = strchr( args, 'l' );
283 if( args2 )
284 parse( &vf->priv->lumaParam, args2 );
285 else {
286 vf->priv->lumaParam.amount =
287 vf->priv->lumaParam.msizeX =
288 vf->priv->lumaParam.msizeY = 0;
291 args2 = strchr( args, 'c' );
292 if( args2 )
293 parse( &vf->priv->chromaParam, args2 );
294 else {
295 vf->priv->chromaParam.amount =
296 vf->priv->chromaParam.msizeX =
297 vf->priv->chromaParam.msizeY = 0;
300 if( !vf->priv->lumaParam.msizeX && !vf->priv->chromaParam.msizeX )
301 return 0; // nothing to do
304 // check csp:
305 vf->priv->outfmt = vf_match_csp( &vf->next, fmt_list, IMGFMT_YV12 );
306 if( !vf->priv->outfmt ) {
307 uninit( vf );
308 return 0; // no csp match :(
311 return 1;
314 const vf_info_t vf_info_unsharp = {
315 "unsharp mask & gaussian blur",
316 "unsharp",
317 "Remi Guyomarch",
319 open,
320 NULL
323 //===========================================================================//