Commit 768d660e authored by Frank Bossen's avatar Frank Bossen

Move boundary info into separate data structure

Reduces cache misses in the decoder and hence reduces run time.
Run time reduction has been measured to be about 15% for HD (1080p)
content.

Change-Id: Ic42de04e0943c0f89c856b61fe174dcea96af5e5
parent 978152a9
...@@ -190,6 +190,11 @@ void av1_free_restoration_buffers(AV1_COMMON *cm) { ...@@ -190,6 +190,11 @@ void av1_free_restoration_buffers(AV1_COMMON *cm) {
void av1_free_context_buffers(AV1_COMMON *cm) { void av1_free_context_buffers(AV1_COMMON *cm) {
int i; int i;
cm->free_mi(cm); cm->free_mi(cm);
aom_free(cm->boundary_info);
cm->boundary_info_alloc_size = 0;
cm->boundary_info = NULL;
#if !CONFIG_SEGMENT_PRED_LAST #if !CONFIG_SEGMENT_PRED_LAST
free_seg_map(cm); free_seg_map(cm);
#endif #endif
...@@ -219,6 +224,16 @@ int av1_alloc_context_buffers(AV1_COMMON *cm, int width, int height) { ...@@ -219,6 +224,16 @@ int av1_alloc_context_buffers(AV1_COMMON *cm, int width, int height) {
if (cm->alloc_mi(cm, new_mi_size)) goto fail; if (cm->alloc_mi(cm, new_mi_size)) goto fail;
} }
const int new_boundary_info_alloc_size = cm->mi_rows * cm->mi_stride;
if (cm->boundary_info_alloc_size < new_boundary_info_alloc_size) {
aom_free(cm->boundary_info);
cm->boundary_info = (BOUNDARY_TYPE *)aom_calloc(
new_boundary_info_alloc_size, sizeof(BOUNDARY_TYPE));
cm->boundary_info_alloc_size = 0;
if (!cm->boundary_info) goto fail;
cm->boundary_info_alloc_size = new_boundary_info_alloc_size;
}
#if !CONFIG_SEGMENT_PRED_LAST #if !CONFIG_SEGMENT_PRED_LAST
if (cm->seg_map_alloc_size < cm->mi_rows * cm->mi_cols) { if (cm->seg_map_alloc_size < cm->mi_rows * cm->mi_cols) {
// Create the segmentation map structure and set to 0. // Create the segmentation map structure and set to 0.
......
...@@ -1020,16 +1020,17 @@ static void update_tile_boundary_filter_mask(AV1_COMMON *const cm, ...@@ -1020,16 +1020,17 @@ static void update_tile_boundary_filter_mask(AV1_COMMON *const cm,
const int mi_row, const int mi_col, const int mi_row, const int mi_col,
LOOP_FILTER_MASK *lfm) { LOOP_FILTER_MASK *lfm) {
int i; int i;
MODE_INFO *const mi = cm->mi + mi_row * cm->mi_stride + mi_col; const BOUNDARY_TYPE *const bi =
cm->boundary_info + mi_row * cm->mi_stride + mi_col;
if (mi->mbmi.boundary_info & TILE_LEFT_BOUNDARY) { if (*bi & TILE_LEFT_BOUNDARY) {
for (i = 0; i <= TX_32X32; i++) { for (i = 0; i <= TX_32X32; i++) {
lfm->left_y[i] &= 0xfefefefefefefefeULL; lfm->left_y[i] &= 0xfefefefefefefefeULL;
lfm->left_uv[i] &= 0xeeee; lfm->left_uv[i] &= 0xeeee;
} }
} }
if (mi->mbmi.boundary_info & TILE_ABOVE_BOUNDARY) { if (*bi & TILE_ABOVE_BOUNDARY) {
for (i = 0; i <= TX_32X32; i++) { for (i = 0; i <= TX_32X32; i++) {
lfm->above_y[i] &= 0xffffffffffffff00ULL; lfm->above_y[i] &= 0xffffffffffffff00ULL;
lfm->above_uv[i] &= 0xfff0; lfm->above_uv[i] &= 0xfff0;
...@@ -1585,9 +1586,10 @@ void av1_filter_block_plane_non420_ver(AV1_COMMON *const cm, ...@@ -1585,9 +1586,10 @@ void av1_filter_block_plane_non420_ver(AV1_COMMON *const cm,
// Disable filtering on the leftmost column or tile boundary // Disable filtering on the leftmost column or tile boundary
unsigned int border_mask = ~(mi_col == 0 ? 1 : 0); unsigned int border_mask = ~(mi_col == 0 ? 1 : 0);
#if CONFIG_LOOPFILTERING_ACROSS_TILES || CONFIG_LOOPFILTERING_ACROSS_TILES_EXT #if CONFIG_LOOPFILTERING_ACROSS_TILES || CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
MODE_INFO *const mi = cm->mi + (mi_row + idx_r) * cm->mi_stride + mi_col; const BOUNDARY_TYPE *const bi =
cm->boundary_info + (mi_row + idx_r) * cm->mi_stride + mi_col;
if (av1_disable_loopfilter_on_tile_boundary(cm) && if (av1_disable_loopfilter_on_tile_boundary(cm) &&
((mi->mbmi.boundary_info & TILE_LEFT_BOUNDARY) != 0)) { ((*bi & TILE_LEFT_BOUNDARY) != 0)) {
border_mask = 0xfffffffe; border_mask = 0xfffffffe;
} }
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES #endif // CONFIG_LOOPFILTERING_ACROSS_TILES
...@@ -1632,9 +1634,10 @@ void av1_filter_block_plane_non420_hor(AV1_COMMON *const cm, ...@@ -1632,9 +1634,10 @@ void av1_filter_block_plane_non420_hor(AV1_COMMON *const cm,
#if CONFIG_LOOPFILTERING_ACROSS_TILES || CONFIG_LOOPFILTERING_ACROSS_TILES_EXT #if CONFIG_LOOPFILTERING_ACROSS_TILES || CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
// Disable filtering on the abovemost row or tile boundary // Disable filtering on the abovemost row or tile boundary
const MODE_INFO *mi = cm->mi + (mi_row + idx_r) * cm->mi_stride + mi_col; const BOUNDARY_TYPE *bi =
cm->boundary_info + (mi_row + idx_r) * cm->mi_stride + mi_col;
if ((av1_disable_loopfilter_on_tile_boundary(cm) && if ((av1_disable_loopfilter_on_tile_boundary(cm) &&
(mi->mbmi.boundary_info & TILE_ABOVE_BOUNDARY)) || (*bi & TILE_ABOVE_BOUNDARY)) ||
(mi_row + idx_r == 0)) (mi_row + idx_r == 0))
memset(&row_masks, 0, sizeof(row_masks)); memset(&row_masks, 0, sizeof(row_masks));
#else #else
...@@ -2096,13 +2099,13 @@ static void set_lpf_parameters( ...@@ -2096,13 +2099,13 @@ static void set_lpf_parameters(
// to extract the correct boundary information. // to extract the correct boundary information.
const int mi_row_bound = ((y << scale_vert) >> MI_SIZE_LOG2); const int mi_row_bound = ((y << scale_vert) >> MI_SIZE_LOG2);
const int mi_col_bound = ((x << scale_horz) >> MI_SIZE_LOG2); const int mi_col_bound = ((x << scale_horz) >> MI_SIZE_LOG2);
MODE_INFO *const mi_bound = BOUNDARY_TYPE *const bi =
cm->mi + mi_row_bound * cm->mi_stride + mi_col_bound; cm->boundary_info + mi_row_bound * cm->mi_stride + mi_col_bound;
// here, assuming boundary_info is set correctly based on the // here, assuming bounfary_info is set correctly based on the
// loop_filter_across_tiles_enabled flag, i.e, tile boundary should // loop_filter_across_tiles_enabled flag, i.e, tile boundary should
// only be set to true when this flag is set to 0. // only be set to true when this flag is set to 0.
int left_boundary = (mi_bound->mbmi.boundary_info & TILE_LEFT_BOUNDARY); int left_boundary = (*bi & TILE_LEFT_BOUNDARY);
int top_boundary = (mi_bound->mbmi.boundary_info & TILE_ABOVE_BOUNDARY); int top_boundary = (*bi & TILE_ABOVE_BOUNDARY);
if (((VERT_EDGE == edge_dir) && (0 == left_boundary)) || if (((VERT_EDGE == edge_dir) && (0 == left_boundary)) ||
((HORZ_EDGE == edge_dir) && (0 == top_boundary))) ((HORZ_EDGE == edge_dir) && (0 == top_boundary)))
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES #endif // CONFIG_LOOPFILTERING_ACROSS_TILES
......
...@@ -319,8 +319,6 @@ typedef struct MB_MODE_INFO { ...@@ -319,8 +319,6 @@ typedef struct MB_MODE_INFO {
int cfl_alpha_signs; int cfl_alpha_signs;
#endif #endif
BOUNDARY_TYPE boundary_info;
#if CONFIG_JNT_COMP #if CONFIG_JNT_COMP
int compound_idx; int compound_idx;
int comp_group_idx; int comp_group_idx;
......
...@@ -231,20 +231,20 @@ void av1_cdef_frame(YV12_BUFFER_CONFIG *frame, AV1_COMMON *cm, ...@@ -231,20 +231,20 @@ void av1_cdef_frame(YV12_BUFFER_CONFIG *frame, AV1_COMMON *cm,
// loop_filter_across_tiles_enabled flag, i.e, if this flag is set to 1, // loop_filter_across_tiles_enabled flag, i.e, if this flag is set to 1,
// then boundary_info should not be treated as tile boundaries. Also // then boundary_info should not be treated as tile boundaries. Also
// assume CDEF filter block size is 64x64. // assume CDEF filter block size is 64x64.
MODE_INFO *const mi_tl = cm->mi + mi_idx_tl; BOUNDARY_TYPE *const bi_tl = cm->boundary_info + mi_idx_tl;
MODE_INFO *const mi_tr = cm->mi + mi_idx_tr; BOUNDARY_TYPE *const bi_tr = cm->boundary_info + mi_idx_tr;
MODE_INFO *const mi_bl = cm->mi + mi_idx_bl; BOUNDARY_TYPE *const bi_bl = cm->boundary_info + mi_idx_bl;
BOUNDARY_TYPE boundary_tl = mi_tl->mbmi.boundary_info; BOUNDARY_TYPE boundary_tl = *bi_tl;
tile_top = boundary_tl & TILE_ABOVE_BOUNDARY; tile_top = boundary_tl & TILE_ABOVE_BOUNDARY;
tile_left = boundary_tl & TILE_LEFT_BOUNDARY; tile_left = boundary_tl & TILE_LEFT_BOUNDARY;
if (fbr != nvfb - 1 && mi_bl) if (fbr != nvfb - 1 && bi_bl)
tile_bottom = mi_bl->mbmi.boundary_info & TILE_BOTTOM_BOUNDARY; tile_bottom = *bi_bl & TILE_BOTTOM_BOUNDARY;
else else
tile_bottom = 1; tile_bottom = 1;
if (fbc != nhfb - 1 && mi_tr) if (fbc != nhfb - 1 && bi_tr)
tile_right = mi_tr->mbmi.boundary_info & TILE_RIGHT_BOUNDARY; tile_right = *bi_tr & TILE_RIGHT_BOUNDARY;
else else
tile_right = 1; tile_right = 1;
......
...@@ -472,6 +472,9 @@ typedef struct AV1Common { ...@@ -472,6 +472,9 @@ typedef struct AV1Common {
int tile_cols, tile_rows; int tile_cols, tile_rows;
int last_tile_cols, last_tile_rows; int last_tile_cols, last_tile_rows;
BOUNDARY_TYPE *boundary_info;
int boundary_info_alloc_size;
#if CONFIG_MAX_TILE #if CONFIG_MAX_TILE
int min_log2_tile_cols; int min_log2_tile_cols;
int max_log2_tile_cols; int max_log2_tile_cols;
......
...@@ -199,30 +199,30 @@ void av1_get_tile_n_bits(int mi_cols, int *min_log2_tile_cols, ...@@ -199,30 +199,30 @@ void av1_get_tile_n_bits(int mi_cols, int *min_log2_tile_cols,
#endif // CONFIG_MAX_TILE #endif // CONFIG_MAX_TILE
void av1_setup_frame_boundary_info(const AV1_COMMON *const cm) { void av1_setup_frame_boundary_info(const AV1_COMMON *const cm) {
MODE_INFO *mi = cm->mi; BOUNDARY_TYPE *bi = cm->boundary_info;
int col; int col;
for (col = 0; col < cm->mi_cols; ++col) { for (col = 0; col < cm->mi_cols; ++col) {
mi->mbmi.boundary_info |= FRAME_ABOVE_BOUNDARY | TILE_ABOVE_BOUNDARY; *bi |= FRAME_ABOVE_BOUNDARY | TILE_ABOVE_BOUNDARY;
mi += 1; bi += 1;
} }
mi = cm->mi; bi = cm->boundary_info;
int row; int row;
for (row = 0; row < cm->mi_rows; ++row) { for (row = 0; row < cm->mi_rows; ++row) {
mi->mbmi.boundary_info |= FRAME_LEFT_BOUNDARY | TILE_LEFT_BOUNDARY; *bi |= FRAME_LEFT_BOUNDARY | TILE_LEFT_BOUNDARY;
mi += cm->mi_stride; bi += cm->mi_stride;
} }
mi = cm->mi + (cm->mi_rows - 1) * cm->mi_stride; bi = cm->boundary_info + (cm->mi_rows - 1) * cm->mi_stride;
for (col = 0; col < cm->mi_cols; ++col) { for (col = 0; col < cm->mi_cols; ++col) {
mi->mbmi.boundary_info |= FRAME_BOTTOM_BOUNDARY | TILE_BOTTOM_BOUNDARY; *bi |= FRAME_BOTTOM_BOUNDARY | TILE_BOTTOM_BOUNDARY;
mi += 1; bi += 1;
} }
mi = cm->mi + cm->mi_cols - 1; bi = cm->boundary_info + cm->mi_cols - 1;
for (row = 0; row < cm->mi_rows; ++row) { for (row = 0; row < cm->mi_rows; ++row) {
mi->mbmi.boundary_info |= FRAME_RIGHT_BOUNDARY | TILE_RIGHT_BOUNDARY; *bi |= FRAME_RIGHT_BOUNDARY | TILE_RIGHT_BOUNDARY;
mi += cm->mi_stride; bi += cm->mi_stride;
} }
} }
...@@ -302,9 +302,10 @@ void av1_setup_across_tile_boundary_info(const AV1_COMMON *const cm, ...@@ -302,9 +302,10 @@ void av1_setup_across_tile_boundary_info(const AV1_COMMON *const cm,
if (cm->tile_cols * cm->tile_rows > 1) { if (cm->tile_cols * cm->tile_rows > 1) {
const int mi_row = tile_info->mi_row_start; const int mi_row = tile_info->mi_row_start;
const int mi_col = tile_info->mi_col_start; const int mi_col = tile_info->mi_col_start;
MODE_INFO *const mi_start = cm->mi + mi_row * cm->mi_stride + mi_col; BOUNDARY_TYPE *const bi_start =
assert(mi_start < cm->mip + cm->mi_alloc_size); cm->boundary_info + mi_row * cm->mi_stride + mi_col;
MODE_INFO *mi = 0; // assert(mi_start < cm->mip + cm->mi_alloc_size);
BOUNDARY_TYPE *bi = 0;
const int row_diff = tile_info->mi_row_end - tile_info->mi_row_start; const int row_diff = tile_info->mi_row_end - tile_info->mi_row_start;
const int col_diff = tile_info->mi_col_end - tile_info->mi_col_start; const int col_diff = tile_info->mi_col_end - tile_info->mi_col_start;
int row, col; int row, col;
...@@ -318,10 +319,10 @@ void av1_setup_across_tile_boundary_info(const AV1_COMMON *const cm, ...@@ -318,10 +319,10 @@ void av1_setup_across_tile_boundary_info(const AV1_COMMON *const cm,
if (cm->loop_filter_across_tiles_h_enabled == 0) if (cm->loop_filter_across_tiles_h_enabled == 0)
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES_EXT #endif // CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
{ {
mi = mi_start; bi = bi_start;
for (col = 0; col < col_diff; ++col) { for (col = 0; col < col_diff; ++col) {
mi->mbmi.boundary_info |= TILE_ABOVE_BOUNDARY; *bi |= TILE_ABOVE_BOUNDARY;
mi += 1; bi += 1;
} }
} }
...@@ -329,10 +330,10 @@ void av1_setup_across_tile_boundary_info(const AV1_COMMON *const cm, ...@@ -329,10 +330,10 @@ void av1_setup_across_tile_boundary_info(const AV1_COMMON *const cm,
if (cm->loop_filter_across_tiles_v_enabled == 0) if (cm->loop_filter_across_tiles_v_enabled == 0)
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES_EXT #endif // CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
{ {
mi = mi_start; bi = bi_start;
for (row = 0; row < row_diff; ++row) { for (row = 0; row < row_diff; ++row) {
mi->mbmi.boundary_info |= TILE_LEFT_BOUNDARY; *bi |= TILE_LEFT_BOUNDARY;
mi += cm->mi_stride; bi += cm->mi_stride;
} }
} }
...@@ -340,12 +341,12 @@ void av1_setup_across_tile_boundary_info(const AV1_COMMON *const cm, ...@@ -340,12 +341,12 @@ void av1_setup_across_tile_boundary_info(const AV1_COMMON *const cm,
if (cm->loop_filter_across_tiles_h_enabled == 0) if (cm->loop_filter_across_tiles_h_enabled == 0)
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES_EXT #endif // CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
{ {
mi = mi_start + (row_diff - 1) * cm->mi_stride; bi = bi_start + (row_diff - 1) * cm->mi_stride;
// explicit bounds checking // explicit bounds checking
assert(mi + col_diff <= cm->mip + cm->mi_alloc_size); // assert(mi + col_diff <= cm->mip + cm->mi_alloc_size);
for (col = 0; col < col_diff; ++col) { for (col = 0; col < col_diff; ++col) {
mi->mbmi.boundary_info |= TILE_BOTTOM_BOUNDARY; *bi |= TILE_BOTTOM_BOUNDARY;
mi += 1; bi += 1;
} }
} }
...@@ -353,10 +354,10 @@ void av1_setup_across_tile_boundary_info(const AV1_COMMON *const cm, ...@@ -353,10 +354,10 @@ void av1_setup_across_tile_boundary_info(const AV1_COMMON *const cm,
if (cm->loop_filter_across_tiles_v_enabled == 0) if (cm->loop_filter_across_tiles_v_enabled == 0)
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES_EXT #endif // CONFIG_LOOPFILTERING_ACROSS_TILES_EXT
{ {
mi = mi_start + col_diff - 1; bi = bi_start + col_diff - 1;
for (row = 0; row < row_diff; ++row) { for (row = 0; row < row_diff; ++row) {
mi->mbmi.boundary_info |= TILE_RIGHT_BOUNDARY; *bi |= TILE_RIGHT_BOUNDARY;
mi += cm->mi_stride; bi += cm->mi_stride;
} }
} }
} // end of cm->tile_cols * cm->tile_rows > 1 } // end of cm->tile_cols * cm->tile_rows > 1
......
...@@ -3264,10 +3264,10 @@ static void dec_setup_frame_boundary_info(AV1_COMMON *const cm) { ...@@ -3264,10 +3264,10 @@ static void dec_setup_frame_boundary_info(AV1_COMMON *const cm) {
{ {
int row, col; int row, col;
for (row = 0; row < cm->mi_rows; ++row) { for (row = 0; row < cm->mi_rows; ++row) {
MODE_INFO *mi = cm->mi + row * cm->mi_stride; BOUNDARY_TYPE *bi = cm->boundary_info + row * cm->mi_stride;
for (col = 0; col < cm->mi_cols; ++col) { for (col = 0; col < cm->mi_cols; ++col) {
mi->mbmi.boundary_info = 0; *bi = 0;
mi++; bi++;
} }
} }
av1_setup_frame_boundary_info(cm); av1_setup_frame_boundary_info(cm);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment