blob: 2e9dfd441bc4d8f004fce9a56840ae5b72928880 [file] [log] [blame]
Jim Bankoski0ce51d82014-10-07 16:36:14 -07001/*
2 * Copyright (c) 2014 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 */
James Zernd36659c2015-12-11 12:40:53 -080010#include <stdlib.h>
11
12#include "./vpx_dsp_rtcd.h"
Jim Bankoski0ce51d82014-10-07 16:36:14 -070013#include "vpx_ports/mem.h"
14
Geza Lore61af8982016-04-11 17:41:58 +010015unsigned int vpx_avg_8x8_c(const uint8_t *src, int stride) {
Jim Bankoski0ce51d82014-10-07 16:36:14 -070016 int i, j;
17 int sum = 0;
Geza Lore61af8982016-04-11 17:41:58 +010018 for (i = 0; i < 8; ++i, src += stride)
19 for (j = 0; j < 8; sum += src[j], ++j) {}
Jim Bankoski0ce51d82014-10-07 16:36:14 -070020
Geza Lore61af8982016-04-11 17:41:58 +010021 return ROUND_POWER_OF_TWO(sum, 6);
Jim Bankoski0ce51d82014-10-07 16:36:14 -070022}
Peter de Rivaz73ae6e42014-10-16 14:36:07 +010023
Geza Lore61af8982016-04-11 17:41:58 +010024unsigned int vpx_avg_4x4_c(const uint8_t *src, int stride) {
Marco8fd3f9a2014-11-12 14:51:49 -080025 int i, j;
26 int sum = 0;
Geza Lore61af8982016-04-11 17:41:58 +010027 for (i = 0; i < 4; ++i, src += stride)
28 for (j = 0; j < 4; sum += src[j], ++j) {}
Marco8fd3f9a2014-11-12 14:51:49 -080029
Geza Lore61af8982016-04-11 17:41:58 +010030 return ROUND_POWER_OF_TWO(sum, 4);
Marco8fd3f9a2014-11-12 14:51:49 -080031}
32
Jingning Han4f52d492015-06-12 10:38:45 -070033// src_diff: first pass, 9 bit, dynamic range [-255, 255]
34// second pass, 12 bit, dynamic range [-2040, 2040]
Jingning Han8c411f72015-03-23 10:02:42 -070035static void hadamard_col8(const int16_t *src_diff, int src_stride,
36 int16_t *coeff) {
37 int16_t b0 = src_diff[0 * src_stride] + src_diff[1 * src_stride];
38 int16_t b1 = src_diff[0 * src_stride] - src_diff[1 * src_stride];
39 int16_t b2 = src_diff[2 * src_stride] + src_diff[3 * src_stride];
40 int16_t b3 = src_diff[2 * src_stride] - src_diff[3 * src_stride];
41 int16_t b4 = src_diff[4 * src_stride] + src_diff[5 * src_stride];
42 int16_t b5 = src_diff[4 * src_stride] - src_diff[5 * src_stride];
43 int16_t b6 = src_diff[6 * src_stride] + src_diff[7 * src_stride];
44 int16_t b7 = src_diff[6 * src_stride] - src_diff[7 * src_stride];
45
46 int16_t c0 = b0 + b2;
47 int16_t c1 = b1 + b3;
48 int16_t c2 = b0 - b2;
49 int16_t c3 = b1 - b3;
50 int16_t c4 = b4 + b6;
51 int16_t c5 = b5 + b7;
52 int16_t c6 = b4 - b6;
53 int16_t c7 = b5 - b7;
54
55 coeff[0] = c0 + c4;
56 coeff[7] = c1 + c5;
57 coeff[3] = c2 + c6;
58 coeff[4] = c3 + c7;
59 coeff[2] = c0 - c4;
60 coeff[6] = c1 - c5;
61 coeff[1] = c2 - c6;
62 coeff[5] = c3 - c7;
63}
64
Johann26faa3e2016-04-14 14:47:16 -070065void vpx_hadamard_8x8_c(const int16_t *src_diff, int src_stride,
Jingning Han8c411f72015-03-23 10:02:42 -070066 int16_t *coeff) {
67 int idx;
68 int16_t buffer[64];
69 int16_t *tmp_buf = &buffer[0];
70 for (idx = 0; idx < 8; ++idx) {
Jingning Han4f52d492015-06-12 10:38:45 -070071 hadamard_col8(src_diff, src_stride, tmp_buf); // src_diff: 9 bit
72 // dynamic range [-255, 255]
Jingning Han8c411f72015-03-23 10:02:42 -070073 tmp_buf += 8;
74 ++src_diff;
75 }
76
77 tmp_buf = &buffer[0];
78 for (idx = 0; idx < 8; ++idx) {
Jingning Han4f52d492015-06-12 10:38:45 -070079 hadamard_col8(tmp_buf, 8, coeff); // tmp_buf: 12 bit
80 // dynamic range [-2040, 2040]
81 coeff += 8; // coeff: 15 bit
82 // dynamic range [-16320, 16320]
Jingning Han8c411f72015-03-23 10:02:42 -070083 ++tmp_buf;
84 }
85}
86
87// In place 16x16 2D Hadamard transform
Johann26faa3e2016-04-14 14:47:16 -070088void vpx_hadamard_16x16_c(const int16_t *src_diff, int src_stride,
Jingning Han26d3d3a2015-03-30 12:31:46 -070089 int16_t *coeff) {
Jingning Han8c411f72015-03-23 10:02:42 -070090 int idx;
Jingning Han26d3d3a2015-03-30 12:31:46 -070091 for (idx = 0; idx < 4; ++idx) {
Jingning Han176c2912015-06-12 10:53:43 -070092 // src_diff: 9 bit, dynamic range [-255, 255]
Johann26faa3e2016-04-14 14:47:16 -070093 const int16_t *src_ptr = src_diff + (idx >> 1) * 8 * src_stride
Jingning Han26d3d3a2015-03-30 12:31:46 -070094 + (idx & 0x01) * 8;
James Zernd36659c2015-12-11 12:40:53 -080095 vpx_hadamard_8x8_c(src_ptr, src_stride, coeff + idx * 64);
Jingning Han26d3d3a2015-03-30 12:31:46 -070096 }
97
Jingning Han176c2912015-06-12 10:53:43 -070098 // coeff: 15 bit, dynamic range [-16320, 16320]
Jingning Han8c411f72015-03-23 10:02:42 -070099 for (idx = 0; idx < 64; ++idx) {
100 int16_t a0 = coeff[0];
101 int16_t a1 = coeff[64];
102 int16_t a2 = coeff[128];
103 int16_t a3 = coeff[192];
104
Jingning Han176c2912015-06-12 10:53:43 -0700105 int16_t b0 = (a0 + a1) >> 1; // (a0 + a1): 16 bit, [-32640, 32640]
106 int16_t b1 = (a0 - a1) >> 1; // b0-b3: 15 bit, dynamic range
107 int16_t b2 = (a2 + a3) >> 1; // [-16320, 16320]
108 int16_t b3 = (a2 - a3) >> 1;
Jingning Han8c411f72015-03-23 10:02:42 -0700109
Jingning Han176c2912015-06-12 10:53:43 -0700110 coeff[0] = b0 + b2; // 16 bit, [-32640, 32640]
111 coeff[64] = b1 + b3;
112 coeff[128] = b0 - b2;
113 coeff[192] = b1 - b3;
Jingning Han8c411f72015-03-23 10:02:42 -0700114
115 ++coeff;
116 }
117}
118
Jingning Han4f1f5102015-06-16 14:35:00 -0700119// coeff: 16 bits, dynamic range [-32640, 32640].
120// length: value range {16, 64, 256, 1024}.
James Zernd36659c2015-12-11 12:40:53 -0800121int vpx_satd_c(const int16_t *coeff, int length) {
Jingning Han8c411f72015-03-23 10:02:42 -0700122 int i;
123 int satd = 0;
124 for (i = 0; i < length; ++i)
125 satd += abs(coeff[i]);
126
Jingning Han4f1f5102015-06-16 14:35:00 -0700127 // satd: 26 bits, dynamic range [-32640 * 1024, 32640 * 1024]
James Zern3e0138e2015-11-18 23:17:27 -0800128 return satd;
Jingning Han8c411f72015-03-23 10:02:42 -0700129}
130
Jingning Haned2dc592015-02-13 11:23:45 -0800131// Integer projection onto row vectors.
Jingning Han922af192015-06-16 14:43:21 -0700132// height: value range {16, 32, 64}.
Johann26faa3e2016-04-14 14:47:16 -0700133void vpx_int_pro_row_c(int16_t hbuf[16], const uint8_t *ref,
Jingning Haned2dc592015-02-13 11:23:45 -0800134 const int ref_stride, const int height) {
135 int idx;
Jingning Han922af192015-06-16 14:43:21 -0700136 const int norm_factor = height >> 1;
Jingning Haned2dc592015-02-13 11:23:45 -0800137 for (idx = 0; idx < 16; ++idx) {
138 int i;
139 hbuf[idx] = 0;
Jingning Han922af192015-06-16 14:43:21 -0700140 // hbuf[idx]: 14 bit, dynamic range [0, 16320].
Jingning Haned2dc592015-02-13 11:23:45 -0800141 for (i = 0; i < height; ++i)
142 hbuf[idx] += ref[i * ref_stride];
Jingning Han922af192015-06-16 14:43:21 -0700143 // hbuf[idx]: 9 bit, dynamic range [0, 510].
Jingning Hana5210082015-03-02 10:28:12 -0800144 hbuf[idx] /= norm_factor;
Jingning Haned2dc592015-02-13 11:23:45 -0800145 ++ref;
146 }
147}
148
Jingning Han8e8bc5f2015-06-16 14:45:58 -0700149// width: value range {16, 32, 64}.
Johann26faa3e2016-04-14 14:47:16 -0700150int16_t vpx_int_pro_col_c(const uint8_t *ref, const int width) {
Jingning Haned2dc592015-02-13 11:23:45 -0800151 int idx;
152 int16_t sum = 0;
Jingning Han8e8bc5f2015-06-16 14:45:58 -0700153 // sum: 14 bit, dynamic range [0, 16320]
Jingning Haned2dc592015-02-13 11:23:45 -0800154 for (idx = 0; idx < width; ++idx)
155 sum += ref[idx];
Jingning Hanc9325842015-03-17 18:50:53 -0700156 return sum;
Jingning Haned2dc592015-02-13 11:23:45 -0800157}
158
Jingning Han36a9a332015-07-31 16:41:51 -0700159// ref: [0 - 510]
160// src: [0 - 510]
161// bwl: {2, 3, 4}
Johann26faa3e2016-04-14 14:47:16 -0700162int vpx_vector_var_c(const int16_t *ref, const int16_t *src,
Jingning Han1790d452015-02-27 13:35:22 -0800163 const int bwl) {
Jingning Haned2dc592015-02-13 11:23:45 -0800164 int i;
Jingning Han1790d452015-02-27 13:35:22 -0800165 int width = 4 << bwl;
166 int sse = 0, mean = 0, var;
167
168 for (i = 0; i < width; ++i) {
Jingning Han36a9a332015-07-31 16:41:51 -0700169 int diff = ref[i] - src[i]; // diff: dynamic range [-510, 510], 10 bits.
170 mean += diff; // mean: dynamic range 16 bits.
171 sse += diff * diff; // sse: dynamic range 26 bits.
Jingning Han1790d452015-02-27 13:35:22 -0800172 }
173
Jingning Han36a9a332015-07-31 16:41:51 -0700174 // (mean * mean): dynamic range 31 bits.
Jingning Han1790d452015-02-27 13:35:22 -0800175 var = sse - ((mean * mean) >> (bwl + 2));
176 return var;
Jingning Haned2dc592015-02-13 11:23:45 -0800177}
178
Geza Lore61af8982016-04-11 17:41:58 +0100179void vpx_minmax_8x8_c(const uint8_t *src, int src_stride,
180 const uint8_t *ref, int ref_stride,
Marco Paniconif76ccce2015-04-15 17:48:20 -0700181 int *min, int *max) {
182 int i, j;
183 *min = 255;
184 *max = 0;
Geza Lore61af8982016-04-11 17:41:58 +0100185 for (i = 0; i < 8; ++i, src += src_stride, ref += ref_stride) {
Marco Paniconif76ccce2015-04-15 17:48:20 -0700186 for (j = 0; j < 8; ++j) {
Geza Lore61af8982016-04-11 17:41:58 +0100187 int diff = abs(src[j]-ref[j]);
Marco Paniconif76ccce2015-04-15 17:48:20 -0700188 *min = diff < *min ? diff : *min;
189 *max = diff > *max ? diff : *max;
190 }
191 }
192}
193
Peter de Rivaz73ae6e42014-10-16 14:36:07 +0100194#if CONFIG_VP9_HIGHBITDEPTH
Geza Lore61af8982016-04-11 17:41:58 +0100195unsigned int vpx_highbd_avg_8x8_c(const uint8_t *src, int stride) {
Peter de Rivaz73ae6e42014-10-16 14:36:07 +0100196 int i, j;
197 int sum = 0;
Geza Lore61af8982016-04-11 17:41:58 +0100198 const uint16_t* s = CONVERT_TO_SHORTPTR(src);
199 for (i = 0; i < 8; ++i, s += stride)
Peter de Rivaz73ae6e42014-10-16 14:36:07 +0100200 for (j = 0; j < 8; sum += s[j], ++j) {}
201
Geza Lore61af8982016-04-11 17:41:58 +0100202 return ROUND_POWER_OF_TWO(sum, 6);
Peter de Rivaz73ae6e42014-10-16 14:36:07 +0100203}
Marco8fd3f9a2014-11-12 14:51:49 -0800204
Geza Lore61af8982016-04-11 17:41:58 +0100205unsigned int vpx_highbd_avg_4x4_c(const uint8_t *src, int stride) {
Marco8fd3f9a2014-11-12 14:51:49 -0800206 int i, j;
207 int sum = 0;
Geza Lore61af8982016-04-11 17:41:58 +0100208 const uint16_t* s = CONVERT_TO_SHORTPTR(src);
209 for (i = 0; i < 4; ++i, s+=stride)
Marco8fd3f9a2014-11-12 14:51:49 -0800210 for (j = 0; j < 4; sum += s[j], ++j) {}
211
Geza Lore61af8982016-04-11 17:41:58 +0100212 return ROUND_POWER_OF_TWO(sum, 4);
Marco8fd3f9a2014-11-12 14:51:49 -0800213}
Marco Paniconif76ccce2015-04-15 17:48:20 -0700214
James Zernd36659c2015-12-11 12:40:53 -0800215void vpx_highbd_minmax_8x8_c(const uint8_t *s8, int p, const uint8_t *d8,
Marco Paniconif76ccce2015-04-15 17:48:20 -0700216 int dp, int *min, int *max) {
217 int i, j;
Marco Paniconif76ccce2015-04-15 17:48:20 -0700218 const uint16_t* s = CONVERT_TO_SHORTPTR(s8);
219 const uint16_t* d = CONVERT_TO_SHORTPTR(d8);
Yaowu Xu305492c2015-04-20 09:50:59 -0700220 *min = 255;
221 *max = 0;
Marco Paniconif76ccce2015-04-15 17:48:20 -0700222 for (i = 0; i < 8; ++i, s += p, d += dp) {
223 for (j = 0; j < 8; ++j) {
224 int diff = abs(s[j]-d[j]);
225 *min = diff < *min ? diff : *min;
226 *max = diff > *max ? diff : *max;
227 }
228 }
229}
Peter de Rivaz73ae6e42014-10-16 14:36:07 +0100230#endif // CONFIG_VP9_HIGHBITDEPTH
231
Marco8fd3f9a2014-11-12 14:51:49 -0800232