diff options
Diffstat (limited to 'vp9/encoder/vp9_encodeframe.c')
-rw-r--r-- | vp9/encoder/vp9_encodeframe.c | 597 |
1 files changed, 279 insertions, 318 deletions
diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c index 8e524f4ba..d40c604a4 100644 --- a/vp9/encoder/vp9_encodeframe.c +++ b/vp9/encoder/vp9_encodeframe.c @@ -562,6 +562,15 @@ void vp9_setup_src_planes(MACROBLOCK *x, x->e_mbd.plane[2].subsampling_y); } +static INLINE void set_partition_seg_context(VP9_COMP *cpi, + int mi_row, int mi_col) { + VP9_COMMON *const cm = &cpi->common; + MACROBLOCKD *const xd = &cpi->mb.e_mbd; + + xd->above_seg_context = cm->above_seg_context + (mi_col >> CONFIG_SB8X8); + xd->left_seg_context = cm->left_seg_context + ((mi_row >> CONFIG_SB8X8) & 3); +} + static void set_offsets(VP9_COMP *cpi, int mi_row, int mi_col, BLOCK_SIZE_TYPE bsize) { MACROBLOCK *const x = &cpi->mb; @@ -574,14 +583,18 @@ static void set_offsets(VP9_COMP *cpi, const int mb_row = mi_row >> CONFIG_SB8X8; const int mb_col = mi_col >> CONFIG_SB8X8; const int idx_map = mb_row * cm->mb_cols + mb_col; + int i; // entropy context structures - xd->above_context = cm->above_context + mb_col; - xd->left_context = cm->left_context + (mb_row & 3); + for (i = 0; i < MAX_MB_PLANE; i++) { + xd->plane[i].above_context = cm->above_context[i] + + (mi_col * 4 >> (CONFIG_SB8X8 + xd->plane[i].subsampling_x)); + xd->plane[i].left_context = cm->left_context[i] + + (((mi_row * 4 >> CONFIG_SB8X8) & 15) >> xd->plane[i].subsampling_y); + } // partition contexts - xd->above_seg_context = cm->above_seg_context + mb_col; - xd->left_seg_context = cm->left_seg_context + (mb_row & 3); + set_partition_seg_context(cpi, mi_row, mi_col); // Activity map pointer x->mb_activity_ptr = &cpi->mb_activity_map[idx_map]; @@ -773,203 +786,134 @@ static void update_stats(VP9_COMP *cpi, int mi_row, int mi_col) { } } -static void encode_sb(VP9_COMP *cpi, - int mi_row, - int mi_col, - int output_enabled, - TOKENEXTRA **tp, BLOCK_SIZE_TYPE is_sb) { - VP9_COMMON *const cm = &cpi->common; - MACROBLOCK *const x = &cpi->mb; - MACROBLOCKD *const xd = &x->e_mbd; - BLOCK_SIZE_TYPE bsize = BLOCK_SIZE_SB32X32; - int pl; - - xd->left_seg_context = - cm->left_seg_context + ((mi_row >> CONFIG_SB8X8) & 0x03); - xd->above_seg_context = - cm->above_seg_context + (mi_col >> CONFIG_SB8X8); - pl = partition_plane_context(xd, bsize); - - if (is_sb == BLOCK_SIZE_SB32X32) { - set_offsets(cpi, mi_row, mi_col, bsize); - update_state(cpi, &x->sb32_context[xd->sb_index], - bsize, output_enabled); - - encode_superblock(cpi, tp, - output_enabled, mi_row, mi_col, bsize); - if (output_enabled) { - update_stats(cpi, mi_row, mi_col); - cpi->partition_count[pl][PARTITION_NONE]++; - - (*tp)->token = EOSB_TOKEN; - (*tp)++; - } - } else if (is_sb == BLOCK_SIZE_SB16X32) { - int i; - - if (output_enabled) - cpi->partition_count[pl][PARTITION_VERT]++; - for (i = 0; i < 2 && mi_col + (i << CONFIG_SB8X8) != cm->mi_cols; i++) { - set_offsets(cpi, mi_row, mi_col + (i << CONFIG_SB8X8), - BLOCK_SIZE_SB16X32); - update_state(cpi, &x->sb16x32_context[xd->sb_index][i], - BLOCK_SIZE_SB16X32, output_enabled); - encode_superblock(cpi, tp, - output_enabled, mi_row, mi_col + (i << CONFIG_SB8X8), - BLOCK_SIZE_SB16X32); - if (output_enabled) { - update_stats(cpi, mi_row, mi_col + i); - - (*tp)->token = EOSB_TOKEN; - (*tp)++; - } - } - } else if (is_sb == BLOCK_SIZE_SB32X16) { - int i; - - if (output_enabled) - cpi->partition_count[pl][PARTITION_HORZ]++; - for (i = 0; i < 2 && mi_row + (i << CONFIG_SB8X8) != cm->mi_rows; i++) { - set_offsets(cpi, mi_row + (i << CONFIG_SB8X8), mi_col, - BLOCK_SIZE_SB32X16); - update_state(cpi, &x->sb32x16_context[xd->sb_index][i], - BLOCK_SIZE_SB32X16, output_enabled); - encode_superblock(cpi, tp, - output_enabled, mi_row + (i << CONFIG_SB8X8), mi_col, - BLOCK_SIZE_SB32X16); - if (output_enabled) { - update_stats(cpi, mi_row + (i << CONFIG_SB8X8), mi_col); - - (*tp)->token = EOSB_TOKEN; - (*tp)++; - } - } +static void set_block_index(MACROBLOCKD *xd, int idx, + BLOCK_SIZE_TYPE bsize) { + if (bsize >= BLOCK_SIZE_SB32X32) { + xd->sb_index = idx; } else { - int i; - if (output_enabled) - cpi->partition_count[pl][PARTITION_SPLIT]++; +#if CONFIG_SB8X8 + assert(bsize >= BLOCK_SIZE_MB16X16); +#endif + xd->mb_index = idx; + } +} - for (i = 0; i < 4; i++) { - const int x_idx = (i & 1) << CONFIG_SB8X8; - const int y_idx = (i >> 1) << CONFIG_SB8X8; +static PICK_MODE_CONTEXT *get_block_context(MACROBLOCK *x, + BLOCK_SIZE_TYPE bsize) { + MACROBLOCKD *const xd = &x->e_mbd; - if ((mi_row + y_idx >= cm->mi_rows) || (mi_col + x_idx >= cm->mi_cols)) { - // MB lies outside frame, move on - continue; - } + switch (bsize) { + case BLOCK_SIZE_SB64X64: + return &x->sb64_context; + case BLOCK_SIZE_SB64X32: + return &x->sb64x32_context[xd->sb_index]; + case BLOCK_SIZE_SB32X64: + return &x->sb32x64_context[xd->sb_index]; + case BLOCK_SIZE_SB32X32: + return &x->sb32_context[xd->sb_index]; + case BLOCK_SIZE_SB32X16: + return &x->sb32x16_context[xd->sb_index][xd->mb_index]; + case BLOCK_SIZE_SB16X32: + return &x->sb16x32_context[xd->sb_index][xd->mb_index]; + case BLOCK_SIZE_MB16X16: + return &x->mb_context[xd->sb_index][xd->mb_index]; + default: + assert(0); + return NULL; + } +} - set_offsets(cpi, mi_row + y_idx, mi_col + x_idx, BLOCK_SIZE_MB16X16); - xd->mb_index = i; - update_state(cpi, &x->mb_context[xd->sb_index][i], - BLOCK_SIZE_MB16X16, output_enabled); +static void encode_b(VP9_COMP *cpi, TOKENEXTRA **tp, + int mi_row, int mi_col, int output_enabled, + BLOCK_SIZE_TYPE bsize, int sub_index) { + VP9_COMMON *const cm = &cpi->common; + MACROBLOCK *const x = &cpi->mb; + MACROBLOCKD *const xd = &x->e_mbd; - if (cpi->oxcf.tuning == VP8_TUNE_SSIM) - vp9_activity_masking(cpi, x); + if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols) + return; - encode_macroblock(cpi, tp, - output_enabled, mi_row + y_idx, mi_col + x_idx); - if (output_enabled) { - update_stats(cpi, mi_row + y_idx, mi_col + x_idx); + if (sub_index != -1) + set_block_index(xd, sub_index, bsize); + set_offsets(cpi, mi_row, mi_col, bsize); + update_state(cpi, get_block_context(x, bsize), bsize, output_enabled); + if (bsize == BLOCK_SIZE_MB16X16) { + if (cpi->oxcf.tuning == VP8_TUNE_SSIM) + vp9_activity_masking(cpi, x); - (*tp)->token = EOSB_TOKEN; - (*tp)++; - } - } + encode_macroblock(cpi, tp, output_enabled, mi_row, mi_col); + } else { + encode_superblock(cpi, tp, output_enabled, mi_row, mi_col, bsize); } - xd->above_seg_context = cm->above_seg_context + (mi_col >> CONFIG_SB8X8); - xd->left_seg_context = cm->left_seg_context + ((mi_row >> CONFIG_SB8X8) & 3); - update_partition_context(xd, is_sb, BLOCK_SIZE_SB32X32); + if (output_enabled) { + update_stats(cpi, mi_row, mi_col); - // debug output -#if DBG_PRNT_SEGMAP - { - FILE *statsfile; - statsfile = fopen("segmap2.stt", "a"); - fprintf(statsfile, "\n"); - fclose(statsfile); + (*tp)->token = EOSB_TOKEN; + (*tp)++; } -#endif } -static void encode_sb64(VP9_COMP *cpi, - int mi_row, - int mi_col, - TOKENEXTRA **tp, BLOCK_SIZE_TYPE is_sb[4]) { +static void encode_sb(VP9_COMP *cpi, TOKENEXTRA **tp, + int mi_row, int mi_col, int output_enabled, + BLOCK_SIZE_TYPE level, + BLOCK_SIZE_TYPE c1, BLOCK_SIZE_TYPE c2[4]) { VP9_COMMON *const cm = &cpi->common; MACROBLOCK *const x = &cpi->mb; MACROBLOCKD *const xd = &x->e_mbd; - BLOCK_SIZE_TYPE bsize = BLOCK_SIZE_SB64X64; + const int bsl = mi_width_log2(level), bs = 1 << (bsl - 1); + const int bwl = mi_width_log2(c1), bhl = mi_height_log2(c1); int pl; - xd->left_seg_context = cm->left_seg_context + ((mi_row >> CONFIG_SB8X8) & 3); - xd->above_seg_context = cm->above_seg_context + (mi_col >> CONFIG_SB8X8); - pl = partition_plane_context(xd, bsize); + if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols) + return; - if (is_sb[0] == BLOCK_SIZE_SB64X64) { - set_offsets(cpi, mi_row, mi_col, bsize); - update_state(cpi, &x->sb64_context, bsize, 1); - encode_superblock(cpi, tp, - 1, mi_row, mi_col, bsize); - update_stats(cpi, mi_row, mi_col); + set_partition_seg_context(cpi, mi_row, mi_col); + pl = partition_plane_context(xd, level); - (*tp)->token = EOSB_TOKEN; - (*tp)++; - cpi->partition_count[pl][PARTITION_NONE]++; - } else if (is_sb[0] == BLOCK_SIZE_SB32X64) { + if (bsl == bwl && bsl == bhl) { + if (output_enabled && level > BLOCK_SIZE_MB16X16) + cpi->partition_count[pl][PARTITION_NONE]++; + encode_b(cpi, tp, mi_row, mi_col, output_enabled, c1, -1); + } else if (bsl == bhl && bsl > bwl) { + if (output_enabled) + cpi->partition_count[pl][PARTITION_VERT]++; + encode_b(cpi, tp, mi_row, mi_col, output_enabled, c1, 0); + encode_b(cpi, tp, mi_row, mi_col + bs, output_enabled, c1, 1); + } else if (bsl == bwl && bsl > bhl) { + if (output_enabled) + cpi->partition_count[pl][PARTITION_HORZ]++; + encode_b(cpi, tp, mi_row, mi_col, output_enabled, c1, 0); + encode_b(cpi, tp, mi_row + bs, mi_col, output_enabled, c1, 1); + } else { + BLOCK_SIZE_TYPE subsize; int i; - cpi->partition_count[pl][PARTITION_VERT]++; - for (i = 0; i < 2 && mi_col + (i * 2 << CONFIG_SB8X8) != cm->mi_cols; i++) { - set_offsets(cpi, mi_row, mi_col + (i * 2 << CONFIG_SB8X8), - BLOCK_SIZE_SB32X64); - update_state(cpi, &x->sb32x64_context[i], BLOCK_SIZE_SB32X64, 1); - encode_superblock(cpi, tp, - 1, mi_row, mi_col + (i * 2 << CONFIG_SB8X8), - BLOCK_SIZE_SB32X64); - update_stats(cpi, mi_row, mi_col + (i * 2 << CONFIG_SB8X8)); - - (*tp)->token = EOSB_TOKEN; - (*tp)++; + assert(bwl < bsl && bhl < bsl); + if (level == BLOCK_SIZE_SB64X64) { + subsize = BLOCK_SIZE_SB32X32; + } else { + assert(level == BLOCK_SIZE_SB32X32); + subsize = BLOCK_SIZE_MB16X16; } - } else if (is_sb[0] == BLOCK_SIZE_SB64X32) { - int i; - cpi->partition_count[pl][PARTITION_HORZ]++; - for (i = 0; i < 2 && mi_row + (i * 2 << CONFIG_SB8X8) != cm->mi_rows; i++) { - set_offsets(cpi, mi_row + (i * 2 << CONFIG_SB8X8), mi_col, - BLOCK_SIZE_SB64X32); - update_state(cpi, &x->sb64x32_context[i], BLOCK_SIZE_SB64X32, 1); - encode_superblock(cpi, tp, - 1, mi_row + (i * 2 << CONFIG_SB8X8), mi_col, - BLOCK_SIZE_SB64X32); - update_stats(cpi, mi_row + (i * 2 << CONFIG_SB8X8), mi_col); - - (*tp)->token = EOSB_TOKEN; - (*tp)++; - } - } else { - int i; - cpi->partition_count[pl][PARTITION_SPLIT]++; + if (output_enabled) + cpi->partition_count[pl][PARTITION_SPLIT]++; + for (i = 0; i < 4; i++) { - const int x_idx = (i & 1) << (1 + CONFIG_SB8X8); - const int y_idx = (i & 2) << CONFIG_SB8X8; + const int x_idx = i & 1, y_idx = i >> 1; - if (mi_row + y_idx >= cm->mi_rows || mi_col + x_idx >= cm->mi_cols) { - // MB lies outside frame, move on - continue; - } - xd->sb_index = i; - encode_sb(cpi, mi_row + y_idx, mi_col + x_idx, 1, tp, - is_sb[i]); + set_block_index(xd, i, subsize); + encode_sb(cpi, tp, mi_row + y_idx * bs, mi_col + x_idx * bs, + output_enabled, subsize, + subsize == BLOCK_SIZE_MB16X16 ? c1 : c2[i], c2); } } - if (is_sb[0] > BLOCK_SIZE_SB32X32) { - xd->above_seg_context = cm->above_seg_context + (mi_col >> CONFIG_SB8X8); - xd->left_seg_context = - cm->left_seg_context + ((mi_row >> CONFIG_SB8X8) & 3); - update_partition_context(xd, is_sb[0], BLOCK_SIZE_SB64X64); + if (level > BLOCK_SIZE_MB16X16 && + (level == BLOCK_SIZE_SB32X32 || bsl == bwl || bsl == bhl)) { + set_partition_seg_context(cpi, mi_row, mi_col); + update_partition_context(xd, c1, level); } } @@ -983,22 +927,27 @@ static void encode_sb_row(VP9_COMP *cpi, int mi_col, pl; // Initialize the left context for the new SB row - vpx_memset(cm->left_context, 0, sizeof(cm->left_context)); + vpx_memset(&cm->left_context, 0, sizeof(cm->left_context)); vpx_memset(cm->left_seg_context, 0, sizeof(cm->left_seg_context)); // Code each SB in the row for (mi_col = cm->cur_tile_mi_col_start; mi_col < cm->cur_tile_mi_col_end; mi_col += (4 << CONFIG_SB8X8)) { - int i; + int i, p; BLOCK_SIZE_TYPE sb_partitioning[4]; int sb64_rate = 0, sb64_dist = 0; int sb64_skip = 0; - ENTROPY_CONTEXT_PLANES l[4], a[4]; + ENTROPY_CONTEXT l[16 * MAX_MB_PLANE], a[16 * MAX_MB_PLANE]; PARTITION_CONTEXT seg_l[4], seg_a[4]; TOKENEXTRA *tp_orig = *tp; - memcpy(&a, cm->above_context + (mi_col >> CONFIG_SB8X8), sizeof(a)); - memcpy(&l, cm->left_context, sizeof(l)); + for (p = 0; p < MAX_MB_PLANE; p++) { + memcpy(a + 16 * p, cm->above_context[p] + + (mi_col * 4 >> (CONFIG_SB8X8 + xd->plane[p].subsampling_x)), + sizeof(ENTROPY_CONTEXT) * 16 >> xd->plane[p].subsampling_x); + memcpy(l + 16 * p, cm->left_context[p], + sizeof(ENTROPY_CONTEXT) * 16 >> xd->plane[p].subsampling_y); + } memcpy(&seg_a, cm->above_seg_context + (mi_col >> CONFIG_SB8X8), sizeof(seg_a)); memcpy(&seg_l, cm->left_seg_context, sizeof(seg_l)); @@ -1009,7 +958,7 @@ static void encode_sb_row(VP9_COMP *cpi, int splitmodes_used = 0; int sb32_skip = 0; int j; - ENTROPY_CONTEXT_PLANES l2[2], a2[2]; + ENTROPY_CONTEXT l2[8 * MAX_MB_PLANE], a2[8 * MAX_MB_PLANE]; if (mi_row + y_idx >= cm->mi_rows || mi_col + x_idx >= cm->mi_cols) continue; @@ -1017,9 +966,18 @@ static void encode_sb_row(VP9_COMP *cpi, xd->sb_index = i; /* Function should not modify L & A contexts; save and restore on exit */ - vpx_memcpy(l2, cm->left_context + (y_idx >> CONFIG_SB8X8), sizeof(l2)); - vpx_memcpy(a2, cm->above_context + ((mi_col + x_idx) >> CONFIG_SB8X8), - sizeof(a2)); + for (p = 0; p < MAX_MB_PLANE; p++) { + vpx_memcpy(l2 + 8 * p, + cm->left_context[p] + + (y_idx * 4 >> (CONFIG_SB8X8 + + xd->plane[p].subsampling_y)), + sizeof(ENTROPY_CONTEXT) * 8 >> xd->plane[p].subsampling_y); + vpx_memcpy(a2 + 8 * p, + cm->above_context[p] + + ((mi_col + x_idx) * 4 >> (CONFIG_SB8X8 + + xd->plane[p].subsampling_x)), + sizeof(ENTROPY_CONTEXT) * 8 >> xd->plane[p].subsampling_x); + } /* Encode MBs in raster order within the SB */ sb_partitioning[i] = BLOCK_SIZE_MB16X16; @@ -1052,13 +1010,20 @@ static void encode_sb_row(VP9_COMP *cpi, } /* Restore L & A coding context to those in place on entry */ - vpx_memcpy(cm->left_context + (y_idx >> CONFIG_SB8X8), l2, sizeof(l2)); - vpx_memcpy(cm->above_context + ((mi_col + x_idx) >> CONFIG_SB8X8), a2, - sizeof(a2)); + for (p = 0; p < MAX_MB_PLANE; p++) { + vpx_memcpy(cm->left_context[p] + + (y_idx * 4 >> (CONFIG_SB8X8 + + xd->plane[p].subsampling_y)), + l2 + 8 * p, + sizeof(ENTROPY_CONTEXT) * 8 >> xd->plane[p].subsampling_y); + vpx_memcpy(cm->above_context[p] + + ((mi_col + x_idx) * 4 >> (CONFIG_SB8X8 + + xd->plane[p].subsampling_x)), + a2 + 8 * p, + sizeof(ENTROPY_CONTEXT) * 8 >> xd->plane[p].subsampling_x); + } - xd->left_seg_context = cm->left_seg_context + (y_idx >> CONFIG_SB8X8); - xd->above_seg_context = - cm->above_seg_context + ((mi_col + x_idx) >> CONFIG_SB8X8); + set_partition_seg_context(cpi, mi_row + y_idx, mi_col + x_idx); pl = partition_plane_context(xd, BLOCK_SIZE_SB32X32); sb32_rate += x->partition_cost[pl][PARTITION_SPLIT]; @@ -1091,9 +1056,7 @@ static void encode_sb_row(VP9_COMP *cpi, d += d2; } - xd->left_seg_context = cm->left_seg_context + (y_idx >> CONFIG_SB8X8); - xd->above_seg_context = - cm->above_seg_context + ((mi_col + x_idx) >> CONFIG_SB8X8); + set_partition_seg_context(cpi, mi_row + y_idx, mi_col + x_idx); pl = partition_plane_context(xd, BLOCK_SIZE_SB32X32); r += x->partition_cost[pl][PARTITION_HORZ]; @@ -1105,9 +1068,18 @@ static void encode_sb_row(VP9_COMP *cpi, sb_partitioning[i] = BLOCK_SIZE_SB32X16; } - vpx_memcpy(cm->left_context + (y_idx >> CONFIG_SB8X8), l2, sizeof(l2)); - vpx_memcpy(cm->above_context + ((mi_col + x_idx) >> CONFIG_SB8X8), a2, - sizeof(a2)); + for (p = 0; p < MAX_MB_PLANE; p++) { + vpx_memcpy(cm->left_context[p] + + (y_idx * 4 >> (CONFIG_SB8X8 + + xd->plane[p].subsampling_y)), + l2 + 8 * p, + sizeof(ENTROPY_CONTEXT) * 8 >> xd->plane[p].subsampling_y); + vpx_memcpy(cm->above_context[p] + + ((mi_col + x_idx) * 4 >> (CONFIG_SB8X8 + + xd->plane[p].subsampling_x)), + a2 + 8 * p, + sizeof(ENTROPY_CONTEXT) * 8 >> xd->plane[p].subsampling_x); + } } // check 16x32 @@ -1135,10 +1107,7 @@ static void encode_sb_row(VP9_COMP *cpi, d += d2; } - xd->left_seg_context = - cm->left_seg_context + (y_idx >> CONFIG_SB8X8); - xd->above_seg_context = - cm->above_seg_context + ((mi_col + x_idx) >> CONFIG_SB8X8); + set_partition_seg_context(cpi, mi_row + y_idx, mi_col + x_idx); pl = partition_plane_context(xd, BLOCK_SIZE_SB32X32); r += x->partition_cost[pl][PARTITION_VERT]; @@ -1150,9 +1119,18 @@ static void encode_sb_row(VP9_COMP *cpi, sb_partitioning[i] = BLOCK_SIZE_SB16X32; } - vpx_memcpy(cm->left_context + (y_idx >> CONFIG_SB8X8), l2, sizeof(l2)); - vpx_memcpy(cm->above_context + ((mi_col + x_idx) >> CONFIG_SB8X8), a2, - sizeof(a2)); + for (p = 0; p < MAX_MB_PLANE; p++) { + vpx_memcpy(cm->left_context[p] + + (y_idx * 4 >> (CONFIG_SB8X8 + + xd->plane[p].subsampling_y)), + l2 + 8 * p, + sizeof(ENTROPY_CONTEXT) * 8 >> xd->plane[p].subsampling_y); + vpx_memcpy(cm->above_context[p] + + ((mi_col + x_idx) * 4 >> (CONFIG_SB8X8 + + xd->plane[p].subsampling_x)), + a2 + 8 * p, + sizeof(ENTROPY_CONTEXT) * 8 >> xd->plane[p].subsampling_x); + } } if (!sb32_skip && @@ -1165,9 +1143,7 @@ static void encode_sb_row(VP9_COMP *cpi, tp, &r, &d, BLOCK_SIZE_SB32X32, &x->sb32_context[xd->sb_index]); - xd->left_seg_context = cm->left_seg_context + (y_idx >> CONFIG_SB8X8); - xd->above_seg_context = - cm->above_seg_context + ((mi_col + x_idx) >> CONFIG_SB8X8); + set_partition_seg_context(cpi, mi_row + y_idx, mi_col + x_idx); pl = partition_plane_context(xd, BLOCK_SIZE_SB32X32); r += x->partition_cost[pl][PARTITION_NONE]; @@ -1193,18 +1169,23 @@ static void encode_sb_row(VP9_COMP *cpi, // pixels of the lower level; also, inverting SB/MB order (big->small // instead of small->big) means we can use as threshold for small, which // may enable breakouts if RD is not good enough (i.e. faster) - encode_sb(cpi, mi_row + y_idx, mi_col + x_idx, 0, tp, - sb_partitioning[i]); + encode_sb(cpi, tp, mi_row + y_idx, mi_col + x_idx, 0, + BLOCK_SIZE_SB32X32, sb_partitioning[i], sb_partitioning); } - memcpy(cm->above_context + (mi_col >> CONFIG_SB8X8), &a, sizeof(a)); - memcpy(cm->left_context, &l, sizeof(l)); + for (p = 0; p < MAX_MB_PLANE; p++) { + memcpy(cm->above_context[p] + + (mi_col * 4 >> (CONFIG_SB8X8 + xd->plane[p].subsampling_x)), + a + 16 * p, + sizeof(ENTROPY_CONTEXT) * 16 >> xd->plane[p].subsampling_x); + memcpy(cm->left_context[p], l + 16 * p, + sizeof(ENTROPY_CONTEXT) * 16 >> xd->plane[p].subsampling_y); + } memcpy(cm->above_seg_context + (mi_col >> CONFIG_SB8X8), &seg_a, sizeof(seg_a)); memcpy(cm->left_seg_context, &seg_l, sizeof(seg_l)); - xd->left_seg_context = cm->left_seg_context; - xd->above_seg_context = cm->above_seg_context + (mi_col >> CONFIG_SB8X8); + set_partition_seg_context(cpi, mi_row, mi_col); pl = partition_plane_context(xd, BLOCK_SIZE_SB64X64); sb64_rate += x->partition_cost[pl][PARTITION_SPLIT]; @@ -1231,8 +1212,7 @@ static void encode_sb_row(VP9_COMP *cpi, d += d2; } - xd->left_seg_context = cm->left_seg_context; - xd->above_seg_context = cm->above_seg_context + (mi_col >> CONFIG_SB8X8); + set_partition_seg_context(cpi, mi_row, mi_col); pl = partition_plane_context(xd, BLOCK_SIZE_SB64X64); r += x->partition_cost[pl][PARTITION_HORZ]; @@ -1244,8 +1224,14 @@ static void encode_sb_row(VP9_COMP *cpi, sb_partitioning[0] = BLOCK_SIZE_SB64X32; } - vpx_memcpy(cm->left_context, l, sizeof(l)); - vpx_memcpy(cm->above_context + (mi_col >> CONFIG_SB8X8), a, sizeof(a)); + for (p = 0; p < MAX_MB_PLANE; p++) { + memcpy(cm->above_context[p] + + (mi_col * 4 >> (CONFIG_SB8X8 + xd->plane[p].subsampling_x)), + a + 16 * p, + sizeof(ENTROPY_CONTEXT) * 16 >> xd->plane[p].subsampling_x); + memcpy(cm->left_context[p], l + 16 * p, + sizeof(ENTROPY_CONTEXT) * 16 >> xd->plane[p].subsampling_y); + } } // check 32x64 @@ -1271,8 +1257,7 @@ static void encode_sb_row(VP9_COMP *cpi, d += d2; } - xd->left_seg_context = cm->left_seg_context; - xd->above_seg_context = cm->above_seg_context + (mi_col >> CONFIG_SB8X8); + set_partition_seg_context(cpi, mi_row, mi_col); pl = partition_plane_context(xd, BLOCK_SIZE_SB64X64); r += x->partition_cost[pl][PARTITION_VERT]; @@ -1284,8 +1269,14 @@ static void encode_sb_row(VP9_COMP *cpi, sb_partitioning[0] = BLOCK_SIZE_SB32X64; } - vpx_memcpy(cm->left_context, l, sizeof(l)); - vpx_memcpy(cm->above_context + (mi_col >> CONFIG_SB8X8), a, sizeof(a)); + for (p = 0; p < MAX_MB_PLANE; p++) { + memcpy(cm->above_context[p] + + (mi_col * 4 >> (CONFIG_SB8X8 + xd->plane[p].subsampling_x)), + a + 16 * p, + sizeof(ENTROPY_CONTEXT) * 16 >> xd->plane[p].subsampling_x); + memcpy(cm->left_context[p], l + 16 * p, + sizeof(ENTROPY_CONTEXT) * 16 >> xd->plane[p].subsampling_y); + } } if (!sb64_skip && @@ -1296,8 +1287,7 @@ static void encode_sb_row(VP9_COMP *cpi, pick_sb_modes(cpi, mi_row, mi_col, tp, &r, &d, BLOCK_SIZE_SB64X64, &x->sb64_context); - xd->left_seg_context = cm->left_seg_context; - xd->above_seg_context = cm->above_seg_context + (mi_col >> CONFIG_SB8X8); + set_partition_seg_context(cpi, mi_row, mi_col); pl = partition_plane_context(xd, BLOCK_SIZE_SB64X64); r += x->partition_cost[pl][PARTITION_NONE]; @@ -1310,7 +1300,8 @@ static void encode_sb_row(VP9_COMP *cpi, } assert(tp_orig == *tp); - encode_sb64(cpi, mi_row, mi_col, tp, sb_partitioning); + encode_sb(cpi, tp, mi_row, mi_col, 1, + BLOCK_SIZE_SB64X64, sb_partitioning[0], sb_partitioning); assert(tp_orig < *tp); } } @@ -1368,8 +1359,10 @@ static void init_encode_frame_mb_context(VP9_COMP *cpi) { vp9_zero(cpi->interintra_select_count); #endif - vpx_memset(cm->above_context, 0, - sizeof(ENTROPY_CONTEXT_PLANES) * mb_cols_aligned_to_sb(cm)); + // Note: this memset assumes above_context[0], [1] and [2] + // are allocated as part of the same buffer. + vpx_memset(cm->above_context[0], 0, sizeof(ENTROPY_CONTEXT) * 4 * + MAX_MB_PLANE * mb_cols_aligned_to_sb(cm)); vpx_memset(cm->above_seg_context, 0, sizeof(PARTITION_CONTEXT) * mb_cols_aligned_to_sb(cm)); } @@ -1564,19 +1557,22 @@ static void set_txfm_flag(MODE_INFO *mi, int mis, int ymbs, int xmbs, } } -static void reset_skip_txfm_size_sb(VP9_COMP *cpi, MODE_INFO *mi, - int mis, TX_SIZE txfm_max, - int mi_rows_left, int mi_cols_left, - BLOCK_SIZE_TYPE bsize) { +static void reset_skip_txfm_size_b(VP9_COMP *cpi, MODE_INFO *mi, + int mis, TX_SIZE txfm_max, + int bw, int bh, int mi_row, int mi_col, + BLOCK_SIZE_TYPE bsize) { + VP9_COMMON *const cm = &cpi->common; MB_MODE_INFO *const mbmi = &mi->mbmi; + if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols) + return; + if (mbmi->txfm_size > txfm_max) { MACROBLOCK *const x = &cpi->mb; MACROBLOCKD *const xd = &x->e_mbd; const int segment_id = mbmi->segment_id; - const int bh = 1 << mi_height_log2(bsize), bw = 1 << mi_width_log2(bsize); - const int ymbs = MIN(bh, mi_rows_left); - const int xmbs = MIN(bw, mi_cols_left); + const int ymbs = MIN(bh, cm->mi_rows - mi_row); + const int xmbs = MIN(bw, cm->mi_cols - mi_col); xd->mode_info_context = mi; assert(vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP) || @@ -1585,6 +1581,56 @@ static void reset_skip_txfm_size_sb(VP9_COMP *cpi, MODE_INFO *mi, } } +static void reset_skip_txfm_size_sb(VP9_COMP *cpi, MODE_INFO *mi, + TX_SIZE txfm_max, + int mi_row, int mi_col, + BLOCK_SIZE_TYPE bsize) { + VP9_COMMON *const cm = &cpi->common; + const int mis = cm->mode_info_stride; + int bwl, bhl; + const int bsl = mi_width_log2(bsize), bs = 1 << (bsl - 1); + + if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols) + return; + + bwl = mi_width_log2(mi->mbmi.sb_type); + bhl = mi_height_log2(mi->mbmi.sb_type); + + if (bwl == bsl && bhl == bsl) { + reset_skip_txfm_size_b(cpi, mi, mis, txfm_max, 1 << bsl, 1 << bsl, + mi_row, mi_col, bsize); + } else if (bwl == bsl && bhl < bsl) { + reset_skip_txfm_size_b(cpi, mi, mis, txfm_max, 1 << bsl, bs, + mi_row, mi_col, bsize); + reset_skip_txfm_size_b(cpi, mi + bs * mis, mis, txfm_max, 1 << bsl, bs, + mi_row + bs, mi_col, bsize); + } else if (bwl < bsl && bhl == bsl) { + reset_skip_txfm_size_b(cpi, mi, mis, txfm_max, bs, 1 << bsl, + mi_row, mi_col, bsize); + reset_skip_txfm_size_b(cpi, mi + bs, mis, txfm_max, bs, 1 << bsl, + mi_row, mi_col + bs, bsize); + } else { + BLOCK_SIZE_TYPE subsize; + int n; + + assert(bwl < bsl && bhl < bsl); + if (bsize == BLOCK_SIZE_SB64X64) { + subsize = BLOCK_SIZE_SB32X32; + } else { + assert(bsize == BLOCK_SIZE_SB32X32); + subsize = BLOCK_SIZE_MB16X16; + } + + for (n = 0; n < 4; n++) { + const int y_idx = n >> 1, x_idx = n & 0x01; + + reset_skip_txfm_size_sb(cpi, mi + y_idx * bs * mis + x_idx * bs, + txfm_max, mi_row + y_idx * bs, + mi_col + x_idx * bs, subsize); + } + } +} + static void reset_skip_txfm_size(VP9_COMP *cpi, TX_SIZE txfm_max) { VP9_COMMON *const cm = &cpi->common; int mi_row, mi_col; @@ -1596,92 +1642,8 @@ static void reset_skip_txfm_size(VP9_COMP *cpi, TX_SIZE txfm_max) { mi = mi_ptr; for (mi_col = 0; mi_col < cm->mi_cols; mi_col += (4 << CONFIG_SB8X8), mi += (4 << CONFIG_SB8X8)) { - if (mi->mbmi.sb_type == BLOCK_SIZE_SB64X64) { - reset_skip_txfm_size_sb(cpi, mi, mis, txfm_max, - cm->mi_rows - mi_row, cm->mi_cols - mi_col, - BLOCK_SIZE_SB64X64); - } else if (mi->mbmi.sb_type == BLOCK_SIZE_SB64X32) { - reset_skip_txfm_size_sb(cpi, mi, mis, txfm_max, - cm->mi_rows - mi_row, cm->mi_cols - mi_col, - BLOCK_SIZE_SB64X32); - if (mi_row + (2 << CONFIG_SB8X8) != cm->mi_rows) - reset_skip_txfm_size_sb(cpi, mi + (2 << CONFIG_SB8X8) * mis, mis, - txfm_max, - cm->mi_rows - mi_row - (2 << CONFIG_SB8X8), - cm->mi_cols - mi_col, - BLOCK_SIZE_SB64X32); - } else if (mi->mbmi.sb_type == BLOCK_SIZE_SB32X64) { - reset_skip_txfm_size_sb(cpi, mi, mis, txfm_max, - cm->mi_rows - mi_row, cm->mi_cols - mi_col, - BLOCK_SIZE_SB32X64); - if (mi_col + (2 << CONFIG_SB8X8) != cm->mi_cols) - reset_skip_txfm_size_sb(cpi, mi + (2 << CONFIG_SB8X8), mis, txfm_max, - cm->mi_rows - mi_row, - cm->mi_cols - mi_col - (2 << CONFIG_SB8X8), - BLOCK_SIZE_SB32X64); - } else { - int i; - - for (i = 0; i < 4; i++) { - const int x_idx_sb = (i & 1) << (1 + CONFIG_SB8X8); - const int y_idx_sb = (i & 2) << CONFIG_SB8X8; - MODE_INFO *sb_mi = mi + y_idx_sb * mis + x_idx_sb; - - if (mi_row + y_idx_sb >= cm->mi_rows || - mi_col + x_idx_sb >= cm->mi_cols) - continue; - - if (sb_mi->mbmi.sb_type == BLOCK_SIZE_SB32X32) { - reset_skip_txfm_size_sb(cpi, sb_mi, mis, txfm_max, - cm->mi_rows - mi_row - y_idx_sb, - cm->mi_cols - mi_col - x_idx_sb, - BLOCK_SIZE_SB32X32); - } else if (sb_mi->mbmi.sb_type == BLOCK_SIZE_SB32X16) { - reset_skip_txfm_size_sb(cpi, sb_mi, mis, txfm_max, - cm->mi_rows - mi_row - y_idx_sb, - cm->mi_cols - mi_col - x_idx_sb, - BLOCK_SIZE_SB32X16); - if (mi_row + y_idx_sb + (1 << CONFIG_SB8X8) != cm->mi_rows) - reset_skip_txfm_size_sb(cpi, sb_mi + (mis << CONFIG_SB8X8), mis, - txfm_max, - cm->mi_rows - mi_row - y_idx_sb - - (1 << CONFIG_SB8X8), - cm->mi_cols - mi_col - x_idx_sb, - BLOCK_SIZE_SB32X16); - } else if (sb_mi->mbmi.sb_type == BLOCK_SIZE_SB16X32) { - reset_skip_txfm_size_sb(cpi, sb_mi, mis, txfm_max, - cm->mi_rows - mi_row - y_idx_sb, - cm->mi_cols - mi_col - x_idx_sb, - BLOCK_SIZE_SB16X32); - if (mi_col + x_idx_sb + (1 << CONFIG_SB8X8) != cm->mi_cols) - reset_skip_txfm_size_sb(cpi, sb_mi + (1 << CONFIG_SB8X8), mis, - txfm_max, - cm->mi_rows - mi_row - y_idx_sb, - cm->mi_cols - mi_col - x_idx_sb - - (1 << CONFIG_SB8X8), - BLOCK_SIZE_SB16X32); - } else { - int m; - - for (m = 0; m < 4; m++) { - const int x_idx = x_idx_sb + ((m & 1) << CONFIG_SB8X8); - const int y_idx = y_idx_sb + ((m >> 1) << CONFIG_SB8X8); - MODE_INFO *mb_mi; - - if (mi_col + x_idx >= cm->mi_cols || - mi_row + y_idx >= cm->mi_rows) - continue; - - mb_mi = mi + y_idx * mis + x_idx; - assert(mb_mi->mbmi.sb_type == BLOCK_SIZE_MB16X16); - reset_skip_txfm_size_sb(cpi, mb_mi, mis, txfm_max, - cm->mi_rows - mi_row - y_idx, - cm->mi_cols - mi_col - x_idx, - BLOCK_SIZE_MB16X16); - } - } - } - } + reset_skip_txfm_size_sb(cpi, mi, txfm_max, + mi_row, mi_col, BLOCK_SIZE_SB64X64); } } } @@ -1984,7 +1946,7 @@ static void encode_macroblock(VP9_COMP *cpi, TOKENEXTRA **t, #endif if (mbmi->mode == I4X4_PRED) { vp9_encode_intra16x16mbuv(cm, x); - vp9_encode_intra4x4mby(x); + vp9_encode_intra4x4mby(x, BLOCK_SIZE_MB16X16); } else if (mbmi->mode == I8X8_PRED) { vp9_encode_intra8x8mby(x); vp9_encode_intra8x8mbuv(x); @@ -2101,8 +2063,7 @@ static void encode_macroblock(VP9_COMP *cpi, TOKENEXTRA **t, } #endif - vp9_tokenize_mb(cpi, xd, t, !output_enabled); - + vp9_tokenize_sb(cpi, xd, t, !output_enabled, BLOCK_SIZE_MB16X16); } else { // FIXME(rbultje): not tile-aware (mi - 1) int mb_skip_context = |