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

libavfilter/libmpcodecs/vf_smartblur.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2002 Michael Niedermayer <michaelni@gmx.at>
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 <assert.h>
00026 
00027 #include "mp_msg.h"
00028 #include "libavutil/avutil.h"
00029 #include "img_format.h"
00030 #include "mp_image.h"
00031 #include "vf.h"
00032 #include "libswscale/swscale.h"
00033 #include "vf_scale.h"
00034 
00035 //===========================================================================//
00036 
00037 typedef struct FilterParam{
00038     float radius;
00039     float strength;
00040     int threshold;
00041     float quality;
00042     struct SwsContext *filterContext;
00043 }FilterParam;
00044 
00045 struct vf_priv_s {
00046     FilterParam luma;
00047     FilterParam chroma;
00048 };
00049 
00050 
00051 /***************************************************************************/
00052 
00053 //FIXME stupid code duplication
00054 static void getSubSampleFactors(int *h, int *v, int format){
00055     switch(format){
00056     case IMGFMT_YV12:
00057     case IMGFMT_I420:
00058         *h=1;
00059         *v=1;
00060         break;
00061     case IMGFMT_YVU9:
00062         *h=2;
00063         *v=2;
00064         break;
00065     case IMGFMT_444P:
00066         *h=0;
00067         *v=0;
00068         break;
00069     case IMGFMT_422P:
00070         *h=1;
00071         *v=0;
00072         break;
00073     case IMGFMT_411P:
00074         *h=2;
00075         *v=0;
00076         break;
00077     }
00078 }
00079 
00080 static int allocStuff(FilterParam *f, int width, int height){
00081     SwsVector *vec;
00082     SwsFilter swsF;
00083 
00084     vec = sws_getGaussianVec(f->radius, f->quality);
00085     sws_scaleVec(vec, f->strength);
00086     vec->coeff[vec->length/2]+= 1.0 - f->strength;
00087     swsF.lumH= swsF.lumV= vec;
00088     swsF.chrH= swsF.chrV= NULL;
00089     f->filterContext= sws_getContext(
00090         width, height, PIX_FMT_GRAY8, width, height, PIX_FMT_GRAY8, SWS_BICUBIC, &swsF, NULL, NULL);
00091 
00092     sws_freeVec(vec);
00093 
00094     return 0;
00095 }
00096 
00097 static int config(struct vf_instance *vf,
00098     int width, int height, int d_width, int d_height,
00099     unsigned int flags, unsigned int outfmt){
00100 
00101     int sw, sh;
00102 
00103     allocStuff(&vf->priv->luma, width, height);
00104 
00105     getSubSampleFactors(&sw, &sh, outfmt);
00106     allocStuff(&vf->priv->chroma, width>>sw, height>>sh);
00107 
00108     return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
00109 }
00110 
00111 static void freeBuffers(FilterParam *f){
00112     if(f->filterContext) sws_freeContext(f->filterContext);
00113     f->filterContext=NULL;
00114 }
00115 
00116 static void uninit(struct vf_instance *vf){
00117     if(!vf->priv) return;
00118 
00119     freeBuffers(&vf->priv->luma);
00120     freeBuffers(&vf->priv->chroma);
00121 
00122     free(vf->priv);
00123     vf->priv=NULL;
00124 }
00125 
00126 static inline void blur(uint8_t *dst, uint8_t *src, int w, int h, int dstStride, int srcStride, FilterParam *fp){
00127     int x, y;
00128     FilterParam f= *fp;
00129     const uint8_t* const srcArray[MP_MAX_PLANES] = {src};
00130     uint8_t *dstArray[MP_MAX_PLANES]= {dst};
00131     int srcStrideArray[MP_MAX_PLANES]= {srcStride};
00132     int dstStrideArray[MP_MAX_PLANES]= {dstStride};
00133 
00134     sws_scale(f.filterContext, srcArray, srcStrideArray, 0, h, dstArray, dstStrideArray);
00135 
00136     if(f.threshold > 0){
00137         for(y=0; y<h; y++){
00138             for(x=0; x<w; x++){
00139                 const int orig= src[x + y*srcStride];
00140                 const int filtered= dst[x + y*dstStride];
00141                 const int diff= orig - filtered;
00142 
00143                 if(diff > 0){
00144                     if(diff > 2*f.threshold){
00145                         dst[x + y*dstStride]= orig;
00146                     }else if(diff > f.threshold){
00147                         dst[x + y*dstStride]= filtered + diff - f.threshold;
00148                     }
00149                 }else{
00150                     if(-diff > 2*f.threshold){
00151                         dst[x + y*dstStride]= orig;
00152                     }else if(-diff > f.threshold){
00153                         dst[x + y*dstStride]= filtered + diff + f.threshold;
00154                     }
00155                 }
00156             }
00157         }
00158     }else if(f.threshold < 0){
00159         for(y=0; y<h; y++){
00160             for(x=0; x<w; x++){
00161                 const int orig= src[x + y*srcStride];
00162                 const int filtered= dst[x + y*dstStride];
00163                 const int diff= orig - filtered;
00164 
00165                 if(diff > 0){
00166                     if(diff > -2*f.threshold){
00167                     }else if(diff > -f.threshold){
00168                         dst[x + y*dstStride]= orig - diff - f.threshold;
00169                     }else
00170                         dst[x + y*dstStride]= orig;
00171                 }else{
00172                     if(diff < 2*f.threshold){
00173                     }else if(diff < f.threshold){
00174                         dst[x + y*dstStride]= orig - diff + f.threshold;
00175                     }else
00176                         dst[x + y*dstStride]= orig;
00177                 }
00178             }
00179         }
00180     }
00181 }
00182 
00183 static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
00184     int cw= mpi->w >> mpi->chroma_x_shift;
00185     int ch= mpi->h >> mpi->chroma_y_shift;
00186     int threshold = vf->priv->luma.threshold || vf->priv->chroma.threshold;
00187 
00188     mp_image_t *dmpi=vf_get_image(vf->next,mpi->imgfmt,
00189         MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE|
00190         (threshold ? MP_IMGFLAG_READABLE : 0),
00191         mpi->w,mpi->h);
00192 
00193     assert(mpi->flags&MP_IMGFLAG_PLANAR);
00194 
00195     blur(dmpi->planes[0], mpi->planes[0], mpi->w,mpi->h, dmpi->stride[0], mpi->stride[0], &vf->priv->luma);
00196     blur(dmpi->planes[1], mpi->planes[1], cw    , ch   , dmpi->stride[1], mpi->stride[1], &vf->priv->chroma);
00197     blur(dmpi->planes[2], mpi->planes[2], cw    , ch   , dmpi->stride[2], mpi->stride[2], &vf->priv->chroma);
00198 
00199     return vf_next_put_image(vf,dmpi, pts);
00200 }
00201 
00202 //===========================================================================//
00203 
00204 static int query_format(struct vf_instance *vf, unsigned int fmt){
00205     switch(fmt)
00206     {
00207     case IMGFMT_YV12:
00208     case IMGFMT_I420:
00209     case IMGFMT_IYUV:
00210     case IMGFMT_YVU9:
00211     case IMGFMT_444P:
00212     case IMGFMT_422P:
00213     case IMGFMT_411P:
00214         return vf_next_query_format(vf, fmt);
00215     }
00216     return 0;
00217 }
00218 
00219 static int vf_open(vf_instance_t *vf, char *args){
00220     int e;
00221 
00222     vf->config=config;
00223     vf->put_image=put_image;
00224 //    vf->get_image=get_image;
00225     vf->query_format=query_format;
00226     vf->uninit=uninit;
00227     vf->priv=malloc(sizeof(struct vf_priv_s));
00228     memset(vf->priv, 0, sizeof(struct vf_priv_s));
00229 
00230     if(args==NULL) return 0;
00231 
00232     e=sscanf(args, "%f:%f:%d:%f:%f:%d",
00233         &vf->priv->luma.radius,
00234         &vf->priv->luma.strength,
00235         &vf->priv->luma.threshold,
00236         &vf->priv->chroma.radius,
00237         &vf->priv->chroma.strength,
00238         &vf->priv->chroma.threshold
00239         );
00240 
00241     vf->priv->luma.quality = vf->priv->chroma.quality= 3.0;
00242 
00243     if(e==3){
00244         vf->priv->chroma.radius= vf->priv->luma.radius;
00245         vf->priv->chroma.strength= vf->priv->luma.strength;
00246         vf->priv->chroma.threshold = vf->priv->luma.threshold;
00247     }else if(e!=6)
00248         return 0;
00249 
00250     return 1;
00251 }
00252 
00253 const vf_info_t vf_info_smartblur = {
00254     "smart blur",
00255     "smartblur",
00256     "Michael Niedermayer",
00257     "",
00258     vf_open,
00259     NULL
00260 };
00261 
00262 //===========================================================================//

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