Unexpected use of above/left in get_tx_size_context
How was the issue detected?
What version / commit were you testing with?
What steps will reproduce the problem?
We are trying to draft specification text for get_tx_size_context, but are worried that it may be operating incorrectly.
The code in pred_common.h reads:
static INLINE int get_tx_size_context(const MACROBLOCKD *xd) {
const MB_MODE_INFO *mbmi = xd->mi[0];
const TX_SIZE max_tx_size =
max_txsize_rect_lookup[mbmi->sb_type[PLANE_TYPE_Y]];
const int max_tx_wide = tx_size_wide[max_tx_size];
const int max_tx_high = tx_size_high[max_tx_size];
const int default_ctx[MAX_NUM_NEIGHBORS] = {
xd->above_txfm_context[0] >= max_tx_wide,
xd->left_txfm_context[0] >= max_tx_high
};
const int max_tx_threshold[MAX_NUM_NEIGHBORS] = { max_tx_wide, max_tx_high };
int ctx = 0;
for (int i = 0; i < MAX_NUM_NEIGHBORS; ++i) {
const MB_MODE_INFO *const neighbor = xd->neighbors[i];
if (neighbor != NULL) {
if (is_inter_block(neighbor, xd->tree_type)) {
const int block_size = neighbor->sb_type[PLANE_TYPE_Y];
ctx += (block_size_wide[block_size] >= max_tx_threshold[i]);
} else {
ctx += default_ctx[i];
}
}
}
The problems are related to the construction of neighbour candidates in fetch_spatial_neighbors:
int index = 0;
#if CONFIG_NEW_CONTEXT_MODELING
if (xd->bottom_left_mbmi) {
xd->neighbors[index++] = xd->bottom_left_mbmi;
if (index >= MAX_NUM_NEIGHBORS) return;
}
if (xd->above_right_mbmi) {
xd->neighbors[index++] = xd->above_right_mbmi;
if (index >= MAX_NUM_NEIGHBORS) return;
}
#endif // CONFIG_NEW_CONTEXT_MODELING
if (xd->left_mbmi) {
xd->neighbors[index++] = xd->left_mbmi;
if (index >= MAX_NUM_NEIGHBORS) return;
}
if (xd->above_mbmi) {
xd->neighbors[index++] = xd->above_mbmi;
if (index >= MAX_NUM_NEIGHBORS) return;
}
Note that neighbours are added based on availability, so if all are available, neighbors[0] is bottom left and neighbours[1] is above right.
The surprising features in the code are:
- block_size_wide is used for both neighbours, but compared to max_tx_high for neighbour 1
- the ordering of default_ctx is above/left which is opposite to the neighbours bottomleft/aboveright order
- the ordering of max_tx_threshold is wide/high which is opposite to the neighbours bottomleft/aboveright order
- If some neighbours are unavailable, the ordering will change, e.g. the neighbours may be left and bottomleft