Index: source/libvpx/vp9/encoder/vp9_encodeframe.c |
=================================================================== |
--- source/libvpx/vp9/encoder/vp9_encodeframe.c (revision 177019) |
+++ source/libvpx/vp9/encoder/vp9_encodeframe.c (working copy) |
@@ -9,13 +9,14 @@ |
*/ |
-#include "vpx_ports/config.h" |
+#include "./vpx_config.h" |
#include "vp9/encoder/vp9_encodeframe.h" |
#include "vp9/encoder/vp9_encodemb.h" |
#include "vp9/encoder/vp9_encodemv.h" |
#include "vp9/common/vp9_common.h" |
#include "vp9/encoder/vp9_onyx_int.h" |
#include "vp9/common/vp9_extend.h" |
+#include "vp9/common/vp9_entropy.h" |
#include "vp9/common/vp9_entropymode.h" |
#include "vp9/common/vp9_quant_common.h" |
#include "vp9/encoder/vp9_segmentation.h" |
@@ -44,15 +45,20 @@ |
int enc_debug = 0; |
#endif |
-static void encode_macroblock(VP9_COMP *cpi, MACROBLOCK *x, |
- TOKENEXTRA **t, int recon_yoffset, |
- int recon_uvoffset, int output_enabled, |
- int mb_col, int mb_row); |
+extern void select_interp_filter_type(VP9_COMP *cpi); |
-static void encode_superblock(VP9_COMP *cpi, MACROBLOCK *x, |
- TOKENEXTRA **t, int recon_yoffset, |
- int recon_uvoffset, int mb_col, int mb_row); |
+static void encode_macroblock(VP9_COMP *cpi, TOKENEXTRA **t, |
+ int recon_yoffset, int recon_uvoffset, |
+ int output_enabled, int mb_row, int mb_col); |
+static void encode_superblock32(VP9_COMP *cpi, TOKENEXTRA **t, |
+ int recon_yoffset, int recon_uvoffset, |
+ int output_enabled, int mb_row, int mb_col); |
+ |
+static void encode_superblock64(VP9_COMP *cpi, TOKENEXTRA **t, |
+ int recon_yoffset, int recon_uvoffset, |
+ int output_enabled, int mb_row, int mb_col); |
+ |
static void adjust_act_zbin(VP9_COMP *cpi, MACROBLOCK *x); |
#ifdef MODE_STATS |
@@ -79,7 +85,7 @@ |
* Eventually this should be replaced by custom no-reference routines, |
* which will be faster. |
*/ |
-static const unsigned char VP9_VAR_OFFS[16] = { |
+static const uint8_t VP9_VAR_OFFS[16] = { |
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 |
}; |
@@ -279,10 +285,6 @@ |
xd->left_available = (mb_col != 0); |
recon_yoffset += 16; |
#endif |
-#if !CONFIG_SUPERBLOCKS |
- // Copy current mb to a buffer |
- vp9_copy_mem16x16(x->src.y_buffer, x->src.y_stride, x->thismb, 16); |
-#endif |
// measure activity |
mb_activity = mb_activity_measure(cpi, x, mb_row, mb_col); |
@@ -391,12 +393,11 @@ |
MACROBLOCKD *xd = &x->e_mbd; |
int max_mv = MV_MAX; |
- cost = vp9_cost_mv_ref_id(xd->mb_mv_ref_id_probs[ref_frame], 0) + |
+ cost = vp9_cost_mv_ref_id(xd->mb_mv_ref_probs[ref_frame], 0) + |
vp9_mv_bit_cost(&target_mv, &mv_ref_list[0], x->nmvjointcost, |
x->mvcost, 96, xd->allow_high_precision_mv); |
- // Use 4 for now : for (i = 1; i < MAX_MV_REFS; ++i ) { |
- for (i = 1; i < 4; ++i) { |
+ for (i = 1; i < MAX_MV_REF_CANDIDATES; ++i) { |
// If we see a 0,0 reference vector for a second time we have reached |
// the end of the list of valid candidate vectors. |
if (!mv_ref_list[i].as_int) { |
@@ -413,7 +414,7 @@ |
continue; |
} |
- cost2 = vp9_cost_mv_ref_id(xd->mb_mv_ref_id_probs[ref_frame], i) + |
+ cost2 = vp9_cost_mv_ref_id(xd->mb_mv_ref_probs[ref_frame], i) + |
vp9_mv_bit_cost(&target_mv, &mv_ref_list[i], x->nmvjointcost, |
x->mvcost, 96, xd->allow_high_precision_mv); |
@@ -422,43 +423,47 @@ |
best_index = i; |
} |
} |
- |
best_ref->as_int = mv_ref_list[best_index].as_int; |
return best_index; |
} |
#endif |
-static void update_state(VP9_COMP *cpi, MACROBLOCK *x, |
- PICK_MODE_CONTEXT *ctx) { |
- int i; |
- MACROBLOCKD *xd = &x->e_mbd; |
+static void update_state(VP9_COMP *cpi, |
+ PICK_MODE_CONTEXT *ctx, int block_size, |
+ int output_enabled) { |
+ int i, x_idx, y; |
+ MACROBLOCK *const x = &cpi->mb; |
+ MACROBLOCKD *const xd = &x->e_mbd; |
MODE_INFO *mi = &ctx->mic; |
- MB_MODE_INFO * mbmi = &xd->mode_info_context->mbmi; |
+ MB_MODE_INFO *const mbmi = &xd->mode_info_context->mbmi; |
int mb_mode = mi->mbmi.mode; |
int mb_mode_index = ctx->best_mode_index; |
+ const int mis = cpi->common.mode_info_stride; |
+ int mb_block_size = 1 << mi->mbmi.sb_type; |
#if CONFIG_DEBUG |
assert(mb_mode < MB_MODE_COUNT); |
assert(mb_mode_index < MAX_MODES); |
assert(mi->mbmi.ref_frame < MAX_REF_FRAMES); |
#endif |
+ assert(mi->mbmi.sb_type == (block_size >> 5)); |
// Restore the coding context of the MB to that that was in place |
// when the mode was picked for it |
- vpx_memcpy(xd->mode_info_context, mi, sizeof(MODE_INFO)); |
-#if CONFIG_SUPERBLOCKS |
- if (mi->mbmi.encoded_as_sb) { |
- const int mis = cpi->common.mode_info_stride; |
- if (xd->mb_to_right_edge >= 0) |
- vpx_memcpy(xd->mode_info_context + 1, mi, sizeof(MODE_INFO)); |
- if (xd->mb_to_bottom_edge >= 0) { |
- vpx_memcpy(xd->mode_info_context + mis, mi, sizeof(MODE_INFO)); |
- if (xd->mb_to_right_edge >= 0) |
- vpx_memcpy(xd->mode_info_context + mis + 1, mi, sizeof(MODE_INFO)); |
+ for (y = 0; y < mb_block_size; y++) { |
+ for (x_idx = 0; x_idx < mb_block_size; x_idx++) { |
+ if ((xd->mb_to_right_edge >> 7) + mb_block_size > x_idx && |
+ (xd->mb_to_bottom_edge >> 7) + mb_block_size > y) { |
+ MODE_INFO *mi_addr = xd->mode_info_context + x_idx + y * mis; |
+ |
+ vpx_memcpy(mi_addr, mi, sizeof(MODE_INFO)); |
+ } |
} |
} |
-#endif |
+ if (block_size == 16) { |
+ ctx->txfm_rd_diff[ALLOW_32X32] = ctx->txfm_rd_diff[ALLOW_16X16]; |
+ } |
if (mb_mode == B_PRED) { |
for (i = 0; i < 16; i++) { |
@@ -477,6 +482,10 @@ |
mbmi->mv[1].as_int = x->partition_info->bmi[15].second_mv.as_int; |
} |
+ x->skip = ctx->skip; |
+ if (!output_enabled) |
+ return; |
+ |
{ |
int segment_id = mbmi->segment_id; |
if (!vp9_segfeature_active(xd, segment_id, SEG_LVL_EOB) || |
@@ -550,6 +559,7 @@ |
best_index = pick_best_mv_ref(x, rf, mbmi->mv[0], |
mbmi->ref_mvs[rf], &best_mv); |
mbmi->best_index = best_index; |
+ ++cpi->mb_mv_ref_count[rf][best_index]; |
if (mbmi->second_ref_frame > 0) { |
unsigned int best_index; |
@@ -558,6 +568,7 @@ |
mbmi->ref_mvs[sec_ref_frame], |
&best_second_mv); |
mbmi->best_second_index = best_index; |
+ ++cpi->mb_mv_ref_count[sec_ref_frame][best_index]; |
} |
#endif |
} |
@@ -578,6 +589,7 @@ |
++cpi->interintra_count[0]; |
} |
} |
+#endif |
if (cpi->common.mcomp_filter_type == SWITCHABLE && |
mbmi->mode >= NEARESTMV && |
mbmi->mode <= SPLITMV) { |
@@ -585,7 +597,6 @@ |
[vp9_get_pred_context(&cpi->common, xd, PRED_SWITCHABLE_INTERP)] |
[vp9_switchable_interp_map[mbmi->interp_filter]]; |
} |
-#endif |
cpi->prediction_error += ctx->distortion; |
cpi->intra_error += ctx->intra_error; |
@@ -596,34 +607,154 @@ |
} |
} |
+static unsigned find_seg_id(uint8_t *buf, int block_size, |
+ int start_y, int height, int start_x, int width) { |
+ const int end_x = MIN(start_x + block_size, width); |
+ const int end_y = MIN(start_y + block_size, height); |
+ int x, y; |
+ unsigned seg_id = -1; |
+ |
+ buf += width * start_y; |
+ for (y = start_y; y < end_y; y++, buf += width) { |
+ for (x = start_x; x < end_x; x++) { |
+ seg_id = MIN(seg_id, buf[x]); |
+ } |
+ } |
+ |
+ return seg_id; |
+} |
+ |
+static void set_offsets(VP9_COMP *cpi, |
+ int mb_row, int mb_col, int block_size, |
+ int *ref_yoffset, int *ref_uvoffset) { |
+ MACROBLOCK *const x = &cpi->mb; |
+ VP9_COMMON *const cm = &cpi->common; |
+ MACROBLOCKD *const xd = &x->e_mbd; |
+ MB_MODE_INFO *mbmi; |
+ const int dst_fb_idx = cm->new_fb_idx; |
+ const int recon_y_stride = cm->yv12_fb[dst_fb_idx].y_stride; |
+ const int recon_uv_stride = cm->yv12_fb[dst_fb_idx].uv_stride; |
+ const int recon_yoffset = 16 * mb_row * recon_y_stride + 16 * mb_col; |
+ const int recon_uvoffset = 8 * mb_row * recon_uv_stride + 8 * mb_col; |
+ const int src_y_stride = x->src.y_stride; |
+ const int src_uv_stride = x->src.uv_stride; |
+ const int src_yoffset = 16 * mb_row * src_y_stride + 16 * mb_col; |
+ const int src_uvoffset = 8 * mb_row * src_uv_stride + 8 * mb_col; |
+ const int ref_fb_idx = cm->lst_fb_idx; |
+ const int ref_y_stride = cm->yv12_fb[ref_fb_idx].y_stride; |
+ const int ref_uv_stride = cm->yv12_fb[ref_fb_idx].uv_stride; |
+ const int idx_map = mb_row * cm->mb_cols + mb_col; |
+ const int idx_str = xd->mode_info_stride * mb_row + mb_col; |
+ |
+ // entropy context structures |
+ xd->above_context = cm->above_context + mb_col; |
+ xd->left_context = cm->left_context + (mb_row & 3); |
+ |
+ // GF active flags data structure |
+ x->gf_active_ptr = (signed char *)&cpi->gf_active_flags[idx_map]; |
+ |
+ // Activity map pointer |
+ x->mb_activity_ptr = &cpi->mb_activity_map[idx_map]; |
+ x->active_ptr = cpi->active_map + idx_map; |
+ |
+ /* pointers to mode info contexts */ |
+ x->partition_info = x->pi + idx_str; |
+ xd->mode_info_context = cm->mi + idx_str; |
+ mbmi = &xd->mode_info_context->mbmi; |
+ xd->prev_mode_info_context = cm->prev_mi + idx_str; |
+ |
+ // Set up destination pointers |
+ xd->dst.y_buffer = cm->yv12_fb[dst_fb_idx].y_buffer + recon_yoffset; |
+ xd->dst.u_buffer = cm->yv12_fb[dst_fb_idx].u_buffer + recon_uvoffset; |
+ xd->dst.v_buffer = cm->yv12_fb[dst_fb_idx].v_buffer + recon_uvoffset; |
+ |
+ /* Set up limit values for MV components to prevent them from |
+ * extending beyond the UMV borders assuming 16x16 block size */ |
+ x->mv_row_min = -((mb_row * 16) + VP9BORDERINPIXELS - VP9_INTERP_EXTEND); |
+ x->mv_col_min = -((mb_col * 16) + VP9BORDERINPIXELS - VP9_INTERP_EXTEND); |
+ x->mv_row_max = ((cm->mb_rows - mb_row) * 16 + |
+ (VP9BORDERINPIXELS - block_size - VP9_INTERP_EXTEND)); |
+ x->mv_col_max = ((cm->mb_cols - mb_col) * 16 + |
+ (VP9BORDERINPIXELS - block_size - VP9_INTERP_EXTEND)); |
+ |
+ // Set up distance of MB to edge of frame in 1/8th pel units |
+ block_size >>= 4; // in macroblock units |
+ assert(!(mb_col & (block_size - 1)) && !(mb_row & (block_size - 1))); |
+ xd->mb_to_top_edge = -((mb_row * 16) << 3); |
+ xd->mb_to_left_edge = -((mb_col * 16) << 3); |
+ xd->mb_to_bottom_edge = ((cm->mb_rows - block_size - mb_row) * 16) << 3; |
+ xd->mb_to_right_edge = ((cm->mb_cols - block_size - mb_col) * 16) << 3; |
+ |
+ // Are edges available for intra prediction? |
+ xd->up_available = (mb_row != 0); |
+ xd->left_available = (mb_col != 0); |
+ |
+ /* Reference buffer offsets */ |
+ *ref_yoffset = (mb_row * ref_y_stride * 16) + (mb_col * 16); |
+ *ref_uvoffset = (mb_row * ref_uv_stride * 8) + (mb_col * 8); |
+ |
+ /* set up source buffers */ |
+ x->src.y_buffer = cpi->Source->y_buffer + src_yoffset; |
+ x->src.u_buffer = cpi->Source->u_buffer + src_uvoffset; |
+ x->src.v_buffer = cpi->Source->v_buffer + src_uvoffset; |
+ |
+ /* R/D setup */ |
+ x->rddiv = cpi->RDDIV; |
+ x->rdmult = cpi->RDMULT; |
+ |
+ /* segment ID */ |
+ if (xd->segmentation_enabled) { |
+ if (xd->update_mb_segmentation_map) { |
+ mbmi->segment_id = find_seg_id(cpi->segmentation_map, block_size, |
+ mb_row, cm->mb_rows, mb_col, cm->mb_cols); |
+ } else { |
+ mbmi->segment_id = find_seg_id(cm->last_frame_seg_map, block_size, |
+ mb_row, cm->mb_rows, mb_col, cm->mb_cols); |
+ } |
+ assert(mbmi->segment_id <= 3); |
+ vp9_mb_init_quantizer(cpi, x); |
+ |
+ if (xd->segmentation_enabled && cpi->seg0_cnt > 0 && |
+ !vp9_segfeature_active(xd, 0, SEG_LVL_REF_FRAME) && |
+ vp9_segfeature_active(xd, 1, SEG_LVL_REF_FRAME) && |
+ vp9_check_segref(xd, 1, INTRA_FRAME) + |
+ vp9_check_segref(xd, 1, LAST_FRAME) + |
+ vp9_check_segref(xd, 1, GOLDEN_FRAME) + |
+ vp9_check_segref(xd, 1, ALTREF_FRAME) == 1) { |
+ cpi->seg0_progress = (cpi->seg0_idx << 16) / cpi->seg0_cnt; |
+ } else { |
+ const int y = mb_row & ~3; |
+ const int x = mb_col & ~3; |
+ const int p16 = ((mb_row & 1) << 1) + (mb_col & 1); |
+ const int p32 = ((mb_row & 2) << 2) + ((mb_col & 2) << 1); |
+ |
+ cpi->seg0_progress = |
+ ((y * cm->mb_cols + x * 4 + p32 + p16) << 16) / cm->MBs; |
+ } |
+ } else { |
+ mbmi->segment_id = 0; |
+ } |
+} |
+ |
static void pick_mb_modes(VP9_COMP *cpi, |
- VP9_COMMON *cm, |
int mb_row, |
int mb_col, |
- MACROBLOCK *x, |
- MACROBLOCKD *xd, |
TOKENEXTRA **tp, |
int *totalrate, |
int *totaldist) { |
+ VP9_COMMON *const cm = &cpi->common; |
+ MACROBLOCK *const x = &cpi->mb; |
+ MACROBLOCKD *const xd = &x->e_mbd; |
int i; |
- int map_index; |
int recon_yoffset, recon_uvoffset; |
- int ref_fb_idx = cm->lst_fb_idx; |
- int dst_fb_idx = cm->new_fb_idx; |
- int recon_y_stride = cm->yv12_fb[ref_fb_idx].y_stride; |
- int recon_uv_stride = cm->yv12_fb[ref_fb_idx].uv_stride; |
ENTROPY_CONTEXT_PLANES left_context[2]; |
ENTROPY_CONTEXT_PLANES above_context[2]; |
ENTROPY_CONTEXT_PLANES *initial_above_context_ptr = cm->above_context |
+ mb_col; |
- // Offsets to move pointers from MB to MB within a SB in raster order |
- int row_delta[4] = { 0, +1, 0, -1}; |
- int col_delta[4] = { +1, -1, +1, +1}; |
- |
/* Function should not modify L & A contexts; save and restore on exit */ |
vpx_memcpy(left_context, |
- cm->left_context, |
+ cm->left_context + (mb_row & 2), |
sizeof(left_context)); |
vpx_memcpy(above_context, |
initial_above_context_ptr, |
@@ -631,113 +762,29 @@ |
/* Encode MBs in raster order within the SB */ |
for (i = 0; i < 4; i++) { |
- int dy = row_delta[i]; |
- int dx = col_delta[i]; |
- int offset_unextended = dy * cm->mb_cols + dx; |
- int offset_extended = dy * xd->mode_info_stride + dx; |
- MB_MODE_INFO * mbmi = &xd->mode_info_context->mbmi; |
+ const int x_idx = i & 1, y_idx = i >> 1; |
+ MB_MODE_INFO *mbmi; |
- // TODO Many of the index items here can be computed more efficiently! |
- |
- if ((mb_row >= cm->mb_rows) || (mb_col >= cm->mb_cols)) { |
+ if ((mb_row + y_idx >= cm->mb_rows) || (mb_col + x_idx >= cm->mb_cols)) { |
// MB lies outside frame, move on |
- mb_row += dy; |
- mb_col += dx; |
- |
- // Update pointers |
- x->src.y_buffer += 16 * (dx + dy * x->src.y_stride); |
- x->src.u_buffer += 8 * (dx + dy * x->src.uv_stride); |
- x->src.v_buffer += 8 * (dx + dy * x->src.uv_stride); |
- |
- x->gf_active_ptr += offset_unextended; |
- x->partition_info += offset_extended; |
- xd->mode_info_context += offset_extended; |
- xd->prev_mode_info_context += offset_extended; |
-#if CONFIG_DEBUG |
- assert((xd->prev_mode_info_context - cpi->common.prev_mip) == |
- (xd->mode_info_context - cpi->common.mip)); |
-#endif |
continue; |
} |
// Index of the MB in the SB 0..3 |
xd->mb_index = i; |
+ set_offsets(cpi, mb_row + y_idx, mb_col + x_idx, 16, |
+ &recon_yoffset, &recon_uvoffset); |
- map_index = (mb_row * cpi->common.mb_cols) + mb_col; |
- x->mb_activity_ptr = &cpi->mb_activity_map[map_index]; |
- |
- // set above context pointer |
- xd->above_context = cm->above_context + mb_col; |
- |
- // Restore the appropriate left context depending on which |
- // row in the SB the MB is situated |
- xd->left_context = cm->left_context + (i >> 1); |
- |
- // Set up distance of MB to edge of frame in 1/8th pel units |
- xd->mb_to_top_edge = -((mb_row * 16) << 3); |
- xd->mb_to_left_edge = -((mb_col * 16) << 3); |
- xd->mb_to_bottom_edge = ((cm->mb_rows - 1 - mb_row) * 16) << 3; |
- xd->mb_to_right_edge = ((cm->mb_cols - 1 - mb_col) * 16) << 3; |
- |
- // Set up limit values for MV components to prevent them from |
- // extending beyond the UMV borders assuming 16x16 block size |
- x->mv_row_min = -((mb_row * 16) + VP9BORDERINPIXELS - VP9_INTERP_EXTEND); |
- x->mv_col_min = -((mb_col * 16) + VP9BORDERINPIXELS - VP9_INTERP_EXTEND); |
- x->mv_row_max = ((cm->mb_rows - mb_row) * 16 + |
- (VP9BORDERINPIXELS - 16 - VP9_INTERP_EXTEND)); |
- x->mv_col_max = ((cm->mb_cols - mb_col) * 16 + |
- (VP9BORDERINPIXELS - 16 - VP9_INTERP_EXTEND)); |
- |
- xd->up_available = (mb_row != 0); |
- xd->left_available = (mb_col != 0); |
- |
- recon_yoffset = (mb_row * recon_y_stride * 16) + (mb_col * 16); |
- recon_uvoffset = (mb_row * recon_uv_stride * 8) + (mb_col * 8); |
- |
- xd->dst.y_buffer = cm->yv12_fb[dst_fb_idx].y_buffer + recon_yoffset; |
- xd->dst.u_buffer = cm->yv12_fb[dst_fb_idx].u_buffer + recon_uvoffset; |
- xd->dst.v_buffer = cm->yv12_fb[dst_fb_idx].v_buffer + recon_uvoffset; |
- |
-#if !CONFIG_SUPERBLOCKS |
- // Copy current MB to a work buffer |
- vp9_copy_mem16x16(x->src.y_buffer, x->src.y_stride, x->thismb, 16); |
-#endif |
- |
- x->rddiv = cpi->RDDIV; |
- x->rdmult = cpi->RDMULT; |
- |
if (cpi->oxcf.tuning == VP8_TUNE_SSIM) |
vp9_activity_masking(cpi, x); |
- // Is segmentation enabled |
- if (xd->segmentation_enabled) { |
- // Code to set segment id in xd->mbmi.segment_id |
- if (xd->update_mb_segmentation_map) |
- mbmi->segment_id = cpi->segmentation_map[map_index]; |
- else |
- mbmi->segment_id = cm->last_frame_seg_map[map_index]; |
- if (mbmi->segment_id > 3) |
- mbmi->segment_id = 0; |
+ mbmi = &xd->mode_info_context->mbmi; |
+ mbmi->sb_type = BLOCK_SIZE_MB16X16; |
- vp9_mb_init_quantizer(cpi, x); |
- } else |
- // Set to Segment 0 by default |
- mbmi->segment_id = 0; |
- |
- x->active_ptr = cpi->active_map + map_index; |
- |
-#if CONFIG_SUPERBLOCKS |
- xd->mode_info_context->mbmi.encoded_as_sb = 0; |
-#endif |
- |
cpi->update_context = 0; // TODO Do we need this now?? |
vp9_intra_prediction_down_copy(xd); |
-#ifdef ENC_DEBUG |
- enc_debug = (cpi->common.current_video_frame == 46 && |
- mb_row == 5 && mb_col == 2); |
-#endif |
// Find best coding mode & reconstruct the MB so it is available |
// as a predictor for MBs that follow in the SB |
if (cm->frame_type == KEY_FRAME) { |
@@ -751,28 +798,16 @@ |
*totaldist += d; |
// Dummy encode, do not do the tokenization |
- encode_macroblock(cpi, x, tp, |
- recon_yoffset, recon_uvoffset, 0, mb_col, mb_row); |
+ encode_macroblock(cpi, tp, recon_yoffset, recon_uvoffset, 0, |
+ mb_row + y_idx, mb_col + x_idx); |
// Note the encoder may have changed the segment_id |
// Save the coding context |
- vpx_memcpy(&x->mb_context[i].mic, xd->mode_info_context, |
+ vpx_memcpy(&x->mb_context[xd->sb_index][i].mic, xd->mode_info_context, |
sizeof(MODE_INFO)); |
} else { |
int seg_id, r, d; |
- if (xd->segmentation_enabled && cpi->seg0_cnt > 0 && |
- !vp9_segfeature_active(xd, 0, SEG_LVL_REF_FRAME) && |
- vp9_segfeature_active(xd, 1, SEG_LVL_REF_FRAME) && |
- vp9_check_segref(xd, 1, INTRA_FRAME) + |
- vp9_check_segref(xd, 1, LAST_FRAME) + |
- vp9_check_segref(xd, 1, GOLDEN_FRAME) + |
- vp9_check_segref(xd, 1, ALTREF_FRAME) == 1) { |
- cpi->seg0_progress = (cpi->seg0_idx << 16) / cpi->seg0_cnt; |
- } else { |
- cpi->seg0_progress = (((mb_col & ~1) * 2 + (mb_row & ~1) * cm->mb_cols + i) << 16) / cm->MBs; |
- } |
- |
#ifdef ENC_DEBUG |
if (enc_debug) |
printf("inter pick_mb_modes %d %d\n", mb_row, mb_col); |
@@ -783,8 +818,8 @@ |
*totaldist += d; |
// Dummy encode, do not do the tokenization |
- encode_macroblock(cpi, x, tp, |
- recon_yoffset, recon_uvoffset, 0, mb_col, mb_row); |
+ encode_macroblock(cpi, tp, recon_yoffset, recon_uvoffset, 0, |
+ mb_row + y_idx, mb_col + x_idx); |
seg_id = mbmi->segment_id; |
if (cpi->mb.e_mbd.segmentation_enabled && seg_id == 0) { |
@@ -804,28 +839,10 @@ |
cpi->ref_pred_count[pred_context][pred_flag]++; |
} |
} |
- |
- // Next MB |
- mb_row += dy; |
- mb_col += dx; |
- |
- x->src.y_buffer += 16 * (dx + dy * x->src.y_stride); |
- x->src.u_buffer += 8 * (dx + dy * x->src.uv_stride); |
- x->src.v_buffer += 8 * (dx + dy * x->src.uv_stride); |
- |
- x->gf_active_ptr += offset_unextended; |
- x->partition_info += offset_extended; |
- xd->mode_info_context += offset_extended; |
- xd->prev_mode_info_context += offset_extended; |
- |
-#if CONFIG_DEBUG |
- assert((xd->prev_mode_info_context - cpi->common.prev_mip) == |
- (xd->mode_info_context - cpi->common.mip)); |
-#endif |
} |
/* Restore L & A coding context to those in place on entry */ |
- vpx_memcpy(cm->left_context, |
+ vpx_memcpy(cm->left_context + (mb_row & 2), |
left_context, |
sizeof(left_context)); |
vpx_memcpy(initial_above_context_ptr, |
@@ -833,393 +850,193 @@ |
sizeof(above_context)); |
} |
-#if CONFIG_SUPERBLOCKS |
-static void pick_sb_modes (VP9_COMP *cpi, |
- VP9_COMMON *cm, |
- int mb_row, |
- int mb_col, |
- MACROBLOCK *x, |
- MACROBLOCKD *xd, |
- TOKENEXTRA **tp, |
- int *totalrate, |
- int *totaldist) |
-{ |
- int map_index; |
+static void pick_sb_modes(VP9_COMP *cpi, |
+ int mb_row, |
+ int mb_col, |
+ TOKENEXTRA **tp, |
+ int *totalrate, |
+ int *totaldist) { |
+ VP9_COMMON *const cm = &cpi->common; |
+ MACROBLOCK *const x = &cpi->mb; |
+ MACROBLOCKD *const xd = &x->e_mbd; |
int recon_yoffset, recon_uvoffset; |
- int ref_fb_idx = cm->lst_fb_idx; |
- int dst_fb_idx = cm->new_fb_idx; |
- int recon_y_stride = cm->yv12_fb[ref_fb_idx].y_stride; |
- int recon_uv_stride = cm->yv12_fb[ref_fb_idx].uv_stride; |
- ENTROPY_CONTEXT_PLANES left_context[2]; |
- ENTROPY_CONTEXT_PLANES above_context[2]; |
- ENTROPY_CONTEXT_PLANES *initial_above_context_ptr = cm->above_context |
- + mb_col; |
- /* Function should not modify L & A contexts; save and restore on exit */ |
- vpx_memcpy (left_context, |
- cm->left_context, |
- sizeof(left_context)); |
- vpx_memcpy (above_context, |
- initial_above_context_ptr, |
- sizeof(above_context)); |
- |
- map_index = (mb_row * cpi->common.mb_cols) + mb_col; |
- x->mb_activity_ptr = &cpi->mb_activity_map[map_index]; |
- |
- /* set above context pointer */ |
- xd->above_context = cm->above_context + mb_col; |
- |
- /* Restore the appropriate left context depending on which |
- * row in the SB the MB is situated */ |
- xd->left_context = cm->left_context; |
- |
- // Set up distance of MB to edge of frame in 1/8th pel units |
- xd->mb_to_top_edge = -((mb_row * 16) << 3); |
- xd->mb_to_left_edge = -((mb_col * 16) << 3); |
- xd->mb_to_bottom_edge = ((cm->mb_rows - 2 - mb_row) * 16) << 3; |
- xd->mb_to_right_edge = ((cm->mb_cols - 2 - mb_col) * 16) << 3; |
- |
- /* Set up limit values for MV components to prevent them from |
- * extending beyond the UMV borders assuming 16x16 block size */ |
- x->mv_row_min = -((mb_row * 16) + VP9BORDERINPIXELS - VP9_INTERP_EXTEND); |
- x->mv_col_min = -((mb_col * 16) + VP9BORDERINPIXELS - VP9_INTERP_EXTEND); |
- x->mv_row_max = ((cm->mb_rows - mb_row) * 16 + |
- (VP9BORDERINPIXELS - 32 - VP9_INTERP_EXTEND)); |
- x->mv_col_max = ((cm->mb_cols - mb_col) * 16 + |
- (VP9BORDERINPIXELS - 32 - VP9_INTERP_EXTEND)); |
- |
- xd->up_available = (mb_row != 0); |
- xd->left_available = (mb_col != 0); |
- |
- recon_yoffset = (mb_row * recon_y_stride * 16) + (mb_col * 16); |
- recon_uvoffset = (mb_row * recon_uv_stride * 8) + (mb_col * 8); |
- |
- xd->dst.y_buffer = cm->yv12_fb[dst_fb_idx].y_buffer + recon_yoffset; |
- xd->dst.u_buffer = cm->yv12_fb[dst_fb_idx].u_buffer + recon_uvoffset; |
- xd->dst.v_buffer = cm->yv12_fb[dst_fb_idx].v_buffer + recon_uvoffset; |
-#if 0 // FIXME |
- /* Copy current MB to a work buffer */ |
- vp9_copy_mem16x16(x->src.y_buffer, x->src.y_stride, x->thismb, 16); |
-#endif |
- x->rddiv = cpi->RDDIV; |
- x->rdmult = cpi->RDMULT; |
- if(cpi->oxcf.tuning == VP8_TUNE_SSIM) |
+ set_offsets(cpi, mb_row, mb_col, 32, &recon_yoffset, &recon_uvoffset); |
+ xd->mode_info_context->mbmi.sb_type = BLOCK_SIZE_SB32X32; |
+ if (cpi->oxcf.tuning == VP8_TUNE_SSIM) |
vp9_activity_masking(cpi, x); |
- /* Is segmentation enabled */ |
- if (xd->segmentation_enabled) |
- { |
- /* Code to set segment id in xd->mbmi.segment_id */ |
- if (xd->update_mb_segmentation_map) |
- xd->mode_info_context->mbmi.segment_id = |
- cpi->segmentation_map[map_index] && |
- cpi->segmentation_map[map_index + 1] && |
- cpi->segmentation_map[map_index + cm->mb_cols] && |
- cpi->segmentation_map[map_index + cm->mb_cols + 1]; |
- else |
- xd->mode_info_context->mbmi.segment_id = |
- cm->last_frame_seg_map[map_index] && |
- cm->last_frame_seg_map[map_index + 1] && |
- cm->last_frame_seg_map[map_index + cm->mb_cols] && |
- cm->last_frame_seg_map[map_index + cm->mb_cols + 1]; |
- if (xd->mode_info_context->mbmi.segment_id > 3) |
- xd->mode_info_context->mbmi.segment_id = 0; |
- |
- vp9_mb_init_quantizer(cpi, x); |
- } |
- else |
- /* Set to Segment 0 by default */ |
- xd->mode_info_context->mbmi.segment_id = 0; |
- |
- x->active_ptr = cpi->active_map + map_index; |
- |
cpi->update_context = 0; // TODO Do we need this now?? |
/* Find best coding mode & reconstruct the MB so it is available |
* as a predictor for MBs that follow in the SB */ |
- if (cm->frame_type == KEY_FRAME) |
- { |
- vp9_rd_pick_intra_mode_sb(cpi, x, |
- totalrate, |
- totaldist); |
+ if (cm->frame_type == KEY_FRAME) { |
+ vp9_rd_pick_intra_mode_sb32(cpi, x, |
+ totalrate, |
+ totaldist); |
/* Save the coding context */ |
- vpx_memcpy(&x->sb_context[0].mic, xd->mode_info_context, |
+ vpx_memcpy(&x->sb32_context[xd->sb_index].mic, xd->mode_info_context, |
sizeof(MODE_INFO)); |
} else { |
- if (xd->segmentation_enabled && cpi->seg0_cnt > 0 && |
- !vp9_segfeature_active(xd, 0, SEG_LVL_REF_FRAME) && |
- vp9_segfeature_active(xd, 1, SEG_LVL_REF_FRAME) && |
- vp9_check_segref(xd, 1, INTRA_FRAME) + |
- vp9_check_segref(xd, 1, LAST_FRAME) + |
- vp9_check_segref(xd, 1, GOLDEN_FRAME) + |
- vp9_check_segref(xd, 1, ALTREF_FRAME) == 1) { |
- cpi->seg0_progress = (cpi->seg0_idx << 16) / cpi->seg0_cnt; |
- } else { |
- cpi->seg0_progress = |
- (((mb_col & ~1) * 2 + (mb_row & ~1) * cm->mb_cols) << 16) / cm->MBs; |
- } |
- |
- vp9_rd_pick_inter_mode_sb(cpi, x, |
- recon_yoffset, |
- recon_uvoffset, |
- totalrate, |
- totaldist); |
+ vp9_rd_pick_inter_mode_sb32(cpi, x, |
+ recon_yoffset, |
+ recon_uvoffset, |
+ totalrate, |
+ totaldist); |
} |
- |
- /* Restore L & A coding context to those in place on entry */ |
- vpx_memcpy (cm->left_context, |
- left_context, |
- sizeof(left_context)); |
- vpx_memcpy (initial_above_context_ptr, |
- above_context, |
- sizeof(above_context)); |
} |
-#endif |
-static void encode_sb(VP9_COMP *cpi, |
- VP9_COMMON *cm, |
- int mbrow, |
- int mbcol, |
- MACROBLOCK *x, |
- MACROBLOCKD *xd, |
- TOKENEXTRA **tp) { |
- int i; |
- int map_index; |
- int mb_row, mb_col; |
+static void pick_sb64_modes(VP9_COMP *cpi, |
+ int mb_row, |
+ int mb_col, |
+ TOKENEXTRA **tp, |
+ int *totalrate, |
+ int *totaldist) { |
+ VP9_COMMON *const cm = &cpi->common; |
+ MACROBLOCK *const x = &cpi->mb; |
+ MACROBLOCKD *const xd = &x->e_mbd; |
int recon_yoffset, recon_uvoffset; |
- int ref_fb_idx = cm->lst_fb_idx; |
- int dst_fb_idx = cm->new_fb_idx; |
- int recon_y_stride = cm->yv12_fb[ref_fb_idx].y_stride; |
- int recon_uv_stride = cm->yv12_fb[ref_fb_idx].uv_stride; |
- int row_delta[4] = { 0, +1, 0, -1}; |
- int col_delta[4] = { +1, -1, +1, +1}; |
- mb_row = mbrow; |
- mb_col = mbcol; |
+ set_offsets(cpi, mb_row, mb_col, 64, &recon_yoffset, &recon_uvoffset); |
+ xd->mode_info_context->mbmi.sb_type = BLOCK_SIZE_SB64X64; |
+ if (cpi->oxcf.tuning == VP8_TUNE_SSIM) |
+ vp9_activity_masking(cpi, x); |
+ cpi->update_context = 0; // TODO(rbultje) Do we need this now?? |
- /* Encode MBs in raster order within the SB */ |
- for (i = 0; i < 4; i++) { |
- int dy = row_delta[i]; |
- int dx = col_delta[i]; |
- int offset_extended = dy * xd->mode_info_stride + dx; |
- int offset_unextended = dy * cm->mb_cols + dx; |
- MB_MODE_INFO * mbmi = &xd->mode_info_context->mbmi; |
+ /* Find best coding mode & reconstruct the MB so it is available |
+ * as a predictor for MBs that follow in the SB */ |
+ if (cm->frame_type == KEY_FRAME) { |
+ vp9_rd_pick_intra_mode_sb64(cpi, x, |
+ totalrate, |
+ totaldist); |
- if ((mb_row >= cm->mb_rows) || (mb_col >= cm->mb_cols)) { |
- // MB lies outside frame, move on |
- mb_row += dy; |
- mb_col += dx; |
+ /* Save the coding context */ |
+ vpx_memcpy(&x->sb64_context.mic, xd->mode_info_context, |
+ sizeof(MODE_INFO)); |
+ } else { |
+ vp9_rd_pick_inter_mode_sb64(cpi, x, |
+ recon_yoffset, |
+ recon_uvoffset, |
+ totalrate, |
+ totaldist); |
+ } |
+} |
- x->src.y_buffer += 16 * (dx + dy * x->src.y_stride); |
- x->src.u_buffer += 8 * (dx + dy * x->src.uv_stride); |
- x->src.v_buffer += 8 * (dx + dy * x->src.uv_stride); |
+static void update_stats(VP9_COMP *cpi) { |
+ VP9_COMMON *const cm = &cpi->common; |
+ MACROBLOCK *const x = &cpi->mb; |
+ MACROBLOCKD *const xd = &x->e_mbd; |
+ MODE_INFO *mi = xd->mode_info_context; |
+ MB_MODE_INFO *const mbmi = &mi->mbmi; |
- x->gf_active_ptr += offset_unextended; |
- x->partition_info += offset_extended; |
- xd->mode_info_context += offset_extended; |
- xd->prev_mode_info_context += offset_extended; |
- |
-#if CONFIG_DEBUG |
- assert((xd->prev_mode_info_context - cpi->common.prev_mip) == |
- (xd->mode_info_context - cpi->common.mip)); |
+ if (cm->frame_type == KEY_FRAME) { |
+#ifdef MODE_STATS |
+ y_modes[mbmi->mode]++; |
#endif |
- continue; |
- } |
+ } else { |
+ int segment_id, seg_ref_active; |
- xd->mb_index = i; |
+ if (mbmi->ref_frame) { |
+ int pred_context = vp9_get_pred_context(cm, xd, PRED_COMP); |
- // Restore MB state to that when it was picked |
-#if CONFIG_SUPERBLOCKS |
- if (xd->mode_info_context->mbmi.encoded_as_sb) { |
- update_state(cpi, x, &x->sb_context[i]); |
- cpi->sb_count++; |
- } else |
-#endif |
- update_state(cpi, x, &x->mb_context[i]); |
+ if (mbmi->second_ref_frame <= INTRA_FRAME) |
+ cpi->single_pred_count[pred_context]++; |
+ else |
+ cpi->comp_pred_count[pred_context]++; |
+ } |
- map_index = (mb_row * cpi->common.mb_cols) + mb_col; |
- x->mb_activity_ptr = &cpi->mb_activity_map[map_index]; |
+#ifdef MODE_STATS |
+ inter_y_modes[mbmi->mode]++; |
- // reset above block coeffs |
- xd->above_context = cm->above_context + mb_col; |
- xd->left_context = cm->left_context + (i >> 1); |
+ if (mbmi->mode == SPLITMV) { |
+ int b; |
- // Set up distance of MB to edge of the frame in 1/8th pel units |
- // Set up limit values for MV components to prevent them from |
- // extending beyond the UMV borders assuming 32x32 block size |
- x->mv_row_min = -((mb_row * 16) + VP9BORDERINPIXELS - VP9_INTERP_EXTEND); |
- x->mv_col_min = -((mb_col * 16) + VP9BORDERINPIXELS - VP9_INTERP_EXTEND); |
- |
- xd->mb_to_top_edge = -((mb_row * 16) << 3); |
- xd->mb_to_left_edge = -((mb_col * 16) << 3); |
- |
-#if CONFIG_SUPERBLOCKS |
- if (xd->mode_info_context->mbmi.encoded_as_sb) { |
- x->mv_row_max = ((cm->mb_rows - mb_row) * 16 + |
- (VP9BORDERINPIXELS - 32 - VP9_INTERP_EXTEND)); |
- x->mv_col_max = ((cm->mb_cols - mb_col) * 16 + |
- (VP9BORDERINPIXELS - 32 - VP9_INTERP_EXTEND)); |
- |
- xd->mb_to_bottom_edge = ((cm->mb_rows - 2 - mb_row) * 16) << 3; |
- xd->mb_to_right_edge = ((cm->mb_cols - 2 - mb_col) * 16) << 3; |
- } else { |
+ for (b = 0; b < x->partition_info->count; b++) { |
+ inter_b_modes[x->partition_info->bmi[b].mode]++; |
+ } |
+ } |
#endif |
- x->mv_row_max = ((cm->mb_rows - mb_row) * 16 + |
- (VP9BORDERINPIXELS - 16 - VP9_INTERP_EXTEND)); |
- x->mv_col_max = ((cm->mb_cols - mb_col) * 16 + |
- (VP9BORDERINPIXELS - 16 - VP9_INTERP_EXTEND)); |
- xd->mb_to_bottom_edge = ((cm->mb_rows - 1 - mb_row) * 16) << 3; |
- xd->mb_to_right_edge = ((cm->mb_cols - 1 - mb_col) * 16) << 3; |
-#if CONFIG_SUPERBLOCKS |
+ // If we have just a single reference frame coded for a segment then |
+ // exclude from the reference frame counts used to work out |
+ // probabilities. NOTE: At the moment we dont support custom trees |
+ // for the reference frame coding for each segment but this is a |
+ // possible future action. |
+ segment_id = mbmi->segment_id; |
+ seg_ref_active = vp9_segfeature_active(xd, segment_id, |
+ SEG_LVL_REF_FRAME); |
+ if (!seg_ref_active || |
+ ((vp9_check_segref(xd, segment_id, INTRA_FRAME) + |
+ vp9_check_segref(xd, segment_id, LAST_FRAME) + |
+ vp9_check_segref(xd, segment_id, GOLDEN_FRAME) + |
+ vp9_check_segref(xd, segment_id, ALTREF_FRAME)) > 1)) { |
+ cpi->count_mb_ref_frame_usage[mbmi->ref_frame]++; |
} |
-#endif |
+ // Count of last ref frame 0,0 usage |
+ if ((mbmi->mode == ZEROMV) && (mbmi->ref_frame == LAST_FRAME)) |
+ cpi->inter_zz_count++; |
+ } |
+} |
- xd->up_available = (mb_row != 0); |
- xd->left_available = (mb_col != 0); |
+static void encode_sb(VP9_COMP *cpi, |
+ int mb_row, |
+ int mb_col, |
+ int output_enabled, |
+ TOKENEXTRA **tp, int is_sb) { |
+ VP9_COMMON *const cm = &cpi->common; |
+ MACROBLOCK *const x = &cpi->mb; |
+ MACROBLOCKD *const xd = &x->e_mbd; |
+ int recon_yoffset, recon_uvoffset; |
- recon_yoffset = (mb_row * recon_y_stride * 16) + (mb_col * 16); |
- recon_uvoffset = (mb_row * recon_uv_stride * 8) + (mb_col * 8); |
+ cpi->sb32_count[is_sb]++; |
+ if (is_sb) { |
+ set_offsets(cpi, mb_row, mb_col, 32, &recon_yoffset, &recon_uvoffset); |
+ update_state(cpi, &x->sb32_context[xd->sb_index], 32, output_enabled); |
- xd->dst.y_buffer = cm->yv12_fb[dst_fb_idx].y_buffer + recon_yoffset; |
- xd->dst.u_buffer = cm->yv12_fb[dst_fb_idx].u_buffer + recon_uvoffset; |
- xd->dst.v_buffer = cm->yv12_fb[dst_fb_idx].v_buffer + recon_uvoffset; |
+ encode_superblock32(cpi, tp, recon_yoffset, recon_uvoffset, |
+ output_enabled, mb_row, mb_col); |
+ if (output_enabled) |
+ update_stats(cpi); |
-#if !CONFIG_SUPERBLOCKS |
- // Copy current MB to a work buffer |
- vp9_copy_mem16x16(x->src.y_buffer, x->src.y_stride, x->thismb, 16); |
-#endif |
- |
- if (cpi->oxcf.tuning == VP8_TUNE_SSIM) |
- vp9_activity_masking(cpi, x); |
- |
- // Is segmentation enabled |
- if (xd->segmentation_enabled) { |
- vp9_mb_init_quantizer(cpi, x); |
+ if (output_enabled) { |
+ (*tp)->Token = EOSB_TOKEN; |
+ (*tp)++; |
+ if (mb_row < cm->mb_rows) |
+ cpi->tplist[mb_row].stop = *tp; |
} |
+ } else { |
+ int i; |
- x->active_ptr = cpi->active_map + map_index; |
+ for (i = 0; i < 4; i++) { |
+ const int x_idx = i & 1, y_idx = i >> 1; |
- cpi->update_context = 0; |
- |
-#if CONFIG_SUPERBLOCKS |
- if (!xd->mode_info_context->mbmi.encoded_as_sb) |
-#endif |
- vp9_intra_prediction_down_copy(xd); |
- |
- if (cm->frame_type == KEY_FRAME) { |
-#if CONFIG_SUPERBLOCKS |
- if (xd->mode_info_context->mbmi.encoded_as_sb) |
- encode_superblock(cpi, x, tp, recon_yoffset, recon_uvoffset, |
- mb_col, mb_row); |
- else |
-#endif |
- encode_macroblock(cpi, x, tp, recon_yoffset, recon_uvoffset, 1, |
- mb_col, mb_row); |
- // Note the encoder may have changed the segment_id |
- |
-#ifdef MODE_STATS |
- y_modes[mbmi->mode]++; |
-#endif |
- } else { |
- unsigned char *segment_id; |
- int seg_ref_active; |
- |
- if (xd->mode_info_context->mbmi.ref_frame) { |
- unsigned char pred_context; |
- |
- pred_context = vp9_get_pred_context(cm, xd, PRED_COMP); |
- |
- if (xd->mode_info_context->mbmi.second_ref_frame <= INTRA_FRAME) |
- cpi->single_pred_count[pred_context]++; |
- else |
- cpi->comp_pred_count[pred_context]++; |
+ if ((mb_row + y_idx >= cm->mb_rows) || (mb_col + x_idx >= cm->mb_cols)) { |
+ // MB lies outside frame, move on |
+ continue; |
} |
-#if CONFIG_SUPERBLOCKS |
- if (xd->mode_info_context->mbmi.encoded_as_sb) |
- encode_superblock(cpi, x, tp, recon_yoffset, recon_uvoffset, |
- mb_col, mb_row); |
- else |
-#endif |
- encode_macroblock(cpi, x, tp, recon_yoffset, recon_uvoffset, 1, |
- mb_col, mb_row); |
- // Note the encoder may have changed the segment_id |
+ set_offsets(cpi, mb_row + y_idx, mb_col + x_idx, 16, |
+ &recon_yoffset, &recon_uvoffset); |
+ xd->mb_index = i; |
+ update_state(cpi, &x->mb_context[xd->sb_index][i], 16, output_enabled); |
-#ifdef MODE_STATS |
- inter_y_modes[mbmi->mode]++; |
+ if (cpi->oxcf.tuning == VP8_TUNE_SSIM) |
+ vp9_activity_masking(cpi, x); |
- if (mbmi->mode == SPLITMV) { |
- int b; |
+ vp9_intra_prediction_down_copy(xd); |
- for (b = 0; b < x->partition_info->count; b++) { |
- inter_b_modes[x->partition_info->bmi[b].mode]++; |
- } |
- } |
+ encode_macroblock(cpi, tp, recon_yoffset, recon_uvoffset, |
+ output_enabled, mb_row + y_idx, mb_col + x_idx); |
+ if (output_enabled) |
+ update_stats(cpi); |
-#endif |
- |
- // If we have just a single reference frame coded for a segment then |
- // exclude from the reference frame counts used to work out |
- // probabilities. NOTE: At the moment we dont support custom trees |
- // for the reference frame coding for each segment but this is a |
- // possible future action. |
- segment_id = &mbmi->segment_id; |
- seg_ref_active = vp9_segfeature_active(xd, *segment_id, |
- SEG_LVL_REF_FRAME); |
- if (!seg_ref_active || |
- ((vp9_check_segref(xd, *segment_id, INTRA_FRAME) + |
- vp9_check_segref(xd, *segment_id, LAST_FRAME) + |
- vp9_check_segref(xd, *segment_id, GOLDEN_FRAME) + |
- vp9_check_segref(xd, *segment_id, ALTREF_FRAME)) > 1)) { |
- { |
- cpi->count_mb_ref_frame_usage[mbmi->ref_frame]++; |
- } |
+ if (output_enabled) { |
+ (*tp)->Token = EOSB_TOKEN; |
+ (*tp)++; |
+ if (mb_row + y_idx < cm->mb_rows) |
+ cpi->tplist[mb_row + y_idx].stop = *tp; |
} |
- |
- // Count of last ref frame 0,0 usage |
- if ((mbmi->mode == ZEROMV) && (mbmi->ref_frame == LAST_FRAME)) |
- cpi->inter_zz_count++; |
} |
- |
-#if CONFIG_SUPERBLOCKS |
- if (xd->mode_info_context->mbmi.encoded_as_sb) { |
- x->src.y_buffer += 32; |
- x->src.u_buffer += 16; |
- x->src.v_buffer += 16; |
- |
- x->gf_active_ptr += 2; |
- x->partition_info += 2; |
- xd->mode_info_context += 2; |
- xd->prev_mode_info_context += 2; |
- |
- (*tp)->Token = EOSB_TOKEN; |
- (*tp)++; |
- if (mb_row < cm->mb_rows) cpi->tplist[mb_row].stop = *tp; |
- break; |
- } |
-#endif |
- |
- // Next MB |
- mb_row += dy; |
- mb_col += dx; |
- |
- x->src.y_buffer += 16 * (dx + dy * x->src.y_stride); |
- x->src.u_buffer += 8 * (dx + dy * x->src.uv_stride); |
- x->src.v_buffer += 8 * (dx + dy * x->src.uv_stride); |
- |
- x->gf_active_ptr += offset_unextended; |
- x->partition_info += offset_extended; |
- xd->mode_info_context += offset_extended; |
- xd->prev_mode_info_context += offset_extended; |
- |
-#if CONFIG_DEBUG |
- assert((xd->prev_mode_info_context - cpi->common.prev_mip) == |
- (xd->mode_info_context - cpi->common.mip)); |
-#endif |
- (*tp)->Token = EOSB_TOKEN; |
- (*tp)++; |
- if (mb_row < cm->mb_rows) cpi->tplist[mb_row].stop = *tp; |
} |
// debug output |
@@ -1233,14 +1050,53 @@ |
#endif |
} |
-static |
-void encode_sb_row(VP9_COMP *cpi, |
- VP9_COMMON *cm, |
- int mb_row, |
- MACROBLOCK *x, |
- MACROBLOCKD *xd, |
- TOKENEXTRA **tp, |
- int *totalrate) { |
+static void encode_sb64(VP9_COMP *cpi, |
+ int mb_row, |
+ int mb_col, |
+ TOKENEXTRA **tp, int is_sb[4]) { |
+ VP9_COMMON *const cm = &cpi->common; |
+ MACROBLOCK *const x = &cpi->mb; |
+ MACROBLOCKD *const xd = &x->e_mbd; |
+ |
+ cpi->sb64_count[is_sb[0] == 2]++; |
+ if (is_sb[0] == 2) { |
+ int recon_yoffset, recon_uvoffset; |
+ |
+ set_offsets(cpi, mb_row, mb_col, 64, &recon_yoffset, &recon_uvoffset); |
+ update_state(cpi, &x->sb64_context, 64, 1); |
+ encode_superblock64(cpi, tp, recon_yoffset, recon_uvoffset, |
+ 1, mb_row, mb_col); |
+ update_stats(cpi); |
+ |
+ (*tp)->Token = EOSB_TOKEN; |
+ (*tp)++; |
+ if (mb_row < cm->mb_rows) |
+ cpi->tplist[mb_row].stop = *tp; |
+ } else { |
+ int i; |
+ |
+ for (i = 0; i < 4; i++) { |
+ const int x_idx = i & 1, y_idx = i >> 1; |
+ |
+ if (mb_row + y_idx * 2 >= cm->mb_rows || |
+ mb_col + x_idx * 2 >= cm->mb_cols) { |
+ // MB lies outside frame, move on |
+ continue; |
+ } |
+ xd->sb_index = i; |
+ encode_sb(cpi, mb_row + 2 * y_idx, mb_col + 2 * x_idx, 1, tp, |
+ is_sb[i]); |
+ } |
+ } |
+} |
+ |
+static void encode_sb_row(VP9_COMP *cpi, |
+ int mb_row, |
+ TOKENEXTRA **tp, |
+ int *totalrate) { |
+ VP9_COMMON *const cm = &cpi->common; |
+ MACROBLOCK *const x = &cpi->mb; |
+ MACROBLOCKD *const xd = &x->e_mbd; |
int mb_col; |
int mb_cols = cm->mb_cols; |
@@ -1248,105 +1104,84 @@ |
vpx_memset(cm->left_context, 0, sizeof(cm->left_context)); |
// Code each SB in the row |
- for (mb_col = 0; mb_col < mb_cols; mb_col += 2) { |
- int mb_rate = 0, mb_dist = 0; |
-#if CONFIG_SUPERBLOCKS |
- int sb_rate = INT_MAX, sb_dist; |
-#endif |
+ for (mb_col = 0; mb_col < mb_cols; mb_col += 4) { |
+ int i; |
+ int sb32_rate = 0, sb32_dist = 0; |
+ int is_sb[4]; |
+ int sb64_rate = INT_MAX, sb64_dist; |
+ ENTROPY_CONTEXT_PLANES l[4], a[4]; |
+ TOKENEXTRA *tp_orig = *tp; |
-#if CONFIG_DEBUG |
- MODE_INFO *mic = xd->mode_info_context; |
- PARTITION_INFO *pi = x->partition_info; |
- signed char *gfa = x->gf_active_ptr; |
- unsigned char *yb = x->src.y_buffer; |
- unsigned char *ub = x->src.u_buffer; |
- unsigned char *vb = x->src.v_buffer; |
-#endif |
+ memcpy(&a, cm->above_context + mb_col, sizeof(a)); |
+ memcpy(&l, cm->left_context, sizeof(l)); |
+ for (i = 0; i < 4; i++) { |
+ const int x_idx = (i & 1) << 1, y_idx = i & 2; |
+ int mb_rate = 0, mb_dist = 0; |
+ int sb_rate = INT_MAX, sb_dist; |
-#if CONFIG_SUPERBLOCKS |
- // Pick modes assuming the SB is coded as 4 independent MBs |
- xd->mode_info_context->mbmi.encoded_as_sb = 0; |
-#endif |
- pick_mb_modes(cpi, cm, mb_row, mb_col, x, xd, tp, &mb_rate, &mb_dist); |
-#if CONFIG_SUPERBLOCKS |
- mb_rate += vp9_cost_bit(cm->sb_coded, 0); |
-#endif |
+ if (mb_row + y_idx >= cm->mb_rows || mb_col + x_idx >= cm->mb_cols) |
+ continue; |
- x->src.y_buffer -= 32; |
- x->src.u_buffer -= 16; |
- x->src.v_buffer -= 16; |
+ xd->sb_index = i; |
- x->gf_active_ptr -= 2; |
- x->partition_info -= 2; |
- xd->mode_info_context -= 2; |
- xd->prev_mode_info_context -= 2; |
+ pick_mb_modes(cpi, mb_row + y_idx, mb_col + x_idx, |
+ tp, &mb_rate, &mb_dist); |
+ mb_rate += vp9_cost_bit(cm->sb32_coded, 0); |
-#if CONFIG_DEBUG |
- assert(x->gf_active_ptr == gfa); |
- assert(x->partition_info == pi); |
- assert(xd->mode_info_context == mic); |
- assert(x->src.y_buffer == yb); |
- assert(x->src.u_buffer == ub); |
- assert(x->src.v_buffer == vb); |
-#endif |
+ if (!((( mb_cols & 1) && mb_col + x_idx == mb_cols - 1) || |
+ ((cm->mb_rows & 1) && mb_row + y_idx == cm->mb_rows - 1))) { |
+ /* Pick a mode assuming that it applies to all 4 of the MBs in the SB */ |
+ pick_sb_modes(cpi, mb_row + y_idx, mb_col + x_idx, |
+ tp, &sb_rate, &sb_dist); |
+ sb_rate += vp9_cost_bit(cm->sb32_coded, 1); |
+ } |
-#if CONFIG_SUPERBLOCKS |
- if (!((( mb_cols & 1) && mb_col == mb_cols - 1) || |
- ((cm->mb_rows & 1) && mb_row == cm->mb_rows - 1))) { |
- /* Pick a mode assuming that it applies to all 4 of the MBs in the SB */ |
- xd->mode_info_context->mbmi.encoded_as_sb = 1; |
- pick_sb_modes(cpi, cm, mb_row, mb_col, x, xd, tp, &sb_rate, &sb_dist); |
- sb_rate += vp9_cost_bit(cm->sb_coded, 1); |
+ /* Decide whether to encode as a SB or 4xMBs */ |
+ if (sb_rate < INT_MAX && |
+ RDCOST(x->rdmult, x->rddiv, sb_rate, sb_dist) < |
+ RDCOST(x->rdmult, x->rddiv, mb_rate, mb_dist)) { |
+ is_sb[i] = 1; |
+ sb32_rate += sb_rate; |
+ sb32_dist += sb_dist; |
+ } else { |
+ is_sb[i] = 0; |
+ sb32_rate += mb_rate; |
+ sb32_dist += mb_dist; |
+ } |
+ |
+ /* Encode SB using best computed mode(s) */ |
+ // FIXME(rbultje): there really shouldn't be any need to encode_mb/sb |
+ // for each level that we go up, we can just keep tokens and recon |
+ // 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, mb_row + y_idx, mb_col + x_idx, 0, tp, is_sb[i]); |
} |
+ memcpy(cm->above_context + mb_col, &a, sizeof(a)); |
+ memcpy(cm->left_context, &l, sizeof(l)); |
+ sb32_rate += vp9_cost_bit(cm->sb64_coded, 0); |
+ |
+ if (!((( mb_cols & 3) && mb_col + 3 >= mb_cols) || |
+ ((cm->mb_rows & 3) && mb_row + 3 >= cm->mb_rows))) { |
+ pick_sb64_modes(cpi, mb_row, mb_col, tp, &sb64_rate, &sb64_dist); |
+ sb64_rate += vp9_cost_bit(cm->sb64_coded, 1); |
+ } |
+ |
/* Decide whether to encode as a SB or 4xMBs */ |
- if (sb_rate < INT_MAX && |
- RDCOST(x->rdmult, x->rddiv, sb_rate, sb_dist) < |
- RDCOST(x->rdmult, x->rddiv, mb_rate, mb_dist)) { |
- xd->mode_info_context->mbmi.encoded_as_sb = 1; |
- xd->mode_info_context[1].mbmi.encoded_as_sb = 1; |
- xd->mode_info_context[cm->mode_info_stride].mbmi.encoded_as_sb = 1; |
- xd->mode_info_context[1 + cm->mode_info_stride].mbmi.encoded_as_sb = 1; |
- *totalrate += sb_rate; |
- } else |
-#endif |
- { |
-#if CONFIG_SUPERBLOCKS |
- xd->mode_info_context->mbmi.encoded_as_sb = 0; |
- if (cm->mb_cols - 1 > mb_col) |
- xd->mode_info_context[1].mbmi.encoded_as_sb = 0; |
- if (cm->mb_rows - 1 > mb_row) { |
- xd->mode_info_context[cm->mode_info_stride].mbmi.encoded_as_sb = 0; |
- if (cm->mb_cols - 1 > mb_col) |
- xd->mode_info_context[1 + cm->mode_info_stride].mbmi.encoded_as_sb = 0; |
- } |
-#endif |
- *totalrate += mb_rate; |
+ if (sb64_rate < INT_MAX && |
+ RDCOST(x->rdmult, x->rddiv, sb64_rate, sb64_dist) < |
+ RDCOST(x->rdmult, x->rddiv, sb32_rate, sb32_dist)) { |
+ is_sb[0] = 2; |
+ *totalrate += sb64_rate; |
+ } else { |
+ *totalrate += sb32_rate; |
} |
- /* Encode SB using best computed mode(s) */ |
- encode_sb(cpi, cm, mb_row, mb_col, x, xd, tp); |
- |
-#if CONFIG_DEBUG |
- assert(x->gf_active_ptr == gfa + 2); |
- assert(x->partition_info == pi + 2); |
- assert(xd->mode_info_context == mic + 2); |
- assert(x->src.y_buffer == yb + 32); |
- assert(x->src.u_buffer == ub + 16); |
- assert(x->src.v_buffer == vb + 16); |
-#endif |
+ assert(tp_orig == *tp); |
+ encode_sb64(cpi, mb_row, mb_col, tp, is_sb); |
+ assert(tp_orig < *tp); |
} |
- |
- // this is to account for the border |
- x->gf_active_ptr += mb_cols - (mb_cols & 0x1); |
- x->partition_info += xd->mode_info_stride + 1 - (mb_cols & 0x1); |
- xd->mode_info_context += xd->mode_info_stride + 1 - (mb_cols & 0x1); |
- xd->prev_mode_info_context += xd->mode_info_stride + 1 - (mb_cols & 0x1); |
- |
-#if CONFIG_DEBUG |
- assert((xd->prev_mode_info_context - cpi->common.prev_mip) == |
- (xd->mode_info_context - cpi->common.mip)); |
-#endif |
} |
static void init_encode_frame_mb_context(VP9_COMP *cpi) { |
@@ -1354,22 +1189,11 @@ |
VP9_COMMON *const cm = &cpi->common; |
MACROBLOCKD *const xd = &x->e_mbd; |
- // GF active flags data structure |
- x->gf_active_ptr = (signed char *)cpi->gf_active_flags; |
- |
- // Activity map pointer |
- x->mb_activity_ptr = cpi->mb_activity_map; |
- |
x->act_zbin_adj = 0; |
cpi->seg0_idx = 0; |
vpx_memset(cpi->ref_pred_count, 0, sizeof(cpi->ref_pred_count)); |
- x->partition_info = x->pi; |
- |
- xd->mode_info_context = cm->mi; |
xd->mode_info_stride = cm->mode_info_stride; |
- xd->prev_mode_info_context = cm->prev_mi; |
- |
xd->frame_type = cm->frame_type; |
xd->frames_since_golden = cm->frames_since_golden; |
@@ -1380,7 +1204,7 @@ |
vp9_init_mbmode_probs(cm); |
// Copy data over into macro block data structures. |
- x->src = * cpi->Source; |
+ x->src = *cpi->Source; |
xd->pre = cm->yv12_fb[cm->lst_fb_idx]; |
xd->dst = cm->yv12_fb[cm->new_fb_idx]; |
@@ -1404,10 +1228,9 @@ |
vp9_zero(cpi->sub_mv_ref_count) |
vp9_zero(cpi->mbsplit_count) |
vp9_zero(cpi->common.fc.mv_ref_ct) |
-#if CONFIG_SUPERBLOCKS |
vp9_zero(cpi->sb_ymode_count) |
- cpi->sb_count = 0; |
-#endif |
+ vp9_zero(cpi->sb32_count); |
+ vp9_zero(cpi->sb64_count); |
#if CONFIG_COMP_INTERINTRA_PRED |
vp9_zero(cpi->interintra_count); |
vp9_zero(cpi->interintra_select_count); |
@@ -1438,11 +1261,6 @@ |
// this frame which may be updated with each iteration of the recode loop. |
vp9_compute_mod_refprobs(cm); |
-#if CONFIG_NEW_MVREF |
- // temp stats reset |
- vp9_zero( cpi->best_ref_index_counts ); |
-#endif |
- |
// debug output |
#if DBG_PRNT_SEGMAP |
{ |
@@ -1466,28 +1284,23 @@ |
cpi->skip_true_count[0] = cpi->skip_true_count[1] = cpi->skip_true_count[2] = 0; |
cpi->skip_false_count[0] = cpi->skip_false_count[1] = cpi->skip_false_count[2] = 0; |
-#if CONFIG_PRED_FILTER |
- if (cm->current_video_frame == 0) { |
- // Initially assume that we'll signal the prediction filter |
- // state at the frame level and that it is off. |
- cpi->common.pred_filter_mode = 0; |
- cpi->common.prob_pred_filter_off = 128; |
- } |
- cpi->pred_filter_on_count = 0; |
- cpi->pred_filter_off_count = 0; |
-#endif |
vp9_zero(cpi->switchable_interp_count); |
+ vp9_zero(cpi->best_switchable_interp_count); |
xd->mode_info_context = cm->mi; |
xd->prev_mode_info_context = cm->prev_mi; |
vp9_zero(cpi->NMVcount); |
- vp9_zero(cpi->coef_counts); |
- vp9_zero(cpi->hybrid_coef_counts); |
+ vp9_zero(cpi->coef_counts_4x4); |
+ vp9_zero(cpi->hybrid_coef_counts_4x4); |
vp9_zero(cpi->coef_counts_8x8); |
vp9_zero(cpi->hybrid_coef_counts_8x8); |
vp9_zero(cpi->coef_counts_16x16); |
vp9_zero(cpi->hybrid_coef_counts_16x16); |
+ vp9_zero(cpi->coef_counts_32x32); |
+#if CONFIG_NEW_MVREF |
+ vp9_zero(cpi->mb_mv_ref_count); |
+#endif |
vp9_frame_init_quantizer(cpi); |
@@ -1508,7 +1321,8 @@ |
vpx_memset(cpi->rd_comp_pred_diff, 0, sizeof(cpi->rd_comp_pred_diff)); |
vpx_memset(cpi->single_pred_count, 0, sizeof(cpi->single_pred_count)); |
vpx_memset(cpi->comp_pred_count, 0, sizeof(cpi->comp_pred_count)); |
- vpx_memset(cpi->txfm_count, 0, sizeof(cpi->txfm_count)); |
+ vpx_memset(cpi->txfm_count_32x32p, 0, sizeof(cpi->txfm_count_32x32p)); |
+ vpx_memset(cpi->txfm_count_16x16p, 0, sizeof(cpi->txfm_count_16x16p)); |
vpx_memset(cpi->txfm_count_8x8p, 0, sizeof(cpi->txfm_count_8x8p)); |
vpx_memset(cpi->rd_tx_select_diff, 0, sizeof(cpi->rd_tx_select_diff)); |
{ |
@@ -1517,15 +1331,8 @@ |
{ |
// For each row of SBs in the frame |
- for (mb_row = 0; mb_row < cm->mb_rows; mb_row += 2) { |
- int offset = (cm->mb_cols + 1) & ~0x1; |
- |
- encode_sb_row(cpi, cm, mb_row, x, xd, &tp, &totalrate); |
- |
- // adjust to the next row of SBs |
- x->src.y_buffer += 32 * x->src.y_stride - 16 * offset; |
- x->src.u_buffer += 16 * x->src.uv_stride - 8 * offset; |
- x->src.v_buffer += 16 * x->src.uv_stride - 8 * offset; |
+ for (mb_row = 0; mb_row < cm->mb_rows; mb_row += 4) { |
+ encode_sb_row(cpi, mb_row, &tp, &totalrate); |
} |
cpi->tok_count = (unsigned int)(tp - cpi->tok); |
@@ -1570,78 +1377,136 @@ |
} |
} |
+static void reset_skip_txfm_size_mb(VP9_COMP *cpi, |
+ MODE_INFO *mi, TX_SIZE txfm_max) { |
+ MB_MODE_INFO *const mbmi = &mi->mbmi; |
+ |
+ if (mbmi->txfm_size > txfm_max) { |
+ VP9_COMMON *const cm = &cpi->common; |
+ MACROBLOCK *const x = &cpi->mb; |
+ MACROBLOCKD *const xd = &x->e_mbd; |
+ const int segment_id = mbmi->segment_id; |
+ |
+ xd->mode_info_context = mi; |
+ assert((vp9_segfeature_active(xd, segment_id, SEG_LVL_EOB) && |
+ vp9_get_segdata(xd, segment_id, SEG_LVL_EOB) == 0) || |
+ (cm->mb_no_coeff_skip && mbmi->mb_skip_coeff)); |
+ mbmi->txfm_size = txfm_max; |
+ } |
+} |
+ |
+static int get_skip_flag(MODE_INFO *mi, int mis, int ymbs, int xmbs) { |
+ int x, y; |
+ |
+ for (y = 0; y < ymbs; y++) { |
+ for (x = 0; x < xmbs; x++) { |
+ if (!mi[y * mis + x].mbmi.mb_skip_coeff) |
+ return 0; |
+ } |
+ } |
+ |
+ return 1; |
+} |
+ |
+static void set_txfm_flag(MODE_INFO *mi, int mis, int ymbs, int xmbs, |
+ TX_SIZE txfm_size) { |
+ int x, y; |
+ |
+ for (y = 0; y < ymbs; y++) { |
+ for (x = 0; x < xmbs; x++) { |
+ mi[y * mis + x].mbmi.txfm_size = txfm_size; |
+ } |
+ } |
+} |
+ |
+static void reset_skip_txfm_size_sb32(VP9_COMP *cpi, MODE_INFO *mi, |
+ int mis, TX_SIZE txfm_max, |
+ int mb_rows_left, int mb_cols_left) { |
+ MB_MODE_INFO *const mbmi = &mi->mbmi; |
+ |
+ if (mbmi->txfm_size > txfm_max) { |
+ VP9_COMMON *const cm = &cpi->common; |
+ MACROBLOCK *const x = &cpi->mb; |
+ MACROBLOCKD *const xd = &x->e_mbd; |
+ const int segment_id = mbmi->segment_id; |
+ const int ymbs = MIN(2, mb_rows_left); |
+ const int xmbs = MIN(2, mb_cols_left); |
+ |
+ xd->mode_info_context = mi; |
+ assert((vp9_segfeature_active(xd, segment_id, SEG_LVL_EOB) && |
+ vp9_get_segdata(xd, segment_id, SEG_LVL_EOB) == 0) || |
+ (cm->mb_no_coeff_skip && get_skip_flag(mi, mis, ymbs, xmbs))); |
+ set_txfm_flag(mi, mis, ymbs, xmbs, txfm_max); |
+ } |
+} |
+ |
+static void reset_skip_txfm_size_sb64(VP9_COMP *cpi, MODE_INFO *mi, |
+ int mis, TX_SIZE txfm_max, |
+ int mb_rows_left, int mb_cols_left) { |
+ MB_MODE_INFO *const mbmi = &mi->mbmi; |
+ |
+ if (mbmi->txfm_size > txfm_max) { |
+ VP9_COMMON *const cm = &cpi->common; |
+ MACROBLOCK *const x = &cpi->mb; |
+ MACROBLOCKD *const xd = &x->e_mbd; |
+ const int segment_id = mbmi->segment_id; |
+ const int ymbs = MIN(4, mb_rows_left); |
+ const int xmbs = MIN(4, mb_cols_left); |
+ |
+ xd->mode_info_context = mi; |
+ assert((vp9_segfeature_active(xd, segment_id, SEG_LVL_EOB) && |
+ vp9_get_segdata(xd, segment_id, SEG_LVL_EOB) == 0) || |
+ (cm->mb_no_coeff_skip && get_skip_flag(mi, mis, ymbs, xmbs))); |
+ set_txfm_flag(mi, mis, ymbs, xmbs, txfm_max); |
+ } |
+} |
+ |
static void reset_skip_txfm_size(VP9_COMP *cpi, TX_SIZE txfm_max) { |
- VP9_COMMON *cm = &cpi->common; |
- int mb_row, mb_col, mis = cm->mode_info_stride, segment_id; |
+ VP9_COMMON *const cm = &cpi->common; |
+ int mb_row, mb_col; |
+ const int mis = cm->mode_info_stride; |
MODE_INFO *mi, *mi_ptr = cm->mi; |
-#if CONFIG_SUPERBLOCKS |
- int skip; |
- MODE_INFO *sb_mi_ptr = cm->mi, *sb_mi; |
- MB_MODE_INFO *sb_mbmi; |
-#endif |
- MB_MODE_INFO *mbmi; |
- MACROBLOCK *x = &cpi->mb; |
- MACROBLOCKD *xd = &x->e_mbd; |
- for (mb_row = 0; mb_row < cm->mb_rows; mb_row++, mi_ptr += mis) { |
+ for (mb_row = 0; mb_row < cm->mb_rows; mb_row += 4, mi_ptr += 4 * mis) { |
mi = mi_ptr; |
-#if CONFIG_SUPERBLOCKS |
- sb_mi = sb_mi_ptr; |
-#endif |
- for (mb_col = 0; mb_col < cm->mb_cols; mb_col++, mi++) { |
- mbmi = &mi->mbmi; |
-#if CONFIG_SUPERBLOCKS |
- sb_mbmi = &sb_mi->mbmi; |
-#endif |
- if (mbmi->txfm_size > txfm_max) { |
-#if CONFIG_SUPERBLOCKS |
- if (sb_mbmi->encoded_as_sb) { |
- if (!((mb_col & 1) || (mb_row & 1))) { |
- segment_id = mbmi->segment_id; |
- skip = mbmi->mb_skip_coeff; |
- if (mb_col < cm->mb_cols - 1) { |
- segment_id = segment_id && mi[1].mbmi.segment_id; |
- skip = skip && mi[1].mbmi.mb_skip_coeff; |
+ for (mb_col = 0; mb_col < cm->mb_cols; mb_col += 4, mi += 4) { |
+ if (mi->mbmi.sb_type == BLOCK_SIZE_SB64X64) { |
+ reset_skip_txfm_size_sb64(cpi, mi, mis, txfm_max, |
+ cm->mb_rows - mb_row, cm->mb_cols - mb_col); |
+ } else { |
+ int i; |
+ |
+ for (i = 0; i < 4; i++) { |
+ const int x_idx_sb = (i & 1) << 1, y_idx_sb = i & 2; |
+ MODE_INFO *sb_mi = mi + y_idx_sb * mis + x_idx_sb; |
+ |
+ if (mb_row + y_idx_sb >= cm->mb_rows || |
+ mb_col + x_idx_sb >= cm->mb_cols) |
+ continue; |
+ |
+ if (sb_mi->mbmi.sb_type) { |
+ reset_skip_txfm_size_sb32(cpi, sb_mi, mis, txfm_max, |
+ cm->mb_rows - mb_row - y_idx_sb, |
+ cm->mb_cols - mb_col - x_idx_sb); |
+ } else { |
+ int m; |
+ |
+ for (m = 0; m < 4; m++) { |
+ const int x_idx = x_idx_sb + (m & 1), y_idx = y_idx_sb + (m >> 1); |
+ MODE_INFO *mb_mi; |
+ |
+ if (mb_col + x_idx >= cm->mb_cols || |
+ mb_row + y_idx >= cm->mb_rows) |
+ continue; |
+ |
+ mb_mi = mi + y_idx * mis + x_idx; |
+ assert(mb_mi->mbmi.sb_type == BLOCK_SIZE_MB16X16); |
+ reset_skip_txfm_size_mb(cpi, mb_mi, txfm_max); |
} |
- if (mb_row < cm->mb_rows - 1) { |
- segment_id = segment_id && |
- mi[cm->mode_info_stride].mbmi.segment_id; |
- skip = skip && mi[cm->mode_info_stride].mbmi.mb_skip_coeff; |
- if (mb_col < cm->mb_cols - 1) { |
- segment_id = segment_id && |
- mi[cm->mode_info_stride + 1].mbmi.segment_id; |
- skip = skip && mi[cm->mode_info_stride + 1].mbmi.mb_skip_coeff; |
- } |
- } |
- xd->mode_info_context = mi; |
- assert((vp9_segfeature_active(xd, segment_id, SEG_LVL_EOB) && |
- vp9_get_segdata(xd, segment_id, SEG_LVL_EOB) == 0) || |
- (cm->mb_no_coeff_skip && skip)); |
- mbmi->txfm_size = txfm_max; |
- } else { |
- mbmi->txfm_size = sb_mbmi->txfm_size; |
} |
- } else { |
-#endif |
- segment_id = mbmi->segment_id; |
- xd->mode_info_context = mi; |
- assert((vp9_segfeature_active(xd, segment_id, SEG_LVL_EOB) && |
- vp9_get_segdata(xd, segment_id, SEG_LVL_EOB) == 0) || |
- (cm->mb_no_coeff_skip && mbmi->mb_skip_coeff)); |
- mbmi->txfm_size = txfm_max; |
-#if CONFIG_SUPERBLOCKS |
} |
-#endif |
} |
-#if CONFIG_SUPERBLOCKS |
- if (mb_col & 1) |
- sb_mi += 2; |
-#endif |
} |
-#if CONFIG_SUPERBLOCKS |
- if (mb_row & 1) |
- sb_mi_ptr += 2 * mis; |
-#endif |
} |
} |
@@ -1701,7 +1566,7 @@ |
* keyframe's probabilities as an estimate of what the current keyframe's |
* coefficient cost distributions may look like. */ |
if (frame_type == 0) { |
- txfm_type = ALLOW_16X16; |
+ txfm_type = ALLOW_32X32; |
} else |
#if 0 |
/* FIXME (rbultje) |
@@ -1732,9 +1597,9 @@ |
} else |
txfm_type = ALLOW_8X8; |
#else |
- txfm_type = cpi->rd_tx_select_threshes[frame_type][ALLOW_16X16] >= |
- cpi->rd_tx_select_threshes[frame_type][TX_MODE_SELECT] ? |
- ALLOW_16X16 : TX_MODE_SELECT; |
+ txfm_type = cpi->rd_tx_select_threshes[frame_type][ALLOW_32X32] >= |
+ cpi->rd_tx_select_threshes[frame_type][TX_MODE_SELECT] ? |
+ ALLOW_32X32 : TX_MODE_SELECT; |
#endif |
cpi->common.txfm_mode = txfm_type; |
if (txfm_type != TX_MODE_SELECT) { |
@@ -1754,7 +1619,8 @@ |
int64_t pd = cpi->rd_tx_select_diff[i]; |
int diff; |
if (i == TX_MODE_SELECT) |
- pd -= RDCOST(cpi->mb.rdmult, cpi->mb.rddiv, 2048 * (TX_SIZE_MAX - 1), 0); |
+ pd -= RDCOST(cpi->mb.rdmult, cpi->mb.rddiv, |
+ 2048 * (TX_SIZE_MAX_SB - 1), 0); |
diff = (int)(pd / cpi->common.MBs); |
cpi->rd_tx_select_threshes[frame_type][i] += diff; |
cpi->rd_tx_select_threshes[frame_type][i] /= 2; |
@@ -1777,21 +1643,35 @@ |
} |
if (cpi->common.txfm_mode == TX_MODE_SELECT) { |
- const int count4x4 = cpi->txfm_count[TX_4X4] + cpi->txfm_count_8x8p[TX_4X4]; |
- const int count8x8 = cpi->txfm_count[TX_8X8]; |
+ const int count4x4 = cpi->txfm_count_16x16p[TX_4X4] + |
+ cpi->txfm_count_32x32p[TX_4X4] + |
+ cpi->txfm_count_8x8p[TX_4X4]; |
+ const int count8x8_lp = cpi->txfm_count_32x32p[TX_8X8] + |
+ cpi->txfm_count_16x16p[TX_8X8]; |
const int count8x8_8x8p = cpi->txfm_count_8x8p[TX_8X8]; |
- const int count16x16 = cpi->txfm_count[TX_16X16]; |
+ const int count16x16_16x16p = cpi->txfm_count_16x16p[TX_16X16]; |
+ const int count16x16_lp = cpi->txfm_count_32x32p[TX_16X16]; |
+ const int count32x32 = cpi->txfm_count_32x32p[TX_32X32]; |
- if (count4x4 == 0 && count16x16 == 0) { |
+ if (count4x4 == 0 && count16x16_lp == 0 && count16x16_16x16p == 0 && |
+ count32x32 == 0) { |
cpi->common.txfm_mode = ALLOW_8X8; |
reset_skip_txfm_size(cpi, TX_8X8); |
- } else if (count8x8 == 0 && count16x16 == 0 && count8x8_8x8p == 0) { |
+ } else if (count8x8_8x8p == 0 && count16x16_16x16p == 0 && |
+ count8x8_lp == 0 && count16x16_lp == 0 && count32x32 == 0) { |
cpi->common.txfm_mode = ONLY_4X4; |
reset_skip_txfm_size(cpi, TX_4X4); |
- } else if (count8x8 == 0 && count4x4 == 0) { |
+ } else if (count8x8_lp == 0 && count16x16_lp == 0 && count4x4 == 0) { |
+ cpi->common.txfm_mode = ALLOW_32X32; |
+ } else if (count32x32 == 0 && count8x8_lp == 0 && count4x4 == 0) { |
cpi->common.txfm_mode = ALLOW_16X16; |
+ reset_skip_txfm_size(cpi, TX_16X16); |
} |
} |
+ |
+ // Update interpolation filter strategy for next frame. |
+ if ((cpi->common.frame_type != KEY_FRAME) && (cpi->sf.search_best_filter)) |
+ select_interp_filter_type(cpi); |
} else { |
encode_frame_internal(cpi); |
} |
@@ -1835,35 +1715,18 @@ |
vp9_build_block_doffsets(&x->e_mbd); |
-#if !CONFIG_SUPERBLOCKS |
- // y blocks |
- x->thismb_ptr = &x->thismb[0]; |
for (br = 0; br < 4; br++) { |
for (bc = 0; bc < 4; bc++) { |
BLOCK *this_block = &x->block[block]; |
// this_block->base_src = &x->src.y_buffer; |
// this_block->src_stride = x->src.y_stride; |
// this_block->src = 4 * br * this_block->src_stride + 4 * bc; |
- this_block->base_src = &x->thismb_ptr; |
- this_block->src_stride = 16; |
- this_block->src = 4 * br * 16 + 4 * bc; |
- ++block; |
- } |
- } |
-#else |
- for (br = 0; br < 4; br++) { |
- for (bc = 0; bc < 4; bc++) { |
- BLOCK *this_block = &x->block[block]; |
- // this_block->base_src = &x->src.y_buffer; |
- // this_block->src_stride = x->src.y_stride; |
- // this_block->src = 4 * br * this_block->src_stride + 4 * bc; |
this_block->base_src = &x->src.y_buffer; |
this_block->src_stride = x->src.y_stride; |
this_block->src = 4 * br * this_block->src_stride + 4 * bc; |
++block; |
} |
} |
-#endif |
// u blocks |
for (br = 0; br < 2; br++) { |
@@ -1917,12 +1780,11 @@ |
} |
#endif |
-#if CONFIG_SUPERBLOCKS |
- if (xd->mode_info_context->mbmi.encoded_as_sb) { |
+ if (xd->mode_info_context->mbmi.sb_type) { |
++cpi->sb_ymode_count[m]; |
- } else |
-#endif |
+ } else { |
++cpi->ymode_count[m]; |
+ } |
if (m != I8X8_PRED) |
++cpi->y_uv_mode_count[m][uvm]; |
else { |
@@ -1964,16 +1826,14 @@ |
#endif |
} |
-#if CONFIG_SUPERBLOCKS |
static void update_sb_skip_coeff_state(VP9_COMP *cpi, |
- MACROBLOCK *x, |
ENTROPY_CONTEXT_PLANES ta[4], |
ENTROPY_CONTEXT_PLANES tl[4], |
TOKENEXTRA *t[4], |
TOKENEXTRA **tp, |
- int skip[4]) |
-{ |
- TOKENEXTRA tokens[4][16 * 24]; |
+ int skip[4], int output_enabled) { |
+ MACROBLOCK *const x = &cpi->mb; |
+ TOKENEXTRA tokens[4][16 * 25]; |
int n_tokens[4], n; |
// if there were no skips, we don't need to do anything |
@@ -2013,7 +1873,7 @@ |
if (skip[n]) { |
x->e_mbd.above_context = &ta[n]; |
x->e_mbd.left_context = &tl[n]; |
- vp9_stuff_mb(cpi, &x->e_mbd, tp, 0); |
+ vp9_stuff_mb(cpi, &x->e_mbd, tp, !output_enabled); |
} else { |
if (n_tokens[n]) { |
memcpy(*tp, tokens[n], sizeof(*t[0]) * n_tokens[n]); |
@@ -2022,23 +1882,129 @@ |
} |
} |
} |
-#endif /* CONFIG_SUPERBLOCKS */ |
-static void encode_macroblock(VP9_COMP *cpi, MACROBLOCK *x, |
- TOKENEXTRA **t, int recon_yoffset, |
- int recon_uvoffset, int output_enabled, |
- int mb_col, int mb_row) { |
- VP9_COMMON *cm = &cpi->common; |
+static void update_sb64_skip_coeff_state(VP9_COMP *cpi, |
+ ENTROPY_CONTEXT_PLANES ta[16], |
+ ENTROPY_CONTEXT_PLANES tl[16], |
+ TOKENEXTRA *t[16], |
+ TOKENEXTRA **tp, |
+ int skip[16], int output_enabled) { |
+ MACROBLOCK *const x = &cpi->mb; |
+ |
+ if (x->e_mbd.mode_info_context->mbmi.txfm_size == TX_32X32) { |
+ TOKENEXTRA tokens[4][1024+512]; |
+ int n_tokens[4], n; |
+ |
+ // if there were no skips, we don't need to do anything |
+ if (!skip[0] && !skip[1] && !skip[2] && !skip[3]) |
+ return; |
+ |
+ // if we don't do coeff skipping for this frame, we don't |
+ // need to do anything here |
+ if (!cpi->common.mb_no_coeff_skip) |
+ return; |
+ |
+ // if all 4 MBs skipped coeff coding, nothing to be done |
+ if (skip[0] && skip[1] && skip[2] && skip[3]) |
+ return; |
+ |
+ // so the situation now is that we want to skip coeffs |
+ // for some MBs, but not all, and we didn't code EOB |
+ // coefficients for them. However, the skip flag for this |
+ // SB will be 0 overall, so we need to insert EOBs in the |
+ // middle of the token tree. Do so here. |
+ for (n = 0; n < 4; n++) { |
+ if (n < 3) { |
+ n_tokens[n] = t[n + 1] - t[n]; |
+ } else { |
+ n_tokens[n] = *tp - t[3]; |
+ } |
+ if (n_tokens[n]) { |
+ memcpy(tokens[n], t[n], n_tokens[n] * sizeof(*t[0])); |
+ } |
+ } |
+ |
+ // reset pointer, stuff EOBs where necessary |
+ *tp = t[0]; |
+ for (n = 0; n < 4; n++) { |
+ if (skip[n]) { |
+ x->e_mbd.above_context = &ta[n * 2]; |
+ x->e_mbd.left_context = &tl[n * 2]; |
+ vp9_stuff_sb(cpi, &x->e_mbd, tp, !output_enabled); |
+ } else { |
+ if (n_tokens[n]) { |
+ memcpy(*tp, tokens[n], sizeof(*t[0]) * n_tokens[n]); |
+ } |
+ (*tp) += n_tokens[n]; |
+ } |
+ } |
+ } else { |
+ TOKENEXTRA tokens[16][16 * 25]; |
+ int n_tokens[16], n; |
+ |
+ // if there were no skips, we don't need to do anything |
+ if (!skip[ 0] && !skip[ 1] && !skip[ 2] && !skip[ 3] && |
+ !skip[ 4] && !skip[ 5] && !skip[ 6] && !skip[ 7] && |
+ !skip[ 8] && !skip[ 9] && !skip[10] && !skip[11] && |
+ !skip[12] && !skip[13] && !skip[14] && !skip[15]) |
+ return; |
+ |
+ // if we don't do coeff skipping for this frame, we don't |
+ // need to do anything here |
+ if (!cpi->common.mb_no_coeff_skip) |
+ return; |
+ |
+ // if all 4 MBs skipped coeff coding, nothing to be done |
+ if (skip[ 0] && skip[ 1] && skip[ 2] && skip[ 3] && |
+ skip[ 4] && skip[ 5] && skip[ 6] && skip[ 7] && |
+ skip[ 8] && skip[ 9] && skip[10] && skip[11] && |
+ skip[12] && skip[13] && skip[14] && skip[15]) |
+ return; |
+ |
+ // so the situation now is that we want to skip coeffs |
+ // for some MBs, but not all, and we didn't code EOB |
+ // coefficients for them. However, the skip flag for this |
+ // SB will be 0 overall, so we need to insert EOBs in the |
+ // middle of the token tree. Do so here. |
+ for (n = 0; n < 16; n++) { |
+ if (n < 15) { |
+ n_tokens[n] = t[n + 1] - t[n]; |
+ } else { |
+ n_tokens[n] = *tp - t[15]; |
+ } |
+ if (n_tokens[n]) { |
+ memcpy(tokens[n], t[n], n_tokens[n] * sizeof(*t[0])); |
+ } |
+ } |
+ |
+ // reset pointer, stuff EOBs where necessary |
+ *tp = t[0]; |
+ for (n = 0; n < 16; n++) { |
+ if (skip[n]) { |
+ x->e_mbd.above_context = &ta[n]; |
+ x->e_mbd.left_context = &tl[n]; |
+ vp9_stuff_mb(cpi, &x->e_mbd, tp, !output_enabled); |
+ } else { |
+ if (n_tokens[n]) { |
+ memcpy(*tp, tokens[n], sizeof(*t[0]) * n_tokens[n]); |
+ } |
+ (*tp) += n_tokens[n]; |
+ } |
+ } |
+ } |
+} |
+ |
+static void encode_macroblock(VP9_COMP *cpi, TOKENEXTRA **t, |
+ int recon_yoffset, int recon_uvoffset, |
+ int output_enabled, |
+ int mb_row, int mb_col) { |
+ VP9_COMMON *const cm = &cpi->common; |
+ MACROBLOCK *const x = &cpi->mb; |
MACROBLOCKD *const xd = &x->e_mbd; |
- MB_MODE_INFO * mbmi = &xd->mode_info_context->mbmi; |
- unsigned char *segment_id = &mbmi->segment_id; |
- int seg_ref_active; |
+ MB_MODE_INFO *const mbmi = &xd->mode_info_context->mbmi; |
unsigned char ref_pred_flag; |
- x->skip = 0; |
-#if CONFIG_SUPERBLOCKS |
- assert(!xd->mode_info_context->mbmi.encoded_as_sb); |
-#endif |
+ assert(!xd->mode_info_context->mbmi.sb_type); |
#ifdef ENC_DEBUG |
enc_debug = (cpi->common.current_video_frame == 46 && |
@@ -2079,8 +2045,6 @@ |
vp9_update_zbin_extra(cpi, x); |
- seg_ref_active = vp9_segfeature_active(xd, *segment_id, SEG_LVL_REF_FRAME); |
- |
// SET VARIOUS PREDICTION FLAGS |
// Did the chosen reference frame match its predicted value. |
@@ -2250,7 +2214,7 @@ |
mbmi->mb_skip_coeff = 1; |
if (output_enabled) |
cpi->skip_true_count[mb_skip_context]++; |
- vp9_fix_contexts(xd); |
+ vp9_reset_mb_tokens_context(xd); |
} else { |
vp9_stuff_mb(cpi, xd, t, !output_enabled); |
mbmi->mb_skip_coeff = 0; |
@@ -2265,9 +2229,10 @@ |
!((cpi->common.mb_no_coeff_skip && mbmi->mb_skip_coeff) || |
(vp9_segfeature_active(&x->e_mbd, segment_id, SEG_LVL_EOB) && |
vp9_get_segdata(&x->e_mbd, segment_id, SEG_LVL_EOB) == 0))) { |
+ assert(mbmi->txfm_size <= TX_16X16); |
if (mbmi->mode != B_PRED && mbmi->mode != I8X8_PRED && |
mbmi->mode != SPLITMV) { |
- cpi->txfm_count[mbmi->txfm_size]++; |
+ cpi->txfm_count_16x16p[mbmi->txfm_size]++; |
} else if (mbmi->mode == I8X8_PRED || |
(mbmi->mode == SPLITMV && |
mbmi->partitioning != PARTITIONING_4X4)) { |
@@ -2287,11 +2252,11 @@ |
} |
} |
-#if CONFIG_SUPERBLOCKS |
-static void encode_superblock(VP9_COMP *cpi, MACROBLOCK *x, |
- TOKENEXTRA **t, int recon_yoffset, |
- int recon_uvoffset, int mb_col, int mb_row) { |
+static void encode_superblock32(VP9_COMP *cpi, TOKENEXTRA **t, |
+ int recon_yoffset, int recon_uvoffset, |
+ int output_enabled, int mb_row, int mb_col) { |
VP9_COMMON *const cm = &cpi->common; |
+ MACROBLOCK *const x = &cpi->mb; |
MACROBLOCKD *const xd = &x->e_mbd; |
const uint8_t *src = x->src.y_buffer; |
uint8_t *dst = xd->dst.y_buffer; |
@@ -2301,7 +2266,6 @@ |
uint8_t *vdst = xd->dst.v_buffer; |
int src_y_stride = x->src.y_stride, dst_y_stride = xd->dst.y_stride; |
int src_uv_stride = x->src.uv_stride, dst_uv_stride = xd->dst.uv_stride; |
- int seg_ref_active; |
unsigned char ref_pred_flag; |
int n; |
TOKENEXTRA *tp[4]; |
@@ -2309,9 +2273,8 @@ |
MODE_INFO *mi = x->e_mbd.mode_info_context; |
unsigned int segment_id = mi->mbmi.segment_id; |
ENTROPY_CONTEXT_PLANES ta[4], tl[4]; |
+ const int mis = cm->mode_info_stride; |
- x->skip = 0; |
- |
if (cm->frame_type == KEY_FRAME) { |
if (cpi->oxcf.tuning == VP8_TUNE_SSIM) { |
adjust_act_zbin(cpi, x); |
@@ -2344,10 +2307,7 @@ |
vp9_update_zbin_extra(cpi, x); |
- seg_ref_active = vp9_segfeature_active(xd, segment_id, SEG_LVL_REF_FRAME); |
- |
// SET VARIOUS PREDICTION FLAGS |
- |
// Did the chosen reference frame match its predicted value. |
ref_pred_flag = ((xd->mode_info_context->mbmi.ref_frame == |
vp9_get_pred_ref(cm, xd))); |
@@ -2358,7 +2318,8 @@ |
if (xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME) { |
vp9_build_intra_predictors_sby_s(&x->e_mbd); |
vp9_build_intra_predictors_sbuv_s(&x->e_mbd); |
- sum_intra_stats(cpi, x); |
+ if (output_enabled) |
+ sum_intra_stats(cpi, x); |
} else { |
int ref_fb_idx; |
@@ -2398,74 +2359,391 @@ |
xd->dst.y_stride, xd->dst.uv_stride); |
} |
- for (n = 0; n < 4; n++) { |
- int x_idx = n & 1, y_idx = n >> 1; |
+ if (xd->mode_info_context->mbmi.txfm_size == TX_32X32) { |
+ if (!x->skip) { |
+ vp9_subtract_sby_s_c(x->sb_coeff_data.src_diff, src, src_y_stride, |
+ dst, dst_y_stride); |
+ vp9_subtract_sbuv_s_c(x->sb_coeff_data.src_diff, |
+ usrc, vsrc, src_uv_stride, |
+ udst, vdst, dst_uv_stride); |
+ vp9_transform_sby_32x32(x); |
+ vp9_transform_sbuv_16x16(x); |
+ vp9_quantize_sby_32x32(x); |
+ vp9_quantize_sbuv_16x16(x); |
+ // TODO(rbultje): trellis optimize |
+ vp9_inverse_transform_sbuv_16x16(&x->e_mbd.sb_coeff_data); |
+ vp9_inverse_transform_sby_32x32(&x->e_mbd.sb_coeff_data); |
+ vp9_recon_sby_s_c(&x->e_mbd, dst); |
+ vp9_recon_sbuv_s_c(&x->e_mbd, udst, vdst); |
- xd->left_context = cm->left_context + y_idx; |
- xd->above_context = cm->above_context + mb_col + x_idx; |
- memcpy(&ta[n], xd->above_context, sizeof(ta[n])); |
- memcpy(&tl[n], xd->left_context, sizeof(tl[n])); |
- tp[n] = *t; |
- xd->mode_info_context = mi + x_idx + y_idx * cm->mode_info_stride; |
- |
- vp9_subtract_mby_s_c(x->src_diff, |
- src + x_idx * 16 + y_idx * 16 * src_y_stride, |
- src_y_stride, |
- dst + x_idx * 16 + y_idx * 16 * dst_y_stride, |
- dst_y_stride); |
- vp9_subtract_mbuv_s_c(x->src_diff, |
- usrc + x_idx * 8 + y_idx * 8 * src_uv_stride, |
- vsrc + x_idx * 8 + y_idx * 8 * src_uv_stride, |
- src_uv_stride, |
- udst + x_idx * 8 + y_idx * 8 * dst_uv_stride, |
- vdst + x_idx * 8 + y_idx * 8 * dst_uv_stride, |
- dst_uv_stride); |
- vp9_fidct_mb(x); |
- vp9_recon_mby_s_c(&x->e_mbd, |
- dst + x_idx * 16 + y_idx * 16 * dst_y_stride); |
- vp9_recon_mbuv_s_c(&x->e_mbd, |
- udst + x_idx * 8 + y_idx * 8 * dst_uv_stride, |
- vdst + x_idx * 8 + y_idx * 8 * dst_uv_stride); |
- |
- if (!x->skip) { |
- vp9_tokenize_mb(cpi, &x->e_mbd, t, 0); |
- skip[n] = xd->mode_info_context->mbmi.mb_skip_coeff; |
+ vp9_tokenize_sb(cpi, &x->e_mbd, t, !output_enabled); |
} else { |
int mb_skip_context = |
- cpi->common.mb_no_coeff_skip ? |
- (x->e_mbd.mode_info_context - 1)->mbmi.mb_skip_coeff + |
- (x->e_mbd.mode_info_context - cpi->common.mode_info_stride)->mbmi.mb_skip_coeff : |
+ cpi->common.mb_no_coeff_skip ? |
+ (mi - 1)->mbmi.mb_skip_coeff + |
+ (mi - mis)->mbmi.mb_skip_coeff : |
0; |
- xd->mode_info_context->mbmi.mb_skip_coeff = skip[n] = 1; |
- if (cpi->common.mb_no_coeff_skip) { |
- // TODO(rbultje) this should be done per-sb instead of per-mb? |
- cpi->skip_true_count[mb_skip_context]++; |
- vp9_fix_contexts(xd); |
+ mi->mbmi.mb_skip_coeff = 1; |
+ if (cm->mb_no_coeff_skip) { |
+ if (output_enabled) |
+ cpi->skip_true_count[mb_skip_context]++; |
+ vp9_fix_contexts_sb(xd); |
} else { |
- vp9_stuff_mb(cpi, xd, t, 0); |
- // TODO(rbultje) this should be done per-sb instead of per-mb? |
- cpi->skip_false_count[mb_skip_context]++; |
+ vp9_stuff_sb(cpi, xd, t, !output_enabled); |
+ if (output_enabled) |
+ cpi->skip_false_count[mb_skip_context]++; |
} |
} |
- } |
- xd->mode_info_context = mi; |
- update_sb_skip_coeff_state(cpi, x, ta, tl, tp, t, skip); |
- if (cm->txfm_mode == TX_MODE_SELECT && |
- !((cm->mb_no_coeff_skip && skip[0] && skip[1] && skip[2] && skip[3]) || |
- (vp9_segfeature_active(xd, segment_id, SEG_LVL_EOB) && |
- vp9_get_segdata(xd, segment_id, SEG_LVL_EOB) == 0))) { |
- cpi->txfm_count[mi->mbmi.txfm_size]++; |
- } else { |
- TX_SIZE sz = (cm->txfm_mode == TX_MODE_SELECT) ? TX_16X16 : cm->txfm_mode; |
- mi->mbmi.txfm_size = sz; |
+ // copy skip flag on all mb_mode_info contexts in this SB |
+ // if this was a skip at this txfm size |
if (mb_col < cm->mb_cols - 1) |
- mi[1].mbmi.txfm_size = sz; |
+ mi[1].mbmi.mb_skip_coeff = mi->mbmi.mb_skip_coeff; |
if (mb_row < cm->mb_rows - 1) { |
- mi[cm->mode_info_stride].mbmi.txfm_size = sz; |
+ mi[mis].mbmi.mb_skip_coeff = mi->mbmi.mb_skip_coeff; |
if (mb_col < cm->mb_cols - 1) |
- mi[cm->mode_info_stride + 1].mbmi.txfm_size = sz; |
+ mi[mis + 1].mbmi.mb_skip_coeff = mi->mbmi.mb_skip_coeff; |
} |
+ skip[0] = skip[2] = skip[1] = skip[3] = mi->mbmi.mb_skip_coeff; |
+ } else { |
+ for (n = 0; n < 4; n++) { |
+ int x_idx = n & 1, y_idx = n >> 1; |
+ |
+ xd->left_context = cm->left_context + y_idx + (mb_row & 2); |
+ xd->above_context = cm->above_context + mb_col + x_idx; |
+ memcpy(&ta[n], xd->above_context, sizeof(ta[n])); |
+ memcpy(&tl[n], xd->left_context, sizeof(tl[n])); |
+ tp[n] = *t; |
+ xd->mode_info_context = mi + x_idx + y_idx * mis; |
+ |
+ if (!x->skip) { |
+ vp9_subtract_mby_s_c(x->src_diff, |
+ src + x_idx * 16 + y_idx * 16 * src_y_stride, |
+ src_y_stride, |
+ dst + x_idx * 16 + y_idx * 16 * dst_y_stride, |
+ dst_y_stride); |
+ vp9_subtract_mbuv_s_c(x->src_diff, |
+ usrc + x_idx * 8 + y_idx * 8 * src_uv_stride, |
+ vsrc + x_idx * 8 + y_idx * 8 * src_uv_stride, |
+ src_uv_stride, |
+ udst + x_idx * 8 + y_idx * 8 * dst_uv_stride, |
+ vdst + x_idx * 8 + y_idx * 8 * dst_uv_stride, |
+ dst_uv_stride); |
+ vp9_fidct_mb(x); |
+ vp9_recon_mby_s_c(&x->e_mbd, |
+ dst + x_idx * 16 + y_idx * 16 * dst_y_stride); |
+ vp9_recon_mbuv_s_c(&x->e_mbd, |
+ udst + x_idx * 8 + y_idx * 8 * dst_uv_stride, |
+ vdst + x_idx * 8 + y_idx * 8 * dst_uv_stride); |
+ |
+ vp9_tokenize_mb(cpi, &x->e_mbd, t, !output_enabled); |
+ skip[n] = xd->mode_info_context->mbmi.mb_skip_coeff; |
+ } else { |
+ int mb_skip_context = cpi->common.mb_no_coeff_skip ? |
+ (x->e_mbd.mode_info_context - 1)->mbmi.mb_skip_coeff + |
+ (x->e_mbd.mode_info_context - mis)->mbmi.mb_skip_coeff : |
+ 0; |
+ xd->mode_info_context->mbmi.mb_skip_coeff = skip[n] = 1; |
+ if (cpi->common.mb_no_coeff_skip) { |
+ // TODO(rbultje) this should be done per-sb instead of per-mb? |
+ if (output_enabled) |
+ cpi->skip_true_count[mb_skip_context]++; |
+ vp9_reset_mb_tokens_context(xd); |
+ } else { |
+ vp9_stuff_mb(cpi, xd, t, !output_enabled); |
+ // TODO(rbultje) this should be done per-sb instead of per-mb? |
+ if (output_enabled) |
+ cpi->skip_false_count[mb_skip_context]++; |
+ } |
+ } |
+ } |
+ |
+ xd->mode_info_context = mi; |
+ update_sb_skip_coeff_state(cpi, ta, tl, tp, t, skip, output_enabled); |
} |
+ |
+ if (output_enabled) { |
+ if (cm->txfm_mode == TX_MODE_SELECT && |
+ !((cm->mb_no_coeff_skip && skip[0] && skip[1] && skip[2] && skip[3]) || |
+ (vp9_segfeature_active(xd, segment_id, SEG_LVL_EOB) && |
+ vp9_get_segdata(xd, segment_id, SEG_LVL_EOB) == 0))) { |
+ cpi->txfm_count_32x32p[mi->mbmi.txfm_size]++; |
+ } else { |
+ TX_SIZE sz = (cm->txfm_mode == TX_MODE_SELECT) ? |
+ TX_32X32 : |
+ cm->txfm_mode; |
+ mi->mbmi.txfm_size = sz; |
+ if (mb_col < cm->mb_cols - 1) |
+ mi[1].mbmi.txfm_size = sz; |
+ if (mb_row < cm->mb_rows - 1) { |
+ mi[mis].mbmi.txfm_size = sz; |
+ if (mb_col < cm->mb_cols - 1) |
+ mi[mis + 1].mbmi.txfm_size = sz; |
+ } |
+ } |
+ } |
} |
-#endif |
+ |
+static void encode_superblock64(VP9_COMP *cpi, TOKENEXTRA **t, |
+ int recon_yoffset, int recon_uvoffset, |
+ int output_enabled, int mb_row, int mb_col) { |
+ VP9_COMMON *const cm = &cpi->common; |
+ MACROBLOCK *const x = &cpi->mb; |
+ MACROBLOCKD *const xd = &x->e_mbd; |
+ const uint8_t *src = x->src.y_buffer; |
+ uint8_t *dst = xd->dst.y_buffer; |
+ const uint8_t *usrc = x->src.u_buffer; |
+ uint8_t *udst = xd->dst.u_buffer; |
+ const uint8_t *vsrc = x->src.v_buffer; |
+ uint8_t *vdst = xd->dst.v_buffer; |
+ int src_y_stride = x->src.y_stride, dst_y_stride = xd->dst.y_stride; |
+ int src_uv_stride = x->src.uv_stride, dst_uv_stride = xd->dst.uv_stride; |
+ unsigned char ref_pred_flag; |
+ int n; |
+ TOKENEXTRA *tp[16]; |
+ int skip[16]; |
+ MODE_INFO *mi = x->e_mbd.mode_info_context; |
+ unsigned int segment_id = mi->mbmi.segment_id; |
+ ENTROPY_CONTEXT_PLANES ta[16], tl[16]; |
+ const int mis = cm->mode_info_stride; |
+ |
+ if (cm->frame_type == KEY_FRAME) { |
+ if (cpi->oxcf.tuning == VP8_TUNE_SSIM) { |
+ adjust_act_zbin(cpi, x); |
+ vp9_update_zbin_extra(cpi, x); |
+ } |
+ } else { |
+ vp9_setup_interp_filters(xd, xd->mode_info_context->mbmi.interp_filter, cm); |
+ |
+ if (cpi->oxcf.tuning == VP8_TUNE_SSIM) { |
+ // Adjust the zbin based on this MB rate. |
+ adjust_act_zbin(cpi, x); |
+ } |
+ |
+ // Experimental code. Special case for gf and arf zeromv modes. |
+ // Increase zbin size to suppress noise |
+ cpi->zbin_mode_boost = 0; |
+ if (cpi->zbin_mode_boost_enabled) { |
+ if (xd->mode_info_context->mbmi.ref_frame != INTRA_FRAME) { |
+ if (xd->mode_info_context->mbmi.mode == ZEROMV) { |
+ if (xd->mode_info_context->mbmi.ref_frame != LAST_FRAME) |
+ cpi->zbin_mode_boost = GF_ZEROMV_ZBIN_BOOST; |
+ else |
+ cpi->zbin_mode_boost = LF_ZEROMV_ZBIN_BOOST; |
+ } else if (xd->mode_info_context->mbmi.mode == SPLITMV) { |
+ cpi->zbin_mode_boost = 0; |
+ } else { |
+ cpi->zbin_mode_boost = MV_ZBIN_BOOST; |
+ } |
+ } |
+ } |
+ |
+ vp9_update_zbin_extra(cpi, x); |
+ |
+ // Did the chosen reference frame match its predicted value. |
+ ref_pred_flag = ((xd->mode_info_context->mbmi.ref_frame == |
+ vp9_get_pred_ref(cm, xd))); |
+ vp9_set_pred_flag(xd, PRED_REF, ref_pred_flag); |
+ } |
+ |
+ if (xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME) { |
+ vp9_build_intra_predictors_sb64y_s(&x->e_mbd); |
+ vp9_build_intra_predictors_sb64uv_s(&x->e_mbd); |
+ if (output_enabled) |
+ sum_intra_stats(cpi, x); |
+ } else { |
+ int ref_fb_idx; |
+ |
+ assert(cm->frame_type != KEY_FRAME); |
+ |
+ if (xd->mode_info_context->mbmi.ref_frame == LAST_FRAME) |
+ ref_fb_idx = cpi->common.lst_fb_idx; |
+ else if (xd->mode_info_context->mbmi.ref_frame == GOLDEN_FRAME) |
+ ref_fb_idx = cpi->common.gld_fb_idx; |
+ else |
+ ref_fb_idx = cpi->common.alt_fb_idx; |
+ |
+ xd->pre.y_buffer = |
+ cpi->common.yv12_fb[ref_fb_idx].y_buffer + recon_yoffset; |
+ xd->pre.u_buffer = |
+ cpi->common.yv12_fb[ref_fb_idx].u_buffer + recon_uvoffset; |
+ xd->pre.v_buffer = |
+ cpi->common.yv12_fb[ref_fb_idx].v_buffer + recon_uvoffset; |
+ |
+ if (xd->mode_info_context->mbmi.second_ref_frame > 0) { |
+ int second_ref_fb_idx; |
+ |
+ if (xd->mode_info_context->mbmi.second_ref_frame == LAST_FRAME) |
+ second_ref_fb_idx = cpi->common.lst_fb_idx; |
+ else if (xd->mode_info_context->mbmi.second_ref_frame == GOLDEN_FRAME) |
+ second_ref_fb_idx = cpi->common.gld_fb_idx; |
+ else |
+ second_ref_fb_idx = cpi->common.alt_fb_idx; |
+ |
+ xd->second_pre.y_buffer = |
+ cpi->common.yv12_fb[second_ref_fb_idx].y_buffer + recon_yoffset; |
+ xd->second_pre.u_buffer = |
+ cpi->common.yv12_fb[second_ref_fb_idx].u_buffer + recon_uvoffset; |
+ xd->second_pre.v_buffer = |
+ cpi->common.yv12_fb[second_ref_fb_idx].v_buffer + recon_uvoffset; |
+ } |
+ |
+ vp9_build_inter64x64_predictors_sb(xd, xd->dst.y_buffer, |
+ xd->dst.u_buffer, xd->dst.v_buffer, |
+ xd->dst.y_stride, xd->dst.uv_stride); |
+ } |
+ |
+ if (xd->mode_info_context->mbmi.txfm_size == TX_32X32) { |
+ int n; |
+ |
+ for (n = 0; n < 4; n++) { |
+ int x_idx = n & 1, y_idx = n >> 1; |
+ |
+ xd->mode_info_context = mi + x_idx * 2 + mis * y_idx * 2; |
+ xd->left_context = cm->left_context + (y_idx << 1); |
+ xd->above_context = cm->above_context + mb_col + (x_idx << 1); |
+ memcpy(&ta[n * 2], xd->above_context, sizeof(*ta) * 2); |
+ memcpy(&tl[n * 2], xd->left_context, sizeof(*tl) * 2); |
+ tp[n] = *t; |
+ xd->mode_info_context = mi + x_idx * 2 + y_idx * mis * 2; |
+ if (!x->skip) { |
+ vp9_subtract_sby_s_c(x->sb_coeff_data.src_diff, |
+ src + x_idx * 32 + y_idx * 32 * src_y_stride, |
+ src_y_stride, |
+ dst + x_idx * 32 + y_idx * 32 * dst_y_stride, |
+ dst_y_stride); |
+ vp9_subtract_sbuv_s_c(x->sb_coeff_data.src_diff, |
+ usrc + x_idx * 16 + y_idx * 16 * src_uv_stride, |
+ vsrc + x_idx * 16 + y_idx * 16 * src_uv_stride, |
+ src_uv_stride, |
+ udst + x_idx * 16 + y_idx * 16 * dst_uv_stride, |
+ vdst + x_idx * 16 + y_idx * 16 * dst_uv_stride, |
+ dst_uv_stride); |
+ vp9_transform_sby_32x32(x); |
+ vp9_transform_sbuv_16x16(x); |
+ vp9_quantize_sby_32x32(x); |
+ vp9_quantize_sbuv_16x16(x); |
+ // TODO(rbultje): trellis optimize |
+ vp9_inverse_transform_sbuv_16x16(&x->e_mbd.sb_coeff_data); |
+ vp9_inverse_transform_sby_32x32(&x->e_mbd.sb_coeff_data); |
+ vp9_recon_sby_s_c(&x->e_mbd, |
+ dst + 32 * x_idx + 32 * y_idx * dst_y_stride); |
+ vp9_recon_sbuv_s_c(&x->e_mbd, |
+ udst + x_idx * 16 + y_idx * 16 * dst_uv_stride, |
+ vdst + x_idx * 16 + y_idx * 16 * dst_uv_stride); |
+ |
+ vp9_tokenize_sb(cpi, &x->e_mbd, t, !output_enabled); |
+ } else { |
+ int mb_skip_context = cpi->common.mb_no_coeff_skip ? |
+ (mi - 1)->mbmi.mb_skip_coeff + |
+ (mi - mis)->mbmi.mb_skip_coeff : 0; |
+ xd->mode_info_context->mbmi.mb_skip_coeff = 1; |
+ if (cm->mb_no_coeff_skip) { |
+ if (output_enabled) |
+ cpi->skip_true_count[mb_skip_context]++; |
+ vp9_fix_contexts_sb(xd); |
+ } else { |
+ vp9_stuff_sb(cpi, xd, t, !output_enabled); |
+ if (output_enabled) |
+ cpi->skip_false_count[mb_skip_context]++; |
+ } |
+ } |
+ |
+ // copy skip flag on all mb_mode_info contexts in this SB |
+ // if this was a skip at this txfm size |
+ if (mb_col + x_idx * 2 < cm->mb_cols - 1) |
+ mi[mis * y_idx * 2 + x_idx * 2 + 1].mbmi.mb_skip_coeff = |
+ mi[mis * y_idx * 2 + x_idx * 2].mbmi.mb_skip_coeff; |
+ if (mb_row + y_idx * 2 < cm->mb_rows - 1) { |
+ mi[mis * y_idx * 2 + x_idx * 2 + mis].mbmi.mb_skip_coeff = |
+ mi[mis * y_idx * 2 + x_idx * 2].mbmi.mb_skip_coeff; |
+ if (mb_col + x_idx * 2 < cm->mb_cols - 1) |
+ mi[mis * y_idx * 2 + x_idx * 2 + mis + 1].mbmi.mb_skip_coeff = |
+ mi[mis * y_idx * 2 + x_idx * 2].mbmi.mb_skip_coeff; |
+ } |
+ skip[n] = xd->mode_info_context->mbmi.mb_skip_coeff; |
+ } |
+ } else { |
+ for (n = 0; n < 16; n++) { |
+ const int x_idx = n & 3, y_idx = n >> 2; |
+ |
+ xd->left_context = cm->left_context + y_idx; |
+ xd->above_context = cm->above_context + mb_col + x_idx; |
+ memcpy(&ta[n], xd->above_context, sizeof(ta[n])); |
+ memcpy(&tl[n], xd->left_context, sizeof(tl[n])); |
+ tp[n] = *t; |
+ xd->mode_info_context = mi + x_idx + y_idx * mis; |
+ |
+ if (!x->skip) { |
+ vp9_subtract_mby_s_c(x->src_diff, |
+ src + x_idx * 16 + y_idx * 16 * src_y_stride, |
+ src_y_stride, |
+ dst + x_idx * 16 + y_idx * 16 * dst_y_stride, |
+ dst_y_stride); |
+ vp9_subtract_mbuv_s_c(x->src_diff, |
+ usrc + x_idx * 8 + y_idx * 8 * src_uv_stride, |
+ vsrc + x_idx * 8 + y_idx * 8 * src_uv_stride, |
+ src_uv_stride, |
+ udst + x_idx * 8 + y_idx * 8 * dst_uv_stride, |
+ vdst + x_idx * 8 + y_idx * 8 * dst_uv_stride, |
+ dst_uv_stride); |
+ vp9_fidct_mb(x); |
+ vp9_recon_mby_s_c(&x->e_mbd, |
+ dst + x_idx * 16 + y_idx * 16 * dst_y_stride); |
+ vp9_recon_mbuv_s_c(&x->e_mbd, |
+ udst + x_idx * 8 + y_idx * 8 * dst_uv_stride, |
+ vdst + x_idx * 8 + y_idx * 8 * dst_uv_stride); |
+ |
+ vp9_tokenize_mb(cpi, &x->e_mbd, t, !output_enabled); |
+ skip[n] = xd->mode_info_context->mbmi.mb_skip_coeff; |
+ } else { |
+ int mb_skip_context = cpi->common.mb_no_coeff_skip ? |
+ (x->e_mbd.mode_info_context - 1)->mbmi.mb_skip_coeff + |
+ (x->e_mbd.mode_info_context - mis)->mbmi.mb_skip_coeff : 0; |
+ xd->mode_info_context->mbmi.mb_skip_coeff = skip[n] = 1; |
+ if (cpi->common.mb_no_coeff_skip) { |
+ // TODO(rbultje) this should be done per-sb instead of per-mb? |
+ if (output_enabled) |
+ cpi->skip_true_count[mb_skip_context]++; |
+ vp9_reset_mb_tokens_context(xd); |
+ } else { |
+ vp9_stuff_mb(cpi, xd, t, !output_enabled); |
+ // TODO(rbultje) this should be done per-sb instead of per-mb? |
+ if (output_enabled) |
+ cpi->skip_false_count[mb_skip_context]++; |
+ } |
+ } |
+ } |
+ } |
+ |
+ xd->mode_info_context = mi; |
+ update_sb64_skip_coeff_state(cpi, ta, tl, tp, t, skip, output_enabled); |
+ |
+ if (output_enabled) { |
+ if (cm->txfm_mode == TX_MODE_SELECT && |
+ !((cm->mb_no_coeff_skip && |
+ ((mi->mbmi.txfm_size == TX_32X32 && |
+ skip[0] && skip[1] && skip[2] && skip[3]) || |
+ (mi->mbmi.txfm_size != TX_32X32 && |
+ skip[0] && skip[1] && skip[2] && skip[3] && |
+ skip[4] && skip[5] && skip[6] && skip[7] && |
+ skip[8] && skip[9] && skip[10] && skip[11] && |
+ skip[12] && skip[13] && skip[14] && skip[15]))) || |
+ (vp9_segfeature_active(xd, segment_id, SEG_LVL_EOB) && |
+ vp9_get_segdata(xd, segment_id, SEG_LVL_EOB) == 0))) { |
+ cpi->txfm_count_32x32p[mi->mbmi.txfm_size]++; |
+ } else { |
+ int x, y; |
+ TX_SIZE sz = (cm->txfm_mode == TX_MODE_SELECT) ? |
+ TX_32X32 : |
+ cm->txfm_mode; |
+ for (y = 0; y < 4; y++) { |
+ for (x = 0; x < 4; x++) { |
+ if (mb_col + x < cm->mb_cols && mb_row + y < cm->mb_rows) { |
+ mi[mis * y + x].mbmi.txfm_size = sz; |
+ } |
+ } |
+ } |
+ } |
+ } |
+} |