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