-
Notifications
You must be signed in to change notification settings - Fork 36
/
Encoder.cpp
93 lines (81 loc) · 2.25 KB
/
Encoder.cpp
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
#include "Encoder.hpp"
Encoder::Encoder(Shared* const sharedMain, bool doEncoding, Mode m, File *f) :
doEncoding(doEncoding),
ari(f),
mode(m),
archive(f),
alt(nullptr),
sharedBlock(),
predictorMain(sharedMain),
predictorBlock(&sharedBlock)
{
sharedBlock.init(sharedMain->level, 16);
sharedBlock.chosenSimd = sharedMain->chosenSimd;
if( mode == DECOMPRESS ) {
uint64_t start = size();
archive->setEnd();
uint64_t end = size();
if( end >= (UINT64_C(1) << 31)) {
quit("Large archives not yet supported.");
}
setStatusRange(0.0, static_cast<float>(end));
archive->setpos(start);
}
if( doEncoding && mode == DECOMPRESS ) { // x = first 4 bytes of archive
ari.prefetch();
}
}
Mode Encoder::getMode() const { return mode; }
uint64_t Encoder::size() const { return archive->curPos(); }
void Encoder::flush() {
if(doEncoding && mode == COMPRESS) {
ari.flush();
}
}
void Encoder::setFile(File *f) { alt = f; }
void Encoder::compressByte(Predictor *predictor, uint8_t c) {
assert(mode == COMPRESS);
if (!doEncoding) {
archive->putChar(c);
} else {
for( int i = 7; i >= 0; --i ) {
uint32_t p = predictor->p();
int y = (c >> i) & 1;
ari.encodeBit(p, y);
updateModels(predictor, p, y);
}
assert(predictor->shared->State.c1 == c);
}
}
uint8_t Encoder::decompressByte(Predictor *predictor) {
if( mode == COMPRESS ) {
assert(alt);
return alt->getchar();
}
if (!doEncoding) {
return archive->getchar();
} else {
for( int i = 0; i < 8; ++i ) {
int p = predictor->p();
int y = ari.decodeBit(p);
updateModels(predictor, p, y);
}
return predictor->shared->State.c1;
}
}
void Encoder::updateModels(Predictor* predictor, uint32_t p, int y) {
bool isMissed = ((p >> (ArithmeticEncoder::PRECISION - 1)) != y);
predictor->shared->update(y, isMissed);
}
void Encoder::setStatusRange(float perc1, float perc2) {
p1 = perc1;
p2 = perc2;
}
void Encoder::printStatus(uint64_t n, uint64_t size) const {
fprintf(stderr, "%6.2f%%\b\b\b\b\b\b\b", (p1 + (p2 - p1) * n / (size + 1)) * 100);
fflush(stderr);
}
void Encoder::printStatus() const {
fprintf(stderr, "%6.2f%%\b\b\b\b\b\b\b", float(size()) / (p2 + 1) * 100);
fflush(stderr);
}