Improve coefficient sign decoding #167
Open
+80
−10
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR introduces a more efficient method for decoding coefficient signs in the WebP decoder.
Background
The existing implementation derived the range shift after decoding a sign of a coefficient by performing a (rather time consuming in terms of bit decoding) leading_zeros() calculation on the range.
Since the range after a sign decoding is guaranteed to lie within a range of 64..127, that shift is always 1. See also libwebp's VP8GetSigned() function in src/utils/bit_reader_inl_utils.h
Similar conditions are true for flag decoding with the exception that the range could still be in the range of 64..128 and 128 doesn't need any shifting.
That difference between flags and signs comes from the initial range value of 255 that can reach flag decoding but not sign decoding since after any symbol has been decoded, range is guaranteed to be within 128..254 and signs are never the first symbol in a VP8 bit stream.
Too bad Google didn't initialize the arithmetic coder with 254 instead of 255...
What Changed
range.shiftto be 0 (for range=128) or 1 (for range in 64..127)Performance
Performance has been benchmarked using all test images in the repository plus two additional larger WebP images (gallery1/6 and gallery1/7)
Each image was decoded 20 times, and the total decoding time was measured.
Overall, the new method consistently shows a 1–4% improvement in decode time across all tested images.