Welcome to mirror list, hosted at ThFree Co, Russian Federation.

rans_symbol_decoder.h « entropy « compression « draco « src « dracoenc « draco « extern - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 1b5f1c8b7159ff0e7d6e18c83da2f3dfcd7960da (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// Copyright 2016 The Draco 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 DRACO_COMPRESSION_ENTROPY_RANS_SYMBOL_DECODER_H_
#define DRACO_COMPRESSION_ENTROPY_RANS_SYMBOL_DECODER_H_

#include "draco/draco_features.h"

#include "draco/compression/config/compression_shared.h"
#include "draco/compression/entropy/rans_symbol_coding.h"
#include "draco/core/decoder_buffer.h"
#include "draco/core/varint_decoding.h"

namespace draco {

// A helper class for decoding symbols using the rANS algorithm (see ans.h).
// The class can be used to decode the probability table and the data encoded
// by the RAnsSymbolEncoder. |unique_symbols_bit_length_t| must be the same as
// the one used for the corresponding RAnsSymbolEncoder.
template <int unique_symbols_bit_length_t>
class RAnsSymbolDecoder {
 public:
  RAnsSymbolDecoder() : num_symbols_(0) {}

  // Initialize the decoder and decode the probability table.
  bool Create(DecoderBuffer *buffer);

  uint32_t num_symbols() const { return num_symbols_; }

  // Starts decoding from the buffer. The buffer will be advanced past the
  // encoded data after this call.
  bool StartDecoding(DecoderBuffer *buffer);
  uint32_t DecodeSymbol() { return ans_.rans_read(); }
  void EndDecoding();

 private:
  static constexpr int rans_precision_bits_ =
      ComputeRAnsPrecisionFromUniqueSymbolsBitLength(
          unique_symbols_bit_length_t);
  static constexpr int rans_precision_ = 1 << rans_precision_bits_;

  std::vector<uint32_t> probability_table_;
  uint32_t num_symbols_;
  RAnsDecoder<rans_precision_bits_> ans_;
};

template <int unique_symbols_bit_length_t>
bool RAnsSymbolDecoder<unique_symbols_bit_length_t>::Create(
    DecoderBuffer *buffer) {
  // Check that the DecoderBuffer version is set.
  if (buffer->bitstream_version() == 0)
    return false;
    // Decode the number of alphabet symbols.
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
    if (!buffer->Decode(&num_symbols_))
      return false;

  } else
#endif
  {
    if (!DecodeVarint(&num_symbols_, buffer))
      return false;
  }
  probability_table_.resize(num_symbols_);
  if (num_symbols_ == 0)
    return true;
  // Decode the table.
  for (uint32_t i = 0; i < num_symbols_; ++i) {
    uint8_t prob_data = 0;
    // Decode the first byte and extract the number of extra bytes we need to
    // get, or the offset to the next symbol with non-zero probability.
    if (!buffer->Decode(&prob_data))
      return false;
    // Token is stored in the first two bits of the first byte. Values 0-2 are
    // used to indicate the number of extra bytes, and value 3 is a special
    // symbol used to denote run-length coding of zero probability entries.
    // See rans_symbol_encoder.h for more details.
    const int token = prob_data & 3;
    if (token == 3) {
      const uint32_t offset = prob_data >> 2;
      if (i + offset >= num_symbols_)
        return false;
      // Set zero probability for all symbols in the specified range.
      for (uint32_t j = 0; j < offset + 1; ++j) {
        probability_table_[i + j] = 0;
      }
      i += offset;
    } else {
      const int extra_bytes = token;
      uint32_t prob = prob_data >> 2;
      for (int b = 0; b < extra_bytes; ++b) {
        uint8_t eb;
        if (!buffer->Decode(&eb))
          return false;
        // Shift 8 bits for each extra byte and subtract 2 for the two first
        // bits.
        prob |= static_cast<uint32_t>(eb) << (8 * (b + 1) - 2);
      }
      probability_table_[i] = prob;
    }
  }
  if (!ans_.rans_build_look_up_table(&probability_table_[0], num_symbols_))
    return false;
  return true;
}

template <int unique_symbols_bit_length_t>
bool RAnsSymbolDecoder<unique_symbols_bit_length_t>::StartDecoding(
    DecoderBuffer *buffer) {
  uint64_t bytes_encoded;
  // Decode the number of bytes encoded by the encoder.
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
  if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
    if (!buffer->Decode(&bytes_encoded))
      return false;

  } else
#endif
  {
    if (!DecodeVarint<uint64_t>(&bytes_encoded, buffer))
      return false;
  }
  if (bytes_encoded > static_cast<uint64_t>(buffer->remaining_size()))
    return false;
  const uint8_t *const data_head =
      reinterpret_cast<const uint8_t *>(buffer->data_head());
  // Advance the buffer past the rANS data.
  buffer->Advance(bytes_encoded);
  if (ans_.read_init(data_head, static_cast<int>(bytes_encoded)) != 0)
    return false;
  return true;
}

template <int unique_symbols_bit_length_t>
void RAnsSymbolDecoder<unique_symbols_bit_length_t>::EndDecoding() {
  ans_.read_end();
}

}  // namespace draco

#endif  // DRACO_COMPRESSION_ENTROPY_RANS_SYMBOL_DECODER_H_