blob: f7c1778d61c3d220cfa72dcb1965d18576ed08b8 [file] [log] [blame]
Johannea5139b2018-06-27 10:14:14 -07001/*
James Zernb7c05bd2024-06-11 19:15:10 -07002 * Copyright (c) 2018, Alliance for Open Media. All rights reserved.
Johannea5139b2018-06-27 10:14:14 -07003 *
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
Yue Chen2dbdbc92018-05-24 09:54:01 -070012#include <assert.h>
13#include <stdlib.h>
14#include <math.h>
15
16#include "config/av1_rtcd.h"
17#include "av1/encoder/dwt.h"
18
19// Note: block length must be even for this implementation
20static void analysis_53_row(int length, tran_low_t *x, tran_low_t *lowpass,
21 tran_low_t *highpass) {
22 int n;
23 tran_low_t r, *a, *b;
24
25 n = length >> 1;
26 b = highpass;
27 a = lowpass;
28 while (--n) {
Yaowu Xu63256262018-06-22 07:52:34 -070029 *a++ = (r = *x++) * 2;
Yue Chen2dbdbc92018-05-24 09:54:01 -070030 *b++ = *x - ((r + x[1] + 1) >> 1);
31 x++;
32 }
Yaowu Xu63256262018-06-22 07:52:34 -070033 *a = (r = *x++) * 2;
Yue Chen2dbdbc92018-05-24 09:54:01 -070034 *b = *x - r;
35
36 n = length >> 1;
37 b = highpass;
38 a = lowpass;
39 r = *highpass;
40 while (n--) {
41 *a++ += (r + (*b) + 1) >> 1;
42 r = *b++;
43 }
44}
45
46static void analysis_53_col(int length, tran_low_t *x, tran_low_t *lowpass,
47 tran_low_t *highpass) {
48 int n;
49 tran_low_t r, *a, *b;
50
51 n = length >> 1;
52 b = highpass;
53 a = lowpass;
54 while (--n) {
55 *a++ = (r = *x++);
Yaowu Xu63256262018-06-22 07:52:34 -070056 *b++ = (((*x) * 2) - (r + x[1]) + 2) >> 2;
Yue Chen2dbdbc92018-05-24 09:54:01 -070057 x++;
58 }
59 *a = (r = *x++);
60 *b = (*x - r + 1) >> 1;
61
62 n = length >> 1;
63 b = highpass;
64 a = lowpass;
65 r = *highpass;
66 while (n--) {
67 *a++ += (r + (*b) + 1) >> 1;
68 r = *b++;
69 }
70}
71
72static void dyadic_analyze_53_uint8_input(int levels, int width, int height,
chiyotsai601b8422021-03-12 13:15:33 -080073 const uint8_t *x, int pitch_x,
Yue Chen2dbdbc92018-05-24 09:54:01 -070074 tran_low_t *c, int pitch_c,
75 int dwt_scale_bits, int hbd) {
76 int lv, i, j, nh, nw, hh = height, hw = width;
77 tran_low_t buffer[2 * DWT_MAX_LENGTH];
78
79 if (hbd) {
chiyotsai601b8422021-03-12 13:15:33 -080080 const uint16_t *x16 = CONVERT_TO_SHORTPTR(x);
Yue Chen2dbdbc92018-05-24 09:54:01 -070081 for (i = 0; i < height; i++) {
82 for (j = 0; j < width; j++) {
83 c[i * pitch_c + j] = x16[i * pitch_x + j] << dwt_scale_bits;
84 }
85 }
86 } else {
87 for (i = 0; i < height; i++) {
88 for (j = 0; j < width; j++) {
89 c[i * pitch_c + j] = x[i * pitch_x + j] << dwt_scale_bits;
90 }
91 }
92 }
93
94 for (lv = 0; lv < levels; lv++) {
95 nh = hh;
96 hh = (hh + 1) >> 1;
97 nw = hw;
98 hw = (hw + 1) >> 1;
99 if ((nh < 2) || (nw < 2)) return;
100 for (i = 0; i < nh; i++) {
101 memcpy(buffer, &c[i * pitch_c], nw * sizeof(tran_low_t));
102 analysis_53_row(nw, buffer, &c[i * pitch_c], &c[i * pitch_c] + hw);
103 }
104 for (j = 0; j < nw; j++) {
105 for (i = 0; i < nh; i++) buffer[i + nh] = c[i * pitch_c + j];
106 analysis_53_col(nh, buffer + nh, buffer, buffer + hh);
107 for (i = 0; i < nh; i++) c[i * pitch_c + j] = buffer[i];
108 }
109 }
110}
111
chiyotsai601b8422021-03-12 13:15:33 -0800112void av1_fdwt8x8_uint8_input_c(const uint8_t *input, tran_low_t *output,
113 int stride, int hbd) {
Yue Chen2dbdbc92018-05-24 09:54:01 -0700114 dyadic_analyze_53_uint8_input(4, 8, 8, input, stride, output, 8, 2, hbd);
115}
116
James Zern9526e0d2023-04-12 11:52:58 -0700117static int haar_ac_sad(const tran_low_t *output, int bw, int bh, int stride) {
Yue Chen2dbdbc92018-05-24 09:54:01 -0700118 int acsad = 0;
119
120 for (int r = 0; r < bh; ++r)
121 for (int c = 0; c < bw; ++c) {
122 if (r >= bh / 2 || c >= bw / 2) acsad += abs(output[r * stride + c]);
123 }
124 return acsad;
125}
126
Deepa K Ge28b2332021-06-02 15:07:47 +0530127static int haar_ac_sad_8x8_uint8_input(const uint8_t *input, int stride,
128 int hbd) {
Yue Chen2dbdbc92018-05-24 09:54:01 -0700129 tran_low_t output[64];
130
James Zern7230cd82024-08-13 18:36:15 -0700131 av1_fdwt8x8_uint8_input(input, output, stride, hbd);
James Zern9526e0d2023-04-12 11:52:58 -0700132 return haar_ac_sad(output, 8, 8, 8);
Yue Chen2dbdbc92018-05-24 09:54:01 -0700133}
Deepa K Ge28b2332021-06-02 15:07:47 +0530134
135int64_t av1_haar_ac_sad_mxn_uint8_input(const uint8_t *input, int stride,
136 int hbd, int num_8x8_rows,
137 int num_8x8_cols) {
138 int64_t wavelet_energy = 0;
139 for (int r8 = 0; r8 < num_8x8_rows; ++r8) {
140 for (int c8 = 0; c8 < num_8x8_cols; ++c8) {
141 wavelet_energy += haar_ac_sad_8x8_uint8_input(
142 input + c8 * 8 + r8 * 8 * stride, stride, hbd);
143 }
144 }
145 return wavelet_energy;
146}