[cvs] / xvidcore / src / plugins / plugin_ssim.c Repository:
ViewVC logotype

Diff of /xvidcore/src/plugins/plugin_ssim.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.2, Fri Oct 13 06:32:02 2006 UTC revision 1.8, Thu Dec 21 23:27:25 2006 UTC
# Line 26  Line 26 
26  #include <malloc.h>  #include <malloc.h>
27  #include <stdio.h>  #include <stdio.h>
28  #include <math.h>  #include <math.h>
29  #include <stdint.h>  #include "../portab.h"
30  #include "../xvid.h"  #include "../xvid.h"
31  #include "plugin_ssim.h"  #include "plugin_ssim.h"
32  #include "../utils/emms.h"  #include "../utils/emms.h"
# Line 37  Line 37 
37    
38  typedef struct framestat_t framestat_t;  typedef struct framestat_t framestat_t;
39    
40    /*dev 1.0 gaussian weighting. the weight for the pixel x,y is w(x)*w(y)*/
41    static float mask8[8] = {
42            0.0069815, 0.1402264, 1.0361408, 2.8165226,
43            2.8165226, 1.0361408, 0.1402264, 0.0069815
44    };
45    
46    /* integer version. Norm: coeffs sums up to 4096.
47      Define USE_INT_GAUSSIAN to use it as replacement to float version */
48    
49    /* #define USE_INT_GAUSSIAN */
50    static const uint16_t imask8[8] = {
51      4, 72, 530, 1442, 1442, 530, 72, 4
52    };
53    #define GACCUM(X)  ( ((X)+(1<<11)) >> 12 )
54    
55    
56  struct framestat_t{  struct framestat_t{
57          int type;          int type;
58          int quant;          int quant;
# Line 62  Line 78 
78          uint8_t* errmap;          uint8_t* errmap;
79          */          */
80    
81            int grid;
82    
83          /*for average SSIM*/          /*for average SSIM*/
84          float ssim_sum;          float ssim_sum;
85          int frame_cnt;          int frame_cnt;
# Line 107  Line 125 
125    
126  /*writeout the collected stats*/  /*writeout the collected stats*/
127  void framestat_write(ssim_data_t* ssim, char* path){  void framestat_write(ssim_data_t* ssim, char* path){
128            framestat_t* tmp = ssim->head;
129          FILE* out = fopen(path,"w");          FILE* out = fopen(path,"w");
130          if(out==NULL) printf("Cannot open %s in plugin_ssim\n",path);          if(out==NULL) printf("Cannot open %s in plugin_ssim\n",path);
         framestat_t* tmp = ssim->head;  
131    
132          fprintf(out,"SSIM Error Metric\n");          fprintf(out,"SSIM Error Metric\n");
133          fprintf(out,"quant   avg     min     max");          fprintf(out,"quant   avg     min     max\n");
134          while(tmp->next->next != NULL){          while(tmp->next->next != NULL){
135                  fprintf(out,"%3d     %1.4f   %1.4f   %1.4f\n",tmp->quant,tmp->ssim_avg,tmp->ssim_min,tmp->ssim_max);                  fprintf(out,"%3d     %1.3f   %1.3f   %1.3f\n",tmp->quant,tmp->ssim_avg,tmp->ssim_min,tmp->ssim_max);
136                  tmp = tmp->next;                  tmp = tmp->next;
137          }          }
138          fclose(out);          fclose(out);
# Line 122  Line 140 
140    
141  /*writeout the collected stats in octave readable format*/  /*writeout the collected stats in octave readable format*/
142  void framestat_write_oct(ssim_data_t* ssim, char* path){  void framestat_write_oct(ssim_data_t* ssim, char* path){
143            framestat_t* tmp;
144          FILE* out = fopen(path,"w");          FILE* out = fopen(path,"w");
145          if(out==NULL) printf("Cannot open %s in plugin_ssim\n",path);          if(out==NULL) printf("Cannot open %s in plugin_ssim\n",path);
         framestat_t* tmp;  
146    
147          fprintf(out,"quant = [");          fprintf(out,"quant = [");
148          tmp = ssim->head;          tmp = ssim->head;
# Line 220  Line 237 
237          return mean;          return mean;
238  }  }
239    
240    int lum_8x8_gaussian(uint8_t* ptr, int stride){
241            float mean=0,sum;
242            int i,j;
243            for(i=0;i<8;i++){
244                    sum = 0;
245                    for(j=0;j<8;j++)
246                            sum += ptr[i*stride + j]*mask8[j];
247    
248                    sum *=mask8[i];
249                    mean += sum;
250            }
251            return (int) mean + 0.5;
252    }
253    
254    int lum_8x8_gaussian_int(uint8_t* ptr, int stride){
255            uint32_t mean;
256            int i,j;
257            mean = 0;
258            for(i=0;i<8;i++){
259                    uint32_t sum = 0;
260                    for(j=0;j<8;j++)
261                            sum += ptr[i*stride + j]*imask8[j];
262    
263                    sum = GACCUM(sum) * imask8[i];
264                    mean += sum;
265            }
266            return (int)GACCUM(mean);
267    }
268    
269  /*calculate the difference between two blocks next to each other on a row*/  /*calculate the difference between two blocks next to each other on a row*/
270  int lum_2x8_c(uint8_t* ptr, int stride){  int lum_2x8_c(uint8_t* ptr, int stride){
271          int mean=0,i;          int mean=0,i;
# Line 233  Line 279 
279  }  }
280    
281  /*calculate contrast and correlation of the two blocks*/  /*calculate contrast and correlation of the two blocks*/
282  void iconsim_c(uint8_t* ptro, uint8_t* ptrc, int stride, int lumo, int lumc, int* pdevo, int* pdevc, int* pcorr){  void consim_gaussian(uint8_t* ptro, uint8_t* ptrc, int stride, int lumo, int lumc, int* pdevo, int* pdevc, int* pcorr){
283          int valo, valc, devo =0, devc=0, corr=0;          unsigned int valo, valc,i,j,str;
284          int i,j;          float devo=0, devc=0, corr=0,sumo,sumc,sumcorr;
285            str = stride - 8;
286          for(i=0;i< 8;i++){          for(i=0;i< 8;i++){
287                    sumo = 0;
288                    sumc = 0;
289                    sumcorr = 0;
290                  for(j=0;j< 8;j++){                  for(j=0;j< 8;j++){
291                          valo = *ptro - lumo;                          valo = *ptro;
292                          valc = *ptrc - lumc;                          valc = *ptrc;
293                          devo += valo*valo;                          sumo += valo*valo*mask8[j];
294                            sumc += valc*valc*mask8[j];
295                            sumcorr += valo*valc*mask8[j];
296                          ptro++;                          ptro++;
                         devc += valc*valc;  
297                          ptrc++;                          ptrc++;
298                    }
299    
300            devo += sumo*mask8[i];
301            devc += sumc*mask8[i];
302            corr += sumcorr*mask8[i];
303            ptro += str;
304            ptrc += str;
305            }
306    
307            *pdevo = (int) (devo - ((lumo*lumo + 32) >> 6)) + 0.5;
308            *pdevc = (int) (devc - ((lumc*lumc + 32) >> 6)) + 0.5;
309            *pcorr = (int) (corr - ((lumo*lumc + 32) >> 6)) + 0.5;
310    };
311    
312    void consim_gaussian_int(uint8_t* ptro, uint8_t* ptrc, int stride, int lumo, int lumc, int* pdevo, int* pdevc, int* pcorr)
313    {
314            unsigned int valo, valc,i,j,str;
315            uint32_t  devo=0, devc=0, corr=0;
316            str = stride - 8;
317            for(i=0;i< 8;i++){
318                    uint32_t sumo = 0;
319                    uint32_t sumc = 0;
320                    uint32_t sumcorr = 0;
321                    for(j=0;j< 8;j++){
322                            valo = *ptro;
323                            valc = *ptrc;
324                            sumo += valo*valo*imask8[j];
325                            sumc += valc*valc*imask8[j];
326                            sumcorr += valo*valc*imask8[j];
327                            ptro++;
328                            ptrc++;
329                    }
330    
331            devo += GACCUM(sumo)*imask8[i];
332            devc += GACCUM(sumc)*imask8[i];
333            corr += GACCUM(sumcorr)*imask8[i];
334            ptro += str;
335            ptrc += str;
336            }
337    
338            devo = GACCUM(devo);
339            devc = GACCUM(devc);
340            corr = GACCUM(corr);
341            *pdevo = (int) (devo - ((lumo*lumo + 32) >> 6)) + 0.5;
342            *pdevc = (int) (devc - ((lumc*lumc + 32) >> 6)) + 0.5;
343            *pcorr = (int) (corr - ((lumo*lumc + 32) >> 6)) + 0.5;
344    };
345    
346    /*calculate contrast and correlation of the two blocks*/
347    void consim_c(uint8_t* ptro, uint8_t* ptrc, int stride, int lumo, int lumc, int* pdevo, int* pdevc, int* pcorr){
348            unsigned int valo, valc, devo=0, devc=0, corr=0,i,j,str;
349            str = stride - 8;
350            for(i=0;i< 8;i++){
351                    for(j=0;j< 8;j++){
352                            valo = *ptro;
353                            valc = *ptrc;
354                            devo += valo*valo;
355                            devc += valc*valc;
356                          corr += valo*valc;                          corr += valo*valc;
357                            ptro++;
358                            ptrc++;
359                  }                  }
360          ptro += stride -8;          ptro += str;
361          ptrc += stride -8;          ptrc += str;
362          }          }
363          *pdevo = devo;  
364          *pdevc = devc;          *pdevo = devo - ((lumo*lumo + 32) >> 6);
365          *pcorr = corr;          *pdevc = devc - ((lumc*lumc + 32) >> 6);
366            *pcorr = corr - ((lumo*lumc + 32) >> 6);
367  };  };
368    
369  /*calculate the final ssim value*/  /*calculate the final ssim value*/
370  static float calc_ssim(int meano, int meanc, int devo, int devc, int corr){  static float calc_ssim(float meano, float meanc, float devo, float devc, float corr){
371          static const float c1 = (0.01*255)*(0.01*255);          static const float c1 = (0.01*255)*(0.01*255);
372          static const float c2 = (0.03*255)*(0.03*255);          static const float c2 = (0.03*255)*(0.03*255);
373          float fmeano,fmeanc,fdevo,fdevc,fcorr;          /*printf("meano: %f meanc: %f devo: %f devc: %f corr: %f\n",meano,meanc,devo,devc,corr);*/
374          fmeanc = (float) meanc;          return ((2.0*meano*meanc + c1)*(corr/32.0 + c2))/((meano*meano + meanc*meanc + c1)*(devc/64.0 + devo/64.0 + c2));
         fmeano = (float) meano;  
         fdevo = (float) devo;  
         fdevc = (float) devc;  
         fcorr = (float) corr;  
 //      printf("meano: %f meanc: %f devo: %f devc: %f corr: %f\n",fmeano,fmeanc,fdevo,fdevc,fcorr);  
         return ((2.0*fmeano*fmeanc + c1)*(fcorr/32.0 + c2))/((fmeano*fmeano + fmeanc*fmeanc + c1)*(fdevc/64.0 + fdevo/64.0 + c2));  
375  }  }
376    
377  static void ssim_after(xvid_plg_data_t* data, ssim_data_t* ssim){  static void ssim_after(xvid_plg_data_t* data, ssim_data_t* ssim){
378          int i,j,c=0;          int i,j,c=0,opt;
379          int width,height,str,ovr;          int width,height,str,ovr;
380          unsigned char * ptr1,*ptr2;          unsigned char * ptr1,*ptr2;
381          float isum=0, min=1.00,max=0.00, val;          float isum=0, min=1.00,max=0.00, val;
382          int meanc, meano;          int meanc, meano;
383          int devc, devo, corr;          int devc, devo, corr;
384    
         #define GRID 1  
   
385          width = data->width - 8;          width = data->width - 8;
386          height = data->height - 8;          height = data->height - 8;
387          str = data->original.stride[0];          str = data->original.stride[0];
388          if(str != data->current.stride[0]) printf("WARNING: Different strides in plugin_ssim original: %d current: %d\n",str,data->current.stride[0]);          if(str != data->current.stride[0]) printf("WARNING: Different strides in plugin_ssim original: %d current: %d\n",str,data->current.stride[0]);
389          ovr = str - width + (width % GRID);          ovr = str - width + (width % ssim->grid);
390    
391          ptr1 = (unsigned char*) data->original.plane[0];          ptr1 = (unsigned char*) data->original.plane[0];
392          ptr2 = (unsigned char*) data->current.plane[0];          ptr2 = (unsigned char*) data->current.plane[0];
393    
394            opt = ssim->grid == 1 && ssim->param->acc != 0;
395    
396          /*TODO: Thread*/          /*TODO: Thread*/
397          for(i=0;i<height;i+=GRID){          for(i=0;i<height;i+=ssim->grid){
398                  /*begin of each row*/                  /*begin of each row*/
399                  meano = meanc = devc = devo = corr = 0;                  meano = meanc = devc = devo = corr = 0;
400                  meano = ssim->func8x8(ptr1,str);                  meano = ssim->func8x8(ptr1,str);
401                  meanc = ssim->func8x8(ptr2,str);                  meanc = ssim->func8x8(ptr2,str);
402                  ssim->consim(ptr1,ptr2,str,meano>>6,meanc>>6,&devo,&devc,&corr);                  ssim->consim(ptr1,ptr2,str,meano,meanc,&devo,&devc,&corr);
403                  emms();                  emms();
404    
405                  val = calc_ssim(meano,meanc,devo,devc,corr);                  val = calc_ssim((float) meano,(float) meanc,(float) devo,(float) devc,(float) corr);
406                  isum += val;                  isum += val;
407                  c++;                  c++;
408                  /* for visualisation                  /* for visualisation
# Line 306  Line 410 
410                          ssim->errmap[i*width] = (uint8_t) 127*val;                          ssim->errmap[i*width] = (uint8_t) 127*val;
411                  */                  */
412    
413    
414                  if(val < min) min = val;                  if(val < min) min = val;
415                  if(val > max) max = val;                  if(val > max) max = val;
416                  ptr1+=GRID;                  ptr1+=ssim->grid;
417                  ptr2+=GRID;                  ptr2+=ssim->grid;
418                  /*rest of each row*/                  /*rest of each row*/
419                  for(j=1;j<width;j+=GRID){                  for(j=ssim->grid;j<width;j+=ssim->grid){
420                          /* for grid = 1 use                          if(opt){
421                          meano += ssim->func2x8(ptr1,str);                          meano += ssim->func2x8(ptr1,str);
422                          meanc += ssim->func2x8(ptr2,str);                          meanc += ssim->func2x8(ptr2,str);
423                          */                          } else {
424                          meano = ssim->func8x8(ptr1,str);                          meano = ssim->func8x8(ptr1,str);
425                          meanc = ssim->func8x8(ptr2,str);                          meanc = ssim->func8x8(ptr2,str);
426                          ssim->consim(ptr1,ptr2,str,meano>>6,meanc>>6,&devo,&devc,&corr);                          }
427                            ssim->consim(ptr1,ptr2,str,meano,meanc,&devo,&devc,&corr);
428                          emms();                          emms();
429    
430                          val = calc_ssim(meano,meanc,devo,devc,corr);                          val = calc_ssim((float) meano,(float) meanc,(float) devo,(float) devc,(float) corr);
431                          isum += val;                          isum += val;
432                          c++;                          c++;
433                          /* for visualisation                          /* for visualisation
# Line 330  Line 436 
436                          */                          */
437                          if(val < min) min = val;                          if(val < min) min = val;
438                          if(val > max) max = val;                          if(val > max) max = val;
439                          ptr1+=GRID;                          ptr1+=ssim->grid;
440                          ptr2+=GRID;                          ptr2+=ssim->grid;
441                  }                  }
442                  ptr1 +=ovr;                  ptr1 +=ovr;
443                  ptr2 +=ovr;                  ptr2 +=ovr;
# Line 352  Line 458 
458          }          }
459  */  */
460          if(ssim->param->b_printstat){          if(ssim->param->b_printstat){
461                  printf("SSIM: avg: %f min: %f max: %f\n",isum,min,max);                  printf("       SSIM: avg: %1.3f min: %1.3f max: %1.3f\n",isum,min,max);
462          }          }
463    
464  }  }
# Line 360  Line 466 
466  static int ssim_create(xvid_plg_create_t* create, void** handle){  static int ssim_create(xvid_plg_create_t* create, void** handle){
467          ssim_data_t* ssim;          ssim_data_t* ssim;
468          plg_ssim_param_t* param;          plg_ssim_param_t* param;
         int cpu_flags;  
469          param = (plg_ssim_param_t*) malloc(sizeof(plg_ssim_param_t));          param = (plg_ssim_param_t*) malloc(sizeof(plg_ssim_param_t));
470          *param = *((plg_ssim_param_t*) create->param);          *param = *((plg_ssim_param_t*) create->param);
471          ssim = (ssim_data_t*) malloc(sizeof(ssim_data_t));          ssim = (ssim_data_t*) malloc(sizeof(ssim_data_t));
472    
         cpu_flags = check_cpu_features();  
   
473          ssim->func8x8 = lum_8x8_c;          ssim->func8x8 = lum_8x8_c;
474          ssim->func2x8 = lum_2x8_c;          ssim->func2x8 = lum_2x8_c;
475          ssim->consim = iconsim_c;          ssim->consim = consim_c;
476    
477          ssim->param = param;          ssim->param = param;
478    
479            ssim->grid = param->acc;
480    
481  #if defined(ARCH_IS_IA32)  #if defined(ARCH_IS_IA32)
482          if(cpu_flags & XVID_CPU_MMX){          {
483                    int cpu_flags = check_cpu_features();
484                    if((cpu_flags & XVID_CPU_MMX) && (param->acc > 0)){
485                  ssim->func8x8 = lum_8x8_mmx;                  ssim->func8x8 = lum_8x8_mmx;
486                  ssim->consim = consim_mmx;                  ssim->consim = consim_mmx;
487          }          }
488          if(cpu_flags & XVID_CPU_SSE2){                  if((cpu_flags & XVID_CPU_SSE2) && (param->acc > 0)){
489                  ssim->consim = consim_sse2;                  ssim->consim = consim_sse2;
490          }          }
491            }
492    #endif
493    
494            /*gaussian weigthing not implemented*/
495    #if !defined(USE_INT_GAUSSIAN)
496            if(ssim->grid == 0){
497                    ssim->grid = 1;
498                    ssim->func8x8 = lum_8x8_gaussian;
499                    ssim->func2x8 = NULL;
500                    ssim->consim = consim_gaussian;
501            }
502    #else
503            if(ssim->grid == 0){
504                    ssim->grid = 1;
505                    ssim->func8x8 = lum_8x8_gaussian_int;
506                    ssim->func2x8 = NULL;
507                    ssim->consim = consim_gaussian_int;
508            }
509  #endif  #endif
510            if(ssim->grid > 4) ssim->grid = 4;
511    
512          ssim->ssim_sum = 0.0;          ssim->ssim_sum = 0.0;
513          ssim->frame_cnt = 0;          ssim->frame_cnt = 0;
# Line 425  Line 551 
551                          if(ssim->param->stat_path != NULL)                          if(ssim->param->stat_path != NULL)
552                                  framestat_write(ssim,ssim->param->stat_path);                                  framestat_write(ssim,ssim->param->stat_path);
553                          framestat_free(ssim->head);                          framestat_free(ssim->head);
554                          //free(ssim->errmap);                          /*free(ssim->errmap);*/
555                          free(ssim->param);                          free(ssim->param);
556                          free(ssim);                          free(ssim);
557                          break;                          break;

Legend:
Removed from v.1.2  
changed lines
  Added in v.1.8

No admin address has been configured
ViewVC Help
Powered by ViewVC 1.0.4