• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • Examples
  • File List
  • Globals

libavfilter/libmpcodecs/vf_unsharp.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2002 Remi Guyomarch <rguyom@pobox.com>
00003  *
00004  * This file is part of MPlayer.
00005  *
00006  * MPlayer is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * MPlayer is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License along
00017  * with MPlayer; if not, write to the Free Software Foundation, Inc.,
00018  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00019  */
00020 
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include <string.h>
00024 #include <inttypes.h>
00025 #include <math.h>
00026 
00027 #include "config.h"
00028 #include "mp_msg.h"
00029 #include "cpudetect.h"
00030 
00031 #if HAVE_MALLOC_H
00032 #include <malloc.h>
00033 #endif
00034 
00035 #include "img_format.h"
00036 #include "mp_image.h"
00037 #include "vf.h"
00038 #include "libvo/fastmemcpy.h"
00039 #include "libavutil/common.h"
00040 
00041 //===========================================================================//
00042 
00043 #define MIN_MATRIX_SIZE 3
00044 #define MAX_MATRIX_SIZE 63
00045 
00046 typedef struct FilterParam {
00047     int msizeX, msizeY;
00048     double amount;
00049     uint32_t *SC[MAX_MATRIX_SIZE-1];
00050 } FilterParam;
00051 
00052 struct vf_priv_s {
00053     FilterParam lumaParam;
00054     FilterParam chromaParam;
00055     unsigned int outfmt;
00056 };
00057 
00058 
00059 //===========================================================================//
00060 
00061 /* This code is based on :
00062 
00063 An Efficient algorithm for Gaussian blur using finite-state machines
00064 Frederick M. Waltz and John W. V. Miller
00065 
00066 SPIE Conf. on Machine Vision Systems for Inspection and Metrology VII
00067 Originally published Boston, Nov 98
00068 
00069 */
00070 
00071 static void unsharp( uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int width, int height, FilterParam *fp ) {
00072 
00073     uint32_t **SC = fp->SC;
00074     uint32_t SR[MAX_MATRIX_SIZE-1], Tmp1, Tmp2;
00075     uint8_t* src2 = src; // avoid gcc warning
00076 
00077     int32_t res;
00078     int x, y, z;
00079     int amount = fp->amount * 65536.0;
00080     int stepsX = fp->msizeX/2;
00081     int stepsY = fp->msizeY/2;
00082     int scalebits = (stepsX+stepsY)*2;
00083     int32_t halfscale = 1 << ((stepsX+stepsY)*2-1);
00084 
00085     if( !fp->amount ) {
00086         if( src == dst )
00087             return;
00088         if( dstStride == srcStride )
00089             fast_memcpy( dst, src, srcStride*height );
00090         else
00091             for( y=0; y<height; y++, dst+=dstStride, src+=srcStride )
00092                 fast_memcpy( dst, src, width );
00093         return;
00094     }
00095 
00096     for( y=0; y<2*stepsY; y++ )
00097         memset( SC[y], 0, sizeof(SC[y][0]) * (width+2*stepsX) );
00098 
00099     for( y=-stepsY; y<height+stepsY; y++ ) {
00100         if( y < height ) src2 = src;
00101         memset( SR, 0, sizeof(SR[0]) * (2*stepsX-1) );
00102         for( x=-stepsX; x<width+stepsX; x++ ) {
00103             Tmp1 = x<=0 ? src2[0] : x>=width ? src2[width-1] : src2[x];
00104             for( z=0; z<stepsX*2; z+=2 ) {
00105                 Tmp2 = SR[z+0] + Tmp1; SR[z+0] = Tmp1;
00106                 Tmp1 = SR[z+1] + Tmp2; SR[z+1] = Tmp2;
00107             }
00108             for( z=0; z<stepsY*2; z+=2 ) {
00109                 Tmp2 = SC[z+0][x+stepsX] + Tmp1; SC[z+0][x+stepsX] = Tmp1;
00110                 Tmp1 = SC[z+1][x+stepsX] + Tmp2; SC[z+1][x+stepsX] = Tmp2;
00111             }
00112             if( x>=stepsX && y>=stepsY ) {
00113                 uint8_t* srx = src - stepsY*srcStride + x - stepsX;
00114                 uint8_t* dsx = dst - stepsY*dstStride + x - stepsX;
00115 
00116                 res = (int32_t)*srx + ( ( ( (int32_t)*srx - (int32_t)((Tmp1+halfscale) >> scalebits) ) * amount ) >> 16 );
00117                 *dsx = res>255 ? 255 : res<0 ? 0 : (uint8_t)res;
00118             }
00119         }
00120         if( y >= 0 ) {
00121             dst += dstStride;
00122             src += srcStride;
00123         }
00124     }
00125 }
00126 
00127 //===========================================================================//
00128 
00129 static int config( struct vf_instance *vf,
00130                    int width, int height, int d_width, int d_height,
00131                    unsigned int flags, unsigned int outfmt ) {
00132 
00133     int z, stepsX, stepsY;
00134     FilterParam *fp;
00135     const char *effect;
00136 
00137     // allocate buffers
00138 
00139     fp = &vf->priv->lumaParam;
00140     effect = fp->amount == 0 ? "don't touch" : fp->amount < 0 ? "blur" : "sharpen";
00141     mp_msg( MSGT_VFILTER, MSGL_INFO, "unsharp: %dx%d:%0.2f (%s luma) \n", fp->msizeX, fp->msizeY, fp->amount, effect );
00142     memset( fp->SC, 0, sizeof( fp->SC ) );
00143     stepsX = fp->msizeX/2;
00144     stepsY = fp->msizeY/2;
00145     for( z=0; z<2*stepsY; z++ )
00146         fp->SC[z] = av_malloc(sizeof(*(fp->SC[z])) * (width+2*stepsX));
00147 
00148     fp = &vf->priv->chromaParam;
00149     effect = fp->amount == 0 ? "don't touch" : fp->amount < 0 ? "blur" : "sharpen";
00150     mp_msg( MSGT_VFILTER, MSGL_INFO, "unsharp: %dx%d:%0.2f (%s chroma)\n", fp->msizeX, fp->msizeY, fp->amount, effect );
00151     memset( fp->SC, 0, sizeof( fp->SC ) );
00152     stepsX = fp->msizeX/2;
00153     stepsY = fp->msizeY/2;
00154     for( z=0; z<2*stepsY; z++ )
00155         fp->SC[z] = av_malloc(sizeof(*(fp->SC[z])) * (width+2*stepsX));
00156 
00157     return vf_next_config( vf, width, height, d_width, d_height, flags, outfmt );
00158 }
00159 
00160 //===========================================================================//
00161 
00162 static void get_image( struct vf_instance *vf, mp_image_t *mpi ) {
00163     if( mpi->flags & MP_IMGFLAG_PRESERVE )
00164         return; // don't change
00165     if( mpi->imgfmt!=vf->priv->outfmt )
00166         return; // colorspace differ
00167 
00168     vf->dmpi = vf_get_image( vf->next, mpi->imgfmt, mpi->type, mpi->flags, mpi->w, mpi->h );
00169     mpi->planes[0] = vf->dmpi->planes[0];
00170     mpi->stride[0] = vf->dmpi->stride[0];
00171     mpi->width = vf->dmpi->width;
00172     if( mpi->flags & MP_IMGFLAG_PLANAR ) {
00173         mpi->planes[1] = vf->dmpi->planes[1];
00174         mpi->planes[2] = vf->dmpi->planes[2];
00175         mpi->stride[1] = vf->dmpi->stride[1];
00176         mpi->stride[2] = vf->dmpi->stride[2];
00177     }
00178     mpi->flags |= MP_IMGFLAG_DIRECT;
00179 }
00180 
00181 static int put_image( struct vf_instance *vf, mp_image_t *mpi, double pts) {
00182     mp_image_t *dmpi;
00183 
00184     if( !(mpi->flags & MP_IMGFLAG_DIRECT) )
00185         // no DR, so get a new image! hope we'll get DR buffer:
00186         vf->dmpi = vf_get_image( vf->next,vf->priv->outfmt, MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE, mpi->w, mpi->h);
00187     dmpi= vf->dmpi;
00188 
00189     unsharp( dmpi->planes[0], mpi->planes[0], dmpi->stride[0], mpi->stride[0], mpi->w,   mpi->h,   &vf->priv->lumaParam );
00190     unsharp( dmpi->planes[1], mpi->planes[1], dmpi->stride[1], mpi->stride[1], mpi->w/2, mpi->h/2, &vf->priv->chromaParam );
00191     unsharp( dmpi->planes[2], mpi->planes[2], dmpi->stride[2], mpi->stride[2], mpi->w/2, mpi->h/2, &vf->priv->chromaParam );
00192 
00193     vf_clone_mpi_attributes(dmpi, mpi);
00194 
00195 #if HAVE_MMX
00196     if(gCpuCaps.hasMMX)
00197         __asm__ volatile ("emms\n\t");
00198 #endif
00199 #if HAVE_MMX2
00200     if(gCpuCaps.hasMMX2)
00201         __asm__ volatile ("sfence\n\t");
00202 #endif
00203 
00204     return vf_next_put_image( vf, dmpi, pts);
00205 }
00206 
00207 static void uninit( struct vf_instance *vf ) {
00208     unsigned int z;
00209     FilterParam *fp;
00210 
00211     if( !vf->priv ) return;
00212 
00213     fp = &vf->priv->lumaParam;
00214     for( z=0; z<sizeof(fp->SC)/sizeof(fp->SC[0]); z++ ) {
00215         av_free( fp->SC[z] );
00216         fp->SC[z] = NULL;
00217     }
00218     fp = &vf->priv->chromaParam;
00219     for( z=0; z<sizeof(fp->SC)/sizeof(fp->SC[0]); z++ ) {
00220         av_free( fp->SC[z] );
00221         fp->SC[z] = NULL;
00222     }
00223 
00224     free( vf->priv );
00225     vf->priv = NULL;
00226 }
00227 
00228 //===========================================================================//
00229 
00230 static int query_format( struct vf_instance *vf, unsigned int fmt ) {
00231     switch(fmt) {
00232     case IMGFMT_YV12:
00233     case IMGFMT_I420:
00234     case IMGFMT_IYUV:
00235         return vf_next_query_format( vf, vf->priv->outfmt );
00236     }
00237     return 0;
00238 }
00239 
00240 //===========================================================================//
00241 
00242 static void parse( FilterParam *fp, char* args ) {
00243 
00244     // l7x5:0.8:c3x3:-0.2
00245 
00246     char *z;
00247     char *pos = args;
00248     char *max = args + strlen(args);
00249 
00250     // parse matrix sizes
00251     fp->msizeX = ( pos && pos+1<max ) ? atoi( pos+1 ) : 0;
00252     z = strchr( pos+1, 'x' );
00253     fp->msizeY = ( z && z+1<max ) ? atoi( pos=z+1 ) : fp->msizeX;
00254 
00255     // min/max & odd
00256     fp->msizeX = 1 | av_clip(fp->msizeX, MIN_MATRIX_SIZE, MAX_MATRIX_SIZE);
00257     fp->msizeY = 1 | av_clip(fp->msizeY, MIN_MATRIX_SIZE, MAX_MATRIX_SIZE);
00258 
00259     // parse amount
00260     pos = strchr( pos+1, ':' );
00261     fp->amount = ( pos && pos+1<max ) ? atof( pos+1 ) : 0;
00262 }
00263 
00264 //===========================================================================//
00265 
00266 static const unsigned int fmt_list[] = {
00267     IMGFMT_YV12,
00268     IMGFMT_I420,
00269     IMGFMT_IYUV,
00270     0
00271 };
00272 
00273 static int vf_open( vf_instance_t *vf, char *args ) {
00274     vf->config       = config;
00275     vf->put_image    = put_image;
00276     vf->get_image    = get_image;
00277     vf->query_format = query_format;
00278     vf->uninit       = uninit;
00279     vf->priv         = malloc( sizeof(struct vf_priv_s) );
00280     memset( vf->priv, 0, sizeof(struct vf_priv_s) );
00281 
00282     if( args ) {
00283         char *args2 = strchr( args, 'l' );
00284         if( args2 )
00285             parse( &vf->priv->lumaParam, args2 );
00286         else {
00287             vf->priv->lumaParam.amount =
00288             vf->priv->lumaParam.msizeX =
00289             vf->priv->lumaParam.msizeY = 0;
00290         }
00291 
00292         args2 = strchr( args, 'c' );
00293         if( args2 )
00294             parse( &vf->priv->chromaParam, args2 );
00295         else {
00296             vf->priv->chromaParam.amount =
00297             vf->priv->chromaParam.msizeX =
00298             vf->priv->chromaParam.msizeY = 0;
00299         }
00300 
00301         if( !vf->priv->lumaParam.msizeX && !vf->priv->chromaParam.msizeX )
00302             return 0; // nothing to do
00303     }
00304 
00305     // check csp:
00306     vf->priv->outfmt = vf_match_csp( &vf->next, fmt_list, IMGFMT_YV12 );
00307     if( !vf->priv->outfmt ) {
00308         uninit( vf );
00309         return 0; // no csp match :(
00310     }
00311 
00312     return 1;
00313 }
00314 
00315 const vf_info_t vf_info_unsharp = {
00316     "unsharp mask & gaussian blur",
00317     "unsharp",
00318     "Remi Guyomarch",
00319     "",
00320     vf_open,
00321     NULL
00322 };
00323 
00324 //===========================================================================//

Generated on Wed Apr 11 2012 07:31:36 for FFmpeg by  doxygen 1.7.1