/*
* 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 "generic_code.h"
void aom_cdf_init(uint16_t *cdf, int ncdfs, int nsyms, int val, int first) {
int i;
int j;
for (i = 0; i < ncdfs; i++) {
for (j = 0; j < nsyms; j++) {
cdf[i*nsyms + j] = val*j + first;
}
}
}
/** Adapts a Q15 cdf after encoding/decoding a symbol. */
void aom_cdf_adapt_q15(int val, uint16_t *cdf, int n, int *count, int rate) {
int i;
*count = OD_MINI(*count + 1, 1 << rate);
OD_ASSERT(cdf[n - 1] == 32768);
if (*count >= 1 << rate) {
/* Steady-state adaptation based on a simple IIR with dyadic rate. */
for (i = 0; i < n; i++) {
int tmp;
/* When (i < val), we want the adjustment ((cdf[i] - tmp) >> rate) to be
positive so long as (cdf[i] > i + 1), and 0 when (cdf[i] == i + 1),
to ensure we don't drive any probabilities to 0. Replacing cdf[i] with
(i + 2) and solving ((i + 2 - tmp) >> rate == 1) for tmp produces
tmp == i + 2 - (1 << rate). Using this value of tmp with
cdf[i] == i + 1 instead gives an adjustment of 0 as desired.
When (i >= val), we want ((cdf[i] - tmp) >> rate) to be negative so
long as cdf[i] < 32768 - (n - 1 - i), and 0 when
cdf[i] == 32768 - (n - 1 - i), again to ensure we don't drive any
probabilities to 0. Since right-shifting any negative value is still
negative, we can solve (32768 - (n - 1 - i) - tmp == 0) for tmp,
producing tmp = 32769 - n + i. Using this value of tmp with smaller
values of cdf[i] instead gives negative adjustments, as desired.
Combining the two cases gives the expression below. These could be
stored in a lookup table indexed by n and rate to avoid the
arithmetic. */
tmp = 2 - (1<= val);
cdf[i] -= (cdf[i] - tmp) >> rate;
}
}
else {
int alpha;
/* Initial adaptation for the first symbols. The adaptation rate is
computed to be equivalent to what od_{en,de}code_cdf_adapt() does
when the initial cdf is set to increment/4. */
alpha = 4*32768/(n + 4**count);
for (i = 0; i < n; i++) {
int tmp;
tmp = (32768 - n)*(i >= val) + i + 1;
cdf[i] -= ((cdf[i] - tmp)*alpha) >> 15;
}
}
OD_ASSERT(cdf[n - 1] == 32768);
}
/** Initializes the cdfs and freq counts for a model.
*
* @param [out] model model being initialized
*/
void generic_model_init(generic_encoder *model) {
int i;
int j;
model->increment = 64;
for (i = 0; i < GENERIC_TABLES; i++) {
for (j = 0; j < 16; j++) {
/* Do flat initialization equivalent to a single symbol in each bin. */
model->cdf[i][j] = (j + 1) * model->increment;
}
}
}
/** Takes the base-2 log of E(x) in Q1.
*
* @param [in] ExQ16 expectation of x in Q16
*
* @retval 2*log2(ExQ16/2^16)
*/
int log_ex(int ex_q16) {
int lg;
int lg_q1;
int odd;
lg = OD_ILOG(ex_q16);
if (lg < 15) {
odd = ex_q16*ex_q16 > 2 << 2*lg;
}
else {
int tmp;
tmp = ex_q16 >> (lg - 8);
odd = tmp*tmp > (1 << 15);
}
lg_q1 = OD_MAXI(0, 2*lg - 33 + odd);
return lg_q1;
}
/** Updates the probability model based on the encoded/decoded value
*
* @param [in,out] model generic prob model
* @param [in,out] ExQ16 expectation of x
* @param [in] x variable encoded/decoded (used for ExQ16)
* @param [in] xs variable x after shift (used for the model)
* @param [in] id id of the icdf to adapt
* @param [in] integration integration period of ExQ16 (leaky average over
* 1<cdf[id];
/* Renormalize if we cannot add increment */
if (cdf[15] + model->increment > 32767) {
for (i = 0; i < 16; i++) {
/* Second term ensures that the pdf is non-null */
cdf[i] = (cdf[i] >> 1) + i + 1;
}
}
/* Update freq count */
xenc = OD_MINI(15, xs);
/* This can be easily vectorized */
for (i = xenc; i < 16; i++) cdf[i] += model->increment;
/* We could have saturated ExQ16 directly, but this is safe and simpler */
x = OD_MINI(x, 32767);
OD_IIR_DIADIC(*ex_q16, x << 16, integration);
}