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
35 // Encodes a value v in [0, n-1] quasi-uniformly
aom_write_primitive_quniform(aom_writer * w,uint16_t n,uint16_t v)36 void aom_write_primitive_quniform(aom_writer *w, uint16_t n, uint16_t v) {
37 if (n <= 1) return;
38 const int l = get_msb(n) + 1;
39 const int m = (1 << l) - n;
40 if (v < m) {
41 aom_write_literal(w, v, l - 1);
42 } else {
43 aom_write_literal(w, m + ((v - m) >> 1), l - 1);
44 aom_write_bit(w, (v - m) & 1);
45 }
46 }
47
count_primitive_quniform(uint16_t n,uint16_t v)48 static int count_primitive_quniform(uint16_t n, uint16_t v) {
49 if (n <= 1) return 0;
50 const int l = get_msb(n) + 1;
51 const int m = (1 << l) - n;
52 return v < m ? l - 1 : l;
53 }
54
55 // 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)56 void aom_write_primitive_subexpfin(aom_writer *w, uint16_t n, uint16_t k,
57 uint16_t v) {
58 int i = 0;
59 int mk = 0;
60 while (1) {
61 int b = (i ? k + i - 1 : k);
62 int a = (1 << b);
63 if (n <= mk + 3 * a) {
64 aom_write_primitive_quniform(w, n - mk, v - mk);
65 break;
66 } else {
67 int t = (v >= mk + a);
68 aom_write_bit(w, t);
69 if (t) {
70 i = i + 1;
71 mk += a;
72 } else {
73 aom_write_literal(w, v - mk, b);
74 break;
75 }
76 }
77 }
78 }
79
count_primitive_subexpfin(uint16_t n,uint16_t k,uint16_t v)80 static int count_primitive_subexpfin(uint16_t n, uint16_t k, uint16_t v) {
81 int count = 0;
82 int i = 0;
83 int mk = 0;
84 while (1) {
85 int b = (i ? k + i - 1 : k);
86 int a = (1 << b);
87 if (n <= mk + 3 * a) {
88 count += count_primitive_quniform(n - mk, v - mk);
89 break;
90 } else {
91 int t = (v >= mk + a);
92 count++;
93 if (t) {
94 i = i + 1;
95 mk += a;
96 } else {
97 count += b;
98 break;
99 }
100 }
101 }
102 return count;
103 }
104
105 // Finite subexponential code that codes a symbol v in [0, n-1] with parameter k
106 // based on a reference ref also in [0, n-1].
107 // 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)108 void aom_write_primitive_refsubexpfin(aom_writer *w, uint16_t n, uint16_t k,
109 uint16_t ref, uint16_t v) {
110 aom_write_primitive_subexpfin(w, n, k, recenter_finite_nonneg(n, ref, v));
111 }
112
aom_write_signed_primitive_refsubexpfin(aom_writer * w,uint16_t n,uint16_t k,int16_t ref,int16_t v)113 void aom_write_signed_primitive_refsubexpfin(aom_writer *w, uint16_t n,
114 uint16_t k, int16_t ref,
115 int16_t v) {
116 ref += n - 1;
117 v += n - 1;
118 const uint16_t scaled_n = (n << 1) - 1;
119 aom_write_primitive_refsubexpfin(w, scaled_n, k, ref, v);
120 }
121
aom_count_primitive_refsubexpfin(uint16_t n,uint16_t k,uint16_t ref,uint16_t v)122 int aom_count_primitive_refsubexpfin(uint16_t n, uint16_t k, uint16_t ref,
123 uint16_t v) {
124 return count_primitive_subexpfin(n, k, recenter_finite_nonneg(n, ref, v));
125 }
126
aom_count_signed_primitive_refsubexpfin(uint16_t n,uint16_t k,int16_t ref,int16_t v)127 int aom_count_signed_primitive_refsubexpfin(uint16_t n, uint16_t k, int16_t ref,
128 int16_t v) {
129 ref += n - 1;
130 v += n - 1;
131 const uint16_t scaled_n = (n << 1) - 1;
132 return aom_count_primitive_refsubexpfin(scaled_n, k, ref, v);
133 }
134