]> git.sesse.net Git - ffmpeg/commit
avcodec/magicyuv: Avoid AV_QSORT when creating Huffman table
authorAndreas Rheinhardt <andreas.rheinhardt@gmail.com>
Wed, 23 Sep 2020 13:17:33 +0000 (15:17 +0200)
committerAndreas Rheinhardt <andreas.rheinhardt@gmail.com>
Sat, 26 Sep 2020 18:38:30 +0000 (20:38 +0200)
commit1bf30a1beb7527887c9b466d07765d20fa3b5412
tree9bc6f30a6fe72c385d2ede87622ed347fdcc386c
parent59f7d685141d724d6ef845a9c0f81106eb87771c
avcodec/magicyuv: Avoid AV_QSORT when creating Huffman table

The MagicYUV format stores Huffman tables in its bitstream by coding
the length of a given symbol; it does not code the actual code directly,
instead this is to be inferred by the rule that a symbol is to the left
of every shorter symbol in the Huffman tree and that for symbols of the
same length the symbol is ascending from left to right.

Our decoder implemented this by first sorting the array containing
length and symbol of each element according to descending length and
for equal length, according to ascending symbol. Afterwards, the current
state in the tree got encoded in a variable code; if the next array entry
had length len, then the len most significant bits of code contained
the code of this entry. Whenever an entry of the array of length
len was processed, code was incremented by 1U << (32 - len). So two
entries of length len have the same effect as incrementing code by
1U << (32 - (len - 1)), which corresponds to the parent node of length
len - 1 of the two nodes of length len etc.

This commit modifies this to avoid sorting the entries before
calculating the codes. This is done by calculating how many non-leaf
nodes there are on each level of the tree before calculating the codes.
Afterwards every leaf node on this level gets assigned the number of
nodes already on this level as code. This of course works only because
the entries are already sorted by their symbol initially, so that this
algorithm indeed gives ascending symbols from left to right on every
level.

This offers both speed- as well as (obvious) codesize advantages. With
Clang 10 the number of decicycles for build_huffman decreased from
1561987 to 1228405; for GCC 9 it went from 1825096 decicyles to 1429921.
These tests were carried out with a sample with 150 frames that was
looped 13 times; and this was iterated 10 times. The earlier reference
point here is from the point when the loop generating the codes was
traversed in reverse order (as the patch reversing the order led to
performance penalties).

Reviewed-by: Paul B Mahol <onemda@gmail.com>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
libavcodec/magicyuv.c