2016-02-17 22:07:20 +03:00
|
|
|
/*
|
2016-09-28 21:33:20 +03:00
|
|
|
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
2016-02-17 22:07:20 +03:00
|
|
|
*
|
2016-09-28 21:33:20 +03:00
|
|
|
* 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.
|
2016-02-17 22:07:20 +03:00
|
|
|
*/
|
|
|
|
|
2016-09-18 01:11:16 +03:00
|
|
|
#ifndef AOM_DSP_BUF_ANS_H_
|
|
|
|
#define AOM_DSP_BUF_ANS_H_
|
2016-02-17 22:07:20 +03:00
|
|
|
// Buffered forward ANS writer.
|
2016-09-28 21:33:20 +03:00
|
|
|
// Symbols are written to the writer in forward (decode) order and serialized
|
2016-02-17 22:07:20 +03:00
|
|
|
// backwards due to ANS's stack like behavior.
|
|
|
|
|
|
|
|
#include <assert.h>
|
2016-08-31 00:01:10 +03:00
|
|
|
#include "./aom_config.h"
|
|
|
|
#include "aom/aom_integer.h"
|
2016-09-18 01:11:16 +03:00
|
|
|
#include "aom_dsp/ans.h"
|
2016-09-28 21:33:20 +03:00
|
|
|
#include "aom_dsp/answriter.h"
|
2016-02-17 22:07:20 +03:00
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif // __cplusplus
|
|
|
|
|
2017-01-26 03:41:05 +03:00
|
|
|
#define ANS_METHOD_RABS 0
|
2016-02-17 22:07:20 +03:00
|
|
|
#define ANS_METHOD_RANS 1
|
|
|
|
|
|
|
|
struct buffered_ans_symbol {
|
2017-01-26 03:41:05 +03:00
|
|
|
unsigned int method : 1; // one of ANS_METHOD_RABS or ANS_METHOD_RANS
|
2016-09-28 21:33:20 +03:00
|
|
|
// TODO(aconverse): Should be possible to write this in terms of start for ABS
|
|
|
|
unsigned int val_start : RANS_PROB_BITS; // Boolean value for ABS
|
|
|
|
// start in symbol cycle for Rans
|
|
|
|
unsigned int prob : RANS_PROB_BITS; // Probability of this symbol
|
2016-02-17 22:07:20 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
struct BufAnsCoder {
|
2016-09-18 01:11:16 +03:00
|
|
|
struct aom_internal_error_info *error;
|
2016-02-17 22:07:20 +03:00
|
|
|
struct buffered_ans_symbol *buf;
|
2016-10-26 23:11:26 +03:00
|
|
|
struct AnsCoder ans;
|
2016-02-17 22:07:20 +03:00
|
|
|
int size;
|
|
|
|
int offset;
|
2016-10-26 23:11:26 +03:00
|
|
|
int output_bytes;
|
2016-12-14 00:53:09 +03:00
|
|
|
#if ANS_MAX_SYMBOLS
|
|
|
|
int window_size;
|
|
|
|
#endif
|
2016-02-17 22:07:20 +03:00
|
|
|
};
|
|
|
|
|
2016-12-14 00:53:09 +03:00
|
|
|
// Allocate a buffered ANS coder to store size symbols.
|
|
|
|
// When ANS_MAX_SYMBOLS is turned on, the size is the fixed size of each ANS
|
|
|
|
// partition.
|
|
|
|
// When ANS_MAX_SYMBOLS is turned off, size is merely an initial hint and the
|
|
|
|
// buffer will grow on demand
|
2016-09-18 01:11:16 +03:00
|
|
|
void aom_buf_ans_alloc(struct BufAnsCoder *c,
|
2016-12-14 00:53:09 +03:00
|
|
|
struct aom_internal_error_info *error, int hint);
|
2016-04-14 00:53:34 +03:00
|
|
|
|
2016-09-18 01:11:16 +03:00
|
|
|
void aom_buf_ans_free(struct BufAnsCoder *c);
|
2016-04-14 00:53:34 +03:00
|
|
|
|
2016-12-14 00:53:09 +03:00
|
|
|
#if !ANS_MAX_SYMBOLS
|
2016-09-18 01:11:16 +03:00
|
|
|
void aom_buf_ans_grow(struct BufAnsCoder *c);
|
2016-12-14 00:53:09 +03:00
|
|
|
#endif
|
2016-04-14 00:53:34 +03:00
|
|
|
|
2016-12-01 02:51:12 +03:00
|
|
|
void aom_buf_ans_flush(struct BufAnsCoder *const c);
|
|
|
|
|
2016-10-26 23:11:26 +03:00
|
|
|
static INLINE void buf_ans_write_init(struct BufAnsCoder *const c,
|
|
|
|
uint8_t *const output_buffer) {
|
2016-02-17 22:07:20 +03:00
|
|
|
c->offset = 0;
|
2016-10-26 23:11:26 +03:00
|
|
|
c->output_bytes = 0;
|
|
|
|
ans_write_init(&c->ans, output_buffer);
|
2016-02-17 22:07:20 +03:00
|
|
|
}
|
|
|
|
|
2017-01-26 03:41:05 +03:00
|
|
|
static INLINE void buf_rabs_write(struct BufAnsCoder *const c, uint8_t val,
|
2016-08-12 06:13:14 +03:00
|
|
|
AnsP8 prob) {
|
2016-04-14 00:53:34 +03:00
|
|
|
assert(c->offset <= c->size);
|
2016-12-14 00:53:09 +03:00
|
|
|
#if !ANS_MAX_SYMBOLS
|
2016-04-14 00:53:34 +03:00
|
|
|
if (c->offset == c->size) {
|
2016-09-18 01:11:16 +03:00
|
|
|
aom_buf_ans_grow(c);
|
2016-04-14 00:53:34 +03:00
|
|
|
}
|
2016-12-14 00:53:09 +03:00
|
|
|
#endif
|
2017-01-26 03:41:05 +03:00
|
|
|
c->buf[c->offset].method = ANS_METHOD_RABS;
|
2016-02-17 22:07:20 +03:00
|
|
|
c->buf[c->offset].val_start = val;
|
|
|
|
c->buf[c->offset].prob = prob;
|
|
|
|
++c->offset;
|
2016-12-01 02:51:50 +03:00
|
|
|
#if ANS_MAX_SYMBOLS
|
2016-12-14 00:53:09 +03:00
|
|
|
if (c->offset == c->size) aom_buf_ans_flush(c);
|
2016-12-01 02:51:50 +03:00
|
|
|
#endif
|
2016-02-17 22:07:20 +03:00
|
|
|
}
|
|
|
|
|
2017-02-08 02:55:24 +03:00
|
|
|
// Buffer one symbol for encoding using rANS.
|
|
|
|
// cum_prob: The cumulative probability before this symbol (the offset of
|
|
|
|
// the symbol in the symbol cycle)
|
|
|
|
// prob: The probability of this symbol (l_s from the paper)
|
|
|
|
// RANS_PRECISION takes the place of m from the paper.
|
2016-02-17 22:07:20 +03:00
|
|
|
static INLINE void buf_rans_write(struct BufAnsCoder *const c,
|
2017-02-08 02:55:24 +03:00
|
|
|
aom_cdf_prob cum_prob, aom_cdf_prob prob) {
|
2016-04-14 00:53:34 +03:00
|
|
|
assert(c->offset <= c->size);
|
2016-12-14 00:53:09 +03:00
|
|
|
#if !ANS_MAX_SYMBOLS
|
2016-04-14 00:53:34 +03:00
|
|
|
if (c->offset == c->size) {
|
2016-09-18 01:11:16 +03:00
|
|
|
aom_buf_ans_grow(c);
|
2016-04-14 00:53:34 +03:00
|
|
|
}
|
2016-12-14 00:53:09 +03:00
|
|
|
#endif
|
2016-02-17 22:07:20 +03:00
|
|
|
c->buf[c->offset].method = ANS_METHOD_RANS;
|
2017-02-08 02:55:24 +03:00
|
|
|
c->buf[c->offset].val_start = cum_prob;
|
|
|
|
c->buf[c->offset].prob = prob;
|
2016-02-17 22:07:20 +03:00
|
|
|
++c->offset;
|
2016-12-01 02:51:50 +03:00
|
|
|
#if ANS_MAX_SYMBOLS
|
2016-12-14 00:53:09 +03:00
|
|
|
if (c->offset == c->size) aom_buf_ans_flush(c);
|
2016-12-01 02:51:50 +03:00
|
|
|
#endif
|
2016-02-17 22:07:20 +03:00
|
|
|
}
|
|
|
|
|
2017-01-26 03:41:05 +03:00
|
|
|
static INLINE void buf_rabs_write_bit(struct BufAnsCoder *c, int bit) {
|
|
|
|
buf_rabs_write(c, bit, 128);
|
2016-03-22 00:56:58 +03:00
|
|
|
}
|
|
|
|
|
2017-01-26 03:41:05 +03:00
|
|
|
static INLINE void buf_rabs_write_literal(struct BufAnsCoder *c, int literal,
|
2016-08-12 06:13:14 +03:00
|
|
|
int bits) {
|
2016-03-22 00:56:58 +03:00
|
|
|
int bit;
|
|
|
|
|
|
|
|
assert(bits < 31);
|
|
|
|
for (bit = bits - 1; bit >= 0; bit--)
|
2017-01-26 03:41:05 +03:00
|
|
|
buf_rabs_write_bit(c, 1 & (literal >> bit));
|
2016-03-22 00:56:58 +03:00
|
|
|
}
|
2016-10-26 23:11:26 +03:00
|
|
|
|
|
|
|
static INLINE int buf_ans_write_end(struct BufAnsCoder *const c) {
|
|
|
|
assert(c->offset == 0);
|
|
|
|
return c->output_bytes;
|
|
|
|
}
|
2016-02-17 22:07:20 +03:00
|
|
|
#ifdef __cplusplus
|
|
|
|
} // extern "C"
|
|
|
|
#endif // __cplusplus
|
2016-09-18 01:11:16 +03:00
|
|
|
#endif // AOM_DSP_BUF_ANS_H_
|