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