Coverage Report

Created: 2024-09-08 06:07

/src/brunsli/c/dec/context_map_decode.cc
Line
Count
Source
1
// Copyright (c) Google LLC 2019
2
//
3
// Use of this source code is governed by an MIT-style
4
// license that can be found in the LICENSE file or at
5
// https://opensource.org/licenses/MIT.
6
7
#include "./context_map_decode.h"
8
9
#include "../common/constants.h"
10
#include "../common/platform.h"
11
#include <brunsli/status.h>
12
#include <brunsli/types.h>
13
#include "./bit_reader.h"
14
#include "./huffman_decode.h"
15
16
namespace brunsli {
17
18
namespace {
19
20
705k
void MoveToFront(uint8_t* v, uint8_t index) {
21
705k
  uint8_t value = v[index];
22
705k
  uint8_t i = index;
23
12.3M
  for (; i; --i) v[i] = v[i - 1];
24
705k
  v[0] = value;
25
705k
}
26
27
973
void InverseMoveToFrontTransform(uint8_t* v, size_t v_len) {
28
973
  uint8_t mtf[256];
29
250k
  for (size_t i = 0; i < 256; ++i) {
30
249k
    mtf[i] = static_cast<uint8_t>(i);
31
249k
  }
32
751k
  for (size_t i = 0; i < v_len; ++i) {
33
750k
    uint8_t index = v[i];
34
750k
    v[i] = mtf[index];
35
750k
    if (index) MoveToFront(mtf, index);
36
750k
  }
37
973
}
38
39
}  // namespace
40
41
BrunsliStatus DecodeContextMap(const HuffmanDecodingData& entropy,
42
                               size_t max_run_length_prefix, size_t* index,
43
                               std::vector<uint8_t>* context_map,
44
6.49k
                               BrunsliBitReader* br) {
45
6.49k
  size_t& i = *index;
46
6.49k
  uint8_t* map = context_map->data();
47
6.49k
  const size_t length = context_map->size();
48
1.44M
  while (i < length) {
49
    // Check there is enough deta for Huffman code, RLE and IMTF bit.
50
1.43M
    if (!BrunsliBitReaderCanRead(br, 15 + max_run_length_prefix + 1)) {
51
5.11k
      return BRUNSLI_NOT_ENOUGH_DATA;
52
5.11k
    }
53
1.43M
    uint32_t code = entropy.ReadSymbol(br);
54
1.43M
    if (code == 0) {
55
182k
      map[i] = 0;
56
182k
      ++i;
57
1.25M
    } else if (code <= max_run_length_prefix) {
58
28.9k
      size_t reps = 1u + (1u << code) + (int)BrunsliBitReaderRead(br, code);
59
570k
      while (--reps) {
60
542k
        if (i >= length) return BRUNSLI_INVALID_BRN;
61
542k
        map[i] = 0;
62
542k
        ++i;
63
542k
      }
64
1.22M
    } else {
65
1.22M
      map[i] = (uint8_t)(code - max_run_length_prefix);
66
1.22M
      ++i;
67
1.22M
    }
68
1.43M
  }
69
1.25k
  if (BrunsliBitReaderRead(br, 1)) {
70
973
    InverseMoveToFrontTransform(map, length);
71
973
  }
72
1.25k
  return BrunsliBitReaderIsHealthy(br) ? BRUNSLI_OK : BRUNSLI_INVALID_BRN;
73
6.49k
}
74
75
}  // namespace brunsli