static void adapt_coef_probs(VP9_COMMON *cm, TX_SIZE tx_size, unsigned int count_sat, unsigned int update_factor) { FRAME_CONTEXT *pre_fc = &cm->frame_contexts[cm->frame_context_idx]; vp9_coeff_probs_model *dst_coef_probs = cm->fc.coef_probs[tx_size]; vp9_coeff_probs_model *pre_coef_probs = pre_fc->coef_probs[tx_size]; vp9_coeff_count_model *coef_counts = cm->counts.coef[tx_size]; unsigned int (*eob_branch_count)[REF_TYPES][COEF_BANDS][PREV_COEF_CONTEXTS] = cm->counts.eob_branch[tx_size]; int t, i, j, k, l; unsigned int branch_ct[UNCONSTRAINED_NODES][2]; vp9_prob coef_probs[UNCONSTRAINED_NODES]; for (i = 0; i < BLOCK_TYPES; ++i) for (j = 0; j < REF_TYPES; ++j) for (k = 0; k < COEF_BANDS; ++k) for (l = 0; l < PREV_COEF_CONTEXTS; ++l) { if (l >= 3 && k == 0) continue; vp9_tree_probs_from_distribution(vp9_coefmodel_tree, coef_probs, branch_ct, coef_counts[i][j][k][l], 0); branch_ct[0][1] = eob_branch_count[i][j][k][l] - branch_ct[0][0]; coef_probs[0] = get_binary_prob(branch_ct[0][0], branch_ct[0][1]); for (t = 0; t < UNCONSTRAINED_NODES; ++t) dst_coef_probs[i][j][k][l][t] = merge_probs( pre_coef_probs[i][j][k][l][t], coef_probs[t], branch_ct[t], count_sat, update_factor); } }
static void build_tree_distribution(VP9_COMP *cpi, TX_SIZE tx_size, vp9_coeff_stats *coef_branch_ct, vp9_coeff_probs_model *coef_probs) { vp9_coeff_count *coef_counts = cpi->td.rd_counts.coef_counts[tx_size]; unsigned int (*eob_branch_ct)[REF_TYPES][COEF_BANDS][COEFF_CONTEXTS] = cpi->common.counts.eob_branch[tx_size]; int i, j, k, l, m; for (i = 0; i < PLANE_TYPES; ++i) { for (j = 0; j < REF_TYPES; ++j) { for (k = 0; k < COEF_BANDS; ++k) { for (l = 0; l < BAND_COEFF_CONTEXTS(k); ++l) { vp9_tree_probs_from_distribution(vp9_coef_tree, coef_branch_ct[i][j][k][l], coef_counts[i][j][k][l]); coef_branch_ct[i][j][k][l][0][1] = eob_branch_ct[i][j][k][l] - coef_branch_ct[i][j][k][l][0][0]; for (m = 0; m < UNCONSTRAINED_NODES; ++m) coef_probs[i][j][k][l][m] = get_binary_prob( coef_branch_ct[i][j][k][l][m][0], coef_branch_ct[i][j][k][l][m][1]); } } } } }
// Based on set of segment counts calculate a probability tree static void calc_segtree_probs(unsigned *segcounts, aom_prob *segment_tree_probs, const aom_prob *cur_tree_probs, const int probwt) { // Work out probabilities of each segment const unsigned cc[4] = { segcounts[0] + segcounts[1], segcounts[2] + segcounts[3], segcounts[4] + segcounts[5], segcounts[6] + segcounts[7] }; const unsigned ccc[2] = { cc[0] + cc[1], cc[2] + cc[3] }; int i; segment_tree_probs[0] = get_binary_prob(ccc[0], ccc[1]); segment_tree_probs[1] = get_binary_prob(cc[0], cc[1]); segment_tree_probs[2] = get_binary_prob(cc[2], cc[3]); segment_tree_probs[3] = get_binary_prob(segcounts[0], segcounts[1]); segment_tree_probs[4] = get_binary_prob(segcounts[2], segcounts[3]); segment_tree_probs[5] = get_binary_prob(segcounts[4], segcounts[5]); segment_tree_probs[6] = get_binary_prob(segcounts[6], segcounts[7]); for (i = 0; i < 7; i++) { const unsigned *ct = i == 0 ? ccc : i < 3 ? cc + (i & 2) : segcounts + (i - 3) * 2; av1_prob_diff_update_savings_search(ct, cur_tree_probs[i], &segment_tree_probs[i], DIFF_UPDATE_PROB, probwt); } }
// Based on set of segment counts calculate a probability tree static void calc_segtree_probs(unsigned *segcounts, vpx_prob *segment_tree_probs, const vpx_prob *cur_tree_probs) { // Work out probabilities of each segment const unsigned cc[4] = { segcounts[0] + segcounts[1], segcounts[2] + segcounts[3], segcounts[4] + segcounts[5], segcounts[6] + segcounts[7] }; const unsigned ccc[2] = { cc[0] + cc[1], cc[2] + cc[3] }; #if CONFIG_MISC_FIXES int i; #endif segment_tree_probs[0] = get_binary_prob(ccc[0], ccc[1]); segment_tree_probs[1] = get_binary_prob(cc[0], cc[1]); segment_tree_probs[2] = get_binary_prob(cc[2], cc[3]); segment_tree_probs[3] = get_binary_prob(segcounts[0], segcounts[1]); segment_tree_probs[4] = get_binary_prob(segcounts[2], segcounts[3]); segment_tree_probs[5] = get_binary_prob(segcounts[4], segcounts[5]); segment_tree_probs[6] = get_binary_prob(segcounts[6], segcounts[7]); #if CONFIG_MISC_FIXES for (i = 0; i < 7; i++) { const unsigned *ct = i == 0 ? ccc : i < 3 ? cc + (i & 2) : segcounts + (i - 3) * 2; vp10_prob_diff_update_savings_search( ct, cur_tree_probs[i], &segment_tree_probs[i], DIFF_UPDATE_PROB); } #else (void)cur_tree_probs; #endif }
static void print_probs(FILE *f, vp9_coeff_accum *context_counters, int block_types, const char *header) { int type, ref, band, pt, t; fprintf(f, "static const vp9_coeff_probs %s = {", header); type = 0; #define Newline(x, spaces) (x ? " " : "\n" spaces) do { fprintf(f, "%s%s{ /* block Type %d */", Comma(type), Newline(type, " "), type); ref = 0; do { fprintf(f, "%s%s{ /* %s */", Comma(band), Newline(band, " "), ref ? "Inter" : "Intra"); band = 0; do { fprintf(f, "%s%s{ /* Coeff Band %d */", Comma(band), Newline(band, " "), band); pt = 0; do { unsigned int branch_ct[ENTROPY_NODES][2]; unsigned int coef_counts[MAX_ENTROPY_TOKENS + 1]; vp9_prob coef_probs[ENTROPY_NODES]; if (pt >= 3 && band == 0) break; for (t = 0; t < MAX_ENTROPY_TOKENS + 1; ++t) coef_counts[t] = context_counters[type][ref][band][pt][t]; vp9_tree_probs_from_distribution(vp9_coef_tree, coef_probs, branch_ct, coef_counts, 0); branch_ct[0][1] = coef_counts[MAX_ENTROPY_TOKENS] - branch_ct[0][0]; coef_probs[0] = get_binary_prob(branch_ct[0][0], branch_ct[0][1]); fprintf(f, "%s\n {", Comma(pt)); t = 0; do { fprintf(f, "%s %3d", Comma(t), coef_probs[t]); } while (++t < ENTROPY_NODES); fprintf(f, " }"); } while (++pt < PREV_COEF_CONTEXTS); fprintf(f, "\n }"); } while (++band < COEF_BANDS); fprintf(f, "\n }"); } while (++ref < REF_TYPES); fprintf(f, "\n }"); } while (++type < block_types); fprintf(f, "\n};\n"); }
void vp9_tree_probs_from_distribution( int n, /* n = size of alphabet */ vp9_token tok [ /* n */ ], vp9_tree tree, vp9_prob probs [ /* n-1 */ ], unsigned int branch_ct [ /* n-1 */ ] [2], const unsigned int num_events[ /* n */ ] ) { const int tree_len = n - 1; int t = 0; branch_counts(n, tok, tree, branch_ct, num_events); do { probs[t] = get_binary_prob(branch_ct[t][0], branch_ct[t][1]); } while (++t < tree_len); }
// Based on set of segment counts calculate a probability tree static void calc_segtree_probs(int *segcounts, vp9_prob *segment_tree_probs) { // Work out probabilities of each segment const int c01 = segcounts[0] + segcounts[1]; const int c23 = segcounts[2] + segcounts[3]; const int c45 = segcounts[4] + segcounts[5]; const int c67 = segcounts[6] + segcounts[7]; segment_tree_probs[0] = get_binary_prob(c01 + c23, c45 + c67); segment_tree_probs[1] = get_binary_prob(c01, c23); segment_tree_probs[2] = get_binary_prob(c45, c67); segment_tree_probs[3] = get_binary_prob(segcounts[0], segcounts[1]); segment_tree_probs[4] = get_binary_prob(segcounts[2], segcounts[3]); segment_tree_probs[5] = get_binary_prob(segcounts[4], segcounts[5]); segment_tree_probs[6] = get_binary_prob(segcounts[6], segcounts[7]); }
void av1_choose_segmap_coding_method(AV1_COMMON *cm, MACROBLOCKD *xd) { struct segmentation *seg = &cm->seg; struct segmentation_probs *segp = &cm->fc->seg; int no_pred_cost; int t_pred_cost = INT_MAX; int i, tile_col, tile_row, mi_row, mi_col; #if CONFIG_TILE_GROUPS const int probwt = cm->num_tg; #else const int probwt = 1; #endif unsigned(*temporal_predictor_count)[2] = cm->counts.seg.pred; unsigned *no_pred_segcounts = cm->counts.seg.tree_total; unsigned *t_unpred_seg_counts = cm->counts.seg.tree_mispred; aom_prob no_pred_tree[SEG_TREE_PROBS]; aom_prob t_pred_tree[SEG_TREE_PROBS]; aom_prob t_nopred_prob[PREDICTION_PROBS]; (void)xd; // We are about to recompute all the segment counts, so zero the accumulators. av1_zero(cm->counts.seg); // First of all generate stats regarding how well the last segment map // predicts this one for (tile_row = 0; tile_row < cm->tile_rows; tile_row++) { TileInfo tile_info; av1_tile_set_row(&tile_info, cm, tile_row); for (tile_col = 0; tile_col < cm->tile_cols; tile_col++) { MODE_INFO **mi_ptr; av1_tile_set_col(&tile_info, cm, tile_col); mi_ptr = cm->mi_grid_visible + tile_info.mi_row_start * cm->mi_stride + tile_info.mi_col_start; for (mi_row = tile_info.mi_row_start; mi_row < tile_info.mi_row_end; mi_row += cm->mib_size, mi_ptr += cm->mib_size * cm->mi_stride) { MODE_INFO **mi = mi_ptr; for (mi_col = tile_info.mi_col_start; mi_col < tile_info.mi_col_end; mi_col += cm->mib_size, mi += cm->mib_size) { count_segs_sb(cm, xd, &tile_info, mi, no_pred_segcounts, temporal_predictor_count, t_unpred_seg_counts, mi_row, mi_col, cm->sb_size); } } } } // Work out probability tree for coding segments without prediction // and the cost. calc_segtree_probs(no_pred_segcounts, no_pred_tree, segp->tree_probs, probwt); no_pred_cost = cost_segmap(no_pred_segcounts, no_pred_tree); // Key frames cannot use temporal prediction if (!frame_is_intra_only(cm) && !cm->error_resilient_mode) { // 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, segp->tree_probs, probwt); 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); av1_prob_diff_update_savings_search( temporal_predictor_count[i], segp->pred_probs[i], &t_nopred_prob[i], DIFF_UPDATE_PROB, probwt); // Add in the predictor signaling cost t_pred_cost += count0 * av1_cost_zero(t_nopred_prob[i]) + count1 * av1_cost_one(t_nopred_prob[i]); } } // Now choose which coding method to use. if (t_pred_cost < no_pred_cost) { assert(!cm->error_resilient_mode); seg->temporal_update = 1; } else { seg->temporal_update = 0; } }
void vp9_choose_segmap_coding_method(VP9_COMP *cpi) { VP9_COMMON *const cm = &cpi->common; MACROBLOCKD *const xd = &cpi->mb.e_mbd; int no_pred_cost; int t_pred_cost = INT_MAX; int i; int tile_col, mi_row, mi_col; int temporal_predictor_count[PREDICTION_PROBS][2]; int no_pred_segcounts[MAX_MB_SEGMENTS]; int t_unpred_seg_counts[MAX_MB_SEGMENTS]; vp9_prob no_pred_tree[MB_SEG_TREE_PROBS]; vp9_prob t_pred_tree[MB_SEG_TREE_PROBS]; vp9_prob t_nopred_prob[PREDICTION_PROBS]; const int mis = cm->mode_info_stride; MODE_INFO *mi_ptr, *mi; // Set default state for the segment tree probabilities and the // temporal coding probabilities vpx_memset(xd->mb_segment_tree_probs, 255, sizeof(xd->mb_segment_tree_probs)); vpx_memset(cm->segment_pred_probs, 255, sizeof(cm->segment_pred_probs)); vpx_memset(no_pred_segcounts, 0, sizeof(no_pred_segcounts)); vpx_memset(t_unpred_seg_counts, 0, sizeof(t_unpred_seg_counts)); vpx_memset(temporal_predictor_count, 0, sizeof(temporal_predictor_count)); // First of all generate stats regarding how well the last segment map // predicts this one for (tile_col = 0; tile_col < cm->tile_columns; tile_col++) { vp9_get_tile_col_offsets(cm, tile_col); mi_ptr = cm->mi + cm->cur_tile_mi_col_start; for (mi_row = 0; mi_row < cm->mi_rows; mi_row += 8, mi_ptr += 8 * mis) { mi = mi_ptr; for (mi_col = cm->cur_tile_mi_col_start; mi_col < cm->cur_tile_mi_col_end; mi_col += 8, mi += 8) { count_segs_sb(cpi, mi, no_pred_segcounts, temporal_predictor_count, t_unpred_seg_counts, mi_row, mi_col, BLOCK_SIZE_SB64X64); } } } // Work out probability tree for coding segments without prediction // and the cost. calc_segtree_probs(xd, no_pred_segcounts, no_pred_tree); no_pred_cost = cost_segmap(xd, no_pred_segcounts, no_pred_tree); // Key frames cannot use temporal prediction if (cm->frame_type != KEY_FRAME) { // Work out probability tree for coding those segments not // predicted using the temporal method and the cost. calc_segtree_probs(xd, t_unpred_seg_counts, t_pred_tree); t_pred_cost = cost_segmap(xd, t_unpred_seg_counts, t_pred_tree); // Add in the cost of the signalling 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) { cm->temporal_update = 1; vpx_memcpy(xd->mb_segment_tree_probs, t_pred_tree, sizeof(t_pred_tree)); vpx_memcpy(cm->segment_pred_probs, t_nopred_prob, sizeof(t_nopred_prob)); } else { cm->temporal_update = 0; vpx_memcpy(xd->mb_segment_tree_probs, no_pred_tree, sizeof(no_pred_tree)); } }
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)); } }
void vp10_choose_segmap_coding_method(VP10_COMMON *cm, MACROBLOCKD *xd) { struct segmentation *seg = &cm->seg; #if CONFIG_MISC_FIXES struct segmentation_probs *segp = &cm->fc->seg; #else struct segmentation_probs *segp = &cm->segp; #endif int no_pred_cost; int t_pred_cost = INT_MAX; int i, tile_col, mi_row, mi_col; #if CONFIG_MISC_FIXES unsigned(*temporal_predictor_count)[2] = cm->counts.seg.pred; unsigned *no_pred_segcounts = cm->counts.seg.tree_total; unsigned *t_unpred_seg_counts = cm->counts.seg.tree_mispred; #else unsigned temporal_predictor_count[PREDICTION_PROBS][2] = { { 0 } }; unsigned no_pred_segcounts[MAX_SEGMENTS] = { 0 }; unsigned t_unpred_seg_counts[MAX_SEGMENTS] = { 0 }; #endif vpx_prob no_pred_tree[SEG_TREE_PROBS]; vpx_prob t_pred_tree[SEG_TREE_PROBS]; vpx_prob t_nopred_prob[PREDICTION_PROBS]; #if CONFIG_MISC_FIXES (void)xd; #else // Set default state for the segment tree probabilities and the // temporal coding probabilities memset(segp->tree_probs, 255, sizeof(segp->tree_probs)); memset(segp->pred_probs, 255, sizeof(segp->pred_probs)); #endif // 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; vp10_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, segp->tree_probs); no_pred_cost = cost_segmap(no_pred_segcounts, no_pred_tree); // Key frames cannot use temporal prediction if (!frame_is_intra_only(cm) && !cm->error_resilient_mode) { // 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, segp->tree_probs); 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]; #if CONFIG_MISC_FIXES vp10_prob_diff_update_savings_search(temporal_predictor_count[i], segp->pred_probs[i], &t_nopred_prob[i], DIFF_UPDATE_PROB); #else t_nopred_prob[i] = get_binary_prob(count0, count1); #endif // Add in the predictor signaling cost t_pred_cost += count0 * vp10_cost_zero(t_nopred_prob[i]) + count1 * vp10_cost_one(t_nopred_prob[i]); } } // Now choose which coding method to use. if (t_pred_cost < no_pred_cost) { assert(!cm->error_resilient_mode); seg->temporal_update = 1; #if !CONFIG_MISC_FIXES memcpy(segp->tree_probs, t_pred_tree, sizeof(t_pred_tree)); memcpy(segp->pred_probs, t_nopred_prob, sizeof(t_nopred_prob)); #endif } else { seg->temporal_update = 0; #if !CONFIG_MISC_FIXES memcpy(segp->tree_probs, no_pred_tree, sizeof(no_pred_tree)); #endif } }