|  | /* | 
|  | * Copyright (c) 2023, Alliance for Open Media. All rights reserved | 
|  | * | 
|  | * This source code is subject to the terms of the BSD 2 Clause License and | 
|  | * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License | 
|  | * was not distributed with this source code in the LICENSE file, you can | 
|  | * obtain it at www.aomedia.org/license/software. If the Alliance for Open | 
|  | * Media Patent License 1.0 was not distributed with this source code in the | 
|  | * PATENTS file, you can obtain it at www.aomedia.org/license/patent. | 
|  | */ | 
|  |  | 
|  | #include <cstdio> | 
|  | #include <memory> | 
|  |  | 
|  | #include "aom_dsp/aom_dsp_common.h" | 
|  | #include "av1/common/av1_common_int.h" | 
|  |  | 
|  | extern "C" { | 
|  | #include "av1/common/intra_matrix.h" | 
|  | } | 
|  |  | 
|  | #include "av1/common/intra_dip.h" | 
|  |  | 
|  | #define INPUT_FEATURES 11 | 
|  |  | 
|  | // Resample output from DIP prediction (8x8) to the actual transform | 
|  | // block size. This is some by upsampling if dimension is > 8, or | 
|  | // downsampling/decimation if dimension is < 8. Resampling is done | 
|  | // in the horizontal dimension first followed by vertical. | 
|  | static void resample_output(uint16_t *dst, int dst_stride, | 
|  | const uint16_t *above_row, const uint16_t *left_col, | 
|  | uint16_t *ml_output, int bw_log2, int bh_log2, | 
|  | int transpose) { | 
|  | // up/down sampling factors | 
|  | int pred_x = 8; | 
|  | int pred_y = 8; | 
|  | int upx_log2 = bw_log2 - 3; | 
|  | int upy_log2 = bh_log2 - 3; | 
|  | int downx_log2 = 0; | 
|  | int downy_log2 = 0; | 
|  | if (upx_log2 < 0) { | 
|  | downx_log2 = -upx_log2; | 
|  | upx_log2 = 0; | 
|  | } | 
|  | if (upy_log2 < 0) { | 
|  | downy_log2 = -upy_log2; | 
|  | upy_log2 = 0; | 
|  | } | 
|  | int mx = 1 << upx_log2; | 
|  | int my = 1 << upy_log2; | 
|  | int downx = 1 << downx_log2; | 
|  | int downy = 1 << downy_log2; | 
|  | int bw = 1 << bw_log2; | 
|  | // Copy ml_output[] into dst[] | 
|  | for (int i = 0; i < pred_y >> downy_log2; i++) { | 
|  | for (int j = 0; j < pred_x >> downx_log2; j++) { | 
|  | int x = j * mx + (mx - 1); | 
|  | int y = i * my + (my - 1); | 
|  | int i1 = i * downy; | 
|  | int j1 = j * downx; | 
|  | int ii = transpose ? j1 : i1; | 
|  | int jj = transpose ? i1 : j1; | 
|  | dst[y * dst_stride + x] = ml_output[ii * pred_x + jj]; | 
|  | } | 
|  | } | 
|  | // Interpolate horizontally. | 
|  | for (int i = 0; i < pred_y >> downy_log2; i++) { | 
|  | int y = i * my + (my - 1); | 
|  | int p0 = 0; | 
|  | int p1 = left_col[y]; | 
|  | for (int j = 0; j < pred_x >> downx_log2; j++) { | 
|  | int x = j * mx; | 
|  | p0 = p1; | 
|  | p1 = dst[y * dst_stride + x + mx - 1]; | 
|  | for (int k = 0; k < mx - 1; k++) { | 
|  | int k1 = k + 1; | 
|  | dst[y * dst_stride + x + k] = (p0 * (mx - k1) + (p1 * k1)) >> upx_log2; | 
|  | } | 
|  | } | 
|  | } | 
|  | // Interpolate vertically. | 
|  | for (int x = 0; x < bw; x++) { | 
|  | int p0 = 0; | 
|  | int p1 = above_row[x]; | 
|  | for (int i = 0; i < pred_y >> downy_log2; i++) { | 
|  | int y = i * my; | 
|  | p0 = p1; | 
|  | p1 = dst[(y + my - 1) * dst_stride + x]; | 
|  | for (int k = 0; k < my - 1; k++) { | 
|  | int k1 = k + 1; | 
|  | dst[(y + k) * dst_stride + x] = | 
|  | (p0 * (my - k1) + (p1 * k1)) >> upy_log2; | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | // Create intra DIP prediction for large blocks | 
|  | extern "C" void av1_highbd_intra_dip_predictor(int mode, uint16_t *dst, | 
|  | int dst_stride, | 
|  | const uint16_t *above_row, | 
|  | const uint16_t *left_col, | 
|  | TX_SIZE tx_size, int bd | 
|  | #if CONFIG_DIP_EXT_PRUNING | 
|  | , | 
|  | uint16_t *intra_dip_features | 
|  | #endif  // CONFIG_DIP_EXT_PRUNING | 
|  | ) { | 
|  | uint16_t ml_input[INPUT_FEATURES]; | 
|  | uint16_t ml_output[64]; | 
|  | const int bw_log2 = tx_size_wide_log2[tx_size]; | 
|  | const int bh_log2 = tx_size_high_log2[tx_size]; | 
|  | int transpose = mode >> 4; | 
|  | int iml_mode = mode & 15; | 
|  | int down_x_log2 = bw_log2 - 2; | 
|  | int down_y_log2 = bh_log2 - 2; | 
|  | const int down0_log2 = transpose ? down_y_log2 : down_x_log2; | 
|  | const int down1_log2 = transpose ? down_x_log2 : down_y_log2; | 
|  | const int down0 = 1 << down0_log2; | 
|  | const int down1 = 1 << down1_log2; | 
|  | int rnd0 = down0 >> 1; | 
|  | int rnd1 = down1 >> 1; | 
|  | const uint16_t *edge0 = transpose ? left_col : above_row; | 
|  | const uint16_t *edge1 = transpose ? above_row : left_col; | 
|  |  | 
|  | int ml_i = 0; | 
|  | // Corner | 
|  | ml_input[ml_i++] = edge0[-1]; | 
|  |  | 
|  | // Calc above input | 
|  | for (int i = 0; i < 4; i++) { | 
|  | int sum = 0; | 
|  | for (int j = 0; j < down0; j++) { | 
|  | sum += *edge0++; | 
|  | } | 
|  | ml_input[ml_i++] = (sum + rnd0) >> down0_log2; | 
|  | } | 
|  |  | 
|  | // Calc left input | 
|  | for (int i = 0; i < 4; i++) { | 
|  | int sum = 0; | 
|  | for (int j = 0; j < down1; j++) { | 
|  | sum += *edge1++; | 
|  | } | 
|  | ml_input[ml_i++] = (sum + rnd1) >> down1_log2; | 
|  | } | 
|  |  | 
|  | int n_overhang = 1; | 
|  | // Calc above_left input | 
|  | for (int i = 0; i < n_overhang; i++) { | 
|  | int sum = 0; | 
|  | for (int j = 0; j < down0; j++) { | 
|  | sum += *edge0++; | 
|  | } | 
|  | ml_input[ml_i++] = (sum + rnd0) >> down0_log2; | 
|  | } | 
|  |  | 
|  | // Calc bottom_left input | 
|  | for (int i = 0; i < n_overhang; i++) { | 
|  | int sum = 0; | 
|  | for (int j = 0; j < down1; j++) { | 
|  | sum += *edge1++; | 
|  | } | 
|  | ml_input[ml_i++] = (sum + rnd1) >> down1_log2; | 
|  | } | 
|  |  | 
|  | av1_intra_matrix_pred(ml_input, iml_mode, ml_output, bd); | 
|  |  | 
|  | #if CONFIG_DIP_EXT_PRUNING | 
|  | // Collect DIP input features for ML pruning. | 
|  | if (mode == 0) { | 
|  | for (int i = 0; i < 11; i++) { | 
|  | intra_dip_features[i] = ml_input[i]; | 
|  | } | 
|  | } | 
|  | #endif  // CONFIG_DIP_EXT_PRUNING | 
|  | resample_output(dst, dst_stride, above_row, left_col, ml_output, bw_log2, | 
|  | bh_log2, transpose); | 
|  | } |