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

libavfilter/libmpcodecs/vf_noise.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 <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/mem.h"
00040 
00041 #define MAX_NOISE 4096
00042 #define MAX_SHIFT 1024
00043 #define MAX_RES (MAX_NOISE-MAX_SHIFT)
00044 
00045 //===========================================================================//
00046 
00047 static inline void lineNoise_C(uint8_t *dst, uint8_t *src, int8_t *noise, int len, int shift);
00048 static inline void lineNoiseAvg_C(uint8_t *dst, uint8_t *src, int len, int8_t **shift);
00049 
00050 static void (*lineNoise)(uint8_t *dst, uint8_t *src, int8_t *noise, int len, int shift)= lineNoise_C;
00051 static void (*lineNoiseAvg)(uint8_t *dst, uint8_t *src, int len, int8_t **shift)= lineNoiseAvg_C;
00052 
00053 typedef struct FilterParam{
00054         int strength;
00055         int uniform;
00056         int temporal;
00057         int quality;
00058         int averaged;
00059         int pattern;
00060         int shiftptr;
00061         int8_t *noise;
00062         int8_t *prev_shift[MAX_RES][3];
00063 }FilterParam;
00064 
00065 struct vf_priv_s {
00066         FilterParam lumaParam;
00067         FilterParam chromaParam;
00068         unsigned int outfmt;
00069 };
00070 
00071 static int nonTempRandShift_init;
00072 static int nonTempRandShift[MAX_RES];
00073 
00074 static int patt[4] = {
00075     -1,0,1,0
00076 };
00077 
00078 #define RAND_N(range) ((int) ((double)range*rand()/(RAND_MAX+1.0)))
00079 static int8_t *initNoise(FilterParam *fp){
00080         int strength= fp->strength;
00081         int uniform= fp->uniform;
00082         int averaged= fp->averaged;
00083         int pattern= fp->pattern;
00084         int8_t *noise= av_malloc(MAX_NOISE*sizeof(int8_t));
00085         int i, j;
00086 
00087         srand(123457);
00088 
00089         for(i=0,j=0; i<MAX_NOISE; i++,j++)
00090         {
00091                 if(uniform) {
00092                         if (averaged) {
00093                                     if (pattern) {
00094                                         noise[i]= (RAND_N(strength) - strength/2)/6
00095                                                 +patt[j%4]*strength*0.25/3;
00096                                 } else {
00097                                         noise[i]= (RAND_N(strength) - strength/2)/3;
00098                                     }
00099                         } else {
00100                                     if (pattern) {
00101                                     noise[i]= (RAND_N(strength) - strength/2)/2
00102                                             + patt[j%4]*strength*0.25;
00103                                 } else {
00104                                         noise[i]= RAND_N(strength) - strength/2;
00105                                     }
00106                         }
00107                     } else {
00108                         double x1, x2, w, y1;
00109                         do {
00110                                 x1 = 2.0 * rand()/(float)RAND_MAX - 1.0;
00111                                 x2 = 2.0 * rand()/(float)RAND_MAX - 1.0;
00112                                 w = x1 * x1 + x2 * x2;
00113                         } while ( w >= 1.0 );
00114 
00115                         w = sqrt( (-2.0 * log( w ) ) / w );
00116                         y1= x1 * w;
00117                         y1*= strength / sqrt(3.0);
00118                         if (pattern) {
00119                             y1 /= 2;
00120                             y1 += patt[j%4]*strength*0.35;
00121                         }
00122                         if     (y1<-128) y1=-128;
00123                         else if(y1> 127) y1= 127;
00124                         if (averaged) y1 /= 3.0;
00125                         noise[i]= (int)y1;
00126                 }
00127                 if (RAND_N(6) == 0) j--;
00128         }
00129 
00130 
00131         for (i = 0; i < MAX_RES; i++)
00132             for (j = 0; j < 3; j++)
00133                 fp->prev_shift[i][j] = noise + (rand()&(MAX_SHIFT-1));
00134 
00135         if(!nonTempRandShift_init){
00136                 for(i=0; i<MAX_RES; i++){
00137                         nonTempRandShift[i]= rand()&(MAX_SHIFT-1);
00138                 }
00139                 nonTempRandShift_init = 1;
00140         }
00141 
00142         fp->noise= noise;
00143         fp->shiftptr= 0;
00144         return noise;
00145 }
00146 
00147 /***************************************************************************/
00148 
00149 #if HAVE_MMX
00150 static inline void lineNoise_MMX(uint8_t *dst, uint8_t *src, int8_t *noise, int len, int shift){
00151         x86_reg mmx_len= len&(~7);
00152         noise+=shift;
00153 
00154         __asm__ volatile(
00155                 "mov %3, %%"REG_a"                \n\t"
00156                 "pcmpeqb %%mm7, %%mm7                \n\t"
00157                 "psllw $15, %%mm7                \n\t"
00158                 "packsswb %%mm7, %%mm7                \n\t"
00159                 ASMALIGN(4)
00160                 "1:                                \n\t"
00161                 "movq (%0, %%"REG_a"), %%mm0        \n\t"
00162                 "movq (%1, %%"REG_a"), %%mm1        \n\t"
00163                 "pxor %%mm7, %%mm0                \n\t"
00164                 "paddsb %%mm1, %%mm0                \n\t"
00165                 "pxor %%mm7, %%mm0                \n\t"
00166                 "movq %%mm0, (%2, %%"REG_a")        \n\t"
00167                 "add $8, %%"REG_a"                \n\t"
00168                 " js 1b                                \n\t"
00169                 :: "r" (src+mmx_len), "r" (noise+mmx_len), "r" (dst+mmx_len), "g" (-mmx_len)
00170                 : "%"REG_a
00171         );
00172         if(mmx_len!=len)
00173                 lineNoise_C(dst+mmx_len, src+mmx_len, noise+mmx_len, len-mmx_len, 0);
00174 }
00175 #endif
00176 
00177 //duplicate of previous except movntq
00178 #if HAVE_MMX2
00179 static inline void lineNoise_MMX2(uint8_t *dst, uint8_t *src, int8_t *noise, int len, int shift){
00180         x86_reg mmx_len= len&(~7);
00181         noise+=shift;
00182 
00183         __asm__ volatile(
00184                 "mov %3, %%"REG_a"                \n\t"
00185                 "pcmpeqb %%mm7, %%mm7                \n\t"
00186                 "psllw $15, %%mm7                \n\t"
00187                 "packsswb %%mm7, %%mm7                \n\t"
00188                 ASMALIGN(4)
00189                 "1:                                \n\t"
00190                 "movq (%0, %%"REG_a"), %%mm0        \n\t"
00191                 "movq (%1, %%"REG_a"), %%mm1        \n\t"
00192                 "pxor %%mm7, %%mm0                \n\t"
00193                 "paddsb %%mm1, %%mm0                \n\t"
00194                 "pxor %%mm7, %%mm0                \n\t"
00195                 "movntq %%mm0, (%2, %%"REG_a")        \n\t"
00196                 "add $8, %%"REG_a"                \n\t"
00197                 " js 1b                                \n\t"
00198                 :: "r" (src+mmx_len), "r" (noise+mmx_len), "r" (dst+mmx_len), "g" (-mmx_len)
00199                 : "%"REG_a
00200         );
00201         if(mmx_len!=len)
00202                 lineNoise_C(dst+mmx_len, src+mmx_len, noise+mmx_len, len-mmx_len, 0);
00203 }
00204 #endif
00205 
00206 static inline void lineNoise_C(uint8_t *dst, uint8_t *src, int8_t *noise, int len, int shift){
00207         int i;
00208         noise+= shift;
00209         for(i=0; i<len; i++)
00210         {
00211                 int v= src[i]+ noise[i];
00212                 if(v>255)         dst[i]=255; //FIXME optimize
00213                 else if(v<0)         dst[i]=0;
00214                 else                dst[i]=v;
00215         }
00216 }
00217 
00218 /***************************************************************************/
00219 
00220 #if HAVE_MMX
00221 static inline void lineNoiseAvg_MMX(uint8_t *dst, uint8_t *src, int len, int8_t **shift){
00222         x86_reg mmx_len= len&(~7);
00223 
00224         __asm__ volatile(
00225                 "mov %5, %%"REG_a"                \n\t"
00226                 ASMALIGN(4)
00227                 "1:                                \n\t"
00228                 "movq (%1, %%"REG_a"), %%mm1        \n\t"
00229                 "movq (%0, %%"REG_a"), %%mm0        \n\t"
00230                 "paddb (%2, %%"REG_a"), %%mm1        \n\t"
00231                 "paddb (%3, %%"REG_a"), %%mm1        \n\t"
00232                 "movq %%mm0, %%mm2                \n\t"
00233                 "movq %%mm1, %%mm3                \n\t"
00234                 "punpcklbw %%mm0, %%mm0                \n\t"
00235                 "punpckhbw %%mm2, %%mm2                \n\t"
00236                 "punpcklbw %%mm1, %%mm1                \n\t"
00237                 "punpckhbw %%mm3, %%mm3                \n\t"
00238                 "pmulhw %%mm0, %%mm1                \n\t"
00239                 "pmulhw %%mm2, %%mm3                \n\t"
00240                 "paddw %%mm1, %%mm1                \n\t"
00241                 "paddw %%mm3, %%mm3                \n\t"
00242                 "paddw %%mm0, %%mm1                \n\t"
00243                 "paddw %%mm2, %%mm3                \n\t"
00244                 "psrlw $8, %%mm1                \n\t"
00245                 "psrlw $8, %%mm3                \n\t"
00246                 "packuswb %%mm3, %%mm1                \n\t"
00247                 "movq %%mm1, (%4, %%"REG_a")        \n\t"
00248                 "add $8, %%"REG_a"                \n\t"
00249                 " js 1b                                \n\t"
00250                 :: "r" (src+mmx_len), "r" (shift[0]+mmx_len), "r" (shift[1]+mmx_len), "r" (shift[2]+mmx_len),
00251                    "r" (dst+mmx_len), "g" (-mmx_len)
00252                 : "%"REG_a
00253         );
00254 
00255         if(mmx_len!=len){
00256                 int8_t *shift2[3]={shift[0]+mmx_len, shift[1]+mmx_len, shift[2]+mmx_len};
00257                 lineNoiseAvg_C(dst+mmx_len, src+mmx_len, len-mmx_len, shift2);
00258         }
00259 }
00260 #endif
00261 
00262 static inline void lineNoiseAvg_C(uint8_t *dst, uint8_t *src, int len, int8_t **shift){
00263         int i;
00264         int8_t *src2= (int8_t*)src;
00265 
00266         for(i=0; i<len; i++)
00267         {
00268             const int n= shift[0][i] + shift[1][i] + shift[2][i];
00269             dst[i]= src2[i]+((n*src2[i])>>7);
00270         }
00271 }
00272 
00273 /***************************************************************************/
00274 
00275 static void noise(uint8_t *dst, uint8_t *src, int dstStride, int srcStride, int width, int height, FilterParam *fp){
00276         int8_t *noise= fp->noise;
00277         int y;
00278         int shift=0;
00279 
00280         if(!noise)
00281         {
00282                 if(src==dst) return;
00283 
00284                 if(dstStride==srcStride) fast_memcpy(dst, src, srcStride*height);
00285                 else
00286                 {
00287                         for(y=0; y<height; y++)
00288                         {
00289                                 fast_memcpy(dst, src, width);
00290                                 dst+= dstStride;
00291                                 src+= srcStride;
00292                         }
00293                 }
00294                 return;
00295         }
00296 
00297         for(y=0; y<height; y++)
00298         {
00299                 if(fp->temporal)        shift=  rand()&(MAX_SHIFT  -1);
00300                 else                        shift= nonTempRandShift[y];
00301 
00302                 if(fp->quality==0) shift&= ~7;
00303                 if (fp->averaged) {
00304                     lineNoiseAvg(dst, src, width, fp->prev_shift[y]);
00305                     fp->prev_shift[y][fp->shiftptr] = noise + shift;
00306                 } else {
00307                     lineNoise(dst, src, noise, width, shift);
00308                 }
00309                 dst+= dstStride;
00310                 src+= srcStride;
00311         }
00312         fp->shiftptr++;
00313         if (fp->shiftptr == 3) fp->shiftptr = 0;
00314 }
00315 
00316 static int config(struct vf_instance *vf,
00317         int width, int height, int d_width, int d_height,
00318         unsigned int flags, unsigned int outfmt){
00319 
00320         return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt);
00321 }
00322 
00323 static void get_image(struct vf_instance *vf, mp_image_t *mpi){
00324     if(mpi->flags&MP_IMGFLAG_PRESERVE) return; // don't change
00325     if(mpi->imgfmt!=vf->priv->outfmt) return; // colorspace differ
00326     // ok, we can do pp in-place (or pp disabled):
00327     vf->dmpi=vf_get_image(vf->next,mpi->imgfmt,
00328         mpi->type, mpi->flags, mpi->w, mpi->h);
00329     mpi->planes[0]=vf->dmpi->planes[0];
00330     mpi->stride[0]=vf->dmpi->stride[0];
00331     mpi->width=vf->dmpi->width;
00332     if(mpi->flags&MP_IMGFLAG_PLANAR){
00333         mpi->planes[1]=vf->dmpi->planes[1];
00334         mpi->planes[2]=vf->dmpi->planes[2];
00335         mpi->stride[1]=vf->dmpi->stride[1];
00336         mpi->stride[2]=vf->dmpi->stride[2];
00337     }
00338     mpi->flags|=MP_IMGFLAG_DIRECT;
00339 }
00340 
00341 static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
00342         mp_image_t *dmpi;
00343 
00344         if(!(mpi->flags&MP_IMGFLAG_DIRECT)){
00345                 // no DR, so get a new image! hope we'll get DR buffer:
00346                 vf->dmpi=vf_get_image(vf->next,vf->priv->outfmt,
00347                 MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE,
00348                 mpi->w,mpi->h);
00349 //printf("nodr\n");
00350         }
00351 //else printf("dr\n");
00352         dmpi= vf->dmpi;
00353 
00354         noise(dmpi->planes[0], mpi->planes[0], dmpi->stride[0], mpi->stride[0], mpi->w, mpi->h, &vf->priv->lumaParam);
00355         noise(dmpi->planes[1], mpi->planes[1], dmpi->stride[1], mpi->stride[1], mpi->w/2, mpi->h/2, &vf->priv->chromaParam);
00356         noise(dmpi->planes[2], mpi->planes[2], dmpi->stride[2], mpi->stride[2], mpi->w/2, mpi->h/2, &vf->priv->chromaParam);
00357 
00358         vf_clone_mpi_attributes(dmpi, mpi);
00359 
00360 #if HAVE_MMX
00361         if(gCpuCaps.hasMMX) __asm__ volatile ("emms\n\t");
00362 #endif
00363 #if HAVE_MMX2
00364         if(gCpuCaps.hasMMX2) __asm__ volatile ("sfence\n\t");
00365 #endif
00366 
00367         return vf_next_put_image(vf,dmpi, pts);
00368 }
00369 
00370 static void uninit(struct vf_instance *vf){
00371         if(!vf->priv) return;
00372 
00373         av_free(vf->priv->chromaParam.noise);
00374         vf->priv->chromaParam.noise= NULL;
00375 
00376         av_free(vf->priv->lumaParam.noise);
00377         vf->priv->lumaParam.noise= NULL;
00378 
00379         free(vf->priv);
00380         vf->priv=NULL;
00381 }
00382 
00383 //===========================================================================//
00384 
00385 static int query_format(struct vf_instance *vf, unsigned int fmt){
00386         switch(fmt)
00387         {
00388         case IMGFMT_YV12:
00389         case IMGFMT_I420:
00390         case IMGFMT_IYUV:
00391                 return vf_next_query_format(vf,vf->priv->outfmt);
00392         }
00393         return 0;
00394 }
00395 
00396 static void parse(FilterParam *fp, char* args){
00397         char *pos;
00398         char *max= strchr(args, ':');
00399 
00400         if(!max) max= args + strlen(args);
00401 
00402         fp->strength= atoi(args);
00403         pos= strchr(args, 'u');
00404         if(pos && pos<max) fp->uniform=1;
00405         pos= strchr(args, 't');
00406         if(pos && pos<max) fp->temporal=1;
00407         pos= strchr(args, 'h');
00408         if(pos && pos<max) fp->quality=1;
00409         pos= strchr(args, 'p');
00410         if(pos && pos<max) fp->pattern=1;
00411         pos= strchr(args, 'a');
00412         if(pos && pos<max) {
00413             fp->temporal=1;
00414             fp->averaged=1;
00415         }
00416 
00417         if(fp->strength) initNoise(fp);
00418 }
00419 
00420 static const unsigned int fmt_list[]={
00421     IMGFMT_YV12,
00422     IMGFMT_I420,
00423     IMGFMT_IYUV,
00424     0
00425 };
00426 
00427 static int vf_open(vf_instance_t *vf, char *args){
00428     vf->config=config;
00429     vf->put_image=put_image;
00430     vf->get_image=get_image;
00431     vf->query_format=query_format;
00432     vf->uninit=uninit;
00433     vf->priv=malloc(sizeof(struct vf_priv_s));
00434     memset(vf->priv, 0, sizeof(struct vf_priv_s));
00435     if(args)
00436     {
00437         char *arg2= strchr(args,':');
00438         if(arg2) parse(&vf->priv->chromaParam, arg2+1);
00439         parse(&vf->priv->lumaParam, args);
00440     }
00441 
00442     // check csp:
00443     vf->priv->outfmt=vf_match_csp(&vf->next,fmt_list,IMGFMT_YV12);
00444     if(!vf->priv->outfmt)
00445     {
00446         uninit(vf);
00447         return 0; // no csp match :(
00448     }
00449 
00450 
00451 #if HAVE_MMX
00452     if(gCpuCaps.hasMMX){
00453         lineNoise= lineNoise_MMX;
00454         lineNoiseAvg= lineNoiseAvg_MMX;
00455     }
00456 #endif
00457 #if HAVE_MMX2
00458     if(gCpuCaps.hasMMX2) lineNoise= lineNoise_MMX2;
00459 //    if(gCpuCaps.hasMMX) lineNoiseAvg= lineNoiseAvg_MMX2;
00460 #endif
00461 
00462     return 1;
00463 }
00464 
00465 const vf_info_t vf_info_noise = {
00466     "noise generator",
00467     "noise",
00468     "Michael Niedermayer",
00469     "",
00470     vf_open,
00471     NULL
00472 };
00473 
00474 //===========================================================================//

Generated on Fri Feb 22 2013 07:24:30 for FFmpeg by  doxygen 1.7.1