Line data Source code
1 : /*
2 : * Copyright (c) 2016, Alliance for Open Media. All rights reserved
3 : *
4 : * This source code is subject to the terms of the BSD 2 Clause License and
5 : * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6 : * was not distributed with this source code in the LICENSE file, you can
7 : * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8 : * Media Patent License 1.0 was not distributed with this source code in the
9 : * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10 : */
11 :
12 : #include "EbDefinitions.h"
13 : #include <assert.h>
14 : #include <math.h>
15 : #include "EbPsnr.h"
16 : #include "EbPictureBufferDesc.h"
17 : #include "aom_dsp_rtcd.h"
18 :
19 0 : double eb_aom_sse_to_psnr(double samples, double peak, double sse) {
20 0 : if (sse > 0.0) {
21 0 : const double psnr = 10.0 * log10(samples * peak * peak / sse);
22 0 : return psnr > MAX_PSNR ? MAX_PSNR : psnr;
23 : }
24 : else
25 0 : return MAX_PSNR;
26 : }
27 :
28 : /* TODO(yaowu): The block_variance calls the unoptimized versions of variance()
29 : * and highbd_8_variance(). It should not.
30 : */
31 9645 : static int32_t encoder_variance(const uint8_t *a, int32_t a_stride, const uint8_t *b,
32 : int32_t b_stride, int32_t w, int32_t h) {
33 : int32_t i, j;
34 9645 : int32_t sse = 0;
35 :
36 74400 : for (i = 0; i < h; i++) {
37 15134400 : for (j = 0; j < w; j++) {
38 15069600 : const int32_t diff = a[j] - b[j];
39 15069600 : sse += diff * diff;
40 : }
41 :
42 64755 : a += a_stride;
43 64755 : b += b_stride;
44 : }
45 9645 : return sse;
46 : }
47 :
48 0 : static int64_t encoder_highbd_variance64(const uint8_t *a8, int32_t a_stride,
49 : const uint8_t *b8, int32_t b_stride, int32_t w, int32_t h) {
50 0 : const uint16_t *a = CONVERT_TO_SHORTPTR(a8);
51 0 : const uint16_t *b = CONVERT_TO_SHORTPTR(b8);
52 0 : int64_t sse = 0;
53 0 : for (int32_t i = 0; i < h; ++i) {
54 0 : for (int32_t j = 0; j < w; ++j) {
55 0 : const int32_t diff = a[j] - b[j];
56 0 : sse += (uint32_t)(diff * diff);
57 : }
58 0 : a += a_stride;
59 0 : b += b_stride;
60 : }
61 0 : return sse;
62 : }
63 :
64 0 : static void encoder_highbd_8_variance(const uint8_t *a8, int32_t a_stride,
65 : const uint8_t *b8, int32_t b_stride, int32_t w,
66 : int32_t h, uint32_t *sse) {
67 0 : *sse = (uint32_t)encoder_highbd_variance64(a8, a_stride, b8, b_stride, w, h);
68 0 : }
69 :
70 0 : static void variance(const uint8_t *a, int32_t a_stride, const uint8_t *b,
71 : int b_stride, int w, int h, uint32_t *sse, int32_t *sum) {
72 : int i, j;
73 :
74 0 : *sum = 0;
75 0 : *sse = 0;
76 :
77 0 : for (i = 0; i < h; ++i) {
78 0 : for (j = 0; j < w; ++j) {
79 0 : const int32_t diff = a[j] - b[j];
80 0 : *sum += diff;
81 0 : *sse += diff * diff;
82 : }
83 :
84 0 : a += a_stride;
85 0 : b += b_stride;
86 : }
87 0 : }
88 :
89 0 : uint32_t eb_aom_mse16x16_c(const uint8_t *src_ptr, int32_t source_stride,
90 : const uint8_t *ref_ptr, int32_t recon_stride, uint32_t *sse){
91 : int32_t sum;
92 0 : variance(src_ptr, source_stride, ref_ptr, recon_stride,16, 16, sse, &sum);
93 0 : return *sse - (uint32_t)(((int64_t)sum * sum) / (16 * 16));
94 : }
95 :
96 9645 : static int64_t get_sse(const uint8_t *a, int32_t a_stride, const uint8_t *b,
97 : int32_t b_stride, int32_t width, int32_t height) {
98 9645 : const int32_t dw = width % 16;
99 9645 : const int32_t dh = height % 16;
100 9645 : int64_t total_sse = 0;
101 9645 : uint32_t sse = 0;
102 : int32_t x, y;
103 :
104 9645 : if (dw > 0) {
105 0 : sse = encoder_variance(&a[width - dw], a_stride, &b[width - dw], b_stride, dw,
106 : height);
107 0 : total_sse += sse;
108 : }
109 :
110 9645 : if (dh > 0) {
111 19290 : sse = encoder_variance(&a[(height - dh) * a_stride], a_stride,
112 9645 : &b[(height - dh) * b_stride], b_stride, width - dw, dh);
113 9645 : total_sse += sse;
114 : }
115 :
116 187722 : for (y = 0; y < height / 16; ++y) {
117 178075 : const uint8_t *pa = a;
118 178075 : const uint8_t *pb = b;
119 2767680 : for (x = 0; x < width / 16; ++x) {
120 2589600 : eb_aom_mse16x16(pa, a_stride, pb, b_stride, &sse);
121 :
122 2589600 : total_sse += sse;
123 :
124 2589600 : pa += 16;
125 2589600 : pb += 16;
126 : }
127 :
128 178077 : a += 16 * a_stride;
129 178077 : b += 16 * b_stride;
130 : }
131 :
132 9647 : return total_sse;
133 : }
134 :
135 0 : static int64_t highbd_get_sse(const uint8_t *a, int32_t a_stride, const uint8_t *b,
136 : int32_t b_stride, int32_t width, int32_t height) {
137 0 : int64_t total_sse = 0;
138 : int32_t x, y;
139 0 : const int32_t dw = width % 16;
140 0 : const int32_t dh = height % 16;
141 0 : uint32_t sse = 0;
142 0 : if (dw > 0) {
143 0 : encoder_highbd_8_variance(&a[width - dw], a_stride, &b[width - dw],
144 : b_stride, dw, height, &sse);
145 0 : total_sse += sse;
146 : }
147 0 : if (dh > 0) {
148 0 : encoder_highbd_8_variance(&a[(height - dh) * a_stride], a_stride,
149 0 : &b[(height - dh) * b_stride], b_stride,
150 : width - dw, dh, &sse);
151 0 : total_sse += sse;
152 : }
153 0 : for (y = 0; y < height / 16; ++y) {
154 0 : const uint8_t *pa = a;
155 0 : const uint8_t *pb = b;
156 0 : for (x = 0; x < width / 16; ++x) {
157 0 : eb_aom_highbd_8_mse16x16(pa, a_stride, pb, b_stride, &sse);
158 :
159 0 : total_sse += sse;
160 0 : pa += 16;
161 0 : pb += 16;
162 : }
163 0 : a += 16 * a_stride;
164 0 : b += 16 * b_stride;
165 : }
166 0 : return total_sse;
167 : }
168 :
169 6544 : int64_t eb_aom_get_y_sse_part(const Yv12BufferConfig *a,
170 : const Yv12BufferConfig *b, int32_t hstart, int32_t width,
171 : int32_t vstart, int32_t height) {
172 13088 : return get_sse(a->y_buffer + vstart * a->y_stride + hstart, a->y_stride,
173 6544 : b->y_buffer + vstart * b->y_stride + hstart, b->y_stride,
174 : width, height);
175 : }
176 :
177 0 : int64_t eb_aom_get_y_sse(const Yv12BufferConfig *a,
178 : const Yv12BufferConfig *b) {
179 0 : assert(a->y_crop_width == b->y_crop_width);
180 0 : assert(a->y_crop_height == b->y_crop_height);
181 :
182 0 : return get_sse(a->y_buffer, a->y_stride, b->y_buffer, b->y_stride,
183 : a->y_crop_width, a->y_crop_height);
184 : }
185 :
186 1555 : int64_t eb_aom_get_u_sse_part(const Yv12BufferConfig *a,
187 : const Yv12BufferConfig *b, int32_t hstart, int32_t width,
188 : int32_t vstart, int32_t height) {
189 3110 : return get_sse(a->u_buffer + vstart * a->uv_stride + hstart, a->uv_stride,
190 1555 : b->u_buffer + vstart * b->uv_stride + hstart, b->uv_stride,
191 : width, height);
192 : }
193 :
194 0 : int64_t eb_aom_get_u_sse(const Yv12BufferConfig *a,
195 : const Yv12BufferConfig *b) {
196 0 : assert(a->uv_crop_width == b->uv_crop_width);
197 0 : assert(a->uv_crop_height == b->uv_crop_height);
198 :
199 0 : return get_sse(a->u_buffer, a->uv_stride, b->u_buffer, b->uv_stride,
200 : a->uv_crop_width, a->uv_crop_height);
201 : }
202 :
203 1546 : int64_t eb_aom_get_v_sse_part(const Yv12BufferConfig *a,
204 : const Yv12BufferConfig *b, int32_t hstart, int32_t width,
205 : int32_t vstart, int32_t height) {
206 3092 : return get_sse(a->v_buffer + vstart * a->uv_stride + hstart, a->uv_stride,
207 1546 : b->v_buffer + vstart * b->uv_stride + hstart, b->uv_stride,
208 : width, height);
209 : }
210 :
211 0 : int64_t eb_aom_get_v_sse(const Yv12BufferConfig *a,
212 : const Yv12BufferConfig *b) {
213 0 : assert(a->uv_crop_width == b->uv_crop_width);
214 0 : assert(a->uv_crop_height == b->uv_crop_height);
215 :
216 0 : return get_sse(a->v_buffer, a->uv_stride, b->v_buffer, b->uv_stride,
217 : a->uv_crop_width, a->uv_crop_height);
218 : }
219 :
220 0 : int64_t eb_aom_highbd_get_y_sse_part(const Yv12BufferConfig *a,
221 : const Yv12BufferConfig *b, int32_t hstart,
222 : int32_t width, int32_t vstart, int32_t height) {
223 0 : return highbd_get_sse(
224 0 : a->y_buffer + vstart * a->y_stride + hstart, a->y_stride,
225 0 : b->y_buffer + vstart * b->y_stride + hstart, b->y_stride, width, height);
226 : }
227 :
228 0 : int64_t eb_aom_highbd_get_y_sse(const Yv12BufferConfig *a,
229 : const Yv12BufferConfig *b) {
230 0 : assert(a->y_crop_width == b->y_crop_width);
231 0 : assert(a->y_crop_height == b->y_crop_height);
232 0 : assert((a->flags & YV12_FLAG_HIGHBITDEPTH) != 0);
233 0 : assert((b->flags & YV12_FLAG_HIGHBITDEPTH) != 0);
234 :
235 0 : return highbd_get_sse(a->y_buffer, a->y_stride, b->y_buffer, b->y_stride,
236 : a->y_crop_width, a->y_crop_height);
237 : }
238 :
239 0 : int64_t eb_aom_highbd_get_u_sse_part(const Yv12BufferConfig *a,
240 : const Yv12BufferConfig *b, int32_t hstart,
241 : int32_t width, int32_t vstart, int32_t height) {
242 0 : return highbd_get_sse(a->u_buffer + vstart * a->uv_stride + hstart,
243 : a->uv_stride,
244 0 : b->u_buffer + vstart * b->uv_stride + hstart,
245 : b->uv_stride, width, height);
246 : }
247 :
248 0 : int64_t eb_aom_highbd_get_u_sse(const Yv12BufferConfig *a,
249 : const Yv12BufferConfig *b) {
250 0 : assert(a->uv_crop_width == b->uv_crop_width);
251 0 : assert(a->uv_crop_height == b->uv_crop_height);
252 0 : assert((a->flags & YV12_FLAG_HIGHBITDEPTH) != 0);
253 0 : assert((b->flags & YV12_FLAG_HIGHBITDEPTH) != 0);
254 :
255 0 : return highbd_get_sse(a->u_buffer, a->uv_stride, b->u_buffer, b->uv_stride,
256 : a->uv_crop_width, a->uv_crop_height);
257 : }
258 :
259 0 : int64_t eb_aom_highbd_get_v_sse_part(const Yv12BufferConfig *a,
260 : const Yv12BufferConfig *b, int32_t hstart,
261 : int32_t width, int32_t vstart, int32_t height) {
262 0 : return highbd_get_sse(a->v_buffer + vstart * a->uv_stride + hstart,
263 : a->uv_stride,
264 0 : b->v_buffer + vstart * b->uv_stride + hstart,
265 : b->uv_stride, width, height);
266 : }
267 :
268 0 : int64_t eb_aom_highbd_get_v_sse(const Yv12BufferConfig *a,
269 : const Yv12BufferConfig *b) {
270 0 : assert(a->uv_crop_width == b->uv_crop_width);
271 0 : assert(a->uv_crop_height == b->uv_crop_height);
272 0 : assert((a->flags & YV12_FLAG_HIGHBITDEPTH) != 0);
273 0 : assert((b->flags & YV12_FLAG_HIGHBITDEPTH) != 0);
274 :
275 0 : return highbd_get_sse(a->v_buffer, a->uv_stride, b->v_buffer, b->uv_stride,
276 : a->uv_crop_width, a->uv_crop_height);
277 : }
|