Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 1 | /* |
Alex Converse | 7fe2ae8 | 2016-09-28 11:33:20 -0700 | [diff] [blame] | 2 | * Copyright (c) 2016, Alliance for Open Media. All rights reserved |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 3 | * |
Alex Converse | 7fe2ae8 | 2016-09-28 11:33:20 -0700 | [diff] [blame] | 4 | * This source code is subject to the terms of the BSD 2 Clause License and |
| 5 | * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License |
| 6 | * was not distributed with this source code in the LICENSE file, you can |
| 7 | * obtain it at www.aomedia.org/license/software. If the Alliance for Open |
| 8 | * Media Patent License 1.0 was not distributed with this source code in the |
| 9 | * PATENTS file, you can obtain it at www.aomedia.org/license/patent. |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 10 | */ |
| 11 | |
Alex Converse | 1ac1ae7 | 2016-09-17 15:11:16 -0700 | [diff] [blame] | 12 | #ifndef AOM_DSP_BUF_ANS_H_ |
| 13 | #define AOM_DSP_BUF_ANS_H_ |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 14 | // Buffered forward ANS writer. |
Alex Converse | 7fe2ae8 | 2016-09-28 11:33:20 -0700 | [diff] [blame] | 15 | // Symbols are written to the writer in forward (decode) order and serialized |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 16 | // backwards due to ANS's stack like behavior. |
| 17 | |
| 18 | #include <assert.h> |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 19 | #include "./aom_config.h" |
| 20 | #include "aom/aom_integer.h" |
Alex Converse | 1ac1ae7 | 2016-09-17 15:11:16 -0700 | [diff] [blame] | 21 | #include "aom_dsp/ans.h" |
Alex Converse | 7fe2ae8 | 2016-09-28 11:33:20 -0700 | [diff] [blame] | 22 | #include "aom_dsp/answriter.h" |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 23 | |
| 24 | #ifdef __cplusplus |
| 25 | extern "C" { |
| 26 | #endif // __cplusplus |
| 27 | |
Alex Converse | c54692b | 2017-01-25 16:41:05 -0800 | [diff] [blame] | 28 | #define ANS_METHOD_RABS 0 |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 29 | #define ANS_METHOD_RANS 1 |
| 30 | |
| 31 | struct buffered_ans_symbol { |
Alex Converse | c54692b | 2017-01-25 16:41:05 -0800 | [diff] [blame] | 32 | unsigned int method : 1; // one of ANS_METHOD_RABS or ANS_METHOD_RANS |
Alex Converse | 7fe2ae8 | 2016-09-28 11:33:20 -0700 | [diff] [blame] | 33 | // TODO(aconverse): Should be possible to write this in terms of start for ABS |
| 34 | unsigned int val_start : RANS_PROB_BITS; // Boolean value for ABS |
| 35 | // start in symbol cycle for Rans |
| 36 | unsigned int prob : RANS_PROB_BITS; // Probability of this symbol |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 37 | }; |
| 38 | |
| 39 | struct BufAnsCoder { |
Alex Converse | 1ac1ae7 | 2016-09-17 15:11:16 -0700 | [diff] [blame] | 40 | struct aom_internal_error_info *error; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 41 | struct buffered_ans_symbol *buf; |
Alex Converse | 2a1b3af | 2016-10-26 13:11:26 -0700 | [diff] [blame] | 42 | struct AnsCoder ans; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 43 | int size; |
| 44 | int offset; |
Alex Converse | 2a1b3af | 2016-10-26 13:11:26 -0700 | [diff] [blame] | 45 | int output_bytes; |
Alex Converse | 2cdf0d8 | 2016-12-13 13:53:09 -0800 | [diff] [blame] | 46 | #if ANS_MAX_SYMBOLS |
| 47 | int window_size; |
| 48 | #endif |
Alex Converse | 30f0e15 | 2017-03-28 10:13:27 -0700 | [diff] [blame] | 49 | int pos; // Dummy variable to store the output buffer after closing |
Yunqing Wang | 0e141b5 | 2017-11-02 15:08:58 -0700 | [diff] [blame] | 50 | uint8_t allow_update_cdf; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 51 | }; |
| 52 | |
Alex Converse | 2cdf0d8 | 2016-12-13 13:53:09 -0800 | [diff] [blame] | 53 | // Allocate a buffered ANS coder to store size symbols. |
| 54 | // When ANS_MAX_SYMBOLS is turned on, the size is the fixed size of each ANS |
| 55 | // partition. |
| 56 | // When ANS_MAX_SYMBOLS is turned off, size is merely an initial hint and the |
| 57 | // buffer will grow on demand |
Alex Converse | 1ac1ae7 | 2016-09-17 15:11:16 -0700 | [diff] [blame] | 58 | void aom_buf_ans_alloc(struct BufAnsCoder *c, |
Alex Converse | 30f0e15 | 2017-03-28 10:13:27 -0700 | [diff] [blame] | 59 | struct aom_internal_error_info *error); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 60 | |
Alex Converse | 1ac1ae7 | 2016-09-17 15:11:16 -0700 | [diff] [blame] | 61 | void aom_buf_ans_free(struct BufAnsCoder *c); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 62 | |
Alex Converse | 2cdf0d8 | 2016-12-13 13:53:09 -0800 | [diff] [blame] | 63 | #if !ANS_MAX_SYMBOLS |
Alex Converse | 1ac1ae7 | 2016-09-17 15:11:16 -0700 | [diff] [blame] | 64 | void aom_buf_ans_grow(struct BufAnsCoder *c); |
Alex Converse | 2cdf0d8 | 2016-12-13 13:53:09 -0800 | [diff] [blame] | 65 | #endif |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 66 | |
Alex Converse | 1ecdf2b | 2016-11-30 15:51:12 -0800 | [diff] [blame] | 67 | void aom_buf_ans_flush(struct BufAnsCoder *const c); |
| 68 | |
Alex Converse | 2a1b3af | 2016-10-26 13:11:26 -0700 | [diff] [blame] | 69 | static INLINE void buf_ans_write_init(struct BufAnsCoder *const c, |
| 70 | uint8_t *const output_buffer) { |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 71 | c->offset = 0; |
Alex Converse | 2a1b3af | 2016-10-26 13:11:26 -0700 | [diff] [blame] | 72 | c->output_bytes = 0; |
| 73 | ans_write_init(&c->ans, output_buffer); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 74 | } |
| 75 | |
Alex Converse | c54692b | 2017-01-25 16:41:05 -0800 | [diff] [blame] | 76 | static INLINE void buf_rabs_write(struct BufAnsCoder *const c, uint8_t val, |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 77 | AnsP8 prob) { |
| 78 | assert(c->offset <= c->size); |
Alex Converse | 2cdf0d8 | 2016-12-13 13:53:09 -0800 | [diff] [blame] | 79 | #if !ANS_MAX_SYMBOLS |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 80 | if (c->offset == c->size) { |
Alex Converse | 1ac1ae7 | 2016-09-17 15:11:16 -0700 | [diff] [blame] | 81 | aom_buf_ans_grow(c); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 82 | } |
Alex Converse | 2cdf0d8 | 2016-12-13 13:53:09 -0800 | [diff] [blame] | 83 | #endif |
Alex Converse | c54692b | 2017-01-25 16:41:05 -0800 | [diff] [blame] | 84 | c->buf[c->offset].method = ANS_METHOD_RABS; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 85 | c->buf[c->offset].val_start = val; |
| 86 | c->buf[c->offset].prob = prob; |
| 87 | ++c->offset; |
Alex Converse | b0be641 | 2016-11-30 15:51:50 -0800 | [diff] [blame] | 88 | #if ANS_MAX_SYMBOLS |
Alex Converse | 2cdf0d8 | 2016-12-13 13:53:09 -0800 | [diff] [blame] | 89 | if (c->offset == c->size) aom_buf_ans_flush(c); |
Alex Converse | b0be641 | 2016-11-30 15:51:50 -0800 | [diff] [blame] | 90 | #endif |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 91 | } |
| 92 | |
Alex Converse | 8c687d2 | 2017-02-07 15:55:24 -0800 | [diff] [blame] | 93 | // Buffer one symbol for encoding using rANS. |
| 94 | // cum_prob: The cumulative probability before this symbol (the offset of |
| 95 | // the symbol in the symbol cycle) |
| 96 | // prob: The probability of this symbol (l_s from the paper) |
| 97 | // RANS_PRECISION takes the place of m from the paper. |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 98 | static INLINE void buf_rans_write(struct BufAnsCoder *const c, |
Alex Converse | 8c687d2 | 2017-02-07 15:55:24 -0800 | [diff] [blame] | 99 | aom_cdf_prob cum_prob, aom_cdf_prob prob) { |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 100 | assert(c->offset <= c->size); |
Alex Converse | 2cdf0d8 | 2016-12-13 13:53:09 -0800 | [diff] [blame] | 101 | #if !ANS_MAX_SYMBOLS |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 102 | if (c->offset == c->size) { |
Alex Converse | 1ac1ae7 | 2016-09-17 15:11:16 -0700 | [diff] [blame] | 103 | aom_buf_ans_grow(c); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 104 | } |
Alex Converse | 2cdf0d8 | 2016-12-13 13:53:09 -0800 | [diff] [blame] | 105 | #endif |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 106 | c->buf[c->offset].method = ANS_METHOD_RANS; |
Alex Converse | 8c687d2 | 2017-02-07 15:55:24 -0800 | [diff] [blame] | 107 | c->buf[c->offset].val_start = cum_prob; |
| 108 | c->buf[c->offset].prob = prob; |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 109 | ++c->offset; |
Alex Converse | b0be641 | 2016-11-30 15:51:50 -0800 | [diff] [blame] | 110 | #if ANS_MAX_SYMBOLS |
Alex Converse | 2cdf0d8 | 2016-12-13 13:53:09 -0800 | [diff] [blame] | 111 | if (c->offset == c->size) aom_buf_ans_flush(c); |
Alex Converse | b0be641 | 2016-11-30 15:51:50 -0800 | [diff] [blame] | 112 | #endif |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 113 | } |
| 114 | |
Alex Converse | c54692b | 2017-01-25 16:41:05 -0800 | [diff] [blame] | 115 | static INLINE void buf_rabs_write_bit(struct BufAnsCoder *c, int bit) { |
| 116 | buf_rabs_write(c, bit, 128); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 117 | } |
| 118 | |
Alex Converse | c54692b | 2017-01-25 16:41:05 -0800 | [diff] [blame] | 119 | static INLINE void buf_rabs_write_literal(struct BufAnsCoder *c, int literal, |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 120 | int bits) { |
| 121 | int bit; |
| 122 | |
| 123 | assert(bits < 31); |
| 124 | for (bit = bits - 1; bit >= 0; bit--) |
Alex Converse | c54692b | 2017-01-25 16:41:05 -0800 | [diff] [blame] | 125 | buf_rabs_write_bit(c, 1 & (literal >> bit)); |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 126 | } |
Alex Converse | 2a1b3af | 2016-10-26 13:11:26 -0700 | [diff] [blame] | 127 | |
| 128 | static INLINE int buf_ans_write_end(struct BufAnsCoder *const c) { |
| 129 | assert(c->offset == 0); |
| 130 | return c->output_bytes; |
| 131 | } |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 132 | #ifdef __cplusplus |
| 133 | } // extern "C" |
| 134 | #endif // __cplusplus |
Alex Converse | 1ac1ae7 | 2016-09-17 15:11:16 -0700 | [diff] [blame] | 135 | #endif // AOM_DSP_BUF_ANS_H_ |