mirror of
https://github.com/ultravideo/uvg266.git
synced 2024-11-23 18:14:06 +00:00
[isp] Add extra logic to reference building to accommodate ISP. Remove some asserts which were invalidated by ISP.
This commit is contained in:
parent
33cd44f11b
commit
59292d8808
3
src/cu.c
3
src/cu.c
|
@ -265,7 +265,8 @@ void uvg_cu_loc_ctor(cu_loc_t* loc, int x, int y, int width, int height)
|
|||
{
|
||||
assert(x >= 0 && y >= 0 && width >= 0 && height >= 0 && "Cannot give negative coordinates or block dimensions.");
|
||||
assert(!(width > LCU_WIDTH || height > LCU_WIDTH) && "Luma CU dimension exceeds maximum (dim > LCU_WIDTH).");
|
||||
assert(!(width < 4 || height < 4) && "Luma CU dimension smaller than 4."); // TODO: change if luma size 2 is allowed
|
||||
// This check is no longer valid. With non-square blocks and ISP enabled, even 1x16 and 16x1 (ISP needs at least 16 samples) blocks are valid
|
||||
//assert(!(width < 4 || height < 4) && "Luma CU dimension smaller than 4.");
|
||||
|
||||
loc->x = x;
|
||||
loc->y = y;
|
||||
|
|
110
src/intra.c
110
src/intra.c
|
@ -930,7 +930,7 @@ static void intra_predict_regular(
|
|||
uint8_t multi_ref_index = color == COLOR_Y ? multi_ref_idx : 0;
|
||||
|
||||
const uvg_intra_ref *used_ref = &refs->ref;
|
||||
if (cfg->intra_smoothing_disabled || color != COLOR_Y || mode == 1 || (width == 4 && height == 4) || multi_ref_index || width != height /*Fake ISP*/) {
|
||||
if (cfg->intra_smoothing_disabled || color != COLOR_Y || mode == 1 || (width == 4 && height == 4) || multi_ref_index || width != height /*ISP_TODO: replace this fake ISP check*/) {
|
||||
// For chroma, DC and 4x4 blocks, always use unfiltered reference.
|
||||
} else if (mode == 0) {
|
||||
// Otherwise, use filtered for planar.
|
||||
|
@ -984,14 +984,15 @@ void uvg_intra_build_reference_any(
|
|||
const lcu_t *const lcu,
|
||||
uvg_intra_references *const refs,
|
||||
const uint8_t multi_ref_idx,
|
||||
uvg_pixel *extra_ref_lines)
|
||||
uvg_pixel *extra_ref_lines,
|
||||
bool is_isp)
|
||||
{
|
||||
const int width = color == COLOR_Y ? cu_loc->width : cu_loc->chroma_width;
|
||||
const int height = color == COLOR_Y ? cu_loc->height : cu_loc->chroma_height;
|
||||
const int log2_width = uvg_g_convert_to_log2[width];
|
||||
const int log2_height = uvg_g_convert_to_log2[height];
|
||||
|
||||
assert((log2_width >= 2 && log2_width <= 5) && (log2_height >= 2 && log2_height <= 5));
|
||||
assert((log2_width >= 1 && log2_width <= 5) && (log2_height >= 1 && log2_height <= 5));
|
||||
|
||||
refs->filtered_initialized = false;
|
||||
uvg_pixel *out_left_ref = &refs->ref.left[0];
|
||||
|
@ -1057,7 +1058,13 @@ void uvg_intra_build_reference_any(
|
|||
// Generate left reference.
|
||||
if (luma_px->x > 0) {
|
||||
// Get the number of reference pixels based on the PU coordinate within the LCU.
|
||||
int px_available_left = num_ref_pixels_left[lcu_px.y / 4][lcu_px.x / 4] >> is_chroma;
|
||||
int px_available_left;
|
||||
if (is_isp && !is_chroma) {
|
||||
px_available_left = height;
|
||||
}
|
||||
else {
|
||||
px_available_left = num_ref_pixels_left[lcu_px.y / 4][lcu_px.x / 4] >> is_chroma;
|
||||
}
|
||||
|
||||
// Limit the number of available pixels based on block size and dimensions
|
||||
// of the picture.
|
||||
|
@ -1161,10 +1168,16 @@ void uvg_intra_build_reference_any(
|
|||
}
|
||||
|
||||
// Generate top reference.
|
||||
int px_available_top;
|
||||
if (luma_px->y > 0) {
|
||||
// Get the number of reference pixels based on the PU coordinate within the LCU.
|
||||
int px_available_top = num_ref_pixels_top[lcu_px.y / 4][lcu_px.x / 4] >> is_chroma;
|
||||
|
||||
if (is_isp && !is_chroma) {
|
||||
px_available_top = width;
|
||||
}
|
||||
else {
|
||||
px_available_top = num_ref_pixels_top[lcu_px.y / 4][lcu_px.x / 4] >> is_chroma;
|
||||
}
|
||||
|
||||
// Limit the number of available pixels based on block size and dimensions
|
||||
// of the picture.
|
||||
px_available_top = MIN(px_available_top, width * 2 + multi_ref_index);
|
||||
|
@ -1197,7 +1210,8 @@ void uvg_intra_build_reference_inner(
|
|||
uvg_intra_references *const refs,
|
||||
bool entropy_sync,
|
||||
const uint8_t multi_ref_idx,
|
||||
uvg_pixel* extra_ref_lines)
|
||||
uvg_pixel* extra_ref_lines,
|
||||
bool is_isp)
|
||||
{
|
||||
const int width = color == COLOR_Y ? cu_loc->width : cu_loc->chroma_width;
|
||||
const int height = color == COLOR_Y ? cu_loc->height : cu_loc->chroma_height;
|
||||
|
@ -1310,8 +1324,14 @@ void uvg_intra_build_reference_inner(
|
|||
}
|
||||
// Generate left reference.
|
||||
|
||||
// Get the number of reference pixels based on the PU coordinate within the LCU.
|
||||
int px_available_left = num_ref_pixels_left[lcu_px.y / 4][lcu_px.x / 4] >> is_chroma;
|
||||
// Get the number of reference pixels based on the PU coordinate within the LCU.
|
||||
int px_available_left;
|
||||
if (is_isp && !is_chroma) {
|
||||
px_available_left = height;
|
||||
}
|
||||
else {
|
||||
px_available_left = num_ref_pixels_left[lcu_px.y / 4][lcu_px.x / 4] >> is_chroma;
|
||||
}
|
||||
|
||||
// Limit the number of available pixels based on block size and dimensions
|
||||
// of the picture.
|
||||
|
@ -1347,7 +1367,13 @@ void uvg_intra_build_reference_inner(
|
|||
// Generate top reference.
|
||||
|
||||
// Get the number of reference pixels based on the PU coordinate within the LCU.
|
||||
int px_available_top = num_ref_pixels_top[lcu_px.y / 4][lcu_px.x / 4] >> is_chroma;
|
||||
int px_available_top;
|
||||
if (is_isp && !is_chroma) {
|
||||
px_available_top = width;
|
||||
}
|
||||
else {
|
||||
px_available_top = num_ref_pixels_top[lcu_px.y / 4][lcu_px.x / 4] >> is_chroma;
|
||||
}
|
||||
|
||||
// Limit the number of available pixels based on block size and dimensions
|
||||
// of the picture.
|
||||
|
@ -1373,7 +1399,46 @@ void uvg_intra_build_reference_inner(
|
|||
}
|
||||
}
|
||||
|
||||
void uvg_intra_build_reference_isp(
|
||||
const cu_loc_t* const split_loc,
|
||||
const cu_loc_t* const origin,
|
||||
const color_t color,
|
||||
const vector2d_t* const luma_px,
|
||||
const vector2d_t* const pic_px,
|
||||
const lcu_t* const lcu,
|
||||
uvg_intra_references* const refs,
|
||||
bool entropy_sync,
|
||||
const int isp_mode)
|
||||
{
|
||||
int ref_length_top = 0, ref_length_left = 0;
|
||||
|
||||
bool left_available = split_loc->x > 0;
|
||||
bool above_available = split_loc->y > 0;
|
||||
|
||||
if (split_loc->x == origin->x && split_loc->y == origin->y)
|
||||
{
|
||||
// First ISP split, call reference builders normally
|
||||
if (luma_px->x > 0 && luma_px->y > 0) {
|
||||
uvg_intra_build_reference_inner(split_loc, color, luma_px, pic_px, lcu, refs, entropy_sync, 0, NULL, false);
|
||||
}
|
||||
else {
|
||||
uvg_intra_build_reference_any(split_loc, color, luma_px, pic_px, lcu, refs, 0, NULL, false);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (luma_px->x > 0 && luma_px->y > 0) {
|
||||
uvg_intra_build_reference_inner(split_loc, color, luma_px, pic_px, lcu, refs, entropy_sync, 0, NULL, true);
|
||||
}
|
||||
else {
|
||||
uvg_intra_build_reference_any(split_loc, color, luma_px, pic_px, lcu, refs, 0, NULL, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void uvg_intra_build_reference(
|
||||
const cu_loc_t* const pu_loc,
|
||||
const cu_loc_t* const cu_loc,
|
||||
const color_t color,
|
||||
const vector2d_t *const luma_px,
|
||||
|
@ -1386,11 +1451,19 @@ void uvg_intra_build_reference(
|
|||
{
|
||||
assert(!(extra_ref_lines == NULL && multi_ref_idx != 0) && "Trying to use MRL with NULL extra references.");
|
||||
|
||||
bool is_isp = (pu_loc->x != cu_loc->x) || (pu_loc->y != cu_loc->y);
|
||||
|
||||
// If isp is in use, some extra logic is needed
|
||||
if (is_isp) {
|
||||
uvg_intra_build_reference_isp(pu_loc, cu_loc, color, luma_px, pic_px, lcu, refs, entropy_sync, is_isp);
|
||||
return;
|
||||
}
|
||||
|
||||
// Much logic can be discarded if not on the edge
|
||||
if (luma_px->x > 0 && luma_px->y > 0) {
|
||||
uvg_intra_build_reference_inner(cu_loc, color, luma_px, pic_px, lcu, refs, entropy_sync, multi_ref_idx, extra_ref_lines);
|
||||
uvg_intra_build_reference_inner(pu_loc, color, luma_px, pic_px, lcu, refs, entropy_sync, multi_ref_idx, extra_ref_lines, is_isp);
|
||||
} else {
|
||||
uvg_intra_build_reference_any(cu_loc, color, luma_px, pic_px, lcu, refs, multi_ref_idx, extra_ref_lines);
|
||||
uvg_intra_build_reference_any(pu_loc, color, luma_px, pic_px, lcu, refs, multi_ref_idx, extra_ref_lines, is_isp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1538,6 +1611,7 @@ void uvg_get_isp_split_loc(cu_loc_t *loc, const int x, const int y, const int bl
|
|||
|
||||
static void intra_recon_tb_leaf(
|
||||
encoder_state_t* const state,
|
||||
const cu_loc_t* pu_loc,
|
||||
const cu_loc_t* cu_loc,
|
||||
lcu_t *lcu,
|
||||
color_t color,
|
||||
|
@ -1586,7 +1660,7 @@ static void intra_recon_tb_leaf(
|
|||
}
|
||||
}
|
||||
|
||||
uvg_intra_build_reference(cu_loc, color, &luma_px, &pic_px, lcu, &refs, cfg->wpp, extra_refs, multi_ref_index);
|
||||
uvg_intra_build_reference(pu_loc, cu_loc, color, &luma_px, &pic_px, lcu, &refs, cfg->wpp, extra_refs, multi_ref_index);
|
||||
|
||||
uvg_pixel pred[32 * 32];
|
||||
uvg_intra_predict(state, &refs, cu_loc, color, pred, search_data, lcu, tree_type);
|
||||
|
@ -1697,12 +1771,14 @@ void uvg_intra_recon_cu(
|
|||
// Small blocks are split only twice.
|
||||
int split_type = search_data->pred_cu.intra.isp_mode;
|
||||
int split_limit = uvg_get_isp_split_num(width, height, split_type);
|
||||
cu_loc_t origin_cu;
|
||||
uvg_cu_loc_ctor(&origin_cu, x, y, width, height);
|
||||
|
||||
for (int i = 0; i < split_limit; ++i) {
|
||||
cu_loc_t split_loc;
|
||||
uvg_get_isp_split_loc(&split_loc, x, y, width, height, i, split_type);
|
||||
|
||||
intra_recon_tb_leaf(state, &split_loc, lcu, COLOR_Y, search_data, tree_type);
|
||||
intra_recon_tb_leaf(state, &split_loc, &origin_cu, lcu, COLOR_Y, search_data, tree_type);
|
||||
uvg_quantize_lcu_residual(state, true, false, false,
|
||||
&split_loc, depth, cur_cu, lcu,
|
||||
false, tree_type);
|
||||
|
@ -1717,11 +1793,11 @@ void uvg_intra_recon_cu(
|
|||
|
||||
// Process a leaf TU.
|
||||
if (has_luma) {
|
||||
intra_recon_tb_leaf(state, &loc, lcu, COLOR_Y, search_data, tree_type);
|
||||
intra_recon_tb_leaf(state, &loc, &loc, lcu, COLOR_Y, search_data, tree_type);
|
||||
}
|
||||
if (has_chroma) {
|
||||
intra_recon_tb_leaf(state, &loc, lcu, COLOR_U, search_data, tree_type);
|
||||
intra_recon_tb_leaf(state, &loc, lcu, COLOR_V, search_data, tree_type);
|
||||
intra_recon_tb_leaf(state, &loc, &loc, lcu, COLOR_U, search_data, tree_type);
|
||||
intra_recon_tb_leaf(state, &loc, &loc, lcu, COLOR_V, search_data, tree_type);
|
||||
}
|
||||
|
||||
// TODO: not necessary to call if only luma and ISP is on
|
||||
|
|
|
@ -108,6 +108,7 @@ int8_t uvg_intra_get_dir_luma_predictor(
|
|||
* \param multi_ref_idx Multi reference line index for the prediction block.
|
||||
*/
|
||||
void uvg_intra_build_reference(
|
||||
const cu_loc_t* const pu_loc,
|
||||
const cu_loc_t* const cu_loc,
|
||||
const color_t color,
|
||||
const vector2d_t *const luma_px,
|
||||
|
|
|
@ -709,10 +709,10 @@ static int search_intra_chroma_rough(
|
|||
const cu_loc_t loc = { luma_px.x, luma_px.y, width, height, width, height };
|
||||
|
||||
uvg_intra_references refs_u;
|
||||
uvg_intra_build_reference(&loc, COLOR_U, &luma_px, &pic_px, lcu, &refs_u, state->encoder_control->cfg.wpp, NULL, 0);
|
||||
uvg_intra_build_reference(&loc, &loc, COLOR_U, &luma_px, &pic_px, lcu, &refs_u, state->encoder_control->cfg.wpp, NULL, 0);
|
||||
|
||||
uvg_intra_references refs_v;
|
||||
uvg_intra_build_reference(&loc, COLOR_V, &luma_px, &pic_px, lcu, &refs_v, state->encoder_control->cfg.wpp, NULL, 0);
|
||||
uvg_intra_build_reference(&loc, &loc, COLOR_V, &luma_px, &pic_px, lcu, &refs_v, state->encoder_control->cfg.wpp, NULL, 0);
|
||||
|
||||
vector2d_t lcu_cpx = { (lcu_px->x & ~7) / 2, (lcu_px->y & ~7) / 2 };
|
||||
uvg_pixel* orig_u = &lcu->ref.u[lcu_cpx.x + lcu_cpx.y * LCU_WIDTH_C];
|
||||
|
@ -1514,8 +1514,8 @@ int8_t uvg_search_intra_chroma_rdo(
|
|||
|
||||
|
||||
if (reconstruct_chroma) {
|
||||
uvg_intra_build_reference(&loc, COLOR_U, &luma_px, &pic_px, lcu, &refs[0], state->encoder_control->cfg.wpp, NULL, 0);
|
||||
uvg_intra_build_reference(&loc, COLOR_V, &luma_px, &pic_px, lcu, &refs[1], state->encoder_control->cfg.wpp, NULL, 0);
|
||||
uvg_intra_build_reference(&loc, &loc, COLOR_U, &luma_px, &pic_px, lcu, &refs[0], state->encoder_control->cfg.wpp, NULL, 0);
|
||||
uvg_intra_build_reference(&loc, &loc, COLOR_V, &luma_px, &pic_px, lcu, &refs[1], state->encoder_control->cfg.wpp, NULL, 0);
|
||||
|
||||
const vector2d_t lcu_px = { SUB_SCU(x_px), SUB_SCU(y_px) };
|
||||
cabac_data_t temp_cabac;
|
||||
|
@ -1858,7 +1858,7 @@ void uvg_search_cu_intra(
|
|||
int8_t num_cand = uvg_intra_get_dir_luma_predictor(x_px, y_px, candidate_modes, cur_cu, left_cu, above_cu);
|
||||
|
||||
if (depth > 0) {
|
||||
uvg_intra_build_reference(&cu_loc, COLOR_Y, &luma_px, &pic_px, lcu, refs, state->encoder_control->cfg.wpp, NULL, 0);
|
||||
uvg_intra_build_reference(&cu_loc, &cu_loc, COLOR_Y, &luma_px, &pic_px, lcu, refs, state->encoder_control->cfg.wpp, NULL, 0);
|
||||
}
|
||||
|
||||
// The maximum number of possible MIP modes depend on block size & shape
|
||||
|
@ -1926,7 +1926,7 @@ void uvg_search_cu_intra(
|
|||
frame->rec->stride, 1);
|
||||
}
|
||||
}
|
||||
uvg_intra_build_reference(&cu_loc, COLOR_Y, &luma_px, &pic_px, lcu, &refs[line], state->encoder_control->cfg.wpp, extra_refs, line);
|
||||
uvg_intra_build_reference(&cu_loc, &cu_loc, COLOR_Y, &luma_px, &pic_px, lcu, &refs[line], state->encoder_control->cfg.wpp, extra_refs, line);
|
||||
for(int i = 1; i < INTRA_MPM_COUNT; i++) {
|
||||
num_mrl_modes++;
|
||||
const int index = (i - 1) + (INTRA_MPM_COUNT -1)*(line-1) + number_of_modes;
|
||||
|
|
|
@ -456,8 +456,10 @@ int uvg_quantize_residual_generic(encoder_state_t *const state,
|
|||
|
||||
int has_coeffs = 0;
|
||||
|
||||
assert(width <= TR_MAX_WIDTH && height <= TR_MAX_WIDTH);
|
||||
assert(width >= TR_MIN_WIDTH && height >= TR_MIN_WIDTH);
|
||||
// With ISP these checks no longer apply, since width and height 2 is now possible
|
||||
// With MTT even 1x16 and 16x1 ISP splits are possible
|
||||
//assert(width <= TR_MAX_WIDTH && height <= TR_MAX_WIDTH);
|
||||
//assert(width >= TR_MIN_WIDTH && height >= TR_MIN_WIDTH);
|
||||
|
||||
// Get residual. (ref_in - pred_in -> residual)
|
||||
uvg_generate_residual(ref_in, pred_in, residual, width, height, in_stride, in_stride);
|
||||
|
|
Loading…
Reference in a new issue