Commit 6048d052 authored by Michael Bebenita's avatar Michael Bebenita Committed by Yaowu Xu

Bit accounting.

This patch adds bit account infrastructure to the bit reader API.
When configured with --enable-accounting, every bit reader API
function records the number of bits necessary to decoding a symbol.
Accounting symbol entries are collected in global accounting data
structure, that can be used to understand exactly where bits are
spent (http://aomanalyzer.org). The data structure is cleared and
reused each frame to reduce memory usage. When configured without
--enable-accounting, bit accounting does not incur any runtime
overhead.

All aom_read_xxx functions now have an additional string parameter
that specifies the symbol name. By default, the ACCT_STR macro is
used (which expands to __func__). For more precise accounting,
these should be replaced with more descriptive names.

Change-Id: Ia2e1343cb842c9391b12b77272587dfbe307a56d
parent 4bacfcff
......@@ -28,6 +28,29 @@
#include "aom_dsp/prob.h"
#include "av1/common/odintrin.h"
#if CONFIG_ACCOUNTING
#include "av1/common/accounting.h"
#define ACCT_STR_NAME acct_str
#define ACCT_STR_PARAM , const char *ACCT_STR_NAME
#define ACCT_STR_ARG(s) , s
#else
#define ACCT_STR_PARAM
#define ACCT_STR_ARG(s)
#endif
#define aom_read(r, prob, ACCT_STR_NAME) \
aom_read_(r, prob ACCT_STR_ARG(ACCT_STR_NAME))
#define aom_read_bit(r, ACCT_STR_NAME) \
aom_read_bit_(r ACCT_STR_ARG(ACCT_STR_NAME))
#define aom_read_tree(r, tree, probs, ACCT_STR_NAME) \
aom_read_tree_(r, tree, probs ACCT_STR_ARG(ACCT_STR_NAME))
#define aom_read_literal(r, bits, ACCT_STR_NAME) \
aom_read_literal_(r, bits ACCT_STR_ARG(ACCT_STR_NAME))
#define aom_read_tree_bits(r, tree, probs, ACCT_STR_NAME) \
aom_read_tree_bits_(r, tree, probs ACCT_STR_ARG(ACCT_STR_NAME))
#define aom_read_symbol(r, cdf, nsymbs, ACCT_STR_NAME) \
aom_read_symbol_(r, cdf, nsymbs ACCT_STR_ARG(ACCT_STR_NAME))
#ifdef __cplusplus
extern "C" {
#endif
......@@ -105,75 +128,100 @@ static INLINE ptrdiff_t aom_reader_tell_frac(const aom_reader *r) {
#endif
}
static INLINE int aom_read(aom_reader *r, int prob) {
#if CONFIG_ACCOUNTING
static INLINE void aom_process_accounting(const aom_reader *r ACCT_STR_PARAM) {
if (r->accounting != NULL) {
uint32_t tell_frac;
tell_frac = aom_reader_tell_frac(r);
aom_accounting_record(r->accounting, ACCT_STR_NAME,
tell_frac - r->accounting->last_tell_frac);
r->accounting->last_tell_frac = tell_frac;
}
}
#endif
static INLINE int aom_read_(aom_reader *r, int prob ACCT_STR_PARAM) {
int ret;
#if CONFIG_ANS
return uabs_read(r, prob);
ret = uabs_read(r, prob);
#elif CONFIG_DAALA_EC
return aom_daala_read(r, prob);
ret = aom_daala_read(r, prob);
#else
return aom_dk_read(r, prob);
ret = aom_dk_read(r, prob);
#endif
#if CONFIG_ACCOUNTING
if (ACCT_STR_NAME) aom_process_accounting(r, ACCT_STR_NAME);
#endif
return ret;
}
static INLINE int aom_read_bit(aom_reader *r) {
static INLINE int aom_read_bit_(aom_reader *r ACCT_STR_PARAM) {
int ret;
#if CONFIG_ANS
return uabs_read_bit(r); // Non trivial optimization at half probability
ret = uabs_read_bit(r); // Non trivial optimization at half probability
#else
return aom_read(r, 128); // aom_prob_half
ret = aom_read(r, 128, NULL); // aom_prob_half
#endif
#if CONFIG_ACCOUNTING
if (ACCT_STR_NAME) aom_process_accounting(r, ACCT_STR_NAME);
#endif
return ret;
}
static INLINE int aom_read_literal(aom_reader *r, int bits) {
static INLINE int aom_read_literal_(aom_reader *r, int bits ACCT_STR_PARAM) {
int literal = 0, bit;
for (bit = bits - 1; bit >= 0; bit--) literal |= aom_read_bit(r) << bit;
for (bit = bits - 1; bit >= 0; bit--) literal |= aom_read_bit(r, NULL) << bit;
#if CONFIG_ACCOUNTING
if (ACCT_STR_NAME) aom_process_accounting(r, ACCT_STR_NAME);
#endif
return literal;
}
static INLINE int aom_read_tree_bits(aom_reader *r, const aom_tree_index *tree,
const aom_prob *probs) {
static INLINE int aom_read_tree_bits_(aom_reader *r, const aom_tree_index *tree,
const aom_prob *probs ACCT_STR_PARAM) {
aom_tree_index i = 0;
while ((i = tree[i + aom_read(r, probs[i >> 1])]) > 0) continue;
while ((i = tree[i + aom_read(r, probs[i >> 1], NULL)]) > 0) continue;
#if CONFIG_ACCOUNTING
if (ACCT_STR_NAME) aom_process_accounting(r, ACCT_STR_NAME);
#endif
return -i;
}
static INLINE int aom_read_tree(aom_reader *r, const aom_tree_index *tree,
const aom_prob *probs) {
static INLINE int aom_read_tree_(aom_reader *r, const aom_tree_index *tree,
const aom_prob *probs ACCT_STR_PARAM) {
int ret;
#if CONFIG_DAALA_EC
return daala_read_tree_bits(r, tree, probs);
ret = daala_read_tree_bits(r, tree, probs);
#else
return aom_read_tree_bits(r, tree, probs);
ret = aom_read_tree_bits(r, tree, probs, NULL);
#endif
#if CONFIG_ACCOUNTING
if (ACCT_STR_NAME) aom_process_accounting(r, ACCT_STR_NAME);
#endif
return ret;
}
static INLINE int aom_read_symbol(aom_reader *r, const aom_cdf_prob *cdf,
int nsymbs) {
static INLINE int aom_read_symbol_(aom_reader *r, const aom_cdf_prob *cdf,
int nsymbs ACCT_STR_PARAM) {
int ret;
#if CONFIG_ANS
(void)nsymbs;
return rans_read(r, cdf);
ret = rans_read(r, cdf);
#elif CONFIG_DAALA_EC
ret = daala_read_symbol(r, cdf, nsymbs);
#else
(void)r;
(void)cdf;
(void)nsymbs;
assert(0 && "Unsupported bitreader operation");
return -1;
ret = -1;
#endif
}
static INLINE int aom_read_tree_cdf(aom_reader *r, const uint16_t *cdf,
int nsymbs) {
#if CONFIG_DAALA_EC
return daala_read_symbol(r, cdf, nsymbs);
#else
(void)r;
(void)cdf;
(void)nsymbs;
assert(0 && "Unsupported bitreader operation");
return -1;
#if CONFIG_ACCOUNTING
if (ACCT_STR_NAME) aom_process_accounting(r, ACCT_STR_NAME);
#endif
return ret;
}
#ifdef __cplusplus
......
......@@ -18,6 +18,9 @@ int aom_daala_reader_init(daala_reader *r, const uint8_t *buffer, int size) {
r->buffer_end = buffer + size;
r->buffer = buffer;
od_ec_dec_init(&r->ec, buffer, size - 1);
#if CONFIG_ACCOUNTING
r->accounting = NULL;
#endif
return 0;
}
......
......@@ -12,8 +12,12 @@
#ifndef AOM_DSP_DAALABOOLREADER_H_
#define AOM_DSP_DAALABOOLREADER_H_
#include "aom/aom_integer.h"
#include "aom_dsp/entdec.h"
#include "aom_dsp/prob.h"
#if CONFIG_ACCOUNTING
#include "av1/common/accounting.h"
#endif
#ifdef __cplusplus
extern "C" {
......@@ -23,6 +27,9 @@ struct daala_reader {
const uint8_t *buffer;
const uint8_t *buffer_end;
od_ec_dec ec;
#if CONFIG_ACCOUNTING
Accounting *accounting;
#endif
};
typedef struct daala_reader daala_reader;
......
......@@ -36,6 +36,9 @@ int aom_dk_reader_init(struct aom_dk_reader *r, const uint8_t *buffer,
r->decrypt_cb = decrypt_cb;
r->decrypt_state = decrypt_state;
aom_dk_reader_fill(r);
#if CONFIG_ACCOUNTING
r->accounting = NULL;
#endif
return aom_dk_read_bit(r) != 0; // marker bit
}
}
......
......@@ -26,6 +26,9 @@
#include "aom/aomdx.h"
#include "aom/aom_integer.h"
#include "aom_dsp/prob.h"
#if CONFIG_ACCOUNTING
#include "av1/common/accounting.h"
#endif
#ifdef __cplusplus
extern "C" {
......@@ -51,6 +54,9 @@ struct aom_dk_reader {
aom_decrypt_cb decrypt_cb;
void *decrypt_state;
uint8_t clear_buffer[sizeof(BD_VALUE) + 1];
#if CONFIG_ACCOUNTING
Accounting *accounting;
#endif
};
int aom_dk_reader_init(struct aom_dk_reader *r, const uint8_t *buffer,
......
......@@ -103,6 +103,10 @@ AV1_COMMON_SRCS-$(HAVE_SSE4_1) += common/x86/od_dering_sse4.h
AV1_COMMON_SRCS-yes += common/dering.c
AV1_COMMON_SRCS-yes += common/dering.h
endif
ifeq ($(CONFIG_ACCOUNTING),yes)
AV1_COMMON_SRCS-yes += common/accounting.h
AV1_COMMON_SRCS-yes += common/accounting.c
endif
AV1_COMMON_SRCS-yes += common/odintrin.c
AV1_COMMON_SRCS-yes += common/odintrin.h
......
/*
* Copyright (c) 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.
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "aom/aom_integer.h"
#include "./accounting.h"
static int aom_accounting_hash(const char *str) {
uint32_t val;
const unsigned char *ustr;
val = 0;
ustr = (const unsigned char *)str;
/* This is about the worst hash one can design, but it should be good enough
here. */
while (*ustr) val += *ustr++;
return val % AOM_ACCOUNTING_HASH_SIZE;
}
/* Dictionary lookup based on an open-addressing hash table. */
int aom_accounting_dictionary_lookup(Accounting *accounting, const char *str) {
int hash;
int len;
AccountingDictionary *dictionary;
dictionary = &accounting->syms.dictionary;
hash = aom_accounting_hash(str);
while (accounting->hash_dictionary[hash] != -1) {
if (strcmp(dictionary->strs[accounting->hash_dictionary[hash]], str) == 0) {
return accounting->hash_dictionary[hash];
}
hash++;
if (hash == AOM_ACCOUNTING_HASH_SIZE) hash = 0;
}
/* No match found. */
assert(dictionary->num_strs + 1 < MAX_SYMBOL_TYPES);
accounting->hash_dictionary[hash] = dictionary->num_strs;
len = strlen(str);
dictionary->strs[dictionary->num_strs] = malloc(len + 1);
snprintf(dictionary->strs[dictionary->num_strs], len + 1, "%s", str);
dictionary->num_strs++;
return dictionary->num_strs - 1;
}
void aom_accounting_init(Accounting *accounting) {
int i;
accounting->num_syms_allocated = 1000;
accounting->syms.syms =
malloc(sizeof(AccountingSymbol) * accounting->num_syms_allocated);
accounting->syms.dictionary.num_strs = 0;
assert(AOM_ACCOUNTING_HASH_SIZE > 2 * MAX_SYMBOL_TYPES);
for (i = 0; i < AOM_ACCOUNTING_HASH_SIZE; i++)
accounting->hash_dictionary[i] = -1;
aom_accounting_reset(accounting);
}
void aom_accounting_reset(Accounting *accounting) {
accounting->syms.num_syms = 0;
accounting->context.x = -1;
accounting->context.y = -1;
accounting->last_tell_frac = 0;
}
void aom_accounting_clear(Accounting *accounting) {
int i;
AccountingDictionary *dictionary;
free(accounting->syms.syms);
dictionary = &accounting->syms.dictionary;
for (i = 0; i < dictionary->num_strs; i++) {
free(dictionary->strs[i]);
}
}
void aom_accounting_set_context(Accounting *accounting, int16_t x, int16_t y) {
accounting->context.x = x;
accounting->context.y = y;
}
void aom_accounting_record(Accounting *accounting, const char *str,
uint32_t bits) {
AccountingSymbol sym;
// Reuse previous symbol if it has the same context and symbol id.
if (accounting->syms.num_syms) {
AccountingSymbol *last_sym;
last_sym = &accounting->syms.syms[accounting->syms.num_syms - 1];
if (memcmp(&last_sym->context, &accounting->context,
sizeof(AccountingSymbolContext)) == 0) {
uint32_t id;
id = aom_accounting_dictionary_lookup(accounting, str);
if (id == last_sym->id) {
last_sym->bits += bits;
last_sym->samples++;
return;
}
}
}
sym.context = accounting->context;
sym.samples = 1;
sym.bits = bits;
sym.id = aom_accounting_dictionary_lookup(accounting, str);
assert(sym.id <= 255);
if (accounting->syms.num_syms == accounting->num_syms_allocated) {
accounting->num_syms_allocated *= 2;
accounting->syms.syms =
realloc(accounting->syms.syms,
sizeof(AccountingSymbol) * accounting->num_syms_allocated);
assert(accounting->syms.syms != NULL);
}
accounting->syms.syms[accounting->syms.num_syms++] = sym;
}
void aom_accounting_dump(Accounting *accounting) {
int i;
AccountingSymbol *sym;
printf("----- %d -----\n", accounting->syms.num_syms);
for (i = 0; i < accounting->syms.num_syms; i++) {
sym = &accounting->syms.syms[i];
printf("%s x: %d, y: %d bits: %f samples: %d\n",
accounting->syms.dictionary.strs[sym->id], sym->context.x,
sym->context.y, (float)sym->bits / 8.0, sym->samples);
}
}
/*
* Copyright (c) 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.
*/
#ifndef AOM_ACCOUNTING_H_
#define AOM_ACCOUNTING_H_
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
#define AOM_ACCOUNTING_HASH_SIZE (1021)
/* Max number of entries for symbol types in the dictionary (increase as
necessary). */
#define MAX_SYMBOL_TYPES (256)
/*The resolution of fractional-precision bit usage measurements, i.e.,
3 => 1/8th bits.*/
#define AOM_ACCT_BITRES (3)
typedef struct {
int16_t x;
int16_t y;
} AccountingSymbolContext;
typedef struct {
AccountingSymbolContext context;
uint32_t id;
/** Number of bits in units of 1/8 bit. */
uint32_t bits;
uint32_t samples;
} AccountingSymbol;
/** Dictionary for translating strings into id. */
typedef struct {
char *(strs[MAX_SYMBOL_TYPES]);
int num_strs;
} AccountingDictionary;
typedef struct {
/** All recorded symbols decoded. */
AccountingSymbol *syms;
/** Number of symbols actually recorded. */
int num_syms;
/** Dictionary for translating strings into id. */
AccountingDictionary dictionary;
} AccountingSymbols;
typedef struct {
AccountingSymbols syms;
/** Size allocated for symbols (not all may be used). */
int num_syms_allocated;
int16_t hash_dictionary[AOM_ACCOUNTING_HASH_SIZE];
AccountingSymbolContext context;
uint32_t last_tell_frac;
} Accounting;
void aom_accounting_init(Accounting *accounting);
void aom_accounting_reset(Accounting *accounting);
void aom_accounting_clear(Accounting *accounting);
void aom_accounting_set_context(Accounting *accounting, int16_t x, int16_t y);
int aom_accounting_dictionary_lookup(Accounting *accounting, const char *str);
void aom_accounting_record(Accounting *accounting, const char *str,
uint32_t bits);
void aom_accounting_dump(Accounting *accounting);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif // AOM_ACCOUNTING_H_
This diff is collapsed.
This diff is collapsed.
......@@ -126,6 +126,9 @@ AV1Decoder *av1_decoder_create(BufferPool *const pool) {
#if CONFIG_LOOP_RESTORATION
av1_loop_restoration_precal();
#endif // CONFIG_LOOP_RESTORATION
#if CONFIG_ACCOUNTING
aom_accounting_init(&pbi->accounting);
#endif
cm->error.setjmp = 0;
......@@ -154,6 +157,10 @@ void av1_decoder_remove(AV1Decoder *pbi) {
av1_loop_filter_dealloc(&pbi->lf_row_sync);
}
#if CONFIG_ACCOUNTING
aom_accounting_clear(&pbi->accounting);
#endif
aom_free(pbi);
}
......
......@@ -22,6 +22,9 @@
#include "av1/common/thread_common.h"
#include "av1/common/onyxc_int.h"
#include "av1/decoder/dthread.h"
#if CONFIG_ACCOUNTING
#include "av1/common/accounting.h"
#endif
#ifdef __cplusplus
extern "C" {
......@@ -100,6 +103,10 @@ typedef struct AV1Decoder {
int tile_col_size_bytes;
int dec_tile_row, dec_tile_col;
#endif // CONFIG_EXT_TILE
#if CONFIG_ACCOUNTING
Accounting accounting;
#endif
} AV1Decoder;
int av1_receive_compressed_data(struct AV1Decoder *pbi, size_t size,
......
......@@ -22,6 +22,8 @@
#include "av1/decoder/detokenize.h"
#define ACCT_STR __func__
#define EOB_CONTEXT_NODE 0
#define ZERO_CONTEXT_NODE 1
#define ONE_CONTEXT_NODE 2
......@@ -41,7 +43,7 @@
static INLINE int read_coeff(const aom_prob *probs, int n, aom_reader *r) {
int i, val = 0;
for (i = 0; i < n; ++i) val = (val << 1) | aom_read(r, probs[i]);
for (i = 0; i < n; ++i) val = (val << 1) | aom_read(r, probs[i], ACCT_STR);
return val;
}
......@@ -142,7 +144,7 @@ static int decode_coefs(const MACROBLOCKD *xd, PLANE_TYPE type,
band = *band_translate++;
prob = coef_probs[band][ctx];
if (counts) ++eob_branch_count[band][ctx];
if (!aom_read(r, prob[EOB_CONTEXT_NODE])) {
if (!aom_read(r, prob[EOB_CONTEXT_NODE], ACCT_STR)) {
INCREMENT_COUNT(EOB_MODEL_TOKEN);
break;
}
......@@ -151,7 +153,7 @@ static int decode_coefs(const MACROBLOCKD *xd, PLANE_TYPE type,
dqv_val = &dq_val[band][0];
#endif // CONFIG_NEW_QUANT
while (!aom_read(r, prob[ZERO_CONTEXT_NODE])) {
while (!aom_read(r, prob[ZERO_CONTEXT_NODE], ACCT_STR)) {
INCREMENT_COUNT(ZERO_TOKEN);
dqv = dq[1];
token_cache[scan[c]] = 0;
......@@ -166,8 +168,8 @@ static int decode_coefs(const MACROBLOCKD *xd, PLANE_TYPE type,
}
#if CONFIG_ANS
cdf = &coef_cdfs[band][ctx];
token =
ONE_TOKEN + aom_read_symbol(r, *cdf, CATEGORY6_TOKEN - ONE_TOKEN + 1);
token = ONE_TOKEN +
aom_read_symbol(r, *cdf, CATEGORY6_TOKEN - ONE_TOKEN + 1, ACCT_STR);
INCREMENT_COUNT(ONE_TOKEN + (token > ONE_TOKEN));
switch (token) {
case ONE_TOKEN:
......@@ -211,14 +213,14 @@ static int decode_coefs(const MACROBLOCKD *xd, PLANE_TYPE type,
} break;
}
#else
if (!aom_read(r, prob[ONE_CONTEXT_NODE])) {
if (!aom_read(r, prob[ONE_CONTEXT_NODE], ACCT_STR)) {
INCREMENT_COUNT(ONE_TOKEN);
token = ONE_TOKEN;
val = 1;
} else {
INCREMENT_COUNT(TWO_TOKEN);
token = aom_read_tree(r, av1_coef_con_tree,
av1_pareto8_full[prob[PIVOT_NODE] - 1]);
av1_pareto8_full[prob[PIVOT_NODE] - 1], ACCT_STR);
switch (token) {
case TWO_TOKEN:
case THREE_TOKEN:
......@@ -275,12 +277,13 @@ static int decode_coefs(const MACROBLOCKD *xd, PLANE_TYPE type,
#if CONFIG_COEFFICIENT_RANGE_CHECKING
#if CONFIG_AOM_HIGHBITDEPTH
dqcoeff[scan[c]] = highbd_check_range((aom_read_bit(r) ? -v : v), xd->bd);
dqcoeff[scan[c]] =
highbd_check_range((aom_read_bit(r, ACCT_STR) ? -v : v), xd->bd);
#else
dqcoeff[scan[c]] = check_range(aom_read_bit(r) ? -v : v);
dqcoeff[scan[c]] = check_range(aom_read_bit(r, ACCT_STR) ? -v : v);
#endif // CONFIG_AOM_HIGHBITDEPTH
#else
dqcoeff[scan[c]] = aom_read_bit(r) ? -v : v;
dqcoeff[scan[c]] = aom_read_bit(r, ACCT_STR) ? -v : v;
#endif // CONFIG_COEFFICIENT_RANGE_CHECKING
token_cache[scan[c]] = av1_pt_energy_class[token];
++c;
......@@ -355,7 +358,7 @@ void av1_decode_palette_tokens(MACROBLOCKD *const xd, int plane,
color_ctx =
av1_get_palette_color_context(color_map, cols, i, j, n, color_order);
color_idx = aom_read_tree(r, av1_palette_color_tree[n - 2],
prob[n - 2][color_ctx]);
prob[n - 2][color_ctx], ACCT_STR);
assert(color_idx >= 0 && color_idx < n);
color_map[i * cols + j] = color_order[color_idx];
}
......
......@@ -21,23 +21,29 @@ static int inv_recenter_nonneg(int v, int m) {
return (v & 1) ? m - ((v + 1) >> 1) : m + (v >> 1);
}
static int decode_uniform(aom_reader *r) {
#define decode_uniform(r, ACCT_STR_NAME) \
decode_uniform_(r ACCT_STR_ARG(ACCT_STR_NAME))
#define decode_term_subexp(r, ACCT_STR_NAME) \
decode_term_subexp_(r ACCT_STR_ARG(ACCT_STR_NAME))
static int decode_uniform_(aom_reader *r ACCT_STR_PARAM) {
const int l = 8;
const int m = (1 << l) - 190;
const int v = aom_read_literal(r, l - 1);
return v < m ? v : (v << 1) - m + aom_read_bit(r);
const int v = aom_read_literal(r, l - 1, ACCT_STR_NAME);
return v < m ? v : (v << 1) - m + aom_read_bit(r, ACCT_STR_NAME);
}
static int inv_remap_prob(int v, int m) {
/* clang-format off */
static uint8_t inv_map_table[MAX_PROB - 1] = {
7, 20, 33, 46, 59, 72, 85, 98, 111, 124, 137, 150, 163, 176, 189,
202, 215, 228, 241, 254, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11,
12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 24, 25, 26, 27,
28, 29, 30, 31, 32, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
44, 45, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 60,
61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 73, 74, 75, 76,
77, 78, 79, 80, 81, 82, 83, 84, 86, 87, 88, 89, 90, 91, 92,
93, 94, 95, 96, 97, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108,
7, 20, 33, 46, 59, 72, 85, 98, 111, 124, 137, 150, 163, 176, 189,
202, 215, 228, 241, 254, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11,
12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 24, 25, 26, 27,
28, 29, 30, 31, 32, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
44, 45, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 60,
61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 73, 74, 75, 76,
77, 78, 79, 80, 81, 82, 83, 84, 86, 87, 88, 89, 90, 91, 92,
93, 94, 95, 96, 97, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108,
109, 110, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 125,
126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 138, 139, 140, 141,
142, 143, 144, 145, 146, 147, 148, 149, 151, 152, 153, 154, 155, 156, 157,
......@@ -46,8 +52,8 @@ static int inv_remap_prob(int v, int m) {
191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 203, 204, 205, 206,
207, 208, 209, 210, 211, 212, 213, 214, 216, 217, 218, 219, 220, 221, 222,
223, 224, 225, 226, 227, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238,
239, 240, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253,
};
239, 240, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253
}; /* clang-format on */
assert(v < (int)(sizeof(inv_map_table) / sizeof(inv_map_table[0])));
v = inv_map_table[v];
m--;
......@@ -58,26 +64,31 @@ static int inv_remap_prob(int v, int m) {
}
}
static int decode_term_subexp(aom_reader *r) {
if (!aom_read_bit(r)) return aom_read_literal(r, 4);
if (!aom_read_bit(r)) return aom_read_literal(r, 4) + 16;
if (!aom_read_bit(r)) return aom_read_literal(r, 5) + 32;
return decode_uniform(r) + 64;
static int decode_term_subexp_(aom_reader *r ACCT_STR_PARAM) {
if (!aom_read_bit(r, ACCT_STR_NAME))
return aom_read_literal(r, 4, ACCT_STR_NAME);
if (!aom_read_bit(r, ACCT_STR_NAME))
return aom_read_literal(r, 4, ACCT_STR_NAME) + 16;
if (!aom_read_bit(r, ACCT_STR_NAME))
return aom_read_literal(r, 5, ACCT_STR_NAME) + 32;
return decode_uniform(r, ACCT_STR_NAME) + 64;
}
void av1_diff_update_prob(aom_reader *r, aom_prob *p) {
if (aom_read(r, DIFF_UPDATE_PROB)) {
const int delp = decode_term_subexp(r);
void av1_diff_update_prob_(aom_reader *r, aom_prob *p ACCT_STR_PARAM) {
if (aom_read(r, DIFF_UPDATE_PROB, ACCT_STR_NAME)) {
const int delp = decode_term_subexp(r, ACCT_STR_NAME);
*p = (aom_prob)inv_remap_prob(delp, *p);
}
}
#if CONFIG_GLOBAL_MOTION
int aom_read_primitive_symmetric(aom_reader *r, unsigned int mag_bits) {
if (aom_read_bit(r)) {
int s = aom_read_bit(r);
int x = aom_read_literal(r, mag_bits) + 1;
if (aom_read_bit(r, ACCT_STR_NAME)) {
int s = aom_read_bit(r, ACCT_STR_NAME);
int x = aom_read_literal(r, mag_bits, ACCT_STR_NAME) + 1;
return (s > 0 ? -x : x);
} else {
return 0;
}
}
#endif // CONFIG_GLOBAL_MOTION
\ No newline at end of file
......@@ -18,15 +18,22 @@
extern "C" {
#endif
void av1_diff_update_prob(aom_reader *r, aom_prob *p);
#if CONFIG_ACCOUNTING
#define av1_diff_update_prob(r, p, str) av1_diff_update_prob_(r, p, str)
#else
#define av1_diff_update_prob(r, p, str) av1_diff_update_prob_(r, p)
#endif
void av1_diff_update_prob_(aom_reader *r, aom_prob *p ACCT_STR_PARAM);
#ifdef __cplusplus
} // extern "C"
#endif
#if CONFIG_GLOBAL_MOTION
// mag_bits is number of bits for magnitude. The alphabet is of size