// Allocate storage for each tile column. // TODO(jzern): when max_threads <= 1 the same storage could be used for each // tile. static void alloc_tile_storage(VP9D_COMP *pbi, int tile_cols) { VP9_COMMON *const cm = &pbi->common; const int aligned_mi_cols = mi_cols_aligned_to_sb(cm->mi_cols); int i, tile_col; CHECK_MEM_ERROR(cm, pbi->mi_streams, vpx_realloc(pbi->mi_streams, tile_cols * sizeof(*pbi->mi_streams))); for (tile_col = 0; tile_col < tile_cols; ++tile_col) { TileInfo tile; vp9_tile_init(&tile, cm, 0, tile_col); pbi->mi_streams[tile_col] = &cm->mi[cm->mi_rows * tile.mi_col_start]; } // 2 contexts per 'mi unit', so that we have one context per 4x4 txfm // block where mi unit size is 8x8. CHECK_MEM_ERROR(cm, pbi->above_context[0], vpx_realloc(pbi->above_context[0], sizeof(*pbi->above_context[0]) * MAX_MB_PLANE * 2 * aligned_mi_cols)); for (i = 1; i < MAX_MB_PLANE; ++i) { pbi->above_context[i] = pbi->above_context[0] + i * sizeof(*pbi->above_context[0]) * 2 * aligned_mi_cols; } // This is sized based on the entire frame. Each tile operates within its // column bounds. CHECK_MEM_ERROR(cm, pbi->above_seg_context, vpx_realloc(pbi->above_seg_context, sizeof(*pbi->above_seg_context) * aligned_mi_cols)); }
void vp9_choose_segmap_coding_method(VP9_COMMON *cm, MACROBLOCKD *xd) { struct segmentation *seg = &cm->seg; int no_pred_cost; int t_pred_cost = INT_MAX; int i, tile_col, mi_row, mi_col; int temporal_predictor_count[PREDICTION_PROBS][2] = { { 0 } }; int no_pred_segcounts[MAX_SEGMENTS] = { 0 }; int t_unpred_seg_counts[MAX_SEGMENTS] = { 0 }; vp9_prob no_pred_tree[SEG_TREE_PROBS]; vp9_prob t_pred_tree[SEG_TREE_PROBS]; vp9_prob t_nopred_prob[PREDICTION_PROBS]; // Set default state for the segment tree probabilities and the // temporal coding probabilities memset(seg->tree_probs, 255, sizeof(seg->tree_probs)); memset(seg->pred_probs, 255, sizeof(seg->pred_probs)); // First of all generate stats regarding how well the last segment map // predicts this one for (tile_col = 0; tile_col < 1 << cm->log2_tile_cols; tile_col++) { TileInfo tile; MODE_INFO **mi_ptr; vp9_tile_init(&tile, cm, 0, tile_col); mi_ptr = cm->mi_grid_visible + tile.mi_col_start; for (mi_row = 0; mi_row < cm->mi_rows; mi_row += 8, mi_ptr += 8 * cm->mi_stride) { MODE_INFO **mi = mi_ptr; for (mi_col = tile.mi_col_start; mi_col < tile.mi_col_end; mi_col += 8, mi += 8) count_segs_sb(cm, xd, &tile, mi, no_pred_segcounts, temporal_predictor_count, t_unpred_seg_counts, mi_row, mi_col, BLOCK_64X64); } } // Work out probability tree for coding segments without prediction // and the cost. calc_segtree_probs(no_pred_segcounts, no_pred_tree); no_pred_cost = cost_segmap(no_pred_segcounts, no_pred_tree); // Key frames cannot use temporal prediction if (!frame_is_intra_only(cm)) { // Work out probability tree for coding those segments not // predicted using the temporal method and the cost. calc_segtree_probs(t_unpred_seg_counts, t_pred_tree); t_pred_cost = cost_segmap(t_unpred_seg_counts, t_pred_tree); // Add in the cost of the signaling for each prediction context. for (i = 0; i < PREDICTION_PROBS; i++) { const int count0 = temporal_predictor_count[i][0]; const int count1 = temporal_predictor_count[i][1]; t_nopred_prob[i] = get_binary_prob(count0, count1); // Add in the predictor signaling cost t_pred_cost += count0 * vp9_cost_zero(t_nopred_prob[i]) + count1 * vp9_cost_one(t_nopred_prob[i]); } } // Now choose which coding method to use. if (t_pred_cost < no_pred_cost) { seg->temporal_update = 1; memcpy(seg->tree_probs, t_pred_tree, sizeof(t_pred_tree)); memcpy(seg->pred_probs, t_nopred_prob, sizeof(t_nopred_prob)); } else { seg->temporal_update = 0; memcpy(seg->tree_probs, no_pred_tree, sizeof(no_pred_tree)); } }