blob: 842702d3cc7544d9689e47ee6e950aefa5a78027 [file] [log] [blame]
#### 7.2 Practical Algorithm Description {#h-07-02}
VP8's boolean coder works with 8-bit probabilities p. The range of
such p is 0 <= p <= 255; the actual probability represented by p is
p/256. Also, the coder is designed so that decoding of a bool
requires no more than an 8-bit comparison, and so that the state of
both the encoder and decoder can be easily represented using a small
number of unsigned 16-bit integers.
The details are most easily understood if we first describe the
algorithm using bit-at-a-time input and output. Aside from the
ability to maintain a position in this bitstream and write/read bits,
the encoder also needs the ability to add 1 to the bits already
output; after writing n bits, adding 1 to the existing output is the
same thing as adding pow(2, -n) to x.
Together with the bit position, the encoder must maintain two
unsigned 8-bit numbers, which we call "bottom" and "range". Writing
w for the n bits already written and S = pow(2, - n - 8) for the
scale of the current bit position one byte out, we have the following
constraint on all future values v of w (including the final value
v = x):
w + ( S * bottom ) <= v < w + ( S * ( bottom + range ) )
Thus, appending bottom to the already-written bits w gives the left
endpoint of the interval of possible values, appending bottom + range
gives the right endpoint, and range itself (scaled to the current
output position) is the length of the interval.
So that our probabilistic encodings are reasonably accurate, we do
not let range vary by more than a factor of two: It stays within the
bounds 128 <= range <= 255.
The process for encoding a boolean value val whose probability of
being zero is prob / 256 -- and whose probability of being one is
( 256 - prob ) / 256 -- with 1 <= prob <= 255 is as follows.
Using an unsigned 16-bit multiply followed by an unsigned right
shift, we calculate an unsigned 8-bit split value:
split = 1 + (((range - 1) * probability)]] >> 8)
split is approximately ( prob / 256 ) * range and lies within the
bounds 1 <= split <= range - 1. These bounds ensure the correctness
of the decoding procedure described below.
If the incoming boolean val to be encoded is false, we leave the left
interval endpoint bottom alone and reduce range, replacing it by
split. If the incoming val is true, we move up the left endpoint to
bottom + split, propagating any carry to the already-written value w
(this is where we need the ability to add 1 to w), and reduce range
to range - split.
Regardless of the value encoded, range has been reduced and now has
the bounds 1 <= range <= 254. If range < 128, the encoder doubles it
and shifts the high-order bit out of bottom to the output as it also
doubles bottom, repeating this process one bit at a time until 128 <=
range <= 255. Once this is completed, the encoder is ready to
accept another bool, maintaining the constraints described above.
After encoding the last bool, the partition may be completed by
appending bottom to the bitstream.
The decoder mimics the state of the encoder. It maintains, together
with an input bit position, two unsigned 8-bit numbers, a range
identical to that maintained by the encoder and a value. Decoding
one bool at a time, the decoder (in effect) tracks the same left
interval endpoint as does the encoder and subtracts it from the
remaining input. Appending the unread portion of the bitstream to
the 8-bit value gives the difference between the actual value encoded
and the known left endpoint.
The decoder is initialized by setting range = 255 and reading the
first 16 input bits into value. The decoder maintains range and
calculates split in exactly the same way as does the encoder.
To decode a bool, it compares value to split; if value < split, the
bool is zero, and range is replaced with split. If value >= split,
the bool is one, range is replaced with range - split, and value is
replaced with value - split.
Again, range is doubled one bit at a time until it is at least 128.
The value is doubled in parallel, shifting a new input bit into the
bottom each time.
Writing Value for value together with the unread input bits and Range
for range extended indefinitely on the right by zeros, the condition
Value < Range is maintained at all times by the decoder. In
particular, the bits shifted out of value as it is doubled are always
zero.