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

Annotation of /trunk/xvidcore/src/plugins/plugin_ssim.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1743 - (view) (download)

1 : Skal 1730 /*****************************************************************************
2 :     *
3 :     * XVID MPEG-4 VIDEO CODEC
4 :     * - SSIM plugin: computes the SSIM metric -
5 :     *
6 :     * Copyright(C) 2005 Johannes Reinhardt <Johannes.Reinhardt@gmx.de>
7 :     *
8 :     * This program is free software ; you can redistribute it and/or modify
9 :     * it under the terms of the GNU General Public License as published by
10 :     * the Free Software Foundation ; either version 2 of the License, or
11 :     * (at your option) any later version.
12 :     *
13 :     * This program is distributed in the hope that it will be useful,
14 :     * but WITHOUT ANY WARRANTY ; without even the implied warranty of
15 :     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 :     * GNU General Public License for more details.
17 :     *
18 :     * You should have received a copy of the GNU General Public License
19 :     * along with this program ; if not, write to the Free Software
20 :     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 :     *
22 :     *
23 :     *
24 :     ****************************************************************************/
25 :    
26 :     #include <malloc.h>
27 :     #include <stdio.h>
28 :     #include <math.h>
29 : Isibaar 1734 #include "../portab.h"
30 : Skal 1730 #include "../xvid.h"
31 :     #include "plugin_ssim.h"
32 :     #include "../utils/emms.h"
33 :    
34 :     /* needed for visualisation of the error map with X
35 :     display.h borrowed from x264
36 :     #include "display.h"*/
37 :    
38 :     typedef struct framestat_t framestat_t;
39 :    
40 :     struct framestat_t{
41 :     int type;
42 :     int quant;
43 :     float ssim_min;
44 :     float ssim_max;
45 :     float ssim_avg;
46 :     framestat_t* next;
47 :     };
48 :    
49 :    
50 :     typedef int (*lumfunc)(uint8_t* ptr, int stride);
51 :     typedef void (*csfunc)(uint8_t* ptro, uint8_t* ptrc, int stride, int lumo, int lumc, int* pdevo, int* pdevc, int* pcorr);
52 :    
53 :     int lum_8x8_mmx(uint8_t* ptr, int stride);
54 :     void consim_mmx(uint8_t* ptro, uint8_t* ptrc, int stride, int lumo, int lumc, int* pdevo, int* pdevc, int* pcorr);
55 :     void consim_sse2(uint8_t* ptro, uint8_t* ptrc, int stride, int lumo, int lumc, int* pdevo, int* pdevc, int* pcorr);
56 :    
57 :     typedef struct{
58 :    
59 :     plg_ssim_param_t* param;
60 :    
61 :     /* for error map visualisation
62 :     uint8_t* errmap;
63 :     */
64 :    
65 : Skal 1743 int grid;
66 :    
67 : Skal 1730 /*for average SSIM*/
68 :     float ssim_sum;
69 :     int frame_cnt;
70 :    
71 :     /*function pointers*/
72 :     lumfunc func8x8;
73 :     lumfunc func2x8;
74 :     csfunc consim;
75 :    
76 :     /*stats - for debugging*/
77 :     framestat_t* head;
78 :     framestat_t* tail;
79 :     } ssim_data_t;
80 :    
81 :     /* append the stats for another frame to the linked list*/
82 :     void framestat_append(ssim_data_t* ssim,int type, int quant, float min, float max, float avg){
83 :     framestat_t* act;
84 :     act = (framestat_t*) malloc(sizeof(framestat_t));
85 :     act->type = type;
86 :     act->quant = quant;
87 :     act->ssim_min = min;
88 :     act->ssim_max = max;
89 :     act->ssim_avg = avg;
90 :     act->next = NULL;
91 :    
92 :     if(ssim->head == NULL){
93 :     ssim->head = act;
94 :     ssim->tail = act;
95 :     } else {
96 :     ssim->tail->next = act;
97 :     ssim->tail = act;
98 :     }
99 :     }
100 :    
101 :     /* destroy the whole list*/
102 :     void framestat_free(framestat_t* stat){
103 :     if(stat != NULL){
104 :     if(stat->next != NULL) framestat_free(stat->next);
105 :     free(stat);
106 :     }
107 :     return;
108 :     }
109 :    
110 :     /*writeout the collected stats*/
111 :     void framestat_write(ssim_data_t* ssim, char* path){
112 : Isibaar 1734 framestat_t* tmp = ssim->head;
113 : Skal 1730 FILE* out = fopen(path,"w");
114 :     if(out==NULL) printf("Cannot open %s in plugin_ssim\n",path);
115 :    
116 :     fprintf(out,"SSIM Error Metric\n");
117 : Skal 1737 fprintf(out,"quant avg min max\n");
118 : Skal 1730 while(tmp->next->next != NULL){
119 :     fprintf(out,"%3d %1.4f %1.4f %1.4f\n",tmp->quant,tmp->ssim_avg,tmp->ssim_min,tmp->ssim_max);
120 :     tmp = tmp->next;
121 :     }
122 :     fclose(out);
123 :     }
124 :    
125 :     /*writeout the collected stats in octave readable format*/
126 :     void framestat_write_oct(ssim_data_t* ssim, char* path){
127 : Isibaar 1734 framestat_t* tmp;
128 : Skal 1730 FILE* out = fopen(path,"w");
129 :     if(out==NULL) printf("Cannot open %s in plugin_ssim\n",path);
130 :    
131 :     fprintf(out,"quant = [");
132 :     tmp = ssim->head;
133 :     while(tmp->next->next != NULL){
134 :     fprintf(out,"%d, ",tmp->quant);
135 :     tmp = tmp->next;
136 :     }
137 :     fprintf(out,"%d];\n\n",tmp->quant);
138 :    
139 :     fprintf(out,"ssim_min = [");
140 :     tmp = ssim->head;
141 :     while(tmp->next->next != NULL){
142 :     fprintf(out,"%f, ",tmp->ssim_min);
143 :     tmp = tmp->next;
144 :     }
145 :     fprintf(out,"%f];\n\n",tmp->ssim_min);
146 :    
147 :     fprintf(out,"ssim_max = [");
148 :     tmp = ssim->head;
149 :     while(tmp->next->next != NULL){
150 :     fprintf(out,"%f, ",tmp->ssim_max);
151 :     tmp = tmp->next;
152 :     }
153 :     fprintf(out,"%f];\n\n",tmp->ssim_max);
154 :    
155 :     fprintf(out,"ssim_avg = [");
156 :     tmp = ssim->head;
157 :     while(tmp->next->next != NULL){
158 :     fprintf(out,"%f, ",tmp->ssim_avg);
159 :     tmp = tmp->next;
160 :     }
161 :     fprintf(out,"%f];\n\n",tmp->ssim_avg);
162 :    
163 :     fprintf(out,"ivop = [");
164 :     tmp = ssim->head;
165 :     while(tmp->next->next != NULL){
166 :     if(tmp->type == XVID_TYPE_IVOP){
167 :     fprintf(out,"%d, ",tmp->quant);
168 :     fprintf(out,"%f, ",tmp->ssim_avg);
169 :     fprintf(out,"%f, ",tmp->ssim_min);
170 :     fprintf(out,"%f; ",tmp->ssim_max);
171 :     }
172 :     tmp = tmp->next;
173 :     }
174 :     fprintf(out,"%d, ",tmp->quant);
175 :     fprintf(out,"%f, ",tmp->ssim_avg);
176 :     fprintf(out,"%f, ",tmp->ssim_min);
177 :     fprintf(out,"%f];\n\n",tmp->ssim_max);
178 :    
179 :     fprintf(out,"pvop = [");
180 :     tmp = ssim->head;
181 :     while(tmp->next->next != NULL){
182 :     if(tmp->type == XVID_TYPE_PVOP){
183 :     fprintf(out,"%d, ",tmp->quant);
184 :     fprintf(out,"%f, ",tmp->ssim_avg);
185 :     fprintf(out,"%f, ",tmp->ssim_min);
186 :     fprintf(out,"%f; ",tmp->ssim_max);
187 :     }
188 :     tmp = tmp->next;
189 :     }
190 :     fprintf(out,"%d, ",tmp->quant);
191 :     fprintf(out,"%f, ",tmp->ssim_avg);
192 :     fprintf(out,"%f, ",tmp->ssim_min);
193 :     fprintf(out,"%f];\n\n",tmp->ssim_max);
194 :    
195 :     fprintf(out,"bvop = [");
196 :     tmp = ssim->head;
197 :     while(tmp->next->next != NULL){
198 :     if(tmp->type == XVID_TYPE_BVOP){
199 :     fprintf(out,"%d, ",tmp->quant);
200 :     fprintf(out,"%f, ",tmp->ssim_avg);
201 :     fprintf(out,"%f, ",tmp->ssim_min);
202 :     fprintf(out,"%f; ",tmp->ssim_max);
203 :     }
204 :     tmp = tmp->next;
205 :     }
206 :     fprintf(out,"%d, ",tmp->quant);
207 :     fprintf(out,"%f, ",tmp->ssim_avg);
208 :     fprintf(out,"%f, ",tmp->ssim_min);
209 :     fprintf(out,"%f];\n\n",tmp->ssim_max);
210 :    
211 :     fclose(out);
212 :     }
213 :    
214 :     /*calculate the luminance of a 8x8 block*/
215 :     int lum_8x8_c(uint8_t* ptr, int stride){
216 :     int mean=0,i,j;
217 :     for(i=0;i< 8;i++)
218 :     for(j=0;j< 8;j++){
219 :     mean += ptr[i*stride + j];
220 :     }
221 :     return mean;
222 :     }
223 :    
224 :     /*calculate the difference between two blocks next to each other on a row*/
225 :     int lum_2x8_c(uint8_t* ptr, int stride){
226 :     int mean=0,i;
227 :     /*Luminance*/
228 :     for(i=0;i< 8;i++){
229 :     mean -= *(ptr-1);
230 :     mean += *(ptr+ 8 - 1);
231 :     ptr+=stride;
232 :     }
233 :     return mean;
234 :     }
235 :    
236 :     /*calculate contrast and correlation of the two blocks*/
237 : Skal 1743 void consim_c(uint8_t* ptro, uint8_t* ptrc, int stride, int lumo, int lumc, int* pdevo, int* pdevc, int* pcorr){
238 :     unsigned int valo, valc, devo=0, devc=0, corr=0,i,j,str;
239 :     str = stride - 8;
240 : Skal 1730 for(i=0;i< 8;i++){
241 :     for(j=0;j< 8;j++){
242 : Skal 1743 valo = *ptro;
243 :     valc = *ptrc;
244 : Skal 1730 devo += valo*valo;
245 : Skal 1743 devc += valc*valc;
246 :     corr += valo*valc;
247 : Skal 1730 ptro++;
248 :     ptrc++;
249 :     }
250 : Skal 1743 ptro += str;
251 :     ptrc += str;
252 : Skal 1730 }
253 : Skal 1743
254 :     *pdevo = devo - ((lumo*lumo + 32) >> 6);
255 :     *pdevc = devc - ((lumc*lumc + 32) >> 6);
256 :     *pcorr = corr - ((lumo*lumc + 32) >> 6);
257 : Skal 1730 };
258 :    
259 :     /*calculate the final ssim value*/
260 :     static float calc_ssim(int meano, int meanc, int devo, int devc, int corr){
261 :     static const float c1 = (0.01*255)*(0.01*255);
262 :     static const float c2 = (0.03*255)*(0.03*255);
263 :     float fmeano,fmeanc,fdevo,fdevc,fcorr;
264 :     fmeanc = (float) meanc;
265 :     fmeano = (float) meano;
266 :     fdevo = (float) devo;
267 :     fdevc = (float) devc;
268 :     fcorr = (float) corr;
269 : Skal 1737 /* printf("meano: %f meanc: %f devo: %f devc: %f corr: %f\n",fmeano,fmeanc,fdevo,fdevc,fcorr); */
270 : Skal 1730 return ((2.0*fmeano*fmeanc + c1)*(fcorr/32.0 + c2))/((fmeano*fmeano + fmeanc*fmeanc + c1)*(fdevc/64.0 + fdevo/64.0 + c2));
271 :     }
272 :    
273 :     static void ssim_after(xvid_plg_data_t* data, ssim_data_t* ssim){
274 :     int i,j,c=0;
275 :     int width,height,str,ovr;
276 :     unsigned char * ptr1,*ptr2;
277 :     float isum=0, min=1.00,max=0.00, val;
278 :     int meanc, meano;
279 :     int devc, devo, corr;
280 :    
281 :     width = data->width - 8;
282 :     height = data->height - 8;
283 :     str = data->original.stride[0];
284 :     if(str != data->current.stride[0]) printf("WARNING: Different strides in plugin_ssim original: %d current: %d\n",str,data->current.stride[0]);
285 : Skal 1743 ovr = str - width + (width % ssim->grid);
286 : Skal 1730
287 :     ptr1 = (unsigned char*) data->original.plane[0];
288 :     ptr2 = (unsigned char*) data->current.plane[0];
289 :    
290 :    
291 :    
292 :     /*TODO: Thread*/
293 : Skal 1743 for(i=0;i<height;i+=ssim->grid){
294 : Skal 1730 /*begin of each row*/
295 :     meano = meanc = devc = devo = corr = 0;
296 :     meano = ssim->func8x8(ptr1,str);
297 :     meanc = ssim->func8x8(ptr2,str);
298 : Skal 1743 ssim->consim(ptr1,ptr2,str,meano,meanc,&devo,&devc,&corr);
299 : Skal 1732 emms();
300 :    
301 : Skal 1730 val = calc_ssim(meano,meanc,devo,devc,corr);
302 :     isum += val;
303 :     c++;
304 :     /* for visualisation
305 :     if(ssim->param->b_visualize)
306 :     ssim->errmap[i*width] = (uint8_t) 127*val;
307 :     */
308 :    
309 : Skal 1743
310 : Skal 1730 if(val < min) min = val;
311 :     if(val > max) max = val;
312 : Skal 1743 ptr1+=ssim->grid;
313 :     ptr2+=ssim->grid;
314 : Skal 1730 /*rest of each row*/
315 : Skal 1743 for(j=ssim->grid;j<width;j+=ssim->grid){
316 :     if(ssim->grid == 1){
317 : Skal 1730 meano += ssim->func2x8(ptr1,str);
318 :     meanc += ssim->func2x8(ptr2,str);
319 : Skal 1743 } else {
320 : Skal 1730 meano = ssim->func8x8(ptr1,str);
321 :     meanc = ssim->func8x8(ptr2,str);
322 : Skal 1743 }
323 :     ssim->consim(ptr1,ptr2,str,meano,meanc,&devo,&devc,&corr);
324 : Skal 1732 emms();
325 :    
326 : Skal 1730 val = calc_ssim(meano,meanc,devo,devc,corr);
327 :     isum += val;
328 :     c++;
329 :     /* for visualisation
330 :     if(ssim->param->b_visualize)
331 :     ssim->errmap[i*width +j] = (uint8_t) 255*val;
332 :     */
333 :     if(val < min) min = val;
334 :     if(val > max) max = val;
335 : Skal 1743 ptr1+=ssim->grid;
336 :     ptr2+=ssim->grid;
337 : Skal 1730 }
338 :     ptr1 +=ovr;
339 :     ptr2 +=ovr;
340 :     }
341 :     isum/=c;
342 :     ssim->ssim_sum += isum;
343 :     ssim->frame_cnt++;
344 :    
345 :     if(ssim->param->stat_path != NULL)
346 :     framestat_append(ssim,data->type,data->quant,min,max,isum);
347 :    
348 :     /* for visualization
349 :     if(ssim->param->b_visualize){
350 :     disp_gray(0,ssim->errmap,width,height,width, "Error-Map");
351 :     disp_gray(1,data->original.plane[0],data->width,data->height,data->original.stride[0],"Original");
352 :     disp_gray(2,data->current.plane[0],data->width,data->height,data->original.stride[0],"Compressed");
353 :     disp_sync();
354 :     }
355 :     */
356 :     if(ssim->param->b_printstat){
357 : Skal 1737 printf(" SSIM: avg: %f min: %f max: %f\n",isum,min,max);
358 : Skal 1730 }
359 :    
360 :     }
361 :    
362 :     static int ssim_create(xvid_plg_create_t* create, void** handle){
363 :     ssim_data_t* ssim;
364 :     plg_ssim_param_t* param;
365 :     int cpu_flags;
366 :     param = (plg_ssim_param_t*) malloc(sizeof(plg_ssim_param_t));
367 :     *param = *((plg_ssim_param_t*) create->param);
368 :     ssim = (ssim_data_t*) malloc(sizeof(ssim_data_t));
369 :    
370 :     cpu_flags = check_cpu_features();
371 :    
372 :     ssim->func8x8 = lum_8x8_c;
373 :     ssim->func2x8 = lum_2x8_c;
374 : Skal 1743 ssim->consim = consim_c;
375 : Skal 1730
376 :     ssim->param = param;
377 :    
378 : Skal 1743 ssim->grid = param->acc;
379 :    
380 :     /*gaussian weigthing not implemented*/
381 :     if(ssim->grid == 0) ssim->grid = 1;
382 :     if(ssim->grid > 4) ssim->grid = 4;
383 :    
384 :     printf("Grid: %d\n",ssim->grid);
385 :    
386 : Skal 1732 #if defined(ARCH_IS_IA32)
387 : Skal 1743 if((cpu_flags & XVID_CPU_MMX) && (param->acc > 0)){
388 : Skal 1730 ssim->func8x8 = lum_8x8_mmx;
389 :     ssim->consim = consim_mmx;
390 :     }
391 : Skal 1743 if((cpu_flags & XVID_CPU_SSE2) && (param->acc > 0)){
392 : Skal 1730 ssim->consim = consim_sse2;
393 :     }
394 : Skal 1732 #endif
395 : Skal 1730
396 :     ssim->ssim_sum = 0.0;
397 :     ssim->frame_cnt = 0;
398 :    
399 :     /* for visualization
400 :     if(param->b_visualize){
401 :     //error map
402 :     ssim->errmap = (uint8_t*) malloc(sizeof(uint8_t)*(create->width-8)*(create->height-8));
403 :     } else {
404 :     ssim->errmap = NULL;
405 :     };
406 :     */
407 :    
408 :     /*stats*/
409 :     ssim->head=NULL;
410 :     ssim->tail=NULL;
411 :    
412 :     *(handle) = (void*) ssim;
413 :    
414 :     return 0;
415 :     }
416 :    
417 :     int xvid_plugin_ssim(void * handle, int opt, void * param1, void * param2){
418 :     ssim_data_t* ssim;
419 :     switch(opt){
420 :     case(XVID_PLG_INFO):
421 :     ((xvid_plg_info_t*) param1)->flags = XVID_REQORIGINAL;
422 :     break;
423 :     case(XVID_PLG_CREATE):
424 :     ssim_create((xvid_plg_create_t*) param1,(void**) param2);
425 :     break;
426 :     case(XVID_PLG_BEFORE):
427 :     case(XVID_PLG_FRAME):
428 :     break;
429 :     case(XVID_PLG_AFTER):
430 :     ssim_after((xvid_plg_data_t*) param1, (ssim_data_t*) handle);
431 :     break;
432 :     case(XVID_PLG_DESTROY):
433 :     ssim = (ssim_data_t*) handle;
434 :     printf("Average SSIM: %f\n",ssim->ssim_sum/ssim->frame_cnt);
435 :     if(ssim->param->stat_path != NULL)
436 :     framestat_write(ssim,ssim->param->stat_path);
437 :     framestat_free(ssim->head);
438 : Skal 1737 /*free(ssim->errmap);*/
439 : Skal 1730 free(ssim->param);
440 :     free(ssim);
441 :     break;
442 :     default:
443 :     break;
444 :     }
445 :     return 0;
446 :     };

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