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

libavfilter/libmpcodecs/vf_sab.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 "config.h"
00028 #include "mp_msg.h"
00029 
00030 #if HAVE_MALLOC_H
00031 #include <malloc.h>
00032 #endif
00033 
00034 #include "libavutil/avutil.h"
00035 #include "img_format.h"
00036 #include "mp_image.h"
00037 #include "vf.h"
00038 #include "libswscale/swscale.h"
00039 #include "vf_scale.h"
00040 
00041 
00042 //===========================================================================//
00043 
00044 typedef struct FilterParam{
00045     float radius;
00046     float preFilterRadius;
00047     float strength;
00048     float quality;
00049     struct SwsContext *preFilterContext;
00050     uint8_t *preFilterBuf;
00051     int preFilterStride;
00052     int distWidth;
00053     int distStride;
00054     int *distCoeff;
00055     int colorDiffCoeff[512];
00056 }FilterParam;
00057 
00058 struct vf_priv_s {
00059     FilterParam luma;
00060     FilterParam chroma;
00061 };
00062 
00063 
00064 /***************************************************************************/
00065 
00066 //FIXME stupid code duplication
00067 static void getSubSampleFactors(int *h, int *v, int format){
00068     switch(format){
00069     default:
00070         assert(0);
00071     case IMGFMT_YV12:
00072     case IMGFMT_I420:
00073         *h=1;
00074         *v=1;
00075         break;
00076     case IMGFMT_YVU9:
00077         *h=2;
00078         *v=2;
00079         break;
00080     case IMGFMT_444P:
00081         *h=0;
00082         *v=0;
00083         break;
00084     case IMGFMT_422P:
00085         *h=1;
00086         *v=0;
00087         break;
00088     case IMGFMT_411P:
00089         *h=2;
00090         *v=0;
00091         break;
00092     }
00093 }
00094 
00095 static int allocStuff(FilterParam *f, int width, int height){
00096     int stride= (width+7)&~7;
00097     SwsVector *vec;
00098     SwsFilter swsF;
00099     int i,x,y;
00100     f->preFilterBuf= av_malloc(stride*height);
00101     f->preFilterStride= stride;
00102 
00103     vec = sws_getGaussianVec(f->preFilterRadius, f->quality);
00104     swsF.lumH= swsF.lumV= vec;
00105     swsF.chrH= swsF.chrV= NULL;
00106     f->preFilterContext= sws_getContext(
00107         width, height, PIX_FMT_GRAY8, width, height, PIX_FMT_GRAY8, SWS_POINT, &swsF, NULL, NULL);
00108 
00109     sws_freeVec(vec);
00110     vec = sws_getGaussianVec(f->strength, 5.0);
00111     for(i=0; i<512; i++){
00112         double d;
00113         int index= i-256 + vec->length/2;
00114 
00115         if(index<0 || index>=vec->length)     d= 0.0;
00116         else                    d= vec->coeff[index];
00117 
00118         f->colorDiffCoeff[i]= (int)(d/vec->coeff[vec->length/2]*(1<<12) + 0.5);
00119     }
00120     sws_freeVec(vec);
00121     vec = sws_getGaussianVec(f->radius, f->quality);
00122     f->distWidth= vec->length;
00123     f->distStride= (vec->length+7)&~7;
00124     f->distCoeff= av_malloc(f->distWidth*f->distStride*sizeof(int32_t));
00125 
00126     for(y=0; y<vec->length; y++){
00127         for(x=0; x<vec->length; x++){
00128             double d= vec->coeff[x] * vec->coeff[y];
00129 
00130             f->distCoeff[x + y*f->distStride]= (int)(d*(1<<10) + 0.5);
00131 //            if(y==vec->length/2)
00132 //                printf("%6d ", f->distCoeff[x + y*f->distStride]);
00133         }
00134     }
00135     sws_freeVec(vec);
00136 
00137     return 0;
00138 }
00139 
00140 static int config(struct vf_instance *vf,
00141     int width, int height, int d_width, int d_height,
00142     unsigned int flags, unsigned int outfmt){
00143 
00144     int sw, sh;
00145 //__asm__ volatile("emms\n\t");
00146     allocStuff(&vf->priv->luma, width, height);
00147 
00148     getSubSampleFactors(&sw, &sh, outfmt);
00149     allocStuff(&vf->priv->chroma, width>>sw, height>>sh);
00150 
00151     return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
00152 }
00153 
00154 static void freeBuffers(FilterParam *f){
00155     if(f->preFilterContext) sws_freeContext(f->preFilterContext);
00156     f->preFilterContext=NULL;
00157 
00158     av_free(f->preFilterBuf);
00159     f->preFilterBuf=NULL;
00160 
00161     av_free(f->distCoeff);
00162     f->distCoeff=NULL;
00163 }
00164 
00165 static void uninit(struct vf_instance *vf){
00166     if(!vf->priv) return;
00167 
00168     freeBuffers(&vf->priv->luma);
00169     freeBuffers(&vf->priv->chroma);
00170 
00171     free(vf->priv);
00172     vf->priv=NULL;
00173 }
00174 
00175 static inline void blur(uint8_t *dst, uint8_t *src, int w, int h, int dstStride, int srcStride, FilterParam *fp){
00176     int x, y;
00177     FilterParam f= *fp;
00178     const int radius= f.distWidth/2;
00179     const uint8_t* const srcArray[MP_MAX_PLANES] = {src};
00180     uint8_t *dstArray[MP_MAX_PLANES]= {f.preFilterBuf};
00181     int srcStrideArray[MP_MAX_PLANES]= {srcStride};
00182     int dstStrideArray[MP_MAX_PLANES]= {f.preFilterStride};
00183 
00184 //    f.preFilterContext->swScale(f.preFilterContext, srcArray, srcStrideArray, 0, h, dstArray, dstStrideArray);
00185     sws_scale(f.preFilterContext, srcArray, srcStrideArray, 0, h, dstArray, dstStrideArray);
00186 
00187     for(y=0; y<h; y++){
00188         for(x=0; x<w; x++){
00189             int sum=0;
00190             int div=0;
00191             int dy;
00192             const int preVal= f.preFilterBuf[x + y*f.preFilterStride];
00193 #if 0
00194             const int srcVal= src[x + y*srcStride];
00195 if((x/32)&1){
00196     dst[x + y*dstStride]= srcVal;
00197     if(y%32==0) dst[x + y*dstStride]= 0;
00198     continue;
00199 }
00200 #endif
00201             if(x >= radius && x < w - radius){
00202                 for(dy=0; dy<radius*2+1; dy++){
00203                     int dx;
00204                     int iy= y+dy - radius;
00205                     if     (iy<0)  iy=  -iy;
00206                     else if(iy>=h) iy= h+h-iy-1;
00207 
00208                     for(dx=0; dx<radius*2+1; dx++){
00209                         const int ix= x+dx - radius;
00210                         int factor;
00211 
00212                         factor= f.colorDiffCoeff[256+preVal - f.preFilterBuf[ix + iy*f.preFilterStride] ]
00213                             *f.distCoeff[dx + dy*f.distStride];
00214                         sum+= src[ix + iy*srcStride] *factor;
00215                         div+= factor;
00216                     }
00217                 }
00218             }else{
00219                 for(dy=0; dy<radius*2+1; dy++){
00220                     int dx;
00221                     int iy= y+dy - radius;
00222                     if     (iy<0)  iy=  -iy;
00223                     else if(iy>=h) iy= h+h-iy-1;
00224 
00225                     for(dx=0; dx<radius*2+1; dx++){
00226                         int ix= x+dx - radius;
00227                         int factor;
00228                         if     (ix<0)  ix=  -ix;
00229                         else if(ix>=w) ix= w+w-ix-1;
00230 
00231                         factor= f.colorDiffCoeff[256+preVal - f.preFilterBuf[ix + iy*f.preFilterStride] ]
00232                             *f.distCoeff[dx + dy*f.distStride];
00233                         sum+= src[ix + iy*srcStride] *factor;
00234                         div+= factor;
00235                     }
00236                 }
00237             }
00238             dst[x + y*dstStride]= (sum + div/2)/div;
00239         }
00240     }
00241 }
00242 
00243 static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
00244     int cw= mpi->w >> mpi->chroma_x_shift;
00245     int ch= mpi->h >> mpi->chroma_y_shift;
00246 
00247     mp_image_t *dmpi=vf_get_image(vf->next,mpi->imgfmt,
00248         MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
00249         mpi->w,mpi->h);
00250 
00251     assert(mpi->flags&MP_IMGFLAG_PLANAR);
00252 
00253     blur(dmpi->planes[0], mpi->planes[0], mpi->w,mpi->h, dmpi->stride[0], mpi->stride[0], &vf->priv->luma);
00254     blur(dmpi->planes[1], mpi->planes[1], cw    , ch   , dmpi->stride[1], mpi->stride[1], &vf->priv->chroma);
00255     blur(dmpi->planes[2], mpi->planes[2], cw    , ch   , dmpi->stride[2], mpi->stride[2], &vf->priv->chroma);
00256 
00257     return vf_next_put_image(vf,dmpi, pts);
00258 }
00259 
00260 //===========================================================================//
00261 
00262 static int query_format(struct vf_instance *vf, unsigned int fmt){
00263     switch(fmt)
00264     {
00265     case IMGFMT_YV12:
00266     case IMGFMT_I420:
00267     case IMGFMT_IYUV:
00268     case IMGFMT_YVU9:
00269     case IMGFMT_444P:
00270     case IMGFMT_422P:
00271     case IMGFMT_411P:
00272         return vf_next_query_format(vf, fmt);
00273     }
00274     return 0;
00275 }
00276 
00277 static int vf_open(vf_instance_t *vf, char *args){
00278     int e;
00279 
00280     vf->config=config;
00281     vf->put_image=put_image;
00282 //    vf->get_image=get_image;
00283     vf->query_format=query_format;
00284     vf->uninit=uninit;
00285     vf->priv=malloc(sizeof(struct vf_priv_s));
00286     memset(vf->priv, 0, sizeof(struct vf_priv_s));
00287 
00288     if(args==NULL) return 0;
00289 
00290     e=sscanf(args, "%f:%f:%f:%f:%f:%f",
00291         &vf->priv->luma.radius,
00292         &vf->priv->luma.preFilterRadius,
00293         &vf->priv->luma.strength,
00294         &vf->priv->chroma.radius,
00295         &vf->priv->chroma.preFilterRadius,
00296         &vf->priv->chroma.strength
00297         );
00298 
00299     vf->priv->luma.quality = vf->priv->chroma.quality= 3.0;
00300 
00301     if(e==3){
00302         vf->priv->chroma.radius= vf->priv->luma.radius;
00303         vf->priv->chroma.preFilterRadius = vf->priv->luma.preFilterRadius;
00304         vf->priv->chroma.strength= vf->priv->luma.strength;
00305     }else if(e!=6)
00306         return 0;
00307 
00308 //    if(vf->priv->luma.radius < 0) return 0;
00309 //    if(vf->priv->chroma.radius < 0) return 0;
00310 
00311     return 1;
00312 }
00313 
00314 const vf_info_t vf_info_sab = {
00315     "shape adaptive blur",
00316     "sab",
00317     "Michael Niedermayer",
00318     "",
00319     vf_open,
00320     NULL
00321 };
00322 
00323 //===========================================================================//
Generated on Fri Feb 1 2013 14:34:49 for FFmpeg by doxygen 1.7.1