324 строки
9.6 KiB
C
324 строки
9.6 KiB
C
/*
|
|
* 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/entdec.h"
|
|
#include "av1/common/pvq.h"
|
|
#include "pvq_decoder.h"
|
|
|
|
#if OD_ACCOUNTING
|
|
# define od_decode_pvq_split(ec, adapt, sum, ctx, str) od_decode_pvq_split_(ec, adapt, sum, ctx, str)
|
|
#else
|
|
# define od_decode_pvq_split(ec, adapt, sum, ctx, str) od_decode_pvq_split_(ec, adapt, sum, ctx)
|
|
#endif
|
|
|
|
static int od_decode_pvq_split_(od_ec_dec *ec, od_pvq_codeword_ctx *adapt,
|
|
int sum, int ctx OD_ACC_STR) {
|
|
int shift;
|
|
int count;
|
|
int msbs;
|
|
int fctx;
|
|
count = 0;
|
|
if (sum == 0) return 0;
|
|
shift = OD_MAXI(0, OD_ILOG(sum) - 3);
|
|
fctx = 7*ctx + (sum >> shift) - 1;
|
|
msbs = od_decode_cdf_adapt(ec, adapt->pvq_split_cdf[fctx],
|
|
(sum >> shift) + 1, adapt->pvq_split_increment, acc_str);
|
|
if (shift) count = od_ec_dec_bits(ec, shift, acc_str);
|
|
count += msbs << shift;
|
|
if (count > sum) {
|
|
count = sum;
|
|
ec->error = 1;
|
|
}
|
|
return count;
|
|
}
|
|
|
|
void od_decode_band_pvq_splits(od_ec_dec *ec, od_pvq_codeword_ctx *adapt,
|
|
od_coeff *y, int n, int k, int level) {
|
|
int mid;
|
|
int count_right;
|
|
if (n == 1) {
|
|
y[0] = k;
|
|
}
|
|
else if (k == 0) {
|
|
OD_CLEAR(y, n);
|
|
}
|
|
else if (k == 1 && n <= 16) {
|
|
int cdf_id;
|
|
int pos;
|
|
cdf_id = od_pvq_k1_ctx(n, level == 0);
|
|
OD_CLEAR(y, n);
|
|
pos = od_decode_cdf_adapt(ec, adapt->pvq_k1_cdf[cdf_id], n,
|
|
adapt->pvq_k1_increment, "pvq:k1");
|
|
y[pos] = 1;
|
|
}
|
|
else {
|
|
mid = n >> 1;
|
|
count_right = od_decode_pvq_split(ec, adapt, k, od_pvq_size_ctx(n),
|
|
"pvq:split");
|
|
od_decode_band_pvq_splits(ec, adapt, y, mid, k - count_right, level + 1);
|
|
od_decode_band_pvq_splits(ec, adapt, y + mid, n - mid, count_right,
|
|
level + 1);
|
|
}
|
|
}
|
|
|
|
/** Decodes the tail of a Laplace-distributed variable, i.e. it doesn't
|
|
* do anything special for the zero case.
|
|
*
|
|
* @param [dec] range decoder
|
|
* @param [decay] decay factor of the distribution, i.e. pdf ~= decay^x
|
|
* @param [max] maximum possible value of x (used to truncate the pdf)
|
|
*
|
|
* @retval decoded variable x
|
|
*/
|
|
int od_laplace_decode_special_(od_ec_dec *dec, unsigned decay, int max OD_ACC_STR) {
|
|
int pos;
|
|
int shift;
|
|
int xs;
|
|
int ms;
|
|
int sym;
|
|
const uint16_t *cdf;
|
|
shift = 0;
|
|
if (max == 0) return 0;
|
|
/* We don't want a large decay value because that would require too many
|
|
symbols. However, it's OK if the max is below 15. */
|
|
while (((max >> shift) >= 15 || max == -1) && decay > 235) {
|
|
decay = (decay*decay + 128) >> 8;
|
|
shift++;
|
|
}
|
|
decay = OD_MINI(decay, 254);
|
|
decay = OD_MAXI(decay, 2);
|
|
ms = max >> shift;
|
|
cdf = EXP_CDF_TABLE[(decay + 1) >> 1];
|
|
OD_LOG((OD_LOG_PVQ, OD_LOG_DEBUG, "decay = %d\n", decay));
|
|
xs = 0;
|
|
do {
|
|
sym = OD_MINI(xs, 15);
|
|
{
|
|
int i;
|
|
OD_LOG((OD_LOG_PVQ, OD_LOG_DEBUG, "%d %d %d %d", xs, shift, sym, max));
|
|
for (i = 0; i < 16; i++) {
|
|
OD_LOG_PARTIAL((OD_LOG_PVQ, OD_LOG_DEBUG, "%d ", cdf[i]));
|
|
}
|
|
OD_LOG_PARTIAL((OD_LOG_PVQ, OD_LOG_DEBUG, "\n"));
|
|
}
|
|
if (ms > 0 && ms < 15) {
|
|
/* Simple way of truncating the pdf when we have a bound. */
|
|
sym = od_ec_decode_cdf_unscaled(dec, cdf, ms + 1);
|
|
}
|
|
else sym = od_ec_decode_cdf_q15(dec, cdf, 16);
|
|
xs += sym;
|
|
ms -= 15;
|
|
}
|
|
while (sym >= 15 && ms != 0);
|
|
if (shift) pos = (xs << shift) + od_ec_dec_bits(dec, shift, acc_str);
|
|
else pos = xs;
|
|
OD_ASSERT(pos >> shift <= max >> shift || max == -1);
|
|
if (max != -1 && pos > max) {
|
|
pos = max;
|
|
dec->error = 1;
|
|
}
|
|
OD_ASSERT(pos <= max || max == -1);
|
|
return pos;
|
|
}
|
|
|
|
/** Decodes a Laplace-distributed variable for use in PVQ.
|
|
*
|
|
* @param [in,out] dec range decoder
|
|
* @param [in] ExQ8 expectation of the absolute value of x
|
|
* @param [in] K maximum value of |x|
|
|
*
|
|
* @retval decoded variable (including sign)
|
|
*/
|
|
int od_laplace_decode_(od_ec_dec *dec, unsigned ex_q8, int k OD_ACC_STR) {
|
|
int j;
|
|
int shift;
|
|
uint16_t cdf[16];
|
|
int sym;
|
|
int lsb;
|
|
int decay;
|
|
int offset;
|
|
lsb = 0;
|
|
/* Shift down x if expectation is too high. */
|
|
shift = OD_ILOG(ex_q8) - 11;
|
|
if (shift < 0) shift = 0;
|
|
/* Apply the shift with rounding to Ex, K and xs. */
|
|
ex_q8 = (ex_q8 + (1 << shift >> 1)) >> shift;
|
|
k = (k + (1 << shift >> 1)) >> shift;
|
|
decay = OD_MINI(254, OD_DIVU(256*ex_q8, (ex_q8 + 256)));
|
|
offset = LAPLACE_OFFSET[(decay + 1) >> 1];
|
|
for (j = 0; j < 16; j++) {
|
|
cdf[j] = EXP_CDF_TABLE[(decay + 1) >> 1][j] - offset;
|
|
}
|
|
/* Simple way of truncating the pdf when we have a bound */
|
|
if (k == 0) sym = 0;
|
|
else sym = od_ec_decode_cdf_unscaled(dec, cdf, OD_MINI(k + 1, 16));
|
|
if (shift) {
|
|
int special;
|
|
/* Because of the rounding, there's only half the number of possibilities
|
|
for xs=0 */
|
|
special = (sym == 0);
|
|
if (shift - special > 0) lsb = od_ec_dec_bits(dec, shift - special, acc_str);
|
|
lsb -= (!special << (shift - 1));
|
|
}
|
|
/* Handle the exponentially-decaying tail of the distribution */
|
|
if (sym == 15) sym += laplace_decode_special(dec, decay, k - 15, acc_str);
|
|
return (sym << shift) + lsb;
|
|
}
|
|
|
|
#if OD_ACCOUNTING
|
|
# define laplace_decode_vector_delta(dec, y, n, k, curr, means, str) laplace_decode_vector_delta_(dec, y, n, k, curr, means, str)
|
|
#else
|
|
# define laplace_decode_vector_delta(dec, y, n, k, curr, means, str) laplace_decode_vector_delta_(dec, y, n, k, curr, means)
|
|
#endif
|
|
|
|
static void laplace_decode_vector_delta_(od_ec_dec *dec, od_coeff *y, int n, int k,
|
|
int32_t *curr, const int32_t *means
|
|
OD_ACC_STR) {
|
|
int i;
|
|
int prev;
|
|
int sum_ex;
|
|
int sum_c;
|
|
int coef;
|
|
int pos;
|
|
int k0;
|
|
int sign;
|
|
int first;
|
|
int k_left;
|
|
prev = 0;
|
|
sum_ex = 0;
|
|
sum_c = 0;
|
|
coef = 256*means[OD_ADAPT_COUNT_Q8]/
|
|
(1 + means[OD_ADAPT_COUNT_EX_Q8]);
|
|
pos = 0;
|
|
sign = 0;
|
|
first = 1;
|
|
k_left = k;
|
|
for (i = 0; i < n; i++) y[i] = 0;
|
|
k0 = k_left;
|
|
coef = OD_MAXI(coef, 1);
|
|
for (i = 0; i < k0; i++) {
|
|
int count;
|
|
if (first) {
|
|
int decay;
|
|
int ex = coef*(n - prev)/k_left;
|
|
if (ex > 65280) decay = 255;
|
|
else {
|
|
decay = OD_MINI(255,
|
|
(int)((256*ex/(ex + 256) + (ex>>5)*ex/((n + 1)*(n - 1)*(n - 1)))));
|
|
}
|
|
/*Update mean position.*/
|
|
count = laplace_decode_special(dec, decay, n - 1, acc_str);
|
|
first = 0;
|
|
}
|
|
else count = laplace_decode(dec, coef*(n - prev)/k_left, n - prev - 1, acc_str);
|
|
sum_ex += 256*(n - prev);
|
|
sum_c += count*k_left;
|
|
pos += count;
|
|
OD_ASSERT(pos < n);
|
|
if (y[pos] == 0)
|
|
sign = od_ec_dec_bits(dec, 1, acc_str);
|
|
y[pos] += sign ? -1 : 1;
|
|
prev = pos;
|
|
k_left--;
|
|
if (k_left == 0) break;
|
|
}
|
|
if (k > 0) {
|
|
curr[OD_ADAPT_COUNT_Q8] = 256*sum_c;
|
|
curr[OD_ADAPT_COUNT_EX_Q8] = sum_ex;
|
|
}
|
|
else {
|
|
curr[OD_ADAPT_COUNT_Q8] = -1;
|
|
curr[OD_ADAPT_COUNT_EX_Q8] = 0;
|
|
}
|
|
curr[OD_ADAPT_K_Q8] = 0;
|
|
curr[OD_ADAPT_SUM_EX_Q8] = 0;
|
|
}
|
|
|
|
/** Decodes a vector of integers assumed to come from rounding a sequence of
|
|
* Laplace-distributed real values in decreasing order of variance.
|
|
*
|
|
* @param [in,out] dec range decoder
|
|
* @param [in] y decoded vector
|
|
* @param [in] N dimension of the vector
|
|
* @param [in] K sum of the absolute value of components of y
|
|
* @param [out] curr Adaptation context output, may alias means.
|
|
* @param [in] means Adaptation context input.
|
|
*/
|
|
void od_laplace_decode_vector_(od_ec_dec *dec, od_coeff *y, int n, int k,
|
|
int32_t *curr, const int32_t *means OD_ACC_STR) {
|
|
int i;
|
|
int sum_ex;
|
|
int kn;
|
|
int exp_q8;
|
|
int mean_k_q8;
|
|
int mean_sum_ex_q8;
|
|
int ran_delta;
|
|
ran_delta = 0;
|
|
if (k <= 1) {
|
|
laplace_decode_vector_delta(dec, y, n, k, curr, means, acc_str);
|
|
return;
|
|
}
|
|
if (k == 0) {
|
|
curr[OD_ADAPT_COUNT_Q8] = OD_ADAPT_NO_VALUE;
|
|
curr[OD_ADAPT_COUNT_EX_Q8] = OD_ADAPT_NO_VALUE;
|
|
curr[OD_ADAPT_K_Q8] = 0;
|
|
curr[OD_ADAPT_SUM_EX_Q8] = 0;
|
|
for (i = 0; i < n; i++) y[i] = 0;
|
|
return;
|
|
}
|
|
sum_ex = 0;
|
|
kn = k;
|
|
/* Estimates the factor relating pulses_left and positions_left to E(|x|).*/
|
|
mean_k_q8 = means[OD_ADAPT_K_Q8];
|
|
mean_sum_ex_q8 = means[OD_ADAPT_SUM_EX_Q8];
|
|
if (mean_k_q8 < 1 << 23) exp_q8 = 256*mean_k_q8/(1 + mean_sum_ex_q8);
|
|
else exp_q8 = mean_k_q8/(1 + (mean_sum_ex_q8 >> 8));
|
|
for (i = 0; i < n; i++) {
|
|
int ex;
|
|
int x;
|
|
if (kn == 0) break;
|
|
if (kn <= 1 && i != n - 1) {
|
|
laplace_decode_vector_delta(dec, y + i, n - i, kn, curr, means, acc_str);
|
|
ran_delta = 1;
|
|
i = n;
|
|
break;
|
|
}
|
|
/* Expected value of x (round-to-nearest) is
|
|
expQ8*pulses_left/positions_left. */
|
|
ex = (2*exp_q8*kn + (n - i))/(2*(n - i));
|
|
if (ex > kn*256) ex = kn*256;
|
|
sum_ex += (2*256*kn + (n - i))/(2*(n - i));
|
|
/* No need to encode the magnitude for the last bin. */
|
|
if (i != n - 1) x = laplace_decode(dec, ex, kn, acc_str);
|
|
else x = kn;
|
|
if (x != 0) {
|
|
if (od_ec_dec_bits(dec, 1, acc_str)) x = -x;
|
|
}
|
|
y[i] = x;
|
|
kn -= abs(x);
|
|
}
|
|
/* Adapting the estimates for expQ8. */
|
|
if (!ran_delta) {
|
|
curr[OD_ADAPT_COUNT_Q8] = OD_ADAPT_NO_VALUE;
|
|
curr[OD_ADAPT_COUNT_EX_Q8] = OD_ADAPT_NO_VALUE;
|
|
}
|
|
curr[OD_ADAPT_K_Q8] = k - kn;
|
|
curr[OD_ADAPT_SUM_EX_Q8] = sum_ex;
|
|
for (; i < n; i++) y[i] = 0;
|
|
}
|