1 /* 2 * Copyright (c) 2010 The WebM project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 12 #include "vpx_scale/yv12config.h" 13 #include "math.h" 14 #include "systemdependent.h" /* for vp8_clear_system_state() */ 15 16 #define MAX_PSNR 60 17 18 double vp8_mse2psnr(double Samples, double Peak, double Mse) 19 { 20 double psnr; 21 22 if ((double)Mse > 0.0) 23 psnr = 10.0 * log10(Peak * Peak * Samples / Mse); 24 else 25 psnr = MAX_PSNR; // Limit to prevent / 0 26 27 if (psnr > MAX_PSNR) 28 psnr = MAX_PSNR; 29 30 return psnr; 31 } 32 33 double vp8_calc_psnr(YV12_BUFFER_CONFIG *source, YV12_BUFFER_CONFIG *dest, double *YPsnr, double *UPsnr, double *VPsnr, double *sq_error) 34 { 35 int i, j; 36 int Diff; 37 double frame_psnr; 38 double Total; 39 double grand_total; 40 unsigned char *src = source->y_buffer; 41 unsigned char *dst = dest->y_buffer; 42 43 Total = 0.0; 44 grand_total = 0.0; 45 46 // Loop throught the Y plane raw and reconstruction data summing (square differences) 47 for (i = 0; i < source->y_height; i++) 48 { 49 50 for (j = 0; j < source->y_width; j++) 51 { 52 Diff = (int)(src[j]) - (int)(dst[j]); 53 Total += Diff * Diff; 54 } 55 56 src += source->y_stride; 57 dst += dest->y_stride; 58 } 59 60 // Work out Y PSNR 61 *YPsnr = vp8_mse2psnr(source->y_height * source->y_width, 255.0, Total); 62 grand_total += Total; 63 Total = 0; 64 65 66 // Loop through the U plane 67 src = source->u_buffer; 68 dst = dest->u_buffer; 69 70 for (i = 0; i < source->uv_height; i++) 71 { 72 73 for (j = 0; j < source->uv_width; j++) 74 { 75 Diff = (int)(src[j]) - (int)(dst[j]); 76 Total += Diff * Diff; 77 } 78 79 src += source->uv_stride; 80 dst += dest->uv_stride; 81 } 82 83 // Work out U PSNR 84 *UPsnr = vp8_mse2psnr(source->uv_height * source->uv_width, 255.0, Total); 85 grand_total += Total; 86 Total = 0; 87 88 89 // V PSNR 90 src = source->v_buffer; 91 dst = dest->v_buffer; 92 93 for (i = 0; i < source->uv_height; i++) 94 { 95 96 for (j = 0; j < source->uv_width; j++) 97 { 98 Diff = (int)(src[j]) - (int)(dst[j]); 99 Total += Diff * Diff; 100 } 101 102 src += source->uv_stride; 103 dst += dest->uv_stride; 104 } 105 106 // Work out UV PSNR 107 *VPsnr = vp8_mse2psnr(source->uv_height * source->uv_width, 255.0, Total); 108 grand_total += Total; 109 Total = 0; 110 111 // Work out total PSNR 112 frame_psnr = vp8_mse2psnr(source->y_height * source->y_width * 3 / 2 , 255.0, grand_total); 113 114 *sq_error = 1.0 * grand_total; 115 116 return frame_psnr; 117 } 118