1 /*
2 * Copyright (c) 2017, Alliance for Open Media. All rights reserved
3 *
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.
10 */
11
12 #include "aom_dsp/bitwriter.h"
13 #include "aom_dsp/binary_codes_writer.h"
14 #include "aom_dsp/recenter.h"
15 #include "aom_ports/bitops.h"
16
17 // Codes a symbol v in [-2^mag_bits, 2^mag_bits].
18 // mag_bits is number of bits for magnitude. The alphabet is of size
19 // 2 * 2^mag_bits + 1, symmetric around 0, where one bit is used to
20 // indicate 0 or non-zero, mag_bits bits are used to indicate magnitide
21 // and 1 more bit for the sign if non-zero.
aom_write_primitive_symmetric(aom_writer * w,int16_t v,unsigned int abs_bits)22 void aom_write_primitive_symmetric(aom_writer *w, int16_t v,
23 unsigned int abs_bits) {
24 if (v == 0) {
25 aom_write_bit(w, 0);
26 } else {
27 const int x = abs(v);
28 const int s = v < 0;
29 aom_write_bit(w, 1);
30 aom_write_bit(w, s);
31 aom_write_literal(w, x - 1, abs_bits);
32 }
33 }
34
aom_count_primitive_symmetric(int16_t v,unsigned int abs_bits)35 int aom_count_primitive_symmetric(int16_t v, unsigned int abs_bits) {
36 return (v == 0 ? 1 : abs_bits + 2);
37 }
38
39 // Encodes a value v in [0, n-1] quasi-uniformly
aom_write_primitive_quniform(aom_writer * w,uint16_t n,uint16_t v)40 void aom_write_primitive_quniform(aom_writer *w, uint16_t n, uint16_t v) {
41 if (n <= 1) return;
42 const int l = get_msb(n) + 1;
43 const int m = (1 << l) - n;
44 if (v < m) {
45 aom_write_literal(w, v, l - 1);
46 } else {
47 aom_write_literal(w, m + ((v - m) >> 1), l - 1);
48 aom_write_bit(w, (v - m) & 1);
49 }
50 }
51
aom_count_primitive_quniform(uint16_t n,uint16_t v)52 int aom_count_primitive_quniform(uint16_t n, uint16_t v) {
53 if (n <= 1) return 0;
54 const int l = get_msb(n) + 1;
55 const int m = (1 << l) - n;
56 return v < m ? l - 1 : l;
57 }
58
59 // Finite subexponential code that codes a symbol v in [0, n-1] with parameter k
aom_write_primitive_subexpfin(aom_writer * w,uint16_t n,uint16_t k,uint16_t v)60 void aom_write_primitive_subexpfin(aom_writer *w, uint16_t n, uint16_t k,
61 uint16_t v) {
62 int i = 0;
63 int mk = 0;
64 while (1) {
65 int b = (i ? k + i - 1 : k);
66 int a = (1 << b);
67 if (n <= mk + 3 * a) {
68 aom_write_primitive_quniform(w, n - mk, v - mk);
69 break;
70 } else {
71 int t = (v >= mk + a);
72 aom_write_bit(w, t);
73 if (t) {
74 i = i + 1;
75 mk += a;
76 } else {
77 aom_write_literal(w, v - mk, b);
78 break;
79 }
80 }
81 }
82 }
83
aom_count_primitive_subexpfin(uint16_t n,uint16_t k,uint16_t v)84 int aom_count_primitive_subexpfin(uint16_t n, uint16_t k, uint16_t v) {
85 int count = 0;
86 int i = 0;
87 int mk = 0;
88 while (1) {
89 int b = (i ? k + i - 1 : k);
90 int a = (1 << b);
91 if (n <= mk + 3 * a) {
92 count += aom_count_primitive_quniform(n - mk, v - mk);
93 break;
94 } else {
95 int t = (v >= mk + a);
96 count++;
97 if (t) {
98 i = i + 1;
99 mk += a;
100 } else {
101 count += b;
102 break;
103 }
104 }
105 }
106 return count;
107 }
108
109 // Finite subexponential code that codes a symbol v in [0, n-1] with parameter k
110 // based on a reference ref also in [0, n-1].
111 // Recenters symbol around r first and then uses a finite subexponential code.
aom_write_primitive_refsubexpfin(aom_writer * w,uint16_t n,uint16_t k,uint16_t ref,uint16_t v)112 void aom_write_primitive_refsubexpfin(aom_writer *w, uint16_t n, uint16_t k,
113 uint16_t ref, uint16_t v) {
114 aom_write_primitive_subexpfin(w, n, k, recenter_finite_nonneg(n, ref, v));
115 }
116
aom_write_signed_primitive_refsubexpfin(aom_writer * w,uint16_t n,uint16_t k,int16_t ref,int16_t v)117 void aom_write_signed_primitive_refsubexpfin(aom_writer *w, uint16_t n,
118 uint16_t k, int16_t ref,
119 int16_t v) {
120 ref += n - 1;
121 v += n - 1;
122 const uint16_t scaled_n = (n << 1) - 1;
123 aom_write_primitive_refsubexpfin(w, scaled_n, k, ref, v);
124 }
125
aom_count_primitive_refsubexpfin(uint16_t n,uint16_t k,uint16_t ref,uint16_t v)126 int aom_count_primitive_refsubexpfin(uint16_t n, uint16_t k, uint16_t ref,
127 uint16_t v) {
128 return aom_count_primitive_subexpfin(n, k, recenter_finite_nonneg(n, ref, v));
129 }
130
aom_count_signed_primitive_refsubexpfin(uint16_t n,uint16_t k,int16_t ref,int16_t v)131 int aom_count_signed_primitive_refsubexpfin(uint16_t n, uint16_t k, int16_t ref,
132 int16_t v) {
133 ref += n - 1;
134 v += n - 1;
135 const uint16_t scaled_n = (n << 1) - 1;
136 return aom_count_primitive_refsubexpfin(scaled_n, k, ref, v);
137 }
138