void kdtree_semigreedy_tour(kdtree *tree, data *d, int start, int *tour, int *len) { int dim = d->numnodes; int i, current, next; int lenght = 0; /* RCL. */ int j, k; double total_bias, prob_acc, prob_pick, prob; struct rcl params; params.candidates = MALLOC(dim, struct heapelm); tour[0] = start; current = start; for (i = 1; i < dim; i++) { kdtree_delete(tree, current); /* Define RCL size. */ params.rcl_used = 0; params.rcl_size = RANDOM(3) + 1; kdtree_m_nearest_neighbours(tree, d, current, ¶ms); /*printf("RCL size: %d, used: %d\n", params.rcl_size, params.rcl_used); heap_dump(params.candidates, params.rcl_used);*/ /* Pick an element from RCL. */ total_bias = 0; for (j = 1; j <= params.rcl_used; j++) { total_bias += BIAS(j); } prob_acc = 0; prob_pick = RANDOM_UNIT(); for (j = params.rcl_used, k = 1; j >= 0; j--, k++) { prob = BIAS(k) / total_bias; if (prob + prob_acc > prob_pick) { break; } prob_acc += prob; } /*printf("Picked %d: %d, %d\n", j, params.candidates[j - 1].num, params.candidates[j - 1].cost);*/ next = params.candidates[j - 1].num; /* Update tour. */ tour[i] = next; lenght += params.candidates[j - 1].cost; current = next; } lenght += d->dist(d, current, start); *len = lenght; kdtree_undelete_all(tree, d->numnodes); free(params.candidates); }
static void mix22toS (sample_t * samples, sample_t bias) { int i; sample_t surround; for (i = 0; i < 256; i++) { surround = samples[i + 512] + samples[i + 768]; samples[i] += BIAS (-surround); samples[i + 256] += BIAS (surround); } }
static void move2to1 (sample_t * src, sample_t * dest, sample_t bias) { int i; for (i = 0; i < 256; i++) dest[i] = BIAS (src[i] + src[i + 256]); }
static void mix3to1 (sample_t * samples, sample_t bias) { int i; for (i = 0; i < 256; i++) samples[i] += BIAS (samples[i + 256] + samples[i + 512]); }
static void mix2to1 (sample_t * dest, sample_t * src, sample_t bias) { int i; for (i = 0; i < 256; i++) dest[i] += BIAS (src[i]); }
static void mix32to2 (sample_t * samples, sample_t bias) { int i; sample_t common; for (i = 0; i < 256; i++) { common = BIAS (samples[i + 256]); samples[i] += common + samples[i + 768]; samples[i + 256] = common + samples[i + 512] + samples[i + 1024]; } }
static void mix31to2 (sample_t * samples, sample_t bias) { int i; sample_t common; for (i = 0; i < 256; i++) { common = BIAS (samples[i + 256] + samples[i + 768]); samples[i] += common; samples[i + 256] = samples[i + 512] + common; } }
static void mix21to2 (sample_t * left, sample_t * right, sample_t bias) { int i; sample_t common; for (i = 0; i < 256; i++) { common = BIAS (right[i + 256]); left[i] += common; right[i] += common; } }
static void mix32toS (sample_t * samples, sample_t bias) { int i; sample_t common, surround; for (i = 0; i < 256; i++) { common = BIAS (samples[i + 256]); surround = samples[i + 768] + samples[i + 1024]; samples[i] += common - surround; samples[i + 256] = samples[i + 512] + common + surround; } }
// Returns the average quantizer static int ExpandMatrix(VP8Matrix* const m, int type) { int i; int sum = 0; for (i = 2; i < 16; ++i) { m->q_[i] = m->q_[1]; } for (i = 0; i < 16; ++i) { const int is_ac_coeff = (i > 0); const int bias = kBiasMatrices[type][is_ac_coeff]; m->iq_[i] = (1 << QFIX) / m->q_[i]; m->bias_[i] = BIAS(bias); // TODO(skal): tune kCoeffThresh[] m->zthresh_[i] = ((256 /*+ kCoeffThresh[i]*/ - bias) * m->q_[i] + 127) >> 8; m->sharpen_[i] = (kFreqSharpening[i] * m->q_[i]) >> 11; sum += m->q_[i]; } return (sum + 8) >> 4; }
// Returns the average quantizer static int ExpandMatrix(VP8Matrix* const m, int type) { int i, sum; for (i = 0; i < 2; ++i) { const int is_ac_coeff = (i > 0); const int bias = kBiasMatrices[type][is_ac_coeff]; m->iq_[i] = (1 << QFIX) / m->q_[i]; m->bias_[i] = BIAS(bias); // zthresh_ is the exact value such that QUANTDIV(coeff, iQ, B) is: // * zero if coeff <= zthresh // * non-zero if coeff > zthresh m->zthresh_[i] = ((1 << QFIX) - 1 - m->bias_[i]) / m->iq_[i]; } for (i = 2; i < 16; ++i) { m->q_[i] = m->q_[1]; m->iq_[i] = m->iq_[1]; m->bias_[i] = m->bias_[1]; m->zthresh_[i] = m->zthresh_[1]; } for (sum = 0, i = 0; i < 16; ++i) { if (type == 0) { // we only use sharpening for AC luma coeffs m->sharpen_[i] = (kFreqSharpening[i] * m->q_[i]) >> SHARPEN_BITS; } else {
static int TrellisQuantizeBlock(const VP8EncIterator* const it, int16_t in[16], int16_t out[16], int ctx0, int coeff_type, const VP8Matrix* const mtx, int lambda) { ProbaArray* const last_costs = it->enc_->proba_.coeffs_[coeff_type]; CostArray* const costs = it->enc_->proba_.level_cost_[coeff_type]; const int first = (coeff_type == 0) ? 1 : 0; Node nodes[17][NUM_NODES]; int best_path[3] = {-1, -1, -1}; // store best-last/best-level/best-previous score_t best_score; int best_node; int last = first - 1; int n, m, p, nz; { score_t cost; score_t max_error; const int thresh = mtx->q_[1] * mtx->q_[1] / 4; const int last_proba = last_costs[VP8EncBands[first]][ctx0][0]; // compute maximal distortion. max_error = 0; for (n = first; n < 16; ++n) { const int j = kZigzag[n]; const int err = in[j] * in[j]; max_error += kWeightTrellis[j] * err; if (err > thresh) last = n; } // we don't need to go inspect up to n = 16 coeffs. We can just go up // to last + 1 (inclusive) without losing much. if (last < 15) ++last; // compute 'skip' score. This is the max score one can do. cost = VP8BitCost(0, last_proba); best_score = RDScoreTrellis(lambda, cost, max_error); // initialize source node. n = first - 1; for (m = -MIN_DELTA; m <= MAX_DELTA; ++m) { NODE(n, m).cost = 0; NODE(n, m).error = max_error; NODE(n, m).ctx = ctx0; } } // traverse trellis. for (n = first; n <= last; ++n) { const int j = kZigzag[n]; const int Q = mtx->q_[j]; const int iQ = mtx->iq_[j]; const int B = BIAS(0x00); // neutral bias // note: it's important to take sign of the _original_ coeff, // so we don't have to consider level < 0 afterward. const int sign = (in[j] < 0); int coeff0 = (sign ? -in[j] : in[j]) + mtx->sharpen_[j]; int level0; if (coeff0 > 2047) coeff0 = 2047; level0 = QUANTDIV(coeff0, iQ, B); // test all alternate level values around level0. for (m = -MIN_DELTA; m <= MAX_DELTA; ++m) { Node* const cur = &NODE(n, m); int delta_error, new_error; score_t cur_score = MAX_COST; int level = level0 + m; int last_proba; cur->sign = sign; cur->level = level; cur->ctx = (level == 0) ? 0 : (level == 1) ? 1 : 2; if (level >= 2048 || level < 0) { // node is dead? cur->cost = MAX_COST; continue; } last_proba = last_costs[VP8EncBands[n + 1]][cur->ctx][0]; // Compute delta_error = how much coding this level will // subtract as distortion to max_error new_error = coeff0 - level * Q; delta_error = kWeightTrellis[j] * (coeff0 * coeff0 - new_error * new_error); // Inspect all possible non-dead predecessors. Retain only the best one. for (p = -MIN_DELTA; p <= MAX_DELTA; ++p) { const Node* const prev = &NODE(n - 1, p); const int prev_ctx = prev->ctx; const uint16_t* const tcost = costs[VP8EncBands[n]][prev_ctx]; const score_t total_error = prev->error - delta_error; score_t cost, base_cost, score; if (prev->cost >= MAX_COST) { // dead node? continue; } // Base cost of both terminal/non-terminal base_cost = prev->cost + VP8LevelCost(tcost, level); // Examine node assuming it's a non-terminal one. cost = base_cost; if (level && n < 15) { cost += VP8BitCost(1, last_proba); } score = RDScoreTrellis(lambda, cost, total_error); if (score < cur_score) { cur_score = score; cur->cost = cost; cur->error = total_error; cur->prev = p; } // Now, record best terminal node (and thus best entry in the graph). if (level) { cost = base_cost; if (n < 15) cost += VP8BitCost(0, last_proba); score = RDScoreTrellis(lambda, cost, total_error); if (score < best_score) { best_score = score; best_path[0] = n; // best eob position best_path[1] = m; // best level best_path[2] = p; // best predecessor } } } } } // Fresh start memset(in + first, 0, (16 - first) * sizeof(*in)); memset(out + first, 0, (16 - first) * sizeof(*out)); if (best_path[0] == -1) { return 0; // skip! } // Unwind the best path. // Note: best-prev on terminal node is not necessarily equal to the // best_prev for non-terminal. So we patch best_path[2] in. n = best_path[0]; best_node = best_path[1]; NODE(n, best_node).prev = best_path[2]; // force best-prev for terminal nz = 0; for (; n >= first; --n) { const Node* const node = &NODE(n, best_node); const int j = kZigzag[n]; out[n] = node->sign ? -node->level : node->level; nz |= (node->level != 0); in[j] = out[n] * mtx->q_[j]; best_node = node->prev; } return nz; }
static void semi_greedy(data *d, int start, int *tour, int *tour_length) { int i, j, k; int dim = d->numnodes; int current, len, dist; int *visited = MALLOC(dim, int); /* RCL. */ struct heapelm *candidates = MALLOC(dim, struct heapelm); int rclsize, rclused; double total_bias, rprob, racc, rpick; memset(visited, 0, dim * sizeof(int)); len = 0; current = start; for (i = 0; i < dim - 1; i++) { visited[current] = 1; tour[i] = current; /* Define RCL size. */ rclused = 0; if (RANDOM_UNIT() < 0.05) rclsize = dim - i - 2; else rclsize = RANDOM(((dim - i - 2) / 4) + 1); rclsize++; DEBUG("RCL size: %d\n", rclsize); /* Define RCL. */ for (j = 0; j < dim; j++) { if (!visited[j]) { dist = d->dist(d, current, j); if (rclused < rclsize) { candidates[rclused].num = j; candidates[rclused].cost = dist; rclused++; if (rclused == rclsize) { heap_build_max(candidates, rclsize); } } else if (dist < candidates[0].cost) { heap_replace_root(candidates, rclsize, j, dist); } } } DEBUG("RCL used: %d\n", rclused); heap_dump(candidates, rclused); /* Pick RCL element based on logarithmic bias. */ #define BIAS_LOG(r) (1/log((r)+1)) #define BIAS_LINEAR(r) (1./(r)) #define BIAS_EXP(r) (1/exp(r)) #define BIAS_RANDOM(r) 1 #define BIAS(r) BIAS_LOG(r) total_bias = 0; for (j = 1; j <= rclused; j++) { total_bias += BIAS(j); } racc = 0; rpick = RANDOM_UNIT(); #if DEBUGGING for (j = rclused; j >= 1; j--) { DEBUG("%f ", BIAS(j) / total_bias); } DEBUG("\nR: %f\n", rpick); #endif for (j = rclused, k = 1; j >= 0; j--, k++) { rprob = BIAS(k) / total_bias; if (rprob + racc > rpick) { break; } racc += rprob; } DEBUG("Picked: j = %d, %d %d\n\n", j, candidates[j-1].num, candidates[j-1].cost); current = candidates[j - 1].num; len += candidates[j - 1].cost; } tour[i] = current; len += d->dist(d, current, start); *tour_length = len; free(visited); free(candidates); #undef BIAS #undef BIAS_LOG }