blob: be48884347330d4c3b5276300427975d08a40ac5 [file] [log] [blame]
// Copyright 2019 Google LLC
//
// 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
//
// https://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.
// -----------------------------------------------------------------------------
//
// ANS symbol decoding.
//
// Author: Vincent Rabaud (vrabaud@google.com)
#ifndef WP2_DEC_SYMBOLS_DEC_H_
#define WP2_DEC_SYMBOLS_DEC_H_
#include "src/common/symbols.h"
#include "src/utils/ans.h"
namespace WP2 {
// Class simplifying the reading of symbols.
struct StatExtra {
uint32_t num_symbols;
// normalized cumulative distribution of counts:
// cumul[0] = 0, cumul[num_symbols] = tab_size
const uint32_t* cumul;
uint32_t log2_tab_size;
const ANSSymbolInfo* codes;
uint32_t freq(uint32_t sym) const { return (cumul[sym + 1] - cumul[sym]); }
};
class SymbolReader : public SymbolIO<StatExtra> {
public:
WP2Status Init(const SymbolsInfo& symbols_info, ANSDec* const dec);
const SymbolsInfo& symbols_info() const { return symbols_info_; }
ANSDec* dec() const { return dec_; }
// Sets the range for a particular symbol.
inline void SetRange(uint32_t sym, int32_t min, int32_t max) {
symbols_info_.SetMinMax(sym, min, max);
}
// For the 'cluster'th cluster of symbol 'sym' (given a maximum value of
// non-zero values of 'max_nnz', which can be the number of pixels for
// examples) reads its header to later decide how to read it.
WP2Status ReadHeader(uint32_t sym, uint32_t cluster, uint32_t max_nnz,
WP2_OPT_LABEL);
// Same as above but reads headers for all clusters.
WP2Status ReadHeader(uint32_t sym, uint32_t max_nnz, WP2_OPT_LABEL);
// can be called once ReadHeader() calls are finished
void Clear() { infos_.reset(); }
// Reads the symbol of type 'sym' in the 'cluster'th cluster.
// If 'cost' is not nullptr, the cost in bits of storing 'sym' is ADDED to
// 'cost'.
int32_t Read(uint32_t sym, uint32_t cluster, WP2_OPT_LABEL,
float* const cost = nullptr);
int32_t Read(uint32_t sym, WP2_OPT_LABEL, float* const cost = nullptr) {
return Read(sym, /*cluster=*/0, label, cost);
}
// Same as above except we know that the read value cannot be strictly
// superior to 'max_value'.
WP2Status ReadWithMax(uint32_t sym, uint32_t cluster, uint32_t max_value,
WP2_OPT_LABEL, int32_t* const value,
float* const cost = nullptr);
// Fills the array 'is_maybe_used' with true when the symbol might be used,
// false if we are sure it is not used.
void GetPotentialUsage(uint32_t sym, uint32_t cluster, bool is_maybe_used[],
uint32_t size) const override;
protected:
// For the 'cluster'th cluster of symbol 'sym', sets the mode to trivial value
// with value 'value'.
void AddTrivial(uint32_t sym, uint32_t cluster, bool is_symmetric,
int32_t value);
// For the 'cluster'th cluster of symbol 'sym', sets the mode to range value,
// in [0:'range'), without mapping by default. Returns the corresponding Stat.
Stat* AddRange(uint32_t sym, uint32_t cluster, bool is_symmetric,
uint16_t range);
// For the 'cluster'th cluster of symbol 'sym', sets the mode to dictionary
// value, using info from 'infos'. 'infos' is modified in this call.
WP2Status AddDict(uint32_t sym, uint32_t cluster, bool is_symmetric,
ANSCodes* const infos);
// For the 'cluster'th cluster of symbol 'sym', sets the mode to kPrefixCode
// value, using info from 'infos'. 'infos' is modified in this call.
// 'prefix_size' is the number of bits in the prefix code.
WP2Status AddPrefixCode(uint32_t sym, uint32_t cluster, bool is_symmetric,
ANSCodes* const infos, uint32_t prefix_size);
private:
// Generic implementation called by the different Read specializations above.
WP2Status ReadInternal(uint32_t sym, uint32_t cluster, bool use_max_value,
uint32_t max_value, WP2_OPT_LABEL,
int32_t* const value, float* const cost = nullptr);
// return the largest index 'idx' such that 'stat.mappings[idx] <= max_value'.
static uint32_t FindSymbol(const Stat& stat, uint32_t max_value);
ANSDec* dec_;
// Code tables used by dictionaries (StatExtra.codes point to them).
Vector<ANSCodes> codes_;
// Cumulative frequencies for dictionaries (StatExtra.cumul point to them).
Vector<Vector_u32> counts_;
// Tmp variable used during the updates to avoid re-allocations.
ANSCodes infos_;
};
} // namespace WP2
#endif /* WP2_DEC_SYMBOLS_DEC_H_ */