blockd.c 10.6 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
44
45
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
#if CONFIG_COEF_INTERLEAVE
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_y = tu_num_w_y * tu_num_h_y;
  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
124
void av1_foreach_transformed_block_in_plane(
Jingning Han's avatar
Jingning Han committed
125
126
127
    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];
clang-format's avatar
clang-format committed
128
  const MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
Jingning Han's avatar
Jingning Han committed
129
130
131
  // 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.
clang-format's avatar
clang-format committed
132
  const TX_SIZE tx_size = plane ? get_uv_tx_size(mbmi, pd) : mbmi->tx_size;
133
134
135
136
#if CONFIG_CB4X4
  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
170
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
198
#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];
  const MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
  // 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.
  const TX_SIZE tx_size = plane ? get_uv_tx_size(mbmi, pd) : mbmi->tx_size;
  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

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

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

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

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

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

Yaowu Xu's avatar
Yaowu Xu committed
243
void av1_setup_block_planes(MACROBLOCKD *xd, int ss_x, int ss_y) {
Jingning Han's avatar
Jingning Han committed
244
245
246
247
248
249
250
251
  int i;

  for (i = 0; i < MAX_MB_PLANE; i++) {
    xd->plane[i].plane_type = i ? PLANE_TYPE_UV : PLANE_TYPE_Y;
    xd->plane[i].subsampling_x = i ? ss_x : 0;
    xd->plane[i].subsampling_y = i ? ss_y : 0;
  }
}
252
253

#if CONFIG_EXT_INTRA
254
const int16_t dr_intra_derivative[90] = {
clang-format's avatar
clang-format committed
255
256
257
258
259
260
261
  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,
262
263
};

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