Coverage Report

Created: 2025-06-22 08:04

/src/aom/av1/encoder/hybrid_fwd_txfm.c
Line
Count
Source (jump to first uncovered line)
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 "config/aom_config.h"
13
#include "config/av1_rtcd.h"
14
#include "config/aom_dsp_rtcd.h"
15
16
#include "av1/common/idct.h"
17
#include "av1/common/blockd.h"
18
#include "av1/encoder/hybrid_fwd_txfm.h"
19
20
/* 4-point reversible, orthonormal Walsh-Hadamard in 3.5 adds, 0.5 shifts per
21
   pixel.
22
   Shared for both high and low bit depth.
23
 */
24
0
void av1_fwht4x4_c(const int16_t *input, tran_low_t *output, int stride) {
25
0
  int i;
26
0
  tran_high_t a1, b1, c1, d1, e1;
27
0
  const int16_t *ip_pass0 = input;
28
0
  const tran_low_t *ip = NULL;
29
0
  tran_low_t *op = output;
30
31
0
  for (i = 0; i < 4; i++) {
32
0
    a1 = ip_pass0[0 * stride];
33
0
    b1 = ip_pass0[1 * stride];
34
0
    c1 = ip_pass0[2 * stride];
35
0
    d1 = ip_pass0[3 * stride];
36
37
0
    a1 += b1;
38
0
    d1 = d1 - c1;
39
0
    e1 = (a1 - d1) >> 1;
40
0
    b1 = e1 - b1;
41
0
    c1 = e1 - c1;
42
0
    a1 -= c1;
43
0
    d1 += b1;
44
0
    op[0] = (tran_low_t)a1;
45
0
    op[1] = (tran_low_t)c1;
46
0
    op[2] = (tran_low_t)d1;
47
0
    op[3] = (tran_low_t)b1;
48
49
0
    ip_pass0++;
50
0
    op += 4;
51
0
  }
52
0
  ip = output;
53
0
  op = output;
54
55
0
  for (i = 0; i < 4; i++) {
56
0
    a1 = ip[4 * 0];
57
0
    b1 = ip[4 * 1];
58
0
    c1 = ip[4 * 2];
59
0
    d1 = ip[4 * 3];
60
61
0
    a1 += b1;
62
0
    d1 -= c1;
63
0
    e1 = (a1 - d1) >> 1;
64
0
    b1 = e1 - b1;
65
0
    c1 = e1 - c1;
66
0
    a1 -= c1;
67
0
    d1 += b1;
68
0
    op[4 * 0] = (tran_low_t)(a1 * UNIT_QUANT_FACTOR);
69
0
    op[4 * 1] = (tran_low_t)(c1 * UNIT_QUANT_FACTOR);
70
0
    op[4 * 2] = (tran_low_t)(d1 * UNIT_QUANT_FACTOR);
71
0
    op[4 * 3] = (tran_low_t)(b1 * UNIT_QUANT_FACTOR);
72
73
0
    ip++;
74
0
    op++;
75
0
  }
76
0
}
77
78
static void highbd_fwd_txfm_4x4(const int16_t *src_diff, tran_low_t *coeff,
79
0
                                int diff_stride, TxfmParam *txfm_param) {
80
0
  int32_t *dst_coeff = (int32_t *)coeff;
81
0
  const TX_TYPE tx_type = txfm_param->tx_type;
82
0
  const int bd = txfm_param->bd;
83
0
  if (txfm_param->lossless) {
84
0
    assert(tx_type == DCT_DCT);
85
0
    av1_fwht4x4(src_diff, coeff, diff_stride);
86
0
    return;
87
0
  }
88
0
  av1_fwd_txfm2d_4x4(src_diff, dst_coeff, diff_stride, tx_type, bd);
89
0
}
90
91
static void highbd_fwd_txfm_4x8(const int16_t *src_diff, tran_low_t *coeff,
92
0
                                int diff_stride, TxfmParam *txfm_param) {
93
0
  int32_t *dst_coeff = (int32_t *)coeff;
94
0
  av1_fwd_txfm2d_4x8(src_diff, dst_coeff, diff_stride, txfm_param->tx_type,
95
0
                     txfm_param->bd);
96
0
}
97
98
static void highbd_fwd_txfm_8x4(const int16_t *src_diff, tran_low_t *coeff,
99
0
                                int diff_stride, TxfmParam *txfm_param) {
100
0
  int32_t *dst_coeff = (int32_t *)coeff;
101
0
  av1_fwd_txfm2d_8x4(src_diff, dst_coeff, diff_stride, txfm_param->tx_type,
102
0
                     txfm_param->bd);
103
0
}
104
105
static void highbd_fwd_txfm_8x16(const int16_t *src_diff, tran_low_t *coeff,
106
0
                                 int diff_stride, TxfmParam *txfm_param) {
107
0
  int32_t *dst_coeff = (int32_t *)coeff;
108
0
  const TX_TYPE tx_type = txfm_param->tx_type;
109
0
  const int bd = txfm_param->bd;
110
0
  av1_fwd_txfm2d_8x16(src_diff, dst_coeff, diff_stride, tx_type, bd);
111
0
}
112
113
static void highbd_fwd_txfm_16x8(const int16_t *src_diff, tran_low_t *coeff,
114
0
                                 int diff_stride, TxfmParam *txfm_param) {
115
0
  int32_t *dst_coeff = (int32_t *)coeff;
116
0
  const TX_TYPE tx_type = txfm_param->tx_type;
117
0
  const int bd = txfm_param->bd;
118
0
  av1_fwd_txfm2d_16x8(src_diff, dst_coeff, diff_stride, tx_type, bd);
119
0
}
120
121
static void highbd_fwd_txfm_16x32(const int16_t *src_diff, tran_low_t *coeff,
122
0
                                  int diff_stride, TxfmParam *txfm_param) {
123
0
  int32_t *dst_coeff = (int32_t *)coeff;
124
0
  av1_fwd_txfm2d_16x32(src_diff, dst_coeff, diff_stride, txfm_param->tx_type,
125
0
                       txfm_param->bd);
126
0
}
127
128
static void highbd_fwd_txfm_32x16(const int16_t *src_diff, tran_low_t *coeff,
129
0
                                  int diff_stride, TxfmParam *txfm_param) {
130
0
  int32_t *dst_coeff = (int32_t *)coeff;
131
0
  av1_fwd_txfm2d_32x16(src_diff, dst_coeff, diff_stride, txfm_param->tx_type,
132
0
                       txfm_param->bd);
133
0
}
134
135
#if !CONFIG_REALTIME_ONLY
136
static void highbd_fwd_txfm_16x4(const int16_t *src_diff, tran_low_t *coeff,
137
0
                                 int diff_stride, TxfmParam *txfm_param) {
138
0
  int32_t *dst_coeff = (int32_t *)coeff;
139
0
  av1_fwd_txfm2d_16x4(src_diff, dst_coeff, diff_stride, txfm_param->tx_type,
140
0
                      txfm_param->bd);
141
0
}
142
143
static void highbd_fwd_txfm_4x16(const int16_t *src_diff, tran_low_t *coeff,
144
0
                                 int diff_stride, TxfmParam *txfm_param) {
145
0
  int32_t *dst_coeff = (int32_t *)coeff;
146
0
  av1_fwd_txfm2d_4x16(src_diff, dst_coeff, diff_stride, txfm_param->tx_type,
147
0
                      txfm_param->bd);
148
0
}
149
150
static void highbd_fwd_txfm_32x8(const int16_t *src_diff, tran_low_t *coeff,
151
0
                                 int diff_stride, TxfmParam *txfm_param) {
152
0
  int32_t *dst_coeff = (int32_t *)coeff;
153
0
  av1_fwd_txfm2d_32x8(src_diff, dst_coeff, diff_stride, txfm_param->tx_type,
154
0
                      txfm_param->bd);
155
0
}
156
157
static void highbd_fwd_txfm_8x32(const int16_t *src_diff, tran_low_t *coeff,
158
0
                                 int diff_stride, TxfmParam *txfm_param) {
159
0
  int32_t *dst_coeff = (int32_t *)coeff;
160
0
  av1_fwd_txfm2d_8x32(src_diff, dst_coeff, diff_stride, txfm_param->tx_type,
161
0
                      txfm_param->bd);
162
0
}
163
#endif
164
165
static void highbd_fwd_txfm_8x8(const int16_t *src_diff, tran_low_t *coeff,
166
0
                                int diff_stride, TxfmParam *txfm_param) {
167
0
  int32_t *dst_coeff = (int32_t *)coeff;
168
0
  const TX_TYPE tx_type = txfm_param->tx_type;
169
0
  const int bd = txfm_param->bd;
170
0
  av1_fwd_txfm2d_8x8(src_diff, dst_coeff, diff_stride, tx_type, bd);
171
0
}
172
173
static void highbd_fwd_txfm_16x16(const int16_t *src_diff, tran_low_t *coeff,
174
0
                                  int diff_stride, TxfmParam *txfm_param) {
175
0
  int32_t *dst_coeff = (int32_t *)coeff;
176
0
  const TX_TYPE tx_type = txfm_param->tx_type;
177
0
  const int bd = txfm_param->bd;
178
0
  av1_fwd_txfm2d_16x16(src_diff, dst_coeff, diff_stride, tx_type, bd);
179
0
}
180
181
static void highbd_fwd_txfm_32x32(const int16_t *src_diff, tran_low_t *coeff,
182
0
                                  int diff_stride, TxfmParam *txfm_param) {
183
0
  int32_t *dst_coeff = (int32_t *)coeff;
184
0
  const TX_TYPE tx_type = txfm_param->tx_type;
185
0
  const int bd = txfm_param->bd;
186
0
  av1_fwd_txfm2d_32x32(src_diff, dst_coeff, diff_stride, tx_type, bd);
187
0
}
188
189
static void highbd_fwd_txfm_32x64(const int16_t *src_diff, tran_low_t *coeff,
190
0
                                  int diff_stride, TxfmParam *txfm_param) {
191
0
  assert(txfm_param->tx_type == DCT_DCT);
192
0
  int32_t *dst_coeff = (int32_t *)coeff;
193
0
  const int bd = txfm_param->bd;
194
0
  av1_fwd_txfm2d_32x64(src_diff, dst_coeff, diff_stride, txfm_param->tx_type,
195
0
                       bd);
196
0
}
197
198
static void highbd_fwd_txfm_64x32(const int16_t *src_diff, tran_low_t *coeff,
199
0
                                  int diff_stride, TxfmParam *txfm_param) {
200
0
  assert(txfm_param->tx_type == DCT_DCT);
201
0
  int32_t *dst_coeff = (int32_t *)coeff;
202
0
  const int bd = txfm_param->bd;
203
0
  av1_fwd_txfm2d_64x32(src_diff, dst_coeff, diff_stride, txfm_param->tx_type,
204
0
                       bd);
205
0
}
206
207
#if !CONFIG_REALTIME_ONLY
208
static void highbd_fwd_txfm_16x64(const int16_t *src_diff, tran_low_t *coeff,
209
0
                                  int diff_stride, TxfmParam *txfm_param) {
210
0
  assert(txfm_param->tx_type == DCT_DCT);
211
0
  int32_t *dst_coeff = (int32_t *)coeff;
212
0
  const int bd = txfm_param->bd;
213
0
  av1_fwd_txfm2d_16x64(src_diff, dst_coeff, diff_stride, DCT_DCT, bd);
214
0
}
215
216
static void highbd_fwd_txfm_64x16(const int16_t *src_diff, tran_low_t *coeff,
217
0
                                  int diff_stride, TxfmParam *txfm_param) {
218
0
  assert(txfm_param->tx_type == DCT_DCT);
219
0
  int32_t *dst_coeff = (int32_t *)coeff;
220
0
  const int bd = txfm_param->bd;
221
0
  av1_fwd_txfm2d_64x16(src_diff, dst_coeff, diff_stride, DCT_DCT, bd);
222
0
}
223
#endif
224
225
static void highbd_fwd_txfm_64x64(const int16_t *src_diff, tran_low_t *coeff,
226
0
                                  int diff_stride, TxfmParam *txfm_param) {
227
0
  assert(txfm_param->tx_type == DCT_DCT);
228
0
  int32_t *dst_coeff = (int32_t *)coeff;
229
0
  const int bd = txfm_param->bd;
230
0
  av1_fwd_txfm2d_64x64(src_diff, dst_coeff, diff_stride, DCT_DCT, bd);
231
0
}
232
233
void av1_fwd_txfm(const int16_t *src_diff, tran_low_t *coeff, int diff_stride,
234
0
                  TxfmParam *txfm_param) {
235
0
  if (txfm_param->bd == 8)
236
0
    av1_lowbd_fwd_txfm(src_diff, coeff, diff_stride, txfm_param);
237
0
  else
238
0
    av1_highbd_fwd_txfm(src_diff, coeff, diff_stride, txfm_param);
239
0
}
240
241
void av1_lowbd_fwd_txfm_c(const int16_t *src_diff, tran_low_t *coeff,
242
0
                          int diff_stride, TxfmParam *txfm_param) {
243
0
  av1_highbd_fwd_txfm(src_diff, coeff, diff_stride, txfm_param);
244
0
}
245
246
void av1_highbd_fwd_txfm(const int16_t *src_diff, tran_low_t *coeff,
247
0
                         int diff_stride, TxfmParam *txfm_param) {
248
0
  assert(av1_ext_tx_used[txfm_param->tx_set_type][txfm_param->tx_type]);
249
0
  const TX_SIZE tx_size = txfm_param->tx_size;
250
0
  switch (tx_size) {
251
0
    case TX_64X64:
252
0
      highbd_fwd_txfm_64x64(src_diff, coeff, diff_stride, txfm_param);
253
0
      break;
254
0
    case TX_32X64:
255
0
      highbd_fwd_txfm_32x64(src_diff, coeff, diff_stride, txfm_param);
256
0
      break;
257
0
    case TX_64X32:
258
0
      highbd_fwd_txfm_64x32(src_diff, coeff, diff_stride, txfm_param);
259
0
      break;
260
261
0
    case TX_32X32:
262
0
      highbd_fwd_txfm_32x32(src_diff, coeff, diff_stride, txfm_param);
263
0
      break;
264
0
    case TX_16X16:
265
0
      highbd_fwd_txfm_16x16(src_diff, coeff, diff_stride, txfm_param);
266
0
      break;
267
0
    case TX_8X8:
268
0
      highbd_fwd_txfm_8x8(src_diff, coeff, diff_stride, txfm_param);
269
0
      break;
270
0
    case TX_4X8:
271
0
      highbd_fwd_txfm_4x8(src_diff, coeff, diff_stride, txfm_param);
272
0
      break;
273
0
    case TX_8X4:
274
0
      highbd_fwd_txfm_8x4(src_diff, coeff, diff_stride, txfm_param);
275
0
      break;
276
0
    case TX_8X16:
277
0
      highbd_fwd_txfm_8x16(src_diff, coeff, diff_stride, txfm_param);
278
0
      break;
279
0
    case TX_16X8:
280
0
      highbd_fwd_txfm_16x8(src_diff, coeff, diff_stride, txfm_param);
281
0
      break;
282
0
    case TX_16X32:
283
0
      highbd_fwd_txfm_16x32(src_diff, coeff, diff_stride, txfm_param);
284
0
      break;
285
0
    case TX_32X16:
286
0
      highbd_fwd_txfm_32x16(src_diff, coeff, diff_stride, txfm_param);
287
0
      break;
288
0
    case TX_4X4:
289
0
      highbd_fwd_txfm_4x4(src_diff, coeff, diff_stride, txfm_param);
290
0
      break;
291
0
#if !CONFIG_REALTIME_ONLY
292
0
    case TX_4X16:
293
0
      highbd_fwd_txfm_4x16(src_diff, coeff, diff_stride, txfm_param);
294
0
      break;
295
0
    case TX_16X4:
296
0
      highbd_fwd_txfm_16x4(src_diff, coeff, diff_stride, txfm_param);
297
0
      break;
298
0
    case TX_8X32:
299
0
      highbd_fwd_txfm_8x32(src_diff, coeff, diff_stride, txfm_param);
300
0
      break;
301
0
    case TX_32X8:
302
0
      highbd_fwd_txfm_32x8(src_diff, coeff, diff_stride, txfm_param);
303
0
      break;
304
0
    case TX_16X64:
305
0
      highbd_fwd_txfm_16x64(src_diff, coeff, diff_stride, txfm_param);
306
0
      break;
307
0
    case TX_64X16:
308
0
      highbd_fwd_txfm_64x16(src_diff, coeff, diff_stride, txfm_param);
309
0
      break;
310
0
#endif
311
0
    default: assert(0); break;
312
0
  }
313
0
}
314
315
#if CONFIG_AV1_HIGHBITDEPTH
316
static inline void highbd_wht_fwd_txfm(TX_SIZE tx_size, const int16_t *src_diff,
317
                                       ptrdiff_t src_stride,
318
0
                                       tran_low_t *coeff) {
319
0
  switch (tx_size) {
320
    // As the output transform co-efficients of 4x4 Hadamard transform can be
321
    // represented using 15 bits (for 12-bit clip) use lowbd variant of
322
    // hadamard_4x4.
323
0
    case TX_4X4: aom_hadamard_4x4(src_diff, src_stride, coeff); break;
324
0
    case TX_8X8: aom_highbd_hadamard_8x8(src_diff, src_stride, coeff); break;
325
0
    case TX_16X16:
326
0
      aom_highbd_hadamard_16x16(src_diff, src_stride, coeff);
327
0
      break;
328
0
    case TX_32X32:
329
0
      aom_highbd_hadamard_32x32(src_diff, src_stride, coeff);
330
0
      break;
331
0
    default: assert(0);
332
0
  }
333
0
}
334
#endif  // CONFIG_AV1_HIGHBITDEPTH
335
336
static inline void wht_fwd_txfm(TX_SIZE tx_size, const int16_t *src_diff,
337
0
                                ptrdiff_t src_stride, tran_low_t *coeff) {
338
0
  switch (tx_size) {
339
0
    case TX_4X4: aom_hadamard_4x4(src_diff, src_stride, coeff); break;
340
0
    case TX_8X8: aom_hadamard_8x8(src_diff, src_stride, coeff); break;
341
0
    case TX_16X16: aom_hadamard_16x16(src_diff, src_stride, coeff); break;
342
0
    case TX_32X32: aom_hadamard_32x32(src_diff, src_stride, coeff); break;
343
0
    default: assert(0);
344
0
  }
345
0
}
346
347
void av1_quick_txfm(int use_hadamard, TX_SIZE tx_size, BitDepthInfo bd_info,
348
                    const int16_t *src_diff, int src_stride,
349
0
                    tran_low_t *coeff) {
350
0
  if (use_hadamard) {
351
0
#if CONFIG_AV1_HIGHBITDEPTH
352
0
    if (bd_info.use_highbitdepth_buf) {
353
0
      highbd_wht_fwd_txfm(tx_size, src_diff, src_stride, coeff);
354
0
    } else {
355
0
      wht_fwd_txfm(tx_size, src_diff, src_stride, coeff);
356
0
    }
357
#else
358
    wht_fwd_txfm(tx_size, src_diff, src_stride, coeff);
359
#endif  // CONFIG_AV1_HIGHBITDEPTH
360
0
  } else {
361
0
    TxfmParam txfm_param;
362
0
    txfm_param.tx_type = DCT_DCT;
363
0
    txfm_param.tx_size = tx_size;
364
0
    txfm_param.lossless = 0;
365
0
    txfm_param.bd = bd_info.bit_depth;
366
0
    txfm_param.is_hbd = bd_info.use_highbitdepth_buf;
367
0
    txfm_param.tx_set_type = EXT_TX_SET_ALL16;
368
0
    av1_fwd_txfm(src_diff, coeff, src_stride, &txfm_param);
369
0
  }
370
0
}