Home | History | Annotate | Download | only in encoder
      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