blockd.c 10.5 KB
Newer Older
Jingning Han's avatar
Jingning Han committed
1
/*
Yaowu Xu's avatar
Yaowu Xu committed
2
 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
Jingning Han's avatar
Jingning Han committed
3
 *
Yaowu Xu's avatar
Yaowu Xu committed
4 5 6 7 8 9
 * 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.
Jingning Han's avatar
Jingning Han committed
10 11
 */

12
#include <math.h>
13

14
#include "aom_ports/system_state.h"
15

16
#include "av1/common/blockd.h"
17
#include "av1/common/onyxc_int.h"
Jingning Han's avatar
Jingning Han committed
18

Yaowu Xu's avatar
Yaowu Xu committed
19 20
PREDICTION_MODE av1_left_block_mode(const MODE_INFO *cur_mi,
                                    const MODE_INFO *left_mi, int b) {
Jingning Han's avatar
Jingning Han committed
21
  if (b == 0 || b == 2) {
clang-format's avatar
clang-format committed
22
    if (!left_mi || is_inter_block(&left_mi->mbmi)) return DC_PRED;
Jingning Han's avatar
Jingning Han committed
23 24 25 26 27 28 29 30

    return get_y_mode(left_mi, b + 1);
  } else {
    assert(b == 1 || b == 3);
    return cur_mi->bmi[b - 1].as_mode;
  }
}

Yaowu Xu's avatar
Yaowu Xu committed
31 32
PREDICTION_MODE av1_above_block_mode(const MODE_INFO *cur_mi,
                                     const MODE_INFO *above_mi, int b) {
Jingning Han's avatar
Jingning Han committed
33
  if (b == 0 || b == 1) {
clang-format's avatar
clang-format committed
34
    if (!above_mi || is_inter_block(&above_mi->mbmi)) return DC_PRED;
Jingning Han's avatar
Jingning Han committed
35 36 37 38 39 40 41 42

    return get_y_mode(above_mi, b + 2);
  } else {
    assert(b == 2 || b == 3);
    return cur_mi->bmi[b - 2].as_mode;
  }
}

43
#if CONFIG_COEF_INTERLEAVE
Fangwen Fu's avatar
Fangwen Fu committed
44 45
// TODO(Fangwen): Make CONFIG_COEF_INTERLEAVE work with
// CONFIG_PALETTE_THROUGHPUT
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
void av1_foreach_transformed_block_interleave(
    const MACROBLOCKD *const xd, BLOCK_SIZE bsize,
    foreach_transformed_block_visitor visit, void *arg) {
  const struct macroblockd_plane *const pd_y = &xd->plane[0];
  const struct macroblockd_plane *const pd_c = &xd->plane[1];
  const MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;

  const TX_SIZE tx_log2_y = mbmi->tx_size;
  const TX_SIZE tx_log2_c = get_uv_tx_size(mbmi, pd_c);
  const int tx_sz_y = (1 << tx_log2_y);
  const int tx_sz_c = (1 << tx_log2_c);

  const BLOCK_SIZE plane_bsize_y = get_plane_block_size(bsize, pd_y);
  const BLOCK_SIZE plane_bsize_c = get_plane_block_size(bsize, pd_c);

  const int num_4x4_w_y = num_4x4_blocks_wide_lookup[plane_bsize_y];
  const int num_4x4_w_c = num_4x4_blocks_wide_lookup[plane_bsize_c];
  const int num_4x4_h_y = num_4x4_blocks_high_lookup[plane_bsize_y];
  const int num_4x4_h_c = num_4x4_blocks_high_lookup[plane_bsize_c];

  const int step_y = 1 << (tx_log2_y << 1);
  const int step_c = 1 << (tx_log2_c << 1);

  const int max_4x4_w_y =
      get_max_4x4_size(num_4x4_w_y, xd->mb_to_right_edge, pd_y->subsampling_x);
  const int max_4x4_h_y =
      get_max_4x4_size(num_4x4_h_y, xd->mb_to_bottom_edge, pd_y->subsampling_y);

  const int extra_step_y = ((num_4x4_w_y - max_4x4_w_y) >> tx_log2_y) * step_y;

  const int max_4x4_w_c =
      get_max_4x4_size(num_4x4_w_c, xd->mb_to_right_edge, pd_c->subsampling_x);
  const int max_4x4_h_c =
      get_max_4x4_size(num_4x4_h_c, xd->mb_to_bottom_edge, pd_c->subsampling_y);

  const int extra_step_c = ((num_4x4_w_c - max_4x4_w_c) >> tx_log2_c) * step_c;

  // The max_4x4_w/h may be smaller than tx_sz under some corner cases,
  // i.e. when the SB is splitted by tile boundaries.
  const int tu_num_w_y = (max_4x4_w_y + tx_sz_y - 1) / tx_sz_y;
  const int tu_num_h_y = (max_4x4_h_y + tx_sz_y - 1) / tx_sz_y;
  const int tu_num_w_c = (max_4x4_w_c + tx_sz_c - 1) / tx_sz_c;
  const int tu_num_h_c = (max_4x4_h_c + tx_sz_c - 1) / tx_sz_c;
  const int tu_num_c = tu_num_w_c * tu_num_h_c;

  int tu_idx_c = 0;
  int offset_y, row_y, col_y;
  int offset_c, row_c, col_c;

  for (row_y = 0; row_y < tu_num_h_y; row_y++) {
    for (col_y = 0; col_y < tu_num_w_y; col_y++) {
      // luma
      offset_y = (row_y * tu_num_w_y + col_y) * step_y + row_y * extra_step_y;
      visit(0, offset_y, row_y * tx_sz_y, col_y * tx_sz_y, plane_bsize_y,
            tx_log2_y, arg);
      // chroma
      if (tu_idx_c < tu_num_c) {
        row_c = (tu_idx_c / tu_num_w_c) * tx_sz_c;
        col_c = (tu_idx_c % tu_num_w_c) * tx_sz_c;
        offset_c = tu_idx_c * step_c + (tu_idx_c / tu_num_w_c) * extra_step_c;
        visit(1, offset_c, row_c, col_c, plane_bsize_c, tx_log2_c, arg);
        visit(2, offset_c, row_c, col_c, plane_bsize_c, tx_log2_c, arg);
        tu_idx_c++;
      }
    }
  }

  // In 422 case, it's possible that Chroma has more TUs than Luma
  while (tu_idx_c < tu_num_c) {
    row_c = (tu_idx_c / tu_num_w_c) * tx_sz_c;
    col_c = (tu_idx_c % tu_num_w_c) * tx_sz_c;
    offset_c = tu_idx_c * step_c + row_c * extra_step_c;
    visit(1, offset_c, row_c, col_c, plane_bsize_c, tx_log2_c, arg);
    visit(2, offset_c, row_c, col_c, plane_bsize_c, tx_log2_c, arg);
    tu_idx_c++;
  }
}
#endif

Yaowu Xu's avatar
Yaowu Xu committed
125
void av1_foreach_transformed_block_in_plane(
Jingning Han's avatar
Jingning Han committed
126 127 128 129 130 131
    const MACROBLOCKD *const xd, BLOCK_SIZE bsize, int plane,
    foreach_transformed_block_visitor visit, void *arg) {
  const struct macroblockd_plane *const pd = &xd->plane[plane];
  // block and transform sizes, in number of 4x4 blocks log 2 ("*_b")
  // 4x4=0, 8x8=2, 16x16=4, 32x32=6, 64x64=8
  // transform size varies per plane, look it up in a common way.
Angie Chiang's avatar
Angie Chiang committed
132
  const TX_SIZE tx_size = get_tx_size(plane, xd);
Jingning Han's avatar
Jingning Han committed
133
#if CONFIG_CB4X4 && !CONFIG_CHROMA_2X2
134 135 136
  const BLOCK_SIZE plane_bsize =
      AOMMAX(BLOCK_4X4, get_plane_block_size(bsize, pd));
#else
Jingning Han's avatar
Jingning Han committed
137
  const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, pd);
138
#endif
139 140 141
  const uint8_t txw_unit = tx_size_wide_unit[tx_size];
  const uint8_t txh_unit = tx_size_high_unit[tx_size];
  const int step = txw_unit * txh_unit;
Jingning Han's avatar
Jingning Han committed
142 143 144 145 146
  int i = 0, r, c;

  // If mb_to_right_edge is < 0 we are in a situation in which
  // the current block size extends into the UMV and we won't
  // visit the sub blocks that are wholly within the UMV.
147 148
  const int max_blocks_wide = max_block_wide(xd, plane_bsize, plane);
  const int max_blocks_high = max_block_high(xd, plane_bsize, plane);
Jingning Han's avatar
Jingning Han committed
149 150 151

  // Keep track of the row and column of the blocks we use so that we know
  // if we are in the unrestricted motion border.
152
  for (r = 0; r < max_blocks_high; r += txh_unit) {
Jingning Han's avatar
Jingning Han committed
153
    // Skip visiting the sub blocks that are wholly within the UMV.
154
    for (c = 0; c < max_blocks_wide; c += txw_unit) {
155
      visit(plane, i, r, c, plane_bsize, tx_size, arg);
Jingning Han's avatar
Jingning Han committed
156 157 158 159 160
      i += step;
    }
  }
}

Yushin Cho's avatar
Yushin Cho committed
161 162 163 164 165 166 167 168 169
#if CONFIG_DAALA_DIST
void av1_foreach_8x8_transformed_block_in_plane(
    const MACROBLOCKD *const xd, BLOCK_SIZE bsize, int plane,
    foreach_transformed_block_visitor visit,
    foreach_transformed_block_visitor mi_visit, void *arg) {
  const struct macroblockd_plane *const pd = &xd->plane[plane];
  // block and transform sizes, in number of 4x4 blocks log 2 ("*_b")
  // 4x4=0, 8x8=2, 16x16=4, 32x32=6, 64x64=8
  // transform size varies per plane, look it up in a common way.
Angie Chiang's avatar
Angie Chiang committed
170
  const TX_SIZE tx_size = get_tx_size(plane, xd);
Yushin Cho's avatar
Yushin Cho committed
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
  const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, pd);
  const uint8_t txw_unit = tx_size_wide_unit[tx_size];
  const uint8_t txh_unit = tx_size_high_unit[tx_size];
  const int step = txw_unit * txh_unit;
  int i = 0, r, c;

  // If mb_to_right_edge is < 0 we are in a situation in which
  // the current block size extends into the UMV and we won't
  // visit the sub blocks that are wholly within the UMV.
  const int max_blocks_wide = max_block_wide(xd, plane_bsize, plane);
  const int max_blocks_high = max_block_high(xd, plane_bsize, plane);

  // Keep track of the row and column of the blocks we use so that we know
  // if we are in the unrestricted motion border.
  for (r = 0; r < max_blocks_high; r += txh_unit) {
    // Skip visiting the sub blocks that are wholly within the UMV.
    for (c = 0; c < max_blocks_wide; c += txw_unit) {
      visit(plane, i, r, c, plane_bsize, tx_size, arg);
      // Call whenever each 8x8 block is done
      if ((r & 1) && (c & 1))
        mi_visit(plane, i, r - 1, c - 1, plane_bsize, TX_8X8, arg);
      i += step;
    }
  }
}
#endif

198
#if !CONFIG_PVQ || CONFIG_VAR_TX
Yaowu Xu's avatar
Yaowu Xu committed
199
void av1_set_contexts(const MACROBLOCKD *xd, struct macroblockd_plane *pd,
200 201
                      int plane, TX_SIZE tx_size, int has_eob, int aoff,
                      int loff) {
Jingning Han's avatar
Jingning Han committed
202 203
  ENTROPY_CONTEXT *const a = pd->above_context + aoff;
  ENTROPY_CONTEXT *const l = pd->left_context + loff;
204 205
  const int txs_wide = tx_size_wide_unit[tx_size];
  const int txs_high = tx_size_high_unit[tx_size];
206 207 208
#if CONFIG_CB4X4
  const BLOCK_SIZE bsize = xd->mi[0]->mbmi.sb_type;
#else
209
  const BLOCK_SIZE bsize = AOMMAX(xd->mi[0]->mbmi.sb_type, BLOCK_8X8);
210
#endif
211
  const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, pd);
Jingning Han's avatar
Jingning Han committed
212 213 214 215

  // above
  if (has_eob && xd->mb_to_right_edge < 0) {
    int i;
216
    const int blocks_wide = max_block_wide(xd, plane_bsize, plane);
217
    int above_contexts = txs_wide;
Jingning Han's avatar
Jingning Han committed
218 219 220
    if (above_contexts + aoff > blocks_wide)
      above_contexts = blocks_wide - aoff;

clang-format's avatar
clang-format committed
221
    for (i = 0; i < above_contexts; ++i) a[i] = has_eob;
222
    for (i = above_contexts; i < txs_wide; ++i) a[i] = 0;
Jingning Han's avatar
Jingning Han committed
223
  } else {
224
    memset(a, has_eob, sizeof(ENTROPY_CONTEXT) * txs_wide);
Jingning Han's avatar
Jingning Han committed
225 226 227 228 229
  }

  // left
  if (has_eob && xd->mb_to_bottom_edge < 0) {
    int i;
230
    const int blocks_high = max_block_high(xd, plane_bsize, plane);
231
    int left_contexts = txs_high;
clang-format's avatar
clang-format committed
232
    if (left_contexts + loff > blocks_high) left_contexts = blocks_high - loff;
Jingning Han's avatar
Jingning Han committed
233

clang-format's avatar
clang-format committed
234
    for (i = 0; i < left_contexts; ++i) l[i] = has_eob;
235
    for (i = left_contexts; i < txs_high; ++i) l[i] = 0;
Jingning Han's avatar
Jingning Han committed
236
  } else {
237
    memset(l, has_eob, sizeof(ENTROPY_CONTEXT) * txs_high);
Jingning Han's avatar
Jingning Han committed
238 239
  }
}
240
#endif
Jingning Han's avatar
Jingning Han committed
241

Yaowu Xu's avatar
Yaowu Xu committed
242
void av1_setup_block_planes(MACROBLOCKD *xd, int ss_x, int ss_y) {
Jingning Han's avatar
Jingning Han committed
243 244 245
  int i;

  for (i = 0; i < MAX_MB_PLANE; i++) {
246
    xd->plane[i].plane_type = get_plane_type(i);
Jingning Han's avatar
Jingning Han committed
247 248 249 250
    xd->plane[i].subsampling_x = i ? ss_x : 0;
    xd->plane[i].subsampling_y = i ? ss_y : 0;
  }
}
251 252

#if CONFIG_EXT_INTRA
253
const int16_t dr_intra_derivative[90] = {
clang-format's avatar
clang-format committed
254 255 256 257 258 259 260
  1,    14666, 7330, 4884, 3660, 2926, 2435, 2084, 1821, 1616, 1451, 1317, 1204,
  1108, 1026,  955,  892,  837,  787,  743,  703,  666,  633,  603,  574,  548,
  524,  502,   481,  461,  443,  426,  409,  394,  379,  365,  352,  339,  327,
  316,  305,   294,  284,  274,  265,  256,  247,  238,  230,  222,  214,  207,
  200,  192,   185,  179,  172,  166,  159,  153,  147,  141,  136,  130,  124,
  119,  113,   108,  103,  98,   93,   88,   83,   78,   73,   68,   63,   59,
  54,   49,    45,   40,   35,   31,   26,   22,   17,   13,   8,    4,
261 262
};

hui su's avatar
hui su committed
263
#if CONFIG_INTRA_INTERP
Yaowu Xu's avatar
Yaowu Xu committed
264
int av1_is_intra_filter_switchable(int angle) {
265
  assert(angle > 0 && angle < 270);
clang-format's avatar
clang-format committed
266
  if (angle % 45 == 0) return 0;
267 268 269
  if (angle > 90 && angle < 180) {
    return 1;
  } else {
clang-format's avatar
clang-format committed
270 271 272
    return ((angle < 90 ? dr_intra_derivative[angle]
                        : dr_intra_derivative[270 - angle]) &
            0xFF) > 0;
273 274
  }
}
hui su's avatar
hui su committed
275
#endif  // CONFIG_INTRA_INTERP
276
#endif  // CONFIG_EXT_INTRA