| /* |
| * Copyright (c) 2001-2016, Alliance for Open Media. All rights reserved |
| * |
| * This source code is subject to the terms of the BSD 2 Clause License and |
| * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License |
| * was not distributed with this source code in the LICENSE file, you can |
| * obtain it at www.aomedia.org/license/software. If the Alliance for Open |
| * Media Patent License 1.0 was not distributed with this source code in the |
| * PATENTS file, you can obtain it at www.aomedia.org/license/patent. |
| */ |
| |
| /* clang-format off */ |
| |
| #ifdef HAVE_CONFIG_H |
| # include "config.h" |
| #endif |
| |
| #include <stdio.h> |
| |
| #include "aom_dsp/bitwriter.h" |
| #include "av1/common/generic_code.h" |
| #include "av1/common/odintrin.h" |
| #include "pvq_encoder.h" |
| |
| /** Encodes a value from 0 to N-1 (with N up to 16) based on a cdf and adapts |
| * the cdf accordingly. |
| * |
| * @param [in,out] w multi-symbol entropy encoder |
| * @param [in] val variable being encoded |
| * @param [in,out] cdf CDF of the variable (Q15) |
| * @param [in] n number of values possible |
| * @param [in,out] count number of symbols encoded with that cdf so far |
| * @param [in] rate adaptation rate shift (smaller is faster) |
| */ |
| void aom_encode_cdf_adapt_q15(aom_writer *w, int val, uint16_t *cdf, int n, |
| int *count, int rate) { |
| int i; |
| if (*count == 0) { |
| /* On the first call, we normalize the cdf to (32768 - n). This should |
| eventually be moved to the state init, but for now it makes it much |
| easier to experiment and convert symbols to the Q15 adaptation.*/ |
| int ft; |
| ft = cdf[n - 1]; |
| for (i = 0; i < n; i++) { |
| cdf[i] = AOM_ICDF(cdf[i]*32768/ft); |
| } |
| } |
| aom_write_cdf(w, val, cdf, n); |
| aom_cdf_adapt_q15(val, cdf, n, count, rate); |
| } |
| |
| /** Encodes a random variable using a "generic" model, assuming that the |
| * distribution is one-sided (zero and up), has a single mode, and decays |
| * exponentially past the model. |
| * |
| * @param [in,out] w multi-symbol entropy encoder |
| * @param [in,out] model generic probability model |
| * @param [in] x variable being encoded |
| * @param [in,out] ExQ16 expectation of x (adapted) |
| * @param [in] integration integration period of ExQ16 (leaky average over |
| * 1<<integration samples) |
| */ |
| void generic_encode(aom_writer *w, generic_encoder *model, int x, |
| int *ex_q16, int integration) { |
| int lg_q1; |
| int shift; |
| int id; |
| uint16_t *cdf; |
| int xs; |
| lg_q1 = log_ex(*ex_q16); |
| OD_LOG((OD_LOG_ENTROPY_CODER, OD_LOG_DEBUG, |
| "%d %d", *ex_q16, lg_q1)); |
| /* If expectation is too large, shift x to ensure that |
| all we have past xs=15 is the exponentially decaying tail |
| of the distribution */ |
| shift = OD_MAXI(0, (lg_q1 - 5) >> 1); |
| /* Choose the cdf to use: we have two per "octave" of ExQ16 */ |
| id = OD_MINI(GENERIC_TABLES - 1, lg_q1); |
| cdf = model->cdf[id]; |
| xs = (x + (1 << shift >> 1)) >> shift; |
| aom_write_symbol_pvq(w, OD_MINI(15, xs), cdf, 16); |
| if (xs >= 15) { |
| int e; |
| unsigned decay; |
| /* Estimate decay based on the assumption that the distribution is close |
| to Laplacian for large values. We should probably have an adaptive |
| estimate instead. Note: The 2* is a kludge that's not fully understood |
| yet. */ |
| OD_ASSERT(*ex_q16 < INT_MAX >> 1); |
| e = ((2**ex_q16 >> 8) + (1 << shift >> 1)) >> shift; |
| decay = OD_MAXI(2, OD_MINI(254, 256*e/(e + 256))); |
| /* Encode the tail of the distribution assuming exponential decay. */ |
| aom_laplace_encode_special(w, xs - 15, decay); |
| } |
| if (shift != 0) { |
| int special; |
| /* Because of the rounding, there's only half the number of possibilities |
| for xs=0. */ |
| special = xs == 0; |
| if (shift - special > 0) { |
| aom_write_literal(w, x - (xs << shift) + (!special << (shift - 1)), |
| shift - special); |
| } |
| } |
| generic_model_update(ex_q16, x, integration); |
| OD_LOG((OD_LOG_ENTROPY_CODER, OD_LOG_DEBUG, |
| "enc: %d %d %d %d %d %x", *ex_q16, x, shift, id, xs, enc->rng)); |
| } |
| |
| /** Estimates the cost of encoding a value with generic_encode(). |
| * |
| * @param [in,out] model generic probability model |
| * @param [in] x variable being encoded |
| * @param [in,out] ExQ16 expectation of x (adapted) |
| * @return number of bits (approximation) |
| */ |
| double generic_encode_cost(generic_encoder *model, int x, int *ex_q16) { |
| int lg_q1; |
| int shift; |
| int id; |
| uint16_t *cdf; |
| int xs; |
| int extra; |
| lg_q1 = log_ex(*ex_q16); |
| /* If expectation is too large, shift x to ensure that |
| all we have past xs=15 is the exponentially decaying tail |
| of the distribution */ |
| shift = OD_MAXI(0, (lg_q1 - 5) >> 1); |
| /* Choose the cdf to use: we have two per "octave" of ExQ16 */ |
| id = OD_MINI(GENERIC_TABLES - 1, lg_q1); |
| cdf = model->cdf[id]; |
| xs = (x + (1 << shift >> 1)) >> shift; |
| extra = 0; |
| if (shift) extra = shift - (xs == 0); |
| xs = OD_MINI(15, xs); |
| /* Shortcut: assume it's going to cost 2 bits for the Laplace coder. */ |
| if (xs == 15) extra += 2; |
| return |
| extra - OD_LOG2((double)(cdf[xs] - (xs == 0 ? 0 : cdf[xs - 1]))/cdf[15]); |
| } |
| |
| /*Estimates the cost of encoding a value with a given CDF.*/ |
| double od_encode_cdf_cost(int val, uint16_t *cdf, int n) { |
| int total_prob; |
| int prev_prob; |
| double val_prob; |
| OD_ASSERT(n > 0); |
| total_prob = cdf[n - 1]; |
| if (val == 0) { |
| prev_prob = 0; |
| } |
| else { |
| prev_prob = cdf[val - 1]; |
| } |
| val_prob = (cdf[val] - prev_prob) / (double)total_prob; |
| return -OD_LOG2(val_prob); |
| } |