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