xref: /aosp_15_r20/external/libaom/aom_dsp/psnr.c (revision 77c1e3ccc04c968bd2bc212e87364f250e820521)
1*77c1e3ccSAndroid Build Coastguard Worker /*
2*77c1e3ccSAndroid Build Coastguard Worker  * Copyright (c) 2016, Alliance for Open Media. All rights reserved.
3*77c1e3ccSAndroid Build Coastguard Worker  *
4*77c1e3ccSAndroid Build Coastguard Worker  * This source code is subject to the terms of the BSD 2 Clause License and
5*77c1e3ccSAndroid Build Coastguard Worker  * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6*77c1e3ccSAndroid Build Coastguard Worker  * was not distributed with this source code in the LICENSE file, you can
7*77c1e3ccSAndroid Build Coastguard Worker  * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8*77c1e3ccSAndroid Build Coastguard Worker  * Media Patent License 1.0 was not distributed with this source code in the
9*77c1e3ccSAndroid Build Coastguard Worker  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10*77c1e3ccSAndroid Build Coastguard Worker  */
11*77c1e3ccSAndroid Build Coastguard Worker 
12*77c1e3ccSAndroid Build Coastguard Worker #include <assert.h>
13*77c1e3ccSAndroid Build Coastguard Worker #include <math.h>
14*77c1e3ccSAndroid Build Coastguard Worker 
15*77c1e3ccSAndroid Build Coastguard Worker #include "config/aom_config.h"
16*77c1e3ccSAndroid Build Coastguard Worker #include "config/aom_dsp_rtcd.h"
17*77c1e3ccSAndroid Build Coastguard Worker 
18*77c1e3ccSAndroid Build Coastguard Worker #include "aom_dsp/psnr.h"
19*77c1e3ccSAndroid Build Coastguard Worker #include "aom_scale/yv12config.h"
20*77c1e3ccSAndroid Build Coastguard Worker 
21*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_INTERNAL_STATS
22*77c1e3ccSAndroid Build Coastguard Worker #define STATIC
23*77c1e3ccSAndroid Build Coastguard Worker #else
24*77c1e3ccSAndroid Build Coastguard Worker #define STATIC static
25*77c1e3ccSAndroid Build Coastguard Worker #endif  // CONFIG_INTERNAL_STATS
26*77c1e3ccSAndroid Build Coastguard Worker 
aom_sse_to_psnr(double samples,double peak,double sse)27*77c1e3ccSAndroid Build Coastguard Worker STATIC double aom_sse_to_psnr(double samples, double peak, double sse) {
28*77c1e3ccSAndroid Build Coastguard Worker   if (sse > 0.0) {
29*77c1e3ccSAndroid Build Coastguard Worker     const double psnr = 10.0 * log10(samples * peak * peak / sse);
30*77c1e3ccSAndroid Build Coastguard Worker     return psnr > MAX_PSNR ? MAX_PSNR : psnr;
31*77c1e3ccSAndroid Build Coastguard Worker   } else {
32*77c1e3ccSAndroid Build Coastguard Worker     return MAX_PSNR;
33*77c1e3ccSAndroid Build Coastguard Worker   }
34*77c1e3ccSAndroid Build Coastguard Worker }
35*77c1e3ccSAndroid Build Coastguard Worker 
36*77c1e3ccSAndroid Build Coastguard Worker #undef STATIC
37*77c1e3ccSAndroid Build Coastguard Worker 
encoder_sse(const uint8_t * a,int a_stride,const uint8_t * b,int b_stride,int w,int h)38*77c1e3ccSAndroid Build Coastguard Worker static int64_t encoder_sse(const uint8_t *a, int a_stride, const uint8_t *b,
39*77c1e3ccSAndroid Build Coastguard Worker                            int b_stride, int w, int h) {
40*77c1e3ccSAndroid Build Coastguard Worker   int i, j;
41*77c1e3ccSAndroid Build Coastguard Worker   int64_t sse = 0;
42*77c1e3ccSAndroid Build Coastguard Worker 
43*77c1e3ccSAndroid Build Coastguard Worker   for (i = 0; i < h; i++) {
44*77c1e3ccSAndroid Build Coastguard Worker     for (j = 0; j < w; j++) {
45*77c1e3ccSAndroid Build Coastguard Worker       const int diff = a[j] - b[j];
46*77c1e3ccSAndroid Build Coastguard Worker       sse += diff * diff;
47*77c1e3ccSAndroid Build Coastguard Worker     }
48*77c1e3ccSAndroid Build Coastguard Worker 
49*77c1e3ccSAndroid Build Coastguard Worker     a += a_stride;
50*77c1e3ccSAndroid Build Coastguard Worker     b += b_stride;
51*77c1e3ccSAndroid Build Coastguard Worker   }
52*77c1e3ccSAndroid Build Coastguard Worker   return sse;
53*77c1e3ccSAndroid Build Coastguard Worker }
54*77c1e3ccSAndroid Build Coastguard Worker 
55*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_AV1_HIGHBITDEPTH
encoder_highbd_sse(const uint8_t * a8,int a_stride,const uint8_t * b8,int b_stride,int w,int h)56*77c1e3ccSAndroid Build Coastguard Worker static int64_t encoder_highbd_sse(const uint8_t *a8, int a_stride,
57*77c1e3ccSAndroid Build Coastguard Worker                                   const uint8_t *b8, int b_stride, int w,
58*77c1e3ccSAndroid Build Coastguard Worker                                   int h) {
59*77c1e3ccSAndroid Build Coastguard Worker   const uint16_t *a = CONVERT_TO_SHORTPTR(a8);
60*77c1e3ccSAndroid Build Coastguard Worker   const uint16_t *b = CONVERT_TO_SHORTPTR(b8);
61*77c1e3ccSAndroid Build Coastguard Worker   int64_t sse = 0;
62*77c1e3ccSAndroid Build Coastguard Worker   for (int i = 0; i < h; ++i) {
63*77c1e3ccSAndroid Build Coastguard Worker     for (int j = 0; j < w; ++j) {
64*77c1e3ccSAndroid Build Coastguard Worker       const int diff = a[j] - b[j];
65*77c1e3ccSAndroid Build Coastguard Worker       sse += diff * diff;
66*77c1e3ccSAndroid Build Coastguard Worker     }
67*77c1e3ccSAndroid Build Coastguard Worker     a += a_stride;
68*77c1e3ccSAndroid Build Coastguard Worker     b += b_stride;
69*77c1e3ccSAndroid Build Coastguard Worker   }
70*77c1e3ccSAndroid Build Coastguard Worker   return sse;
71*77c1e3ccSAndroid Build Coastguard Worker }
72*77c1e3ccSAndroid Build Coastguard Worker 
73*77c1e3ccSAndroid Build Coastguard Worker #endif  // CONFIG_AV1_HIGHBITDEPTH
74*77c1e3ccSAndroid Build Coastguard Worker 
get_sse(const uint8_t * a,int a_stride,const uint8_t * b,int b_stride,int width,int height)75*77c1e3ccSAndroid Build Coastguard Worker static int64_t get_sse(const uint8_t *a, int a_stride, const uint8_t *b,
76*77c1e3ccSAndroid Build Coastguard Worker                        int b_stride, int width, int height) {
77*77c1e3ccSAndroid Build Coastguard Worker   const int dw = width % 16;
78*77c1e3ccSAndroid Build Coastguard Worker   const int dh = height % 16;
79*77c1e3ccSAndroid Build Coastguard Worker   int64_t total_sse = 0;
80*77c1e3ccSAndroid Build Coastguard Worker   int x, y;
81*77c1e3ccSAndroid Build Coastguard Worker 
82*77c1e3ccSAndroid Build Coastguard Worker   if (dw > 0) {
83*77c1e3ccSAndroid Build Coastguard Worker     total_sse += encoder_sse(&a[width - dw], a_stride, &b[width - dw], b_stride,
84*77c1e3ccSAndroid Build Coastguard Worker                              dw, height);
85*77c1e3ccSAndroid Build Coastguard Worker   }
86*77c1e3ccSAndroid Build Coastguard Worker 
87*77c1e3ccSAndroid Build Coastguard Worker   if (dh > 0) {
88*77c1e3ccSAndroid Build Coastguard Worker     total_sse +=
89*77c1e3ccSAndroid Build Coastguard Worker         encoder_sse(&a[(height - dh) * a_stride], a_stride,
90*77c1e3ccSAndroid Build Coastguard Worker                     &b[(height - dh) * b_stride], b_stride, width - dw, dh);
91*77c1e3ccSAndroid Build Coastguard Worker   }
92*77c1e3ccSAndroid Build Coastguard Worker 
93*77c1e3ccSAndroid Build Coastguard Worker   for (y = 0; y < height / 16; ++y) {
94*77c1e3ccSAndroid Build Coastguard Worker     const uint8_t *pa = a;
95*77c1e3ccSAndroid Build Coastguard Worker     const uint8_t *pb = b;
96*77c1e3ccSAndroid Build Coastguard Worker     for (x = 0; x < width / 16; ++x) {
97*77c1e3ccSAndroid Build Coastguard Worker       total_sse += aom_sse(pa, a_stride, pb, b_stride, 16, 16);
98*77c1e3ccSAndroid Build Coastguard Worker 
99*77c1e3ccSAndroid Build Coastguard Worker       pa += 16;
100*77c1e3ccSAndroid Build Coastguard Worker       pb += 16;
101*77c1e3ccSAndroid Build Coastguard Worker     }
102*77c1e3ccSAndroid Build Coastguard Worker 
103*77c1e3ccSAndroid Build Coastguard Worker     a += 16 * a_stride;
104*77c1e3ccSAndroid Build Coastguard Worker     b += 16 * b_stride;
105*77c1e3ccSAndroid Build Coastguard Worker   }
106*77c1e3ccSAndroid Build Coastguard Worker 
107*77c1e3ccSAndroid Build Coastguard Worker   return total_sse;
108*77c1e3ccSAndroid Build Coastguard Worker }
109*77c1e3ccSAndroid Build Coastguard Worker 
110*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_AV1_HIGHBITDEPTH
highbd_get_sse_shift(const uint8_t * a8,int a_stride,const uint8_t * b8,int b_stride,int width,int height,unsigned int input_shift)111*77c1e3ccSAndroid Build Coastguard Worker static int64_t highbd_get_sse_shift(const uint8_t *a8, int a_stride,
112*77c1e3ccSAndroid Build Coastguard Worker                                     const uint8_t *b8, int b_stride, int width,
113*77c1e3ccSAndroid Build Coastguard Worker                                     int height, unsigned int input_shift) {
114*77c1e3ccSAndroid Build Coastguard Worker   const uint16_t *a = CONVERT_TO_SHORTPTR(a8);
115*77c1e3ccSAndroid Build Coastguard Worker   const uint16_t *b = CONVERT_TO_SHORTPTR(b8);
116*77c1e3ccSAndroid Build Coastguard Worker   int64_t total_sse = 0;
117*77c1e3ccSAndroid Build Coastguard Worker   int x, y;
118*77c1e3ccSAndroid Build Coastguard Worker   for (y = 0; y < height; ++y) {
119*77c1e3ccSAndroid Build Coastguard Worker     for (x = 0; x < width; ++x) {
120*77c1e3ccSAndroid Build Coastguard Worker       int64_t diff;
121*77c1e3ccSAndroid Build Coastguard Worker       diff = (a[x] >> input_shift) - (b[x] >> input_shift);
122*77c1e3ccSAndroid Build Coastguard Worker       total_sse += diff * diff;
123*77c1e3ccSAndroid Build Coastguard Worker     }
124*77c1e3ccSAndroid Build Coastguard Worker     a += a_stride;
125*77c1e3ccSAndroid Build Coastguard Worker     b += b_stride;
126*77c1e3ccSAndroid Build Coastguard Worker   }
127*77c1e3ccSAndroid Build Coastguard Worker   return total_sse;
128*77c1e3ccSAndroid Build Coastguard Worker }
129*77c1e3ccSAndroid Build Coastguard Worker 
highbd_get_sse(const uint8_t * a,int a_stride,const uint8_t * b,int b_stride,int width,int height)130*77c1e3ccSAndroid Build Coastguard Worker static int64_t highbd_get_sse(const uint8_t *a, int a_stride, const uint8_t *b,
131*77c1e3ccSAndroid Build Coastguard Worker                               int b_stride, int width, int height) {
132*77c1e3ccSAndroid Build Coastguard Worker   int64_t total_sse = 0;
133*77c1e3ccSAndroid Build Coastguard Worker   int x, y;
134*77c1e3ccSAndroid Build Coastguard Worker   const int dw = width % 16;
135*77c1e3ccSAndroid Build Coastguard Worker   const int dh = height % 16;
136*77c1e3ccSAndroid Build Coastguard Worker 
137*77c1e3ccSAndroid Build Coastguard Worker   if (dw > 0) {
138*77c1e3ccSAndroid Build Coastguard Worker     total_sse += encoder_highbd_sse(&a[width - dw], a_stride, &b[width - dw],
139*77c1e3ccSAndroid Build Coastguard Worker                                     b_stride, dw, height);
140*77c1e3ccSAndroid Build Coastguard Worker   }
141*77c1e3ccSAndroid Build Coastguard Worker   if (dh > 0) {
142*77c1e3ccSAndroid Build Coastguard Worker     total_sse += encoder_highbd_sse(&a[(height - dh) * a_stride], a_stride,
143*77c1e3ccSAndroid Build Coastguard Worker                                     &b[(height - dh) * b_stride], b_stride,
144*77c1e3ccSAndroid Build Coastguard Worker                                     width - dw, dh);
145*77c1e3ccSAndroid Build Coastguard Worker   }
146*77c1e3ccSAndroid Build Coastguard Worker 
147*77c1e3ccSAndroid Build Coastguard Worker   for (y = 0; y < height / 16; ++y) {
148*77c1e3ccSAndroid Build Coastguard Worker     const uint8_t *pa = a;
149*77c1e3ccSAndroid Build Coastguard Worker     const uint8_t *pb = b;
150*77c1e3ccSAndroid Build Coastguard Worker     for (x = 0; x < width / 16; ++x) {
151*77c1e3ccSAndroid Build Coastguard Worker       total_sse += aom_highbd_sse(pa, a_stride, pb, b_stride, 16, 16);
152*77c1e3ccSAndroid Build Coastguard Worker       pa += 16;
153*77c1e3ccSAndroid Build Coastguard Worker       pb += 16;
154*77c1e3ccSAndroid Build Coastguard Worker     }
155*77c1e3ccSAndroid Build Coastguard Worker     a += 16 * a_stride;
156*77c1e3ccSAndroid Build Coastguard Worker     b += 16 * b_stride;
157*77c1e3ccSAndroid Build Coastguard Worker   }
158*77c1e3ccSAndroid Build Coastguard Worker   return total_sse;
159*77c1e3ccSAndroid Build Coastguard Worker }
160*77c1e3ccSAndroid Build Coastguard Worker #endif  // CONFIG_AV1_HIGHBITDEPTH
161*77c1e3ccSAndroid Build Coastguard Worker 
aom_get_y_var(const YV12_BUFFER_CONFIG * a,int hstart,int width,int vstart,int height)162*77c1e3ccSAndroid Build Coastguard Worker uint64_t aom_get_y_var(const YV12_BUFFER_CONFIG *a, int hstart, int width,
163*77c1e3ccSAndroid Build Coastguard Worker                        int vstart, int height) {
164*77c1e3ccSAndroid Build Coastguard Worker   return aom_var_2d_u8(a->y_buffer + vstart * a->y_stride + hstart, a->y_stride,
165*77c1e3ccSAndroid Build Coastguard Worker                        width, height) /
166*77c1e3ccSAndroid Build Coastguard Worker          (width * height);
167*77c1e3ccSAndroid Build Coastguard Worker }
168*77c1e3ccSAndroid Build Coastguard Worker 
aom_get_u_var(const YV12_BUFFER_CONFIG * a,int hstart,int width,int vstart,int height)169*77c1e3ccSAndroid Build Coastguard Worker uint64_t aom_get_u_var(const YV12_BUFFER_CONFIG *a, int hstart, int width,
170*77c1e3ccSAndroid Build Coastguard Worker                        int vstart, int height) {
171*77c1e3ccSAndroid Build Coastguard Worker   return aom_var_2d_u8(a->u_buffer + vstart * a->uv_stride + hstart,
172*77c1e3ccSAndroid Build Coastguard Worker                        a->uv_stride, width, height) /
173*77c1e3ccSAndroid Build Coastguard Worker          (width * height);
174*77c1e3ccSAndroid Build Coastguard Worker }
175*77c1e3ccSAndroid Build Coastguard Worker 
aom_get_v_var(const YV12_BUFFER_CONFIG * a,int hstart,int width,int vstart,int height)176*77c1e3ccSAndroid Build Coastguard Worker uint64_t aom_get_v_var(const YV12_BUFFER_CONFIG *a, int hstart, int width,
177*77c1e3ccSAndroid Build Coastguard Worker                        int vstart, int height) {
178*77c1e3ccSAndroid Build Coastguard Worker   return aom_var_2d_u8(a->v_buffer + vstart * a->uv_stride + hstart,
179*77c1e3ccSAndroid Build Coastguard Worker                        a->uv_stride, width, height) /
180*77c1e3ccSAndroid Build Coastguard Worker          (width * height);
181*77c1e3ccSAndroid Build Coastguard Worker }
182*77c1e3ccSAndroid Build Coastguard Worker 
aom_get_y_sse_part(const YV12_BUFFER_CONFIG * a,const YV12_BUFFER_CONFIG * b,int hstart,int width,int vstart,int height)183*77c1e3ccSAndroid Build Coastguard Worker int64_t aom_get_y_sse_part(const YV12_BUFFER_CONFIG *a,
184*77c1e3ccSAndroid Build Coastguard Worker                            const YV12_BUFFER_CONFIG *b, int hstart, int width,
185*77c1e3ccSAndroid Build Coastguard Worker                            int vstart, int height) {
186*77c1e3ccSAndroid Build Coastguard Worker   return get_sse(a->y_buffer + vstart * a->y_stride + hstart, a->y_stride,
187*77c1e3ccSAndroid Build Coastguard Worker                  b->y_buffer + vstart * b->y_stride + hstart, b->y_stride,
188*77c1e3ccSAndroid Build Coastguard Worker                  width, height);
189*77c1e3ccSAndroid Build Coastguard Worker }
190*77c1e3ccSAndroid Build Coastguard Worker 
aom_get_y_sse(const YV12_BUFFER_CONFIG * a,const YV12_BUFFER_CONFIG * b)191*77c1e3ccSAndroid Build Coastguard Worker int64_t aom_get_y_sse(const YV12_BUFFER_CONFIG *a,
192*77c1e3ccSAndroid Build Coastguard Worker                       const YV12_BUFFER_CONFIG *b) {
193*77c1e3ccSAndroid Build Coastguard Worker   assert(a->y_crop_width == b->y_crop_width);
194*77c1e3ccSAndroid Build Coastguard Worker   assert(a->y_crop_height == b->y_crop_height);
195*77c1e3ccSAndroid Build Coastguard Worker 
196*77c1e3ccSAndroid Build Coastguard Worker   return get_sse(a->y_buffer, a->y_stride, b->y_buffer, b->y_stride,
197*77c1e3ccSAndroid Build Coastguard Worker                  a->y_crop_width, a->y_crop_height);
198*77c1e3ccSAndroid Build Coastguard Worker }
199*77c1e3ccSAndroid Build Coastguard Worker 
aom_get_u_sse_part(const YV12_BUFFER_CONFIG * a,const YV12_BUFFER_CONFIG * b,int hstart,int width,int vstart,int height)200*77c1e3ccSAndroid Build Coastguard Worker int64_t aom_get_u_sse_part(const YV12_BUFFER_CONFIG *a,
201*77c1e3ccSAndroid Build Coastguard Worker                            const YV12_BUFFER_CONFIG *b, int hstart, int width,
202*77c1e3ccSAndroid Build Coastguard Worker                            int vstart, int height) {
203*77c1e3ccSAndroid Build Coastguard Worker   return get_sse(a->u_buffer + vstart * a->uv_stride + hstart, a->uv_stride,
204*77c1e3ccSAndroid Build Coastguard Worker                  b->u_buffer + vstart * b->uv_stride + hstart, b->uv_stride,
205*77c1e3ccSAndroid Build Coastguard Worker                  width, height);
206*77c1e3ccSAndroid Build Coastguard Worker }
207*77c1e3ccSAndroid Build Coastguard Worker 
aom_get_u_sse(const YV12_BUFFER_CONFIG * a,const YV12_BUFFER_CONFIG * b)208*77c1e3ccSAndroid Build Coastguard Worker int64_t aom_get_u_sse(const YV12_BUFFER_CONFIG *a,
209*77c1e3ccSAndroid Build Coastguard Worker                       const YV12_BUFFER_CONFIG *b) {
210*77c1e3ccSAndroid Build Coastguard Worker   assert(a->uv_crop_width == b->uv_crop_width);
211*77c1e3ccSAndroid Build Coastguard Worker   assert(a->uv_crop_height == b->uv_crop_height);
212*77c1e3ccSAndroid Build Coastguard Worker 
213*77c1e3ccSAndroid Build Coastguard Worker   return get_sse(a->u_buffer, a->uv_stride, b->u_buffer, b->uv_stride,
214*77c1e3ccSAndroid Build Coastguard Worker                  a->uv_crop_width, a->uv_crop_height);
215*77c1e3ccSAndroid Build Coastguard Worker }
216*77c1e3ccSAndroid Build Coastguard Worker 
aom_get_v_sse_part(const YV12_BUFFER_CONFIG * a,const YV12_BUFFER_CONFIG * b,int hstart,int width,int vstart,int height)217*77c1e3ccSAndroid Build Coastguard Worker int64_t aom_get_v_sse_part(const YV12_BUFFER_CONFIG *a,
218*77c1e3ccSAndroid Build Coastguard Worker                            const YV12_BUFFER_CONFIG *b, int hstart, int width,
219*77c1e3ccSAndroid Build Coastguard Worker                            int vstart, int height) {
220*77c1e3ccSAndroid Build Coastguard Worker   return get_sse(a->v_buffer + vstart * a->uv_stride + hstart, a->uv_stride,
221*77c1e3ccSAndroid Build Coastguard Worker                  b->v_buffer + vstart * b->uv_stride + hstart, b->uv_stride,
222*77c1e3ccSAndroid Build Coastguard Worker                  width, height);
223*77c1e3ccSAndroid Build Coastguard Worker }
224*77c1e3ccSAndroid Build Coastguard Worker 
aom_get_v_sse(const YV12_BUFFER_CONFIG * a,const YV12_BUFFER_CONFIG * b)225*77c1e3ccSAndroid Build Coastguard Worker int64_t aom_get_v_sse(const YV12_BUFFER_CONFIG *a,
226*77c1e3ccSAndroid Build Coastguard Worker                       const YV12_BUFFER_CONFIG *b) {
227*77c1e3ccSAndroid Build Coastguard Worker   assert(a->uv_crop_width == b->uv_crop_width);
228*77c1e3ccSAndroid Build Coastguard Worker   assert(a->uv_crop_height == b->uv_crop_height);
229*77c1e3ccSAndroid Build Coastguard Worker 
230*77c1e3ccSAndroid Build Coastguard Worker   return get_sse(a->v_buffer, a->uv_stride, b->v_buffer, b->uv_stride,
231*77c1e3ccSAndroid Build Coastguard Worker                  a->uv_crop_width, a->uv_crop_height);
232*77c1e3ccSAndroid Build Coastguard Worker }
233*77c1e3ccSAndroid Build Coastguard Worker 
234*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_AV1_HIGHBITDEPTH
aom_highbd_get_y_var(const YV12_BUFFER_CONFIG * a,int hstart,int width,int vstart,int height)235*77c1e3ccSAndroid Build Coastguard Worker uint64_t aom_highbd_get_y_var(const YV12_BUFFER_CONFIG *a, int hstart,
236*77c1e3ccSAndroid Build Coastguard Worker                               int width, int vstart, int height) {
237*77c1e3ccSAndroid Build Coastguard Worker   return aom_var_2d_u16(a->y_buffer + vstart * a->y_stride + hstart,
238*77c1e3ccSAndroid Build Coastguard Worker                         a->y_stride, width, height) /
239*77c1e3ccSAndroid Build Coastguard Worker          (width * height);
240*77c1e3ccSAndroid Build Coastguard Worker }
241*77c1e3ccSAndroid Build Coastguard Worker 
aom_highbd_get_u_var(const YV12_BUFFER_CONFIG * a,int hstart,int width,int vstart,int height)242*77c1e3ccSAndroid Build Coastguard Worker uint64_t aom_highbd_get_u_var(const YV12_BUFFER_CONFIG *a, int hstart,
243*77c1e3ccSAndroid Build Coastguard Worker                               int width, int vstart, int height) {
244*77c1e3ccSAndroid Build Coastguard Worker   return aom_var_2d_u16(a->u_buffer + vstart * a->uv_stride + hstart,
245*77c1e3ccSAndroid Build Coastguard Worker                         a->uv_stride, width, height) /
246*77c1e3ccSAndroid Build Coastguard Worker          (width * height);
247*77c1e3ccSAndroid Build Coastguard Worker }
248*77c1e3ccSAndroid Build Coastguard Worker 
aom_highbd_get_v_var(const YV12_BUFFER_CONFIG * a,int hstart,int width,int vstart,int height)249*77c1e3ccSAndroid Build Coastguard Worker uint64_t aom_highbd_get_v_var(const YV12_BUFFER_CONFIG *a, int hstart,
250*77c1e3ccSAndroid Build Coastguard Worker                               int width, int vstart, int height) {
251*77c1e3ccSAndroid Build Coastguard Worker   return aom_var_2d_u16(a->v_buffer + vstart * a->uv_stride + hstart,
252*77c1e3ccSAndroid Build Coastguard Worker                         a->uv_stride, width, height) /
253*77c1e3ccSAndroid Build Coastguard Worker          (width * height);
254*77c1e3ccSAndroid Build Coastguard Worker }
255*77c1e3ccSAndroid Build Coastguard Worker 
aom_highbd_get_y_sse_part(const YV12_BUFFER_CONFIG * a,const YV12_BUFFER_CONFIG * b,int hstart,int width,int vstart,int height)256*77c1e3ccSAndroid Build Coastguard Worker int64_t aom_highbd_get_y_sse_part(const YV12_BUFFER_CONFIG *a,
257*77c1e3ccSAndroid Build Coastguard Worker                                   const YV12_BUFFER_CONFIG *b, int hstart,
258*77c1e3ccSAndroid Build Coastguard Worker                                   int width, int vstart, int height) {
259*77c1e3ccSAndroid Build Coastguard Worker   return highbd_get_sse(
260*77c1e3ccSAndroid Build Coastguard Worker       a->y_buffer + vstart * a->y_stride + hstart, a->y_stride,
261*77c1e3ccSAndroid Build Coastguard Worker       b->y_buffer + vstart * b->y_stride + hstart, b->y_stride, width, height);
262*77c1e3ccSAndroid Build Coastguard Worker }
263*77c1e3ccSAndroid Build Coastguard Worker 
aom_highbd_get_y_sse(const YV12_BUFFER_CONFIG * a,const YV12_BUFFER_CONFIG * b)264*77c1e3ccSAndroid Build Coastguard Worker int64_t aom_highbd_get_y_sse(const YV12_BUFFER_CONFIG *a,
265*77c1e3ccSAndroid Build Coastguard Worker                              const YV12_BUFFER_CONFIG *b) {
266*77c1e3ccSAndroid Build Coastguard Worker   assert(a->y_crop_width == b->y_crop_width);
267*77c1e3ccSAndroid Build Coastguard Worker   assert(a->y_crop_height == b->y_crop_height);
268*77c1e3ccSAndroid Build Coastguard Worker   assert((a->flags & YV12_FLAG_HIGHBITDEPTH) != 0);
269*77c1e3ccSAndroid Build Coastguard Worker   assert((b->flags & YV12_FLAG_HIGHBITDEPTH) != 0);
270*77c1e3ccSAndroid Build Coastguard Worker 
271*77c1e3ccSAndroid Build Coastguard Worker   return highbd_get_sse(a->y_buffer, a->y_stride, b->y_buffer, b->y_stride,
272*77c1e3ccSAndroid Build Coastguard Worker                         a->y_crop_width, a->y_crop_height);
273*77c1e3ccSAndroid Build Coastguard Worker }
274*77c1e3ccSAndroid Build Coastguard Worker 
aom_highbd_get_u_sse_part(const YV12_BUFFER_CONFIG * a,const YV12_BUFFER_CONFIG * b,int hstart,int width,int vstart,int height)275*77c1e3ccSAndroid Build Coastguard Worker int64_t aom_highbd_get_u_sse_part(const YV12_BUFFER_CONFIG *a,
276*77c1e3ccSAndroid Build Coastguard Worker                                   const YV12_BUFFER_CONFIG *b, int hstart,
277*77c1e3ccSAndroid Build Coastguard Worker                                   int width, int vstart, int height) {
278*77c1e3ccSAndroid Build Coastguard Worker   return highbd_get_sse(a->u_buffer + vstart * a->uv_stride + hstart,
279*77c1e3ccSAndroid Build Coastguard Worker                         a->uv_stride,
280*77c1e3ccSAndroid Build Coastguard Worker                         b->u_buffer + vstart * b->uv_stride + hstart,
281*77c1e3ccSAndroid Build Coastguard Worker                         b->uv_stride, width, height);
282*77c1e3ccSAndroid Build Coastguard Worker }
283*77c1e3ccSAndroid Build Coastguard Worker 
aom_highbd_get_u_sse(const YV12_BUFFER_CONFIG * a,const YV12_BUFFER_CONFIG * b)284*77c1e3ccSAndroid Build Coastguard Worker int64_t aom_highbd_get_u_sse(const YV12_BUFFER_CONFIG *a,
285*77c1e3ccSAndroid Build Coastguard Worker                              const YV12_BUFFER_CONFIG *b) {
286*77c1e3ccSAndroid Build Coastguard Worker   assert(a->uv_crop_width == b->uv_crop_width);
287*77c1e3ccSAndroid Build Coastguard Worker   assert(a->uv_crop_height == b->uv_crop_height);
288*77c1e3ccSAndroid Build Coastguard Worker   assert((a->flags & YV12_FLAG_HIGHBITDEPTH) != 0);
289*77c1e3ccSAndroid Build Coastguard Worker   assert((b->flags & YV12_FLAG_HIGHBITDEPTH) != 0);
290*77c1e3ccSAndroid Build Coastguard Worker 
291*77c1e3ccSAndroid Build Coastguard Worker   return highbd_get_sse(a->u_buffer, a->uv_stride, b->u_buffer, b->uv_stride,
292*77c1e3ccSAndroid Build Coastguard Worker                         a->uv_crop_width, a->uv_crop_height);
293*77c1e3ccSAndroid Build Coastguard Worker }
294*77c1e3ccSAndroid Build Coastguard Worker 
aom_highbd_get_v_sse_part(const YV12_BUFFER_CONFIG * a,const YV12_BUFFER_CONFIG * b,int hstart,int width,int vstart,int height)295*77c1e3ccSAndroid Build Coastguard Worker int64_t aom_highbd_get_v_sse_part(const YV12_BUFFER_CONFIG *a,
296*77c1e3ccSAndroid Build Coastguard Worker                                   const YV12_BUFFER_CONFIG *b, int hstart,
297*77c1e3ccSAndroid Build Coastguard Worker                                   int width, int vstart, int height) {
298*77c1e3ccSAndroid Build Coastguard Worker   return highbd_get_sse(a->v_buffer + vstart * a->uv_stride + hstart,
299*77c1e3ccSAndroid Build Coastguard Worker                         a->uv_stride,
300*77c1e3ccSAndroid Build Coastguard Worker                         b->v_buffer + vstart * b->uv_stride + hstart,
301*77c1e3ccSAndroid Build Coastguard Worker                         b->uv_stride, width, height);
302*77c1e3ccSAndroid Build Coastguard Worker }
303*77c1e3ccSAndroid Build Coastguard Worker 
aom_highbd_get_v_sse(const YV12_BUFFER_CONFIG * a,const YV12_BUFFER_CONFIG * b)304*77c1e3ccSAndroid Build Coastguard Worker int64_t aom_highbd_get_v_sse(const YV12_BUFFER_CONFIG *a,
305*77c1e3ccSAndroid Build Coastguard Worker                              const YV12_BUFFER_CONFIG *b) {
306*77c1e3ccSAndroid Build Coastguard Worker   assert(a->uv_crop_width == b->uv_crop_width);
307*77c1e3ccSAndroid Build Coastguard Worker   assert(a->uv_crop_height == b->uv_crop_height);
308*77c1e3ccSAndroid Build Coastguard Worker   assert((a->flags & YV12_FLAG_HIGHBITDEPTH) != 0);
309*77c1e3ccSAndroid Build Coastguard Worker   assert((b->flags & YV12_FLAG_HIGHBITDEPTH) != 0);
310*77c1e3ccSAndroid Build Coastguard Worker 
311*77c1e3ccSAndroid Build Coastguard Worker   return highbd_get_sse(a->v_buffer, a->uv_stride, b->v_buffer, b->uv_stride,
312*77c1e3ccSAndroid Build Coastguard Worker                         a->uv_crop_width, a->uv_crop_height);
313*77c1e3ccSAndroid Build Coastguard Worker }
314*77c1e3ccSAndroid Build Coastguard Worker #endif  // CONFIG_AV1_HIGHBITDEPTH
315*77c1e3ccSAndroid Build Coastguard Worker 
aom_get_sse_plane(const YV12_BUFFER_CONFIG * a,const YV12_BUFFER_CONFIG * b,int plane,int highbd)316*77c1e3ccSAndroid Build Coastguard Worker int64_t aom_get_sse_plane(const YV12_BUFFER_CONFIG *a,
317*77c1e3ccSAndroid Build Coastguard Worker                           const YV12_BUFFER_CONFIG *b, int plane, int highbd) {
318*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_AV1_HIGHBITDEPTH
319*77c1e3ccSAndroid Build Coastguard Worker   if (highbd) {
320*77c1e3ccSAndroid Build Coastguard Worker     switch (plane) {
321*77c1e3ccSAndroid Build Coastguard Worker       case 0: return aom_highbd_get_y_sse(a, b);
322*77c1e3ccSAndroid Build Coastguard Worker       case 1: return aom_highbd_get_u_sse(a, b);
323*77c1e3ccSAndroid Build Coastguard Worker       case 2: return aom_highbd_get_v_sse(a, b);
324*77c1e3ccSAndroid Build Coastguard Worker       default: assert(plane >= 0 && plane <= 2); return 0;
325*77c1e3ccSAndroid Build Coastguard Worker     }
326*77c1e3ccSAndroid Build Coastguard Worker   } else {
327*77c1e3ccSAndroid Build Coastguard Worker     switch (plane) {
328*77c1e3ccSAndroid Build Coastguard Worker       case 0: return aom_get_y_sse(a, b);
329*77c1e3ccSAndroid Build Coastguard Worker       case 1: return aom_get_u_sse(a, b);
330*77c1e3ccSAndroid Build Coastguard Worker       case 2: return aom_get_v_sse(a, b);
331*77c1e3ccSAndroid Build Coastguard Worker       default: assert(plane >= 0 && plane <= 2); return 0;
332*77c1e3ccSAndroid Build Coastguard Worker     }
333*77c1e3ccSAndroid Build Coastguard Worker   }
334*77c1e3ccSAndroid Build Coastguard Worker #else
335*77c1e3ccSAndroid Build Coastguard Worker   (void)highbd;
336*77c1e3ccSAndroid Build Coastguard Worker   switch (plane) {
337*77c1e3ccSAndroid Build Coastguard Worker     case 0: return aom_get_y_sse(a, b);
338*77c1e3ccSAndroid Build Coastguard Worker     case 1: return aom_get_u_sse(a, b);
339*77c1e3ccSAndroid Build Coastguard Worker     case 2: return aom_get_v_sse(a, b);
340*77c1e3ccSAndroid Build Coastguard Worker     default: assert(plane >= 0 && plane <= 2); return 0;
341*77c1e3ccSAndroid Build Coastguard Worker   }
342*77c1e3ccSAndroid Build Coastguard Worker #endif
343*77c1e3ccSAndroid Build Coastguard Worker }
344*77c1e3ccSAndroid Build Coastguard Worker 
345*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_AV1_HIGHBITDEPTH
aom_calc_highbd_psnr(const YV12_BUFFER_CONFIG * a,const YV12_BUFFER_CONFIG * b,PSNR_STATS * psnr,uint32_t bit_depth,uint32_t in_bit_depth)346*77c1e3ccSAndroid Build Coastguard Worker void aom_calc_highbd_psnr(const YV12_BUFFER_CONFIG *a,
347*77c1e3ccSAndroid Build Coastguard Worker                           const YV12_BUFFER_CONFIG *b, PSNR_STATS *psnr,
348*77c1e3ccSAndroid Build Coastguard Worker                           uint32_t bit_depth, uint32_t in_bit_depth) {
349*77c1e3ccSAndroid Build Coastguard Worker   assert(a->y_crop_width == b->y_crop_width);
350*77c1e3ccSAndroid Build Coastguard Worker   assert(a->y_crop_height == b->y_crop_height);
351*77c1e3ccSAndroid Build Coastguard Worker   assert(a->uv_crop_width == b->uv_crop_width);
352*77c1e3ccSAndroid Build Coastguard Worker   assert(a->uv_crop_height == b->uv_crop_height);
353*77c1e3ccSAndroid Build Coastguard Worker   const int widths[3] = { a->y_crop_width, a->uv_crop_width, a->uv_crop_width };
354*77c1e3ccSAndroid Build Coastguard Worker   const int heights[3] = { a->y_crop_height, a->uv_crop_height,
355*77c1e3ccSAndroid Build Coastguard Worker                            a->uv_crop_height };
356*77c1e3ccSAndroid Build Coastguard Worker   const int a_strides[3] = { a->y_stride, a->uv_stride, a->uv_stride };
357*77c1e3ccSAndroid Build Coastguard Worker   const int b_strides[3] = { b->y_stride, b->uv_stride, b->uv_stride };
358*77c1e3ccSAndroid Build Coastguard Worker   int i;
359*77c1e3ccSAndroid Build Coastguard Worker   uint64_t total_sse = 0;
360*77c1e3ccSAndroid Build Coastguard Worker   uint32_t total_samples = 0;
361*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_LIBVMAF_PSNR_PEAK
362*77c1e3ccSAndroid Build Coastguard Worker   double peak = (double)(255 << (in_bit_depth - 8));
363*77c1e3ccSAndroid Build Coastguard Worker #else
364*77c1e3ccSAndroid Build Coastguard Worker   double peak = (double)((1 << in_bit_depth) - 1);
365*77c1e3ccSAndroid Build Coastguard Worker #endif  // CONFIG_LIBVMAF_PSNR_PEAK
366*77c1e3ccSAndroid Build Coastguard Worker   const unsigned int input_shift = bit_depth - in_bit_depth;
367*77c1e3ccSAndroid Build Coastguard Worker 
368*77c1e3ccSAndroid Build Coastguard Worker   for (i = 0; i < 3; ++i) {
369*77c1e3ccSAndroid Build Coastguard Worker     const int w = widths[i];
370*77c1e3ccSAndroid Build Coastguard Worker     const int h = heights[i];
371*77c1e3ccSAndroid Build Coastguard Worker     const uint32_t samples = w * h;
372*77c1e3ccSAndroid Build Coastguard Worker     uint64_t sse;
373*77c1e3ccSAndroid Build Coastguard Worker     if (a->flags & YV12_FLAG_HIGHBITDEPTH) {
374*77c1e3ccSAndroid Build Coastguard Worker       if (input_shift) {
375*77c1e3ccSAndroid Build Coastguard Worker         sse = highbd_get_sse_shift(a->buffers[i], a_strides[i], b->buffers[i],
376*77c1e3ccSAndroid Build Coastguard Worker                                    b_strides[i], w, h, input_shift);
377*77c1e3ccSAndroid Build Coastguard Worker       } else {
378*77c1e3ccSAndroid Build Coastguard Worker         sse = highbd_get_sse(a->buffers[i], a_strides[i], b->buffers[i],
379*77c1e3ccSAndroid Build Coastguard Worker                              b_strides[i], w, h);
380*77c1e3ccSAndroid Build Coastguard Worker       }
381*77c1e3ccSAndroid Build Coastguard Worker     } else {
382*77c1e3ccSAndroid Build Coastguard Worker       sse = get_sse(a->buffers[i], a_strides[i], b->buffers[i], b_strides[i], w,
383*77c1e3ccSAndroid Build Coastguard Worker                     h);
384*77c1e3ccSAndroid Build Coastguard Worker     }
385*77c1e3ccSAndroid Build Coastguard Worker     psnr->sse[1 + i] = sse;
386*77c1e3ccSAndroid Build Coastguard Worker     psnr->samples[1 + i] = samples;
387*77c1e3ccSAndroid Build Coastguard Worker     psnr->psnr[1 + i] = aom_sse_to_psnr(samples, peak, (double)sse);
388*77c1e3ccSAndroid Build Coastguard Worker 
389*77c1e3ccSAndroid Build Coastguard Worker     total_sse += sse;
390*77c1e3ccSAndroid Build Coastguard Worker     total_samples += samples;
391*77c1e3ccSAndroid Build Coastguard Worker   }
392*77c1e3ccSAndroid Build Coastguard Worker 
393*77c1e3ccSAndroid Build Coastguard Worker   psnr->sse[0] = total_sse;
394*77c1e3ccSAndroid Build Coastguard Worker   psnr->samples[0] = total_samples;
395*77c1e3ccSAndroid Build Coastguard Worker   psnr->psnr[0] =
396*77c1e3ccSAndroid Build Coastguard Worker       aom_sse_to_psnr((double)total_samples, peak, (double)total_sse);
397*77c1e3ccSAndroid Build Coastguard Worker 
398*77c1e3ccSAndroid Build Coastguard Worker   // Compute PSNR based on stream bit depth
399*77c1e3ccSAndroid Build Coastguard Worker   if ((a->flags & YV12_FLAG_HIGHBITDEPTH) && (in_bit_depth < bit_depth)) {
400*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_LIBVMAF_PSNR_PEAK
401*77c1e3ccSAndroid Build Coastguard Worker     peak = (double)(255 << (bit_depth - 8));
402*77c1e3ccSAndroid Build Coastguard Worker #else
403*77c1e3ccSAndroid Build Coastguard Worker     peak = (double)((1 << bit_depth) - 1);
404*77c1e3ccSAndroid Build Coastguard Worker #endif  // CONFIG_LIBVMAF_PSNR_PEAK
405*77c1e3ccSAndroid Build Coastguard Worker     total_sse = 0;
406*77c1e3ccSAndroid Build Coastguard Worker     total_samples = 0;
407*77c1e3ccSAndroid Build Coastguard Worker     for (i = 0; i < 3; ++i) {
408*77c1e3ccSAndroid Build Coastguard Worker       const int w = widths[i];
409*77c1e3ccSAndroid Build Coastguard Worker       const int h = heights[i];
410*77c1e3ccSAndroid Build Coastguard Worker       const uint32_t samples = w * h;
411*77c1e3ccSAndroid Build Coastguard Worker       uint64_t sse;
412*77c1e3ccSAndroid Build Coastguard Worker       sse = highbd_get_sse(a->buffers[i], a_strides[i], b->buffers[i],
413*77c1e3ccSAndroid Build Coastguard Worker                            b_strides[i], w, h);
414*77c1e3ccSAndroid Build Coastguard Worker       psnr->sse_hbd[1 + i] = sse;
415*77c1e3ccSAndroid Build Coastguard Worker       psnr->samples_hbd[1 + i] = samples;
416*77c1e3ccSAndroid Build Coastguard Worker       psnr->psnr_hbd[1 + i] = aom_sse_to_psnr(samples, peak, (double)sse);
417*77c1e3ccSAndroid Build Coastguard Worker       total_sse += sse;
418*77c1e3ccSAndroid Build Coastguard Worker       total_samples += samples;
419*77c1e3ccSAndroid Build Coastguard Worker     }
420*77c1e3ccSAndroid Build Coastguard Worker 
421*77c1e3ccSAndroid Build Coastguard Worker     psnr->sse_hbd[0] = total_sse;
422*77c1e3ccSAndroid Build Coastguard Worker     psnr->samples_hbd[0] = total_samples;
423*77c1e3ccSAndroid Build Coastguard Worker     psnr->psnr_hbd[0] =
424*77c1e3ccSAndroid Build Coastguard Worker         aom_sse_to_psnr((double)total_samples, peak, (double)total_sse);
425*77c1e3ccSAndroid Build Coastguard Worker   }
426*77c1e3ccSAndroid Build Coastguard Worker }
427*77c1e3ccSAndroid Build Coastguard Worker #endif
428*77c1e3ccSAndroid Build Coastguard Worker 
aom_calc_psnr(const YV12_BUFFER_CONFIG * a,const YV12_BUFFER_CONFIG * b,PSNR_STATS * psnr)429*77c1e3ccSAndroid Build Coastguard Worker void aom_calc_psnr(const YV12_BUFFER_CONFIG *a, const YV12_BUFFER_CONFIG *b,
430*77c1e3ccSAndroid Build Coastguard Worker                    PSNR_STATS *psnr) {
431*77c1e3ccSAndroid Build Coastguard Worker   assert(a->y_crop_width == b->y_crop_width);
432*77c1e3ccSAndroid Build Coastguard Worker   assert(a->y_crop_height == b->y_crop_height);
433*77c1e3ccSAndroid Build Coastguard Worker   assert(a->uv_crop_width == b->uv_crop_width);
434*77c1e3ccSAndroid Build Coastguard Worker   assert(a->uv_crop_height == b->uv_crop_height);
435*77c1e3ccSAndroid Build Coastguard Worker   static const double peak = 255.0;
436*77c1e3ccSAndroid Build Coastguard Worker   const int widths[3] = { a->y_crop_width, a->uv_crop_width, a->uv_crop_width };
437*77c1e3ccSAndroid Build Coastguard Worker   const int heights[3] = { a->y_crop_height, a->uv_crop_height,
438*77c1e3ccSAndroid Build Coastguard Worker                            a->uv_crop_height };
439*77c1e3ccSAndroid Build Coastguard Worker   const int a_strides[3] = { a->y_stride, a->uv_stride, a->uv_stride };
440*77c1e3ccSAndroid Build Coastguard Worker   const int b_strides[3] = { b->y_stride, b->uv_stride, b->uv_stride };
441*77c1e3ccSAndroid Build Coastguard Worker   int i;
442*77c1e3ccSAndroid Build Coastguard Worker   uint64_t total_sse = 0;
443*77c1e3ccSAndroid Build Coastguard Worker   uint32_t total_samples = 0;
444*77c1e3ccSAndroid Build Coastguard Worker 
445*77c1e3ccSAndroid Build Coastguard Worker   for (i = 0; i < 3; ++i) {
446*77c1e3ccSAndroid Build Coastguard Worker     const int w = widths[i];
447*77c1e3ccSAndroid Build Coastguard Worker     const int h = heights[i];
448*77c1e3ccSAndroid Build Coastguard Worker     const uint32_t samples = w * h;
449*77c1e3ccSAndroid Build Coastguard Worker     const uint64_t sse =
450*77c1e3ccSAndroid Build Coastguard Worker         get_sse(a->buffers[i], a_strides[i], b->buffers[i], b_strides[i], w, h);
451*77c1e3ccSAndroid Build Coastguard Worker     psnr->sse[1 + i] = sse;
452*77c1e3ccSAndroid Build Coastguard Worker     psnr->samples[1 + i] = samples;
453*77c1e3ccSAndroid Build Coastguard Worker     psnr->psnr[1 + i] = aom_sse_to_psnr(samples, peak, (double)sse);
454*77c1e3ccSAndroid Build Coastguard Worker 
455*77c1e3ccSAndroid Build Coastguard Worker     total_sse += sse;
456*77c1e3ccSAndroid Build Coastguard Worker     total_samples += samples;
457*77c1e3ccSAndroid Build Coastguard Worker   }
458*77c1e3ccSAndroid Build Coastguard Worker 
459*77c1e3ccSAndroid Build Coastguard Worker   psnr->sse[0] = total_sse;
460*77c1e3ccSAndroid Build Coastguard Worker   psnr->samples[0] = total_samples;
461*77c1e3ccSAndroid Build Coastguard Worker   psnr->psnr[0] =
462*77c1e3ccSAndroid Build Coastguard Worker       aom_sse_to_psnr((double)total_samples, peak, (double)total_sse);
463*77c1e3ccSAndroid Build Coastguard Worker }
464