diff options
Diffstat (limited to 'src/utils/entropy_decoder.h')
-rw-r--r-- | src/utils/entropy_decoder.h | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/src/utils/entropy_decoder.h b/src/utils/entropy_decoder.h new file mode 100644 index 0000000..c066b98 --- /dev/null +++ b/src/utils/entropy_decoder.h @@ -0,0 +1,123 @@ +/* + * Copyright 2019 The libgav1 Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBGAV1_SRC_UTILS_ENTROPY_DECODER_H_ +#define LIBGAV1_SRC_UTILS_ENTROPY_DECODER_H_ + +#include <cstddef> +#include <cstdint> + +#include "src/utils/bit_reader.h" +#include "src/utils/compiler_attributes.h" + +namespace libgav1 { + +class DaalaBitReader : public BitReader { + public: + // WindowSize must be an unsigned integer type with at least 32 bits. Use the + // largest type with fast arithmetic. size_t should meet these requirements. + using WindowSize = size_t; + + DaalaBitReader(const uint8_t* data, size_t size, bool allow_update_cdf); + ~DaalaBitReader() override = default; + + // Move only. + DaalaBitReader(DaalaBitReader&& rhs) noexcept; + DaalaBitReader& operator=(DaalaBitReader&& rhs) noexcept; + + int ReadBit() final; + int64_t ReadLiteral(int num_bits) override; + // ReadSymbol() calls for which the |symbol_count| is only known at runtime + // will use this variant. + int ReadSymbol(uint16_t* cdf, int symbol_count); + // ReadSymbol() calls for which the |symbol_count| is equal to 2 (boolean + // symbols) will use this variant. + bool ReadSymbol(uint16_t* cdf); + bool ReadSymbolWithoutCdfUpdate(uint16_t cdf); + // Use either linear search or binary search for decoding the symbol depending + // on |symbol_count|. ReadSymbol calls for which the |symbol_count| is known + // at compile time will use this variant. + template <int symbol_count> + int ReadSymbol(uint16_t* cdf); + + private: + static constexpr int kWindowSize = static_cast<int>(sizeof(WindowSize)) * 8; + static_assert(kWindowSize >= 32, ""); + + // Reads a symbol using the |cdf| table which contains the probabilities of + // each symbol. On a high level, this function does the following: + // 1) Scale the |cdf| values. + // 2) Find the index in the |cdf| array where the scaled CDF value crosses + // the modified |window_diff_| threshold. + // 3) That index is the symbol that has been decoded. + // 4) Update |window_diff_| and |values_in_range_| based on the symbol that + // has been decoded. + inline int ReadSymbolImpl(const uint16_t* cdf, int symbol_count); + // Similar to ReadSymbolImpl but it uses binary search to perform step 2 in + // the comment above. As of now, this function is called when |symbol_count| + // is greater than or equal to 14. + inline int ReadSymbolImplBinarySearch(const uint16_t* cdf, int symbol_count); + // Specialized implementation of ReadSymbolImpl based on the fact that + // symbol_count == 2. + inline int ReadSymbolImpl(uint16_t cdf); + // ReadSymbolN is a specialization of ReadSymbol for symbol_count == N. + LIBGAV1_ALWAYS_INLINE int ReadSymbol3Or4(uint16_t* cdf, int symbol_count); + // ReadSymbolImplN is a specialization of ReadSymbolImpl for + // symbol_count == N. + LIBGAV1_ALWAYS_INLINE int ReadSymbolImpl8(const uint16_t* cdf); + inline void PopulateBits(); + // Normalizes the range so that 32768 <= |values_in_range_| < 65536. Also + // calls PopulateBits() if necessary. + inline void NormalizeRange(); + + const uint8_t* data_; + const uint8_t* const data_end_; + // If |data_| < |data_memcpy_end_|, then we can read sizeof(WindowSize) bytes + // from |data_|. Note with sizeof(WindowSize) == 4 this is only used in the + // constructor, not PopulateBits(). + const uint8_t* const data_memcpy_end_; + const bool allow_update_cdf_; + // Number of cached bits of data in the current value. + int bits_; + // Number of values in the current range. Declared as uint32_t for better + // performance but only the lower 16 bits are used. + uint32_t values_in_range_; + // The difference between the high end of the current range and the coded + // value minus 1. The 16 bits above |bits_| of this variable are used to + // decode the next symbol. It is filled in whenever |bits_| is less than 0. + // Note this implementation differs from the spec as it trades the need to + // shift in 1s in NormalizeRange() with an extra shift in PopulateBits(), + // which occurs less frequently. + WindowSize window_diff_; +}; + +extern template int DaalaBitReader::ReadSymbol<3>(uint16_t* cdf); +extern template int DaalaBitReader::ReadSymbol<4>(uint16_t* cdf); +extern template int DaalaBitReader::ReadSymbol<5>(uint16_t* cdf); +extern template int DaalaBitReader::ReadSymbol<6>(uint16_t* cdf); +extern template int DaalaBitReader::ReadSymbol<7>(uint16_t* cdf); +extern template int DaalaBitReader::ReadSymbol<8>(uint16_t* cdf); +extern template int DaalaBitReader::ReadSymbol<9>(uint16_t* cdf); +extern template int DaalaBitReader::ReadSymbol<10>(uint16_t* cdf); +extern template int DaalaBitReader::ReadSymbol<11>(uint16_t* cdf); +extern template int DaalaBitReader::ReadSymbol<12>(uint16_t* cdf); +extern template int DaalaBitReader::ReadSymbol<13>(uint16_t* cdf); +extern template int DaalaBitReader::ReadSymbol<14>(uint16_t* cdf); +extern template int DaalaBitReader::ReadSymbol<16>(uint16_t* cdf); + +} // namespace libgav1 + +#endif // LIBGAV1_SRC_UTILS_ENTROPY_DECODER_H_ |