Move encoding inter PUs to a separate function.

Moves code for encoding a single inter prediction unit from function
kvz_encode_coding_tree to function encode_inter_prediction_unit.
This commit is contained in:
Arttu Ylä-Outinen 2015-09-04 08:59:36 +03:00
parent 5ee9f164e8
commit ac952cbb44

View file

@ -977,129 +977,11 @@ void kvz_encoder_next_frame(encoder_state_t *state)
state->prepared = 1; state->prepared = 1;
} }
static void encode_inter_prediction_unit(encoder_state_t * const state,
void kvz_encode_coding_tree(encoder_state_t * const state, cabac_data_t * const cabac,
uint16_t x_ctb, uint16_t y_ctb, uint8_t depth) const cu_info_t * const cur_cu,
int x_ctb, int y_ctb, int depth)
{ {
cabac_data_t * const cabac = &state->cabac;
const videoframe_t * const frame = state->tile->frame;
const cu_info_t *cur_cu = kvz_videoframe_get_cu_const(frame, x_ctb, y_ctb);
uint8_t split_flag = GET_SPLITDATA(cur_cu, depth);
uint8_t split_model = 0;
//Absolute ctb
uint16_t abs_x_ctb = x_ctb + (state->tile->lcu_offset_x * LCU_WIDTH) / (LCU_WIDTH >> MAX_DEPTH);
uint16_t abs_y_ctb = y_ctb + (state->tile->lcu_offset_y * LCU_WIDTH) / (LCU_WIDTH >> MAX_DEPTH);
// Check for slice border FIXME
uint8_t border_x = ((state->encoder_control->in.width) < (abs_x_ctb * (LCU_WIDTH >> MAX_DEPTH) + (LCU_WIDTH >> depth))) ? 1 : 0;
uint8_t border_y = ((state->encoder_control->in.height) < (abs_y_ctb * (LCU_WIDTH >> MAX_DEPTH) + (LCU_WIDTH >> depth))) ? 1 : 0;
uint8_t border_split_x = ((state->encoder_control->in.width) < ((abs_x_ctb + 1) * (LCU_WIDTH >> MAX_DEPTH) + (LCU_WIDTH >> (depth + 1)))) ? 0 : 1;
uint8_t border_split_y = ((state->encoder_control->in.height) < ((abs_y_ctb + 1) * (LCU_WIDTH >> MAX_DEPTH) + (LCU_WIDTH >> (depth + 1)))) ? 0 : 1;
uint8_t border = border_x | border_y; /*!< are we in any border CU */
// When not in MAX_DEPTH, insert split flag and split the blocks if needed
if (depth != MAX_DEPTH) {
// Implisit split flag when on border
if (!border) {
// Get left and top block split_flags and if they are present and true, increase model number
if (x_ctb > 0 && GET_SPLITDATA(kvz_videoframe_get_cu_const(frame, x_ctb - 1, y_ctb), depth) == 1) {
split_model++;
}
if (y_ctb > 0 && GET_SPLITDATA(kvz_videoframe_get_cu_const(frame, x_ctb, y_ctb - 1), depth) == 1) {
split_model++;
}
cabac->cur_ctx = &(cabac->ctx.split_flag_model[split_model]);
CABAC_BIN(cabac, split_flag, "SplitFlag");
}
if (split_flag || border) {
// Split blocks and remember to change x and y block positions
uint8_t change = 1<<(MAX_DEPTH-1-depth);
kvz_encode_coding_tree(state, x_ctb, y_ctb, depth + 1); // x,y
// TODO: fix when other half of the block would not be completely over the border
if (!border_x || border_split_x) {
kvz_encode_coding_tree(state, x_ctb + change, y_ctb, depth + 1);
}
if (!border_y || border_split_y) {
kvz_encode_coding_tree(state, x_ctb, y_ctb + change, depth + 1);
}
if (!border || (border_split_x && border_split_y)) {
kvz_encode_coding_tree(state, x_ctb + change, y_ctb + change, depth + 1);
}
return;
}
}
// Encode skip flag
if (state->global->slicetype != KVZ_SLICE_I) {
int8_t ctx_skip = 0; // uiCtxSkip = aboveskipped + leftskipped;
int ui;
int16_t num_cand = MRG_MAX_NUM_CANDS;
// Get left and top skipped flags and if they are present and true, increase context number
if (x_ctb > 0 && (kvz_videoframe_get_cu_const(frame, x_ctb - 1, y_ctb))->skipped) {
ctx_skip++;
}
if (y_ctb > 0 && (kvz_videoframe_get_cu_const(frame, x_ctb, y_ctb - 1))->skipped) {
ctx_skip++;
}
cabac->cur_ctx = &(cabac->ctx.cu_skip_flag_model[ctx_skip]);
CABAC_BIN(cabac, cur_cu->skipped, "SkipFlag");
// IF SKIP
if (cur_cu->skipped) {
if (num_cand > 1) {
for (ui = 0; ui < num_cand - 1; ui++) {
int32_t symbol = (ui != cur_cu->merge_idx);
if (ui == 0) {
cabac->cur_ctx = &(cabac->ctx.cu_merge_idx_ext_model);
CABAC_BIN(cabac, symbol, "MergeIndex");
} else {
CABAC_BIN_EP(cabac,symbol,"MergeIndex");
}
if (symbol == 0) {
break;
}
}
}
return;
}
}
// ENDIF SKIP
// Prediction mode
if (state->global->slicetype != KVZ_SLICE_I) {
cabac->cur_ctx = &(cabac->ctx.cu_pred_mode_model);
CABAC_BIN(cabac, (cur_cu->type == CU_INTRA), "PredMode");
}
// part_mode
if (cur_cu->type == CU_INTRA) {
if (depth == MAX_DEPTH) {
cabac->cur_ctx = &(cabac->ctx.part_size_model[0]);
if (cur_cu->part_size == SIZE_2Nx2N) {
CABAC_BIN(cabac, 1, "part_mode 2Nx2N");
} else {
CABAC_BIN(cabac, 0, "part_mode NxN");
}
}
} else {
// TODO: Handle inter sizes other than 2Nx2N
cabac->cur_ctx = &(cabac->ctx.part_size_model[0]);
CABAC_BIN(cabac, 1, "part_mode 2Nx2N");
}
//end partsize
if (cur_cu->type == CU_INTER) {
// FOR each part
// Mergeflag // Mergeflag
int16_t num_cand = 0; int16_t num_cand = 0;
cabac->cur_ctx = &(cabac->ctx.cu_merge_flag_ext_model); cabac->cur_ctx = &(cabac->ctx.cu_merge_flag_ext_model);
@ -1225,6 +1107,132 @@ void kvz_encode_coding_tree(encoder_state_t * const state,
} }
} // for ref_list } // for ref_list
} // if !merge } // if !merge
}
void kvz_encode_coding_tree(encoder_state_t * const state,
uint16_t x_ctb, uint16_t y_ctb, uint8_t depth)
{
cabac_data_t * const cabac = &state->cabac;
const videoframe_t * const frame = state->tile->frame;
const cu_info_t *cur_cu = kvz_videoframe_get_cu_const(frame, x_ctb, y_ctb);
uint8_t split_flag = GET_SPLITDATA(cur_cu, depth);
uint8_t split_model = 0;
//Absolute ctb
uint16_t abs_x_ctb = x_ctb + (state->tile->lcu_offset_x * LCU_WIDTH) / (LCU_WIDTH >> MAX_DEPTH);
uint16_t abs_y_ctb = y_ctb + (state->tile->lcu_offset_y * LCU_WIDTH) / (LCU_WIDTH >> MAX_DEPTH);
// Check for slice border FIXME
uint8_t border_x = ((state->encoder_control->in.width) < (abs_x_ctb * (LCU_WIDTH >> MAX_DEPTH) + (LCU_WIDTH >> depth))) ? 1 : 0;
uint8_t border_y = ((state->encoder_control->in.height) < (abs_y_ctb * (LCU_WIDTH >> MAX_DEPTH) + (LCU_WIDTH >> depth))) ? 1 : 0;
uint8_t border_split_x = ((state->encoder_control->in.width) < ((abs_x_ctb + 1) * (LCU_WIDTH >> MAX_DEPTH) + (LCU_WIDTH >> (depth + 1)))) ? 0 : 1;
uint8_t border_split_y = ((state->encoder_control->in.height) < ((abs_y_ctb + 1) * (LCU_WIDTH >> MAX_DEPTH) + (LCU_WIDTH >> (depth + 1)))) ? 0 : 1;
uint8_t border = border_x | border_y; /*!< are we in any border CU */
// When not in MAX_DEPTH, insert split flag and split the blocks if needed
if (depth != MAX_DEPTH) {
// Implisit split flag when on border
if (!border) {
// Get left and top block split_flags and if they are present and true, increase model number
if (x_ctb > 0 && GET_SPLITDATA(kvz_videoframe_get_cu_const(frame, x_ctb - 1, y_ctb), depth) == 1) {
split_model++;
}
if (y_ctb > 0 && GET_SPLITDATA(kvz_videoframe_get_cu_const(frame, x_ctb, y_ctb - 1), depth) == 1) {
split_model++;
}
cabac->cur_ctx = &(cabac->ctx.split_flag_model[split_model]);
CABAC_BIN(cabac, split_flag, "SplitFlag");
}
if (split_flag || border) {
// Split blocks and remember to change x and y block positions
uint8_t change = 1<<(MAX_DEPTH-1-depth);
kvz_encode_coding_tree(state, x_ctb, y_ctb, depth + 1); // x,y
// TODO: fix when other half of the block would not be completely over the border
if (!border_x || border_split_x) {
kvz_encode_coding_tree(state, x_ctb + change, y_ctb, depth + 1);
}
if (!border_y || border_split_y) {
kvz_encode_coding_tree(state, x_ctb, y_ctb + change, depth + 1);
}
if (!border || (border_split_x && border_split_y)) {
kvz_encode_coding_tree(state, x_ctb + change, y_ctb + change, depth + 1);
}
return;
}
}
// Encode skip flag
if (state->global->slicetype != KVZ_SLICE_I) {
int8_t ctx_skip = 0; // uiCtxSkip = aboveskipped + leftskipped;
int ui;
int16_t num_cand = MRG_MAX_NUM_CANDS;
// Get left and top skipped flags and if they are present and true, increase context number
if (x_ctb > 0 && (kvz_videoframe_get_cu_const(frame, x_ctb - 1, y_ctb))->skipped) {
ctx_skip++;
}
if (y_ctb > 0 && (kvz_videoframe_get_cu_const(frame, x_ctb, y_ctb - 1))->skipped) {
ctx_skip++;
}
cabac->cur_ctx = &(cabac->ctx.cu_skip_flag_model[ctx_skip]);
CABAC_BIN(cabac, cur_cu->skipped, "SkipFlag");
// IF SKIP
if (cur_cu->skipped) {
if (num_cand > 1) {
for (ui = 0; ui < num_cand - 1; ui++) {
int32_t symbol = (ui != cur_cu->merge_idx);
if (ui == 0) {
cabac->cur_ctx = &(cabac->ctx.cu_merge_idx_ext_model);
CABAC_BIN(cabac, symbol, "MergeIndex");
} else {
CABAC_BIN_EP(cabac,symbol,"MergeIndex");
}
if (symbol == 0) {
break;
}
}
}
return;
}
}
// ENDIF SKIP
// Prediction mode
if (state->global->slicetype != KVZ_SLICE_I) {
cabac->cur_ctx = &(cabac->ctx.cu_pred_mode_model);
CABAC_BIN(cabac, (cur_cu->type == CU_INTRA), "PredMode");
}
// part_mode
if (cur_cu->type == CU_INTRA) {
if (depth == MAX_DEPTH) {
cabac->cur_ctx = &(cabac->ctx.part_size_model[0]);
if (cur_cu->part_size == SIZE_2Nx2N) {
CABAC_BIN(cabac, 1, "part_mode 2Nx2N");
} else {
CABAC_BIN(cabac, 0, "part_mode NxN");
}
}
} else {
// TODO: Handle inter sizes other than 2Nx2N
cabac->cur_ctx = &(cabac->ctx.part_size_model[0]);
CABAC_BIN(cabac, 1, "part_mode 2Nx2N");
}
//end partsize
if (cur_cu->type == CU_INTER) {
// FOR each part
encode_inter_prediction_unit(state, cabac, cur_cu, x_ctb, y_ctb, depth);
// END for each part
{ {
int cbf = (cbf_is_set(cur_cu->cbf.y, depth) || int cbf = (cbf_is_set(cur_cu->cbf.y, depth) ||
@ -1243,8 +1251,6 @@ void kvz_encode_coding_tree(encoder_state_t * const state,
kvz_encode_transform_coeff(state, x_ctb * 2, y_ctb * 2, depth, 0, 0, 0); kvz_encode_transform_coeff(state, x_ctb * 2, y_ctb * 2, depth, 0, 0, 0);
} }
} }
// END for each part
} else if (cur_cu->type == CU_INTRA) { } else if (cur_cu->type == CU_INTRA) {
uint8_t intra_pred_mode[4] = { uint8_t intra_pred_mode[4] = {
cur_cu->intra[0].mode, cur_cu->intra[1].mode, cur_cu->intra[0].mode, cur_cu->intra[1].mode,