-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathlesson2.cpp
102 lines (93 loc) · 3.67 KB
/
lesson2.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
94
95
96
97
98
99
100
101
102
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include "bitreader.h"
#include "bitwriter.h"
#include "test_harness.h"
#include "dyn_prob.h"
/////////////////
//// Lesson 2 - Basic model
/////////////////
/*
This lesson illustrates that the probabilities being adaptively tracked need not be limited to
a single value over the whole stream.
For instance in this model we track a probability per bit in each byte.
This set of 8 dynamically learned probabilities is known as a "model".
In this case the model works well for ascii, which has the 7th bit as zero always
The EXERCISE asks you to see if you can compress a datastream consisting of single bit flips
There are a number of ways to approach this.
One interesting way is to divide the observations of the probabilities repeatedly so that
The encoder quickly 'learns' that a particular bit is in the 'one' state or the 'zero' state
Another approach is to use the transformation functions to subtract the previous value from the
Current value
*/
void nop(unsigned char*){}
void (*transform)(unsigned char* tmp) = nop;
void (*untransform)(unsigned char* tmp) = nop;
unsigned char tmp[sizeof(uncompressed)];
void encode_with_adaptive_probability() {
memcpy(tmp, uncompressed, sizeof(uncompressed));
(*transform)(tmp);
DynProb encode[8];// one probability per bit position <-- new for lesson2
vpx_writer wri ={0};
vpx_start_encode(&wri, compressed);
for (size_t i = 0; i < sizeof(uncompressed); ++i) {
int bit_index = 0;
for(int bit = 1; bit < 256; ++bit_index, bit <<= 1) {
bool cur_bit = !!(uncompressed[i] & bit);
vpx_write(&wri, cur_bit, encode[bit_index].prob); // <-- bit_index is new for lesson2
encode[bit_index].record_bit(cur_bit); // <-- bit_index is new for lesson2
}
}
vpx_stop_encode(&wri);
printf("Buffer encoded with final prob(0) = {%.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f} results in %d size (%.2f%%)\n",
encode[0].prob / 255.,
encode[1].prob / 255.,
encode[2].prob / 255.,
encode[3].prob / 255.,
encode[4].prob / 255.,
encode[5].prob / 255.,
encode[6].prob / 255.,
encode[7].prob / 255.,
wri.pos,
100 * wri.pos / float(sizeof(uncompressed)));
DynProb decode[8];
vpx_reader rea={0};
vpx_reader_init(&rea,
wri.buffer,
wri.pos);
memset(roundtrip, 0, sizeof(roundtrip));
for (size_t i = 0; i < sizeof(roundtrip); ++i) {
int bit_index = 0;
for(int bit = 1; bit < 256; ++bit_index, bit <<= 1) {
if (vpx_read(&rea, decode[bit_index].prob)) { // <-- bit_index is new for lesson2
roundtrip[i] |= bit;
decode[bit_index].record_bit(true); // <-- bit_index is new for lesson2
} else {
decode[bit_index].record_bit(false); // <-- bit_index is new for lesson2
}
}
}
assert(vpx_reader_has_error(&rea) == 0);
(*untransform)(uncompressed);
assert(memcmp(uncompressed, roundtrip, sizeof(uncompressed)) == 0);
}
int main () {
printf("Random data\n");
populate_random_data();
encode_with_adaptive_probability();
printf("ASCII data\n");
populate_ascii_data();
encode_with_adaptive_probability();
printf("ZERO data\n");
populate_zero_data();
encode_with_adaptive_probability();
printf("0, 1, or 3\n");
populate_small_data();
encode_with_adaptive_probability();
printf("------------------\nEXERCISE\n");
exercise_single_bit_flip();
encode_with_adaptive_probability();
return roundtrip[0];
}