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" |
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 |
struct framestat_t{ |
struct framestat_t{ |
47 |
int type; |
int type; |
48 |
int quant; |
int quant; |
68 |
uint8_t* errmap; |
uint8_t* errmap; |
69 |
*/ |
*/ |
70 |
|
|
71 |
|
int grid; |
72 |
|
|
73 |
/*for average SSIM*/ |
/*for average SSIM*/ |
74 |
float ssim_sum; |
float ssim_sum; |
75 |
int frame_cnt; |
int frame_cnt; |
115 |
|
|
116 |
/*writeout the collected stats*/ |
/*writeout the collected stats*/ |
117 |
void framestat_write(ssim_data_t* ssim, char* path){ |
void framestat_write(ssim_data_t* ssim, char* path){ |
118 |
|
framestat_t* tmp = ssim->head; |
119 |
FILE* out = fopen(path,"w"); |
FILE* out = fopen(path,"w"); |
120 |
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; |
|
121 |
|
|
122 |
fprintf(out,"SSIM Error Metric\n"); |
fprintf(out,"SSIM Error Metric\n"); |
123 |
fprintf(out,"quant avg min max"); |
fprintf(out,"quant avg min max\n"); |
124 |
while(tmp->next->next != NULL){ |
while(tmp->next->next != NULL){ |
125 |
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); |
126 |
tmp = tmp->next; |
tmp = tmp->next; |
127 |
} |
} |
128 |
fclose(out); |
fclose(out); |
130 |
|
|
131 |
/*writeout the collected stats in octave readable format*/ |
/*writeout the collected stats in octave readable format*/ |
132 |
void framestat_write_oct(ssim_data_t* ssim, char* path){ |
void framestat_write_oct(ssim_data_t* ssim, char* path){ |
133 |
|
framestat_t* tmp; |
134 |
FILE* out = fopen(path,"w"); |
FILE* out = fopen(path,"w"); |
135 |
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; |
|
136 |
|
|
137 |
fprintf(out,"quant = ["); |
fprintf(out,"quant = ["); |
138 |
tmp = ssim->head; |
tmp = ssim->head; |
227 |
return mean; |
return mean; |
228 |
} |
} |
229 |
|
|
230 |
|
int lum_8x8_gaussian(uint8_t* ptr, int stride){ |
231 |
|
float mean=0,sum; |
232 |
|
int i,j; |
233 |
|
for(i=0;i<8;i++){ |
234 |
|
sum = 0; |
235 |
|
for(j=0;j<8;j++) |
236 |
|
sum += ptr[i*stride + j]*mask8[j]; |
237 |
|
|
238 |
|
sum *=mask8[i]; |
239 |
|
mean += sum; |
240 |
|
} |
241 |
|
return (int) mean + 0.5; |
242 |
|
} |
243 |
|
|
244 |
/*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*/ |
245 |
int lum_2x8_c(uint8_t* ptr, int stride){ |
int lum_2x8_c(uint8_t* ptr, int stride){ |
246 |
int mean=0,i; |
int mean=0,i; |
254 |
} |
} |
255 |
|
|
256 |
/*calculate contrast and correlation of the two blocks*/ |
/*calculate contrast and correlation of the two blocks*/ |
257 |
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){ |
258 |
int valo, valc, devo =0, devc=0, corr=0; |
unsigned int valo, valc,i,j,str; |
259 |
int i,j; |
float devo=0, devc=0, corr=0,sumo,sumc,sumcorr; |
260 |
|
str = stride - 8; |
261 |
for(i=0;i< 8;i++){ |
for(i=0;i< 8;i++){ |
262 |
|
sumo = 0; |
263 |
|
sumc = 0; |
264 |
|
sumcorr = 0; |
265 |
for(j=0;j< 8;j++){ |
for(j=0;j< 8;j++){ |
266 |
valo = *ptro - lumo; |
valo = *ptro; |
267 |
valc = *ptrc - lumc; |
valc = *ptrc; |
268 |
devo += valo*valo; |
sumo += valo*valo*mask8[j]; |
269 |
|
sumc += valc*valc*mask8[j]; |
270 |
|
sumcorr += valo*valc*mask8[j]; |
271 |
ptro++; |
ptro++; |
|
devc += valc*valc; |
|
272 |
ptrc++; |
ptrc++; |
273 |
|
} |
274 |
|
|
275 |
|
devo += sumo*mask8[i]; |
276 |
|
devc += sumc*mask8[i]; |
277 |
|
corr += sumcorr*mask8[i]; |
278 |
|
ptro += str; |
279 |
|
ptrc += str; |
280 |
|
} |
281 |
|
|
282 |
|
*pdevo = (int) (devo - ((lumo*lumo + 32) >> 6)) + 0.5; |
283 |
|
*pdevc = (int) (devc - ((lumc*lumc + 32) >> 6)) + 0.5; |
284 |
|
*pcorr = (int) (corr - ((lumo*lumc + 32) >> 6)) + 0.5; |
285 |
|
}; |
286 |
|
|
287 |
|
/*calculate contrast and correlation of the two blocks*/ |
288 |
|
void consim_c(uint8_t* ptro, uint8_t* ptrc, int stride, int lumo, int lumc, int* pdevo, int* pdevc, int* pcorr){ |
289 |
|
unsigned int valo, valc, devo=0, devc=0, corr=0,i,j,str; |
290 |
|
str = stride - 8; |
291 |
|
for(i=0;i< 8;i++){ |
292 |
|
for(j=0;j< 8;j++){ |
293 |
|
valo = *ptro; |
294 |
|
valc = *ptrc; |
295 |
|
devo += valo*valo; |
296 |
|
devc += valc*valc; |
297 |
corr += valo*valc; |
corr += valo*valc; |
298 |
|
ptro++; |
299 |
|
ptrc++; |
300 |
} |
} |
301 |
ptro += stride -8; |
ptro += str; |
302 |
ptrc += stride -8; |
ptrc += str; |
303 |
} |
} |
304 |
*pdevo = devo; |
|
305 |
*pdevc = devc; |
*pdevo = devo - ((lumo*lumo + 32) >> 6); |
306 |
*pcorr = corr; |
*pdevc = devc - ((lumc*lumc + 32) >> 6); |
307 |
|
*pcorr = corr - ((lumo*lumc + 32) >> 6); |
308 |
}; |
}; |
309 |
|
|
310 |
/*calculate the final ssim value*/ |
/*calculate the final ssim value*/ |
311 |
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){ |
312 |
static const float c1 = (0.01*255)*(0.01*255); |
static const float c1 = (0.01*255)*(0.01*255); |
313 |
static const float c2 = (0.03*255)*(0.03*255); |
static const float c2 = (0.03*255)*(0.03*255); |
314 |
float fmeano,fmeanc,fdevo,fdevc,fcorr; |
/*printf("meano: %f meanc: %f devo: %f devc: %f corr: %f\n",meano,meanc,devo,devc,corr);*/ |
315 |
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)); |
|
316 |
} |
} |
317 |
|
|
318 |
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){ |
319 |
int i,j,c=0; |
int i,j,c=0,opt; |
320 |
int width,height,str,ovr; |
int width,height,str,ovr; |
321 |
unsigned char * ptr1,*ptr2; |
unsigned char * ptr1,*ptr2; |
322 |
float isum=0, min=1.00,max=0.00, val; |
float isum=0, min=1.00,max=0.00, val; |
323 |
int meanc, meano; |
int meanc, meano; |
324 |
int devc, devo, corr; |
int devc, devo, corr; |
325 |
|
|
|
#define GRID 1 |
|
|
|
|
326 |
width = data->width - 8; |
width = data->width - 8; |
327 |
height = data->height - 8; |
height = data->height - 8; |
328 |
str = data->original.stride[0]; |
str = data->original.stride[0]; |
329 |
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]); |
330 |
ovr = str - width + (width % GRID); |
ovr = str - width + (width % ssim->grid); |
331 |
|
|
332 |
ptr1 = (unsigned char*) data->original.plane[0]; |
ptr1 = (unsigned char*) data->original.plane[0]; |
333 |
ptr2 = (unsigned char*) data->current.plane[0]; |
ptr2 = (unsigned char*) data->current.plane[0]; |
334 |
|
|
335 |
|
opt = ssim->grid == 1 && ssim->param->acc != 0; |
336 |
|
|
337 |
/*TODO: Thread*/ |
/*TODO: Thread*/ |
338 |
for(i=0;i<height;i+=GRID){ |
for(i=0;i<height;i+=ssim->grid){ |
339 |
/*begin of each row*/ |
/*begin of each row*/ |
340 |
meano = meanc = devc = devo = corr = 0; |
meano = meanc = devc = devo = corr = 0; |
341 |
meano = ssim->func8x8(ptr1,str); |
meano = ssim->func8x8(ptr1,str); |
342 |
meanc = ssim->func8x8(ptr2,str); |
meanc = ssim->func8x8(ptr2,str); |
343 |
ssim->consim(ptr1,ptr2,str,meano>>6,meanc>>6,&devo,&devc,&corr); |
ssim->consim(ptr1,ptr2,str,meano,meanc,&devo,&devc,&corr); |
344 |
emms(); |
emms(); |
345 |
|
|
346 |
val = calc_ssim(meano,meanc,devo,devc,corr); |
val = calc_ssim((float) meano,(float) meanc,(float) devo,(float) devc,(float) corr); |
347 |
isum += val; |
isum += val; |
348 |
c++; |
c++; |
349 |
/* for visualisation |
/* for visualisation |
351 |
ssim->errmap[i*width] = (uint8_t) 127*val; |
ssim->errmap[i*width] = (uint8_t) 127*val; |
352 |
*/ |
*/ |
353 |
|
|
354 |
|
|
355 |
if(val < min) min = val; |
if(val < min) min = val; |
356 |
if(val > max) max = val; |
if(val > max) max = val; |
357 |
ptr1+=GRID; |
ptr1+=ssim->grid; |
358 |
ptr2+=GRID; |
ptr2+=ssim->grid; |
359 |
/*rest of each row*/ |
/*rest of each row*/ |
360 |
for(j=1;j<width;j+=GRID){ |
for(j=ssim->grid;j<width;j+=ssim->grid){ |
361 |
/* for grid = 1 use |
if(opt){ |
362 |
meano += ssim->func2x8(ptr1,str); |
meano += ssim->func2x8(ptr1,str); |
363 |
meanc += ssim->func2x8(ptr2,str); |
meanc += ssim->func2x8(ptr2,str); |
364 |
*/ |
} else { |
365 |
meano = ssim->func8x8(ptr1,str); |
meano = ssim->func8x8(ptr1,str); |
366 |
meanc = ssim->func8x8(ptr2,str); |
meanc = ssim->func8x8(ptr2,str); |
367 |
ssim->consim(ptr1,ptr2,str,meano>>6,meanc>>6,&devo,&devc,&corr); |
} |
368 |
|
ssim->consim(ptr1,ptr2,str,meano,meanc,&devo,&devc,&corr); |
369 |
emms(); |
emms(); |
370 |
|
|
371 |
val = calc_ssim(meano,meanc,devo,devc,corr); |
val = calc_ssim((float) meano,(float) meanc,(float) devo,(float) devc,(float) corr); |
372 |
isum += val; |
isum += val; |
373 |
c++; |
c++; |
374 |
/* for visualisation |
/* for visualisation |
377 |
*/ |
*/ |
378 |
if(val < min) min = val; |
if(val < min) min = val; |
379 |
if(val > max) max = val; |
if(val > max) max = val; |
380 |
ptr1+=GRID; |
ptr1+=ssim->grid; |
381 |
ptr2+=GRID; |
ptr2+=ssim->grid; |
382 |
} |
} |
383 |
ptr1 +=ovr; |
ptr1 +=ovr; |
384 |
ptr2 +=ovr; |
ptr2 +=ovr; |
399 |
} |
} |
400 |
*/ |
*/ |
401 |
if(ssim->param->b_printstat){ |
if(ssim->param->b_printstat){ |
402 |
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); |
403 |
} |
} |
404 |
|
|
405 |
} |
} |
416 |
|
|
417 |
ssim->func8x8 = lum_8x8_c; |
ssim->func8x8 = lum_8x8_c; |
418 |
ssim->func2x8 = lum_2x8_c; |
ssim->func2x8 = lum_2x8_c; |
419 |
ssim->consim = iconsim_c; |
ssim->consim = consim_c; |
420 |
|
|
421 |
ssim->param = param; |
ssim->param = param; |
422 |
|
|
423 |
|
ssim->grid = param->acc; |
424 |
|
|
425 |
#if defined(ARCH_IS_IA32) |
#if defined(ARCH_IS_IA32) |
426 |
if(cpu_flags & XVID_CPU_MMX){ |
if((cpu_flags & XVID_CPU_MMX) && (param->acc > 0)){ |
427 |
ssim->func8x8 = lum_8x8_mmx; |
ssim->func8x8 = lum_8x8_mmx; |
428 |
ssim->consim = consim_mmx; |
ssim->consim = consim_mmx; |
429 |
} |
} |
430 |
if(cpu_flags & XVID_CPU_SSE2){ |
if((cpu_flags & XVID_CPU_SSE2) && (param->acc > 0)){ |
431 |
ssim->consim = consim_sse2; |
ssim->consim = consim_sse2; |
432 |
} |
} |
433 |
#endif |
#endif |
434 |
|
|
435 |
|
/*gaussian weigthing not implemented*/ |
436 |
|
if(ssim->grid == 0){ |
437 |
|
ssim->grid = 1; |
438 |
|
ssim->func8x8 = lum_8x8_gaussian; |
439 |
|
ssim->func2x8 = NULL; |
440 |
|
ssim->consim = consim_gaussian; |
441 |
|
} |
442 |
|
if(ssim->grid > 4) ssim->grid = 4; |
443 |
|
|
444 |
ssim->ssim_sum = 0.0; |
ssim->ssim_sum = 0.0; |
445 |
ssim->frame_cnt = 0; |
ssim->frame_cnt = 0; |
446 |
|
|
483 |
if(ssim->param->stat_path != NULL) |
if(ssim->param->stat_path != NULL) |
484 |
framestat_write(ssim,ssim->param->stat_path); |
framestat_write(ssim,ssim->param->stat_path); |
485 |
framestat_free(ssim->head); |
framestat_free(ssim->head); |
486 |
//free(ssim->errmap); |
/*free(ssim->errmap);*/ |
487 |
free(ssim->param); |
free(ssim->param); |
488 |
free(ssim); |
free(ssim); |
489 |
break; |
break; |