xref: /aosp_15_r20/external/libgav1/src/utils/entropy_decoder.h (revision 095378508e87ed692bf8dfeb34008b65b3735891)
1*09537850SAkhilesh Sanikop /*
2*09537850SAkhilesh Sanikop  * Copyright 2019 The libgav1 Authors
3*09537850SAkhilesh Sanikop  *
4*09537850SAkhilesh Sanikop  * Licensed under the Apache License, Version 2.0 (the "License");
5*09537850SAkhilesh Sanikop  * you may not use this file except in compliance with the License.
6*09537850SAkhilesh Sanikop  * You may obtain a copy of the License at
7*09537850SAkhilesh Sanikop  *
8*09537850SAkhilesh Sanikop  *      http://www.apache.org/licenses/LICENSE-2.0
9*09537850SAkhilesh Sanikop  *
10*09537850SAkhilesh Sanikop  * Unless required by applicable law or agreed to in writing, software
11*09537850SAkhilesh Sanikop  * distributed under the License is distributed on an "AS IS" BASIS,
12*09537850SAkhilesh Sanikop  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*09537850SAkhilesh Sanikop  * See the License for the specific language governing permissions and
14*09537850SAkhilesh Sanikop  * limitations under the License.
15*09537850SAkhilesh Sanikop  */
16*09537850SAkhilesh Sanikop 
17*09537850SAkhilesh Sanikop #ifndef LIBGAV1_SRC_UTILS_ENTROPY_DECODER_H_
18*09537850SAkhilesh Sanikop #define LIBGAV1_SRC_UTILS_ENTROPY_DECODER_H_
19*09537850SAkhilesh Sanikop 
20*09537850SAkhilesh Sanikop #include <cstddef>
21*09537850SAkhilesh Sanikop #include <cstdint>
22*09537850SAkhilesh Sanikop 
23*09537850SAkhilesh Sanikop #include "src/utils/bit_reader.h"
24*09537850SAkhilesh Sanikop #include "src/utils/compiler_attributes.h"
25*09537850SAkhilesh Sanikop 
26*09537850SAkhilesh Sanikop namespace libgav1 {
27*09537850SAkhilesh Sanikop 
28*09537850SAkhilesh Sanikop class EntropyDecoder final : public BitReader {
29*09537850SAkhilesh Sanikop  public:
30*09537850SAkhilesh Sanikop   // WindowSize must be an unsigned integer type with at least 32 bits. Use the
31*09537850SAkhilesh Sanikop   // largest type with fast arithmetic. size_t should meet these requirements.
32*09537850SAkhilesh Sanikop   using WindowSize = size_t;
33*09537850SAkhilesh Sanikop 
34*09537850SAkhilesh Sanikop   EntropyDecoder(const uint8_t* data, size_t size, bool allow_update_cdf);
35*09537850SAkhilesh Sanikop   ~EntropyDecoder() override = default;
36*09537850SAkhilesh Sanikop 
37*09537850SAkhilesh Sanikop   // Move only.
38*09537850SAkhilesh Sanikop   EntropyDecoder(EntropyDecoder&& rhs) noexcept;
39*09537850SAkhilesh Sanikop   EntropyDecoder& operator=(EntropyDecoder&& rhs) noexcept;
40*09537850SAkhilesh Sanikop 
41*09537850SAkhilesh Sanikop   int ReadBit() override;
42*09537850SAkhilesh Sanikop   int64_t ReadLiteral(int num_bits) override;
43*09537850SAkhilesh Sanikop   // ReadSymbol() calls for which the |symbol_count| is only known at runtime
44*09537850SAkhilesh Sanikop   // will use this variant.
45*09537850SAkhilesh Sanikop   int ReadSymbol(uint16_t* cdf, int symbol_count);
46*09537850SAkhilesh Sanikop   // ReadSymbol() calls for which the |symbol_count| is equal to 2 (boolean
47*09537850SAkhilesh Sanikop   // symbols) will use this variant.
48*09537850SAkhilesh Sanikop   bool ReadSymbol(uint16_t* cdf);
49*09537850SAkhilesh Sanikop   bool ReadSymbolWithoutCdfUpdate(uint16_t cdf);
50*09537850SAkhilesh Sanikop   // Use either linear search or binary search for decoding the symbol depending
51*09537850SAkhilesh Sanikop   // on |symbol_count|. ReadSymbol calls for which the |symbol_count| is known
52*09537850SAkhilesh Sanikop   // at compile time will use this variant.
53*09537850SAkhilesh Sanikop   template <int symbol_count>
54*09537850SAkhilesh Sanikop   int ReadSymbol(uint16_t* cdf);
55*09537850SAkhilesh Sanikop 
56*09537850SAkhilesh Sanikop  private:
57*09537850SAkhilesh Sanikop   static constexpr int kWindowSize = static_cast<int>(sizeof(WindowSize)) * 8;
58*09537850SAkhilesh Sanikop   static_assert(kWindowSize >= 32, "");
59*09537850SAkhilesh Sanikop 
60*09537850SAkhilesh Sanikop   // Reads a symbol using the |cdf| table which contains the probabilities of
61*09537850SAkhilesh Sanikop   // each symbol. On a high level, this function does the following:
62*09537850SAkhilesh Sanikop   //   1) Scale the |cdf| values.
63*09537850SAkhilesh Sanikop   //   2) Find the index in the |cdf| array where the scaled CDF value crosses
64*09537850SAkhilesh Sanikop   //   the modified |window_diff_| threshold.
65*09537850SAkhilesh Sanikop   //   3) That index is the symbol that has been decoded.
66*09537850SAkhilesh Sanikop   //   4) Update |window_diff_| and |values_in_range_| based on the symbol that
67*09537850SAkhilesh Sanikop   //   has been decoded.
68*09537850SAkhilesh Sanikop   inline int ReadSymbolImpl(const uint16_t* cdf, int symbol_count);
69*09537850SAkhilesh Sanikop   // Similar to ReadSymbolImpl but it uses binary search to perform step 2 in
70*09537850SAkhilesh Sanikop   // the comment above. As of now, this function is called when |symbol_count|
71*09537850SAkhilesh Sanikop   // is greater than or equal to 14.
72*09537850SAkhilesh Sanikop   inline int ReadSymbolImplBinarySearch(const uint16_t* cdf, int symbol_count);
73*09537850SAkhilesh Sanikop   // Specialized implementation of ReadSymbolImpl based on the fact that
74*09537850SAkhilesh Sanikop   // symbol_count == 2.
75*09537850SAkhilesh Sanikop   inline int ReadSymbolImpl(uint16_t cdf);
76*09537850SAkhilesh Sanikop   // ReadSymbolN is a specialization of ReadSymbol for symbol_count == N.
77*09537850SAkhilesh Sanikop   LIBGAV1_ALWAYS_INLINE int ReadSymbol3Or4(uint16_t* cdf, int symbol_count);
78*09537850SAkhilesh Sanikop   // ReadSymbolImplN is a specialization of ReadSymbolImpl for
79*09537850SAkhilesh Sanikop   // symbol_count == N.
80*09537850SAkhilesh Sanikop   LIBGAV1_ALWAYS_INLINE int ReadSymbolImpl8(const uint16_t* cdf);
81*09537850SAkhilesh Sanikop   inline void PopulateBits();
82*09537850SAkhilesh Sanikop   // Normalizes the range so that 32768 <= |values_in_range_| < 65536. Also
83*09537850SAkhilesh Sanikop   // calls PopulateBits() if necessary.
84*09537850SAkhilesh Sanikop   inline void NormalizeRange();
85*09537850SAkhilesh Sanikop 
86*09537850SAkhilesh Sanikop   const uint8_t* data_;
87*09537850SAkhilesh Sanikop   const uint8_t* const data_end_;
88*09537850SAkhilesh Sanikop   // If |data_| < |data_memcpy_end_|, then we can read sizeof(WindowSize) bytes
89*09537850SAkhilesh Sanikop   // from |data_|. Note with sizeof(WindowSize) == 4 this is only used in the
90*09537850SAkhilesh Sanikop   // constructor, not PopulateBits().
91*09537850SAkhilesh Sanikop   const uint8_t* const data_memcpy_end_;
92*09537850SAkhilesh Sanikop   const bool allow_update_cdf_;
93*09537850SAkhilesh Sanikop   // Number of cached bits of data in the current value.
94*09537850SAkhilesh Sanikop   int bits_;
95*09537850SAkhilesh Sanikop   // Number of values in the current range. Declared as uint32_t for better
96*09537850SAkhilesh Sanikop   // performance but only the lower 16 bits are used.
97*09537850SAkhilesh Sanikop   uint32_t values_in_range_;
98*09537850SAkhilesh Sanikop   // The difference between the high end of the current range and the coded
99*09537850SAkhilesh Sanikop   // value minus 1. The 16 bits above |bits_| of this variable are used to
100*09537850SAkhilesh Sanikop   // decode the next symbol. It is filled in whenever |bits_| is less than 0.
101*09537850SAkhilesh Sanikop   // Note this implementation differs from the spec as it trades the need to
102*09537850SAkhilesh Sanikop   // shift in 1s in NormalizeRange() with an extra shift in PopulateBits(),
103*09537850SAkhilesh Sanikop   // which occurs less frequently.
104*09537850SAkhilesh Sanikop   WindowSize window_diff_;
105*09537850SAkhilesh Sanikop };
106*09537850SAkhilesh Sanikop 
107*09537850SAkhilesh Sanikop extern template int EntropyDecoder::ReadSymbol<3>(uint16_t* cdf);
108*09537850SAkhilesh Sanikop extern template int EntropyDecoder::ReadSymbol<4>(uint16_t* cdf);
109*09537850SAkhilesh Sanikop extern template int EntropyDecoder::ReadSymbol<5>(uint16_t* cdf);
110*09537850SAkhilesh Sanikop extern template int EntropyDecoder::ReadSymbol<6>(uint16_t* cdf);
111*09537850SAkhilesh Sanikop extern template int EntropyDecoder::ReadSymbol<7>(uint16_t* cdf);
112*09537850SAkhilesh Sanikop extern template int EntropyDecoder::ReadSymbol<8>(uint16_t* cdf);
113*09537850SAkhilesh Sanikop extern template int EntropyDecoder::ReadSymbol<9>(uint16_t* cdf);
114*09537850SAkhilesh Sanikop extern template int EntropyDecoder::ReadSymbol<10>(uint16_t* cdf);
115*09537850SAkhilesh Sanikop extern template int EntropyDecoder::ReadSymbol<11>(uint16_t* cdf);
116*09537850SAkhilesh Sanikop extern template int EntropyDecoder::ReadSymbol<12>(uint16_t* cdf);
117*09537850SAkhilesh Sanikop extern template int EntropyDecoder::ReadSymbol<13>(uint16_t* cdf);
118*09537850SAkhilesh Sanikop extern template int EntropyDecoder::ReadSymbol<14>(uint16_t* cdf);
119*09537850SAkhilesh Sanikop extern template int EntropyDecoder::ReadSymbol<16>(uint16_t* cdf);
120*09537850SAkhilesh Sanikop 
121*09537850SAkhilesh Sanikop }  // namespace libgav1
122*09537850SAkhilesh Sanikop 
123*09537850SAkhilesh Sanikop #endif  // LIBGAV1_SRC_UTILS_ENTROPY_DECODER_H_
124