diff mbox series

[FFmpeg-devel,6/9] avcodec/asvenc: Avoid reversing output data twice

Message ID 20201013091017.1899676-6-andreas.rheinhardt@gmail.com
State Accepted
Commit 746ab8327c0c8ae1b7e894f3c21d7b7a44c0a0b3
Headers show
Series [FFmpeg-devel,1/9] avcodec/asvdec: Reduce the size of some VLCs | expand

Checks

Context Check Description
andriy/x86_make success Make finished
andriy/x86_make_fate success Make fate finished

Commit Message

Andreas Rheinhardt Oct. 13, 2020, 9:10 a.m. UTC
The ASUS V2 format is designed for a little-endian bitstream reader, yet
our encoder used an ordinary big-endian bitstream writer to write it;
the bits of every byte were swapped at the end and some data (namely the
numbers not in static tables) had to be bitreversed before writing it at
all, so that it would be reversed twice.

This commit stops doing so; instead, a little-endian bitstream writer is
used. This also necessitated to switch certain static tables, which
required trivial modifications to the decoder (that uses the same
tables).

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
---
 libavcodec/asv.c    | 46 +++++++++++++++++++++++++--------------------
 libavcodec/asv.h    |  2 +-
 libavcodec/asvdec.c | 21 +++++++++------------
 libavcodec/asvenc.c | 29 +++++++++++-----------------
 4 files changed, 47 insertions(+), 51 deletions(-)

Comments

Michael Niedermayer Oct. 14, 2020, 7:05 p.m. UTC | #1
On Tue, Oct 13, 2020 at 11:10:14AM +0200, Andreas Rheinhardt wrote:
> The ASUS V2 format is designed for a little-endian bitstream reader, yet
> our encoder used an ordinary big-endian bitstream writer to write it;
> the bits of every byte were swapped at the end and some data (namely the
> numbers not in static tables) had to be bitreversed before writing it at
> all, so that it would be reversed twice.
> 
> This commit stops doing so; instead, a little-endian bitstream writer is
> used. This also necessitated to switch certain static tables, which
> required trivial modifications to the decoder (that uses the same
> tables).
[...]

> -const uint8_t ff_asv2_level_tab[63][2] = {
> -    { 0x3F, 10 }, { 0x2F, 10 }, { 0x37, 10 }, { 0x27, 10 }, { 0x3B, 10 }, { 0x2B, 10 }, { 0x33, 10 }, { 0x23, 10 },
> -    { 0x3D, 10 }, { 0x2D, 10 }, { 0x35, 10 }, { 0x25, 10 }, { 0x39, 10 }, { 0x29, 10 }, { 0x31, 10 }, { 0x21, 10 },
> -    { 0x1F,  8 }, { 0x17,  8 }, { 0x1B,  8 }, { 0x13,  8 }, { 0x1D,  8 }, { 0x15,  8 }, { 0x19,  8 }, { 0x11,  8 },
> -    { 0x0F,  6 }, { 0x0B,  6 }, { 0x0D,  6 }, { 0x09,  6 },
> -    { 0x07,  4 }, { 0x05,  4 },
> -    { 0x03,  2 },
> -    { 0x00,  5 },
> -    { 0x02,  2 },
> -    { 0x04,  4 }, { 0x06,  4 },
> -    { 0x08,  6 }, { 0x0C,  6 }, { 0x0A,  6 }, { 0x0E,  6 },
> -    { 0x10,  8 }, { 0x18,  8 }, { 0x14,  8 }, { 0x1C,  8 }, { 0x12,  8 }, { 0x1A,  8 }, { 0x16,  8 }, { 0x1E,  8 },
> -    { 0x20, 10 }, { 0x30, 10 }, { 0x28, 10 }, { 0x38, 10 }, { 0x24, 10 }, { 0x34, 10 }, { 0x2C, 10 }, { 0x3C, 10 },
> -    { 0x22, 10 }, { 0x32, 10 }, { 0x2A, 10 }, { 0x3A, 10 }, { 0x26, 10 }, { 0x36, 10 }, { 0x2E, 10 }, { 0x3E, 10 },
> +const uint16_t ff_asv2_level_tab[63][2] = {
> +    { 0x3F0, 10 }, { 0x3D0, 10 }, { 0x3B0, 10 }, { 0x390, 10 }, { 0x370, 10 },
> +    { 0x350, 10 }, { 0x330, 10 }, { 0x310, 10 }, { 0x2F0, 10 }, { 0x2D0, 10 },
> +    { 0x2B0, 10 }, { 0x290, 10 }, { 0x270, 10 }, { 0x250, 10 }, { 0x230, 10 },
> +    { 0x210, 10 },
> +    { 0x0F8,  8 }, { 0x0E8,  8 }, { 0x0D8,  8 }, { 0x0C8,  8 }, { 0x0B8,  8 },
> +    { 0x0A8,  8 }, { 0x098,  8 }, { 0x088,  8 },
> +    { 0x03C,  6 }, { 0x034,  6 }, { 0x02C,  6 }, { 0x024,  6 },
> +    { 0x00E,  4 }, { 0x00A,  4 },
> +    { 0x003,  2 },
> +    { 0x000,  5 },
> +    { 0x001,  2 },
> +    { 0x002,  4 }, { 0x006,  4 },
> +    { 0x004,  6 }, { 0x00C,  6 }, { 0x014,  6 }, { 0x01C,  6 },
> +    { 0x008,  8 }, { 0x018,  8 }, { 0x028,  8 }, { 0x038,  8 }, { 0x048,  8 },
> +    { 0x058,  8 }, { 0x068,  8 }, { 0x078,  8 },
> +    { 0x010, 10 }, { 0x030, 10 }, { 0x050, 10 }, { 0x070, 10 }, { 0x090, 10 },
> +    { 0x0B0, 10 }, { 0x0D0, 10 }, { 0x0F0, 10 }, { 0x110, 10 }, { 0x130, 10 },
> +    { 0x150, 10 }, { 0x170, 10 }, { 0x190, 10 }, { 0x1B0, 10 }, { 0x1D0, 10 },
> +    { 0x1F0, 10 }
>  };

would it be worth it to handle codes with length > the 8*sizeof in such a way
that this fits still in uint8 ?

[...]
Andreas Rheinhardt Oct. 15, 2020, 2:12 p.m. UTC | #2
Michael Niedermayer:
> On Tue, Oct 13, 2020 at 11:10:14AM +0200, Andreas Rheinhardt wrote:
>> The ASUS V2 format is designed for a little-endian bitstream reader, yet
>> our encoder used an ordinary big-endian bitstream writer to write it;
>> the bits of every byte were swapped at the end and some data (namely the
>> numbers not in static tables) had to be bitreversed before writing it at
>> all, so that it would be reversed twice.
>>
>> This commit stops doing so; instead, a little-endian bitstream writer is
>> used. This also necessitated to switch certain static tables, which
>> required trivial modifications to the decoder (that uses the same
>> tables).
> [...]
> 
>> -const uint8_t ff_asv2_level_tab[63][2] = {
>> -    { 0x3F, 10 }, { 0x2F, 10 }, { 0x37, 10 }, { 0x27, 10 }, { 0x3B, 10 }, { 0x2B, 10 }, { 0x33, 10 }, { 0x23, 10 },
>> -    { 0x3D, 10 }, { 0x2D, 10 }, { 0x35, 10 }, { 0x25, 10 }, { 0x39, 10 }, { 0x29, 10 }, { 0x31, 10 }, { 0x21, 10 },
>> -    { 0x1F,  8 }, { 0x17,  8 }, { 0x1B,  8 }, { 0x13,  8 }, { 0x1D,  8 }, { 0x15,  8 }, { 0x19,  8 }, { 0x11,  8 },
>> -    { 0x0F,  6 }, { 0x0B,  6 }, { 0x0D,  6 }, { 0x09,  6 },
>> -    { 0x07,  4 }, { 0x05,  4 },
>> -    { 0x03,  2 },
>> -    { 0x00,  5 },
>> -    { 0x02,  2 },
>> -    { 0x04,  4 }, { 0x06,  4 },
>> -    { 0x08,  6 }, { 0x0C,  6 }, { 0x0A,  6 }, { 0x0E,  6 },
>> -    { 0x10,  8 }, { 0x18,  8 }, { 0x14,  8 }, { 0x1C,  8 }, { 0x12,  8 }, { 0x1A,  8 }, { 0x16,  8 }, { 0x1E,  8 },
>> -    { 0x20, 10 }, { 0x30, 10 }, { 0x28, 10 }, { 0x38, 10 }, { 0x24, 10 }, { 0x34, 10 }, { 0x2C, 10 }, { 0x3C, 10 },
>> -    { 0x22, 10 }, { 0x32, 10 }, { 0x2A, 10 }, { 0x3A, 10 }, { 0x26, 10 }, { 0x36, 10 }, { 0x2E, 10 }, { 0x3E, 10 },
>> +const uint16_t ff_asv2_level_tab[63][2] = {
>> +    { 0x3F0, 10 }, { 0x3D0, 10 }, { 0x3B0, 10 }, { 0x390, 10 }, { 0x370, 10 },
>> +    { 0x350, 10 }, { 0x330, 10 }, { 0x310, 10 }, { 0x2F0, 10 }, { 0x2D0, 10 },
>> +    { 0x2B0, 10 }, { 0x290, 10 }, { 0x270, 10 }, { 0x250, 10 }, { 0x230, 10 },
>> +    { 0x210, 10 },
>> +    { 0x0F8,  8 }, { 0x0E8,  8 }, { 0x0D8,  8 }, { 0x0C8,  8 }, { 0x0B8,  8 },
>> +    { 0x0A8,  8 }, { 0x098,  8 }, { 0x088,  8 },
>> +    { 0x03C,  6 }, { 0x034,  6 }, { 0x02C,  6 }, { 0x024,  6 },
>> +    { 0x00E,  4 }, { 0x00A,  4 },
>> +    { 0x003,  2 },
>> +    { 0x000,  5 },
>> +    { 0x001,  2 },
>> +    { 0x002,  4 }, { 0x006,  4 },
>> +    { 0x004,  6 }, { 0x00C,  6 }, { 0x014,  6 }, { 0x01C,  6 },
>> +    { 0x008,  8 }, { 0x018,  8 }, { 0x028,  8 }, { 0x038,  8 }, { 0x048,  8 },
>> +    { 0x058,  8 }, { 0x068,  8 }, { 0x078,  8 },
>> +    { 0x010, 10 }, { 0x030, 10 }, { 0x050, 10 }, { 0x070, 10 }, { 0x090, 10 },
>> +    { 0x0B0, 10 }, { 0x0D0, 10 }, { 0x0F0, 10 }, { 0x110, 10 }, { 0x130, 10 },
>> +    { 0x150, 10 }, { 0x170, 10 }, { 0x190, 10 }, { 0x1B0, 10 }, { 0x1D0, 10 },
>> +    { 0x1F0, 10 }
>>  };
> 
> would it be worth it to handle codes with length > the 8*sizeof in such a way
> that this fits still in uint8 ?
> 
You seem to believe that the reason I switch to little-endian codes
(which entails switching to uint16_t) in this array lies in the VLC API.
This is not so. The reason for the switch is that the little endian
values are now directly written by put_bits_le(). If the values were not
reversed, one would have to reverse them at runtime in the encoder.

- Andreas
Michael Niedermayer Oct. 15, 2020, 5:05 p.m. UTC | #3
On Thu, Oct 15, 2020 at 04:12:01PM +0200, Andreas Rheinhardt wrote:
> Michael Niedermayer:
> > On Tue, Oct 13, 2020 at 11:10:14AM +0200, Andreas Rheinhardt wrote:
> >> The ASUS V2 format is designed for a little-endian bitstream reader, yet
> >> our encoder used an ordinary big-endian bitstream writer to write it;
> >> the bits of every byte were swapped at the end and some data (namely the
> >> numbers not in static tables) had to be bitreversed before writing it at
> >> all, so that it would be reversed twice.
> >>
> >> This commit stops doing so; instead, a little-endian bitstream writer is
> >> used. This also necessitated to switch certain static tables, which
> >> required trivial modifications to the decoder (that uses the same
> >> tables).
> > [...]
> > 
> >> -const uint8_t ff_asv2_level_tab[63][2] = {
> >> -    { 0x3F, 10 }, { 0x2F, 10 }, { 0x37, 10 }, { 0x27, 10 }, { 0x3B, 10 }, { 0x2B, 10 }, { 0x33, 10 }, { 0x23, 10 },
> >> -    { 0x3D, 10 }, { 0x2D, 10 }, { 0x35, 10 }, { 0x25, 10 }, { 0x39, 10 }, { 0x29, 10 }, { 0x31, 10 }, { 0x21, 10 },
> >> -    { 0x1F,  8 }, { 0x17,  8 }, { 0x1B,  8 }, { 0x13,  8 }, { 0x1D,  8 }, { 0x15,  8 }, { 0x19,  8 }, { 0x11,  8 },
> >> -    { 0x0F,  6 }, { 0x0B,  6 }, { 0x0D,  6 }, { 0x09,  6 },
> >> -    { 0x07,  4 }, { 0x05,  4 },
> >> -    { 0x03,  2 },
> >> -    { 0x00,  5 },
> >> -    { 0x02,  2 },
> >> -    { 0x04,  4 }, { 0x06,  4 },
> >> -    { 0x08,  6 }, { 0x0C,  6 }, { 0x0A,  6 }, { 0x0E,  6 },
> >> -    { 0x10,  8 }, { 0x18,  8 }, { 0x14,  8 }, { 0x1C,  8 }, { 0x12,  8 }, { 0x1A,  8 }, { 0x16,  8 }, { 0x1E,  8 },
> >> -    { 0x20, 10 }, { 0x30, 10 }, { 0x28, 10 }, { 0x38, 10 }, { 0x24, 10 }, { 0x34, 10 }, { 0x2C, 10 }, { 0x3C, 10 },
> >> -    { 0x22, 10 }, { 0x32, 10 }, { 0x2A, 10 }, { 0x3A, 10 }, { 0x26, 10 }, { 0x36, 10 }, { 0x2E, 10 }, { 0x3E, 10 },
> >> +const uint16_t ff_asv2_level_tab[63][2] = {
> >> +    { 0x3F0, 10 }, { 0x3D0, 10 }, { 0x3B0, 10 }, { 0x390, 10 }, { 0x370, 10 },
> >> +    { 0x350, 10 }, { 0x330, 10 }, { 0x310, 10 }, { 0x2F0, 10 }, { 0x2D0, 10 },
> >> +    { 0x2B0, 10 }, { 0x290, 10 }, { 0x270, 10 }, { 0x250, 10 }, { 0x230, 10 },
> >> +    { 0x210, 10 },
> >> +    { 0x0F8,  8 }, { 0x0E8,  8 }, { 0x0D8,  8 }, { 0x0C8,  8 }, { 0x0B8,  8 },
> >> +    { 0x0A8,  8 }, { 0x098,  8 }, { 0x088,  8 },
> >> +    { 0x03C,  6 }, { 0x034,  6 }, { 0x02C,  6 }, { 0x024,  6 },
> >> +    { 0x00E,  4 }, { 0x00A,  4 },
> >> +    { 0x003,  2 },
> >> +    { 0x000,  5 },
> >> +    { 0x001,  2 },
> >> +    { 0x002,  4 }, { 0x006,  4 },
> >> +    { 0x004,  6 }, { 0x00C,  6 }, { 0x014,  6 }, { 0x01C,  6 },
> >> +    { 0x008,  8 }, { 0x018,  8 }, { 0x028,  8 }, { 0x038,  8 }, { 0x048,  8 },
> >> +    { 0x058,  8 }, { 0x068,  8 }, { 0x078,  8 },
> >> +    { 0x010, 10 }, { 0x030, 10 }, { 0x050, 10 }, { 0x070, 10 }, { 0x090, 10 },
> >> +    { 0x0B0, 10 }, { 0x0D0, 10 }, { 0x0F0, 10 }, { 0x110, 10 }, { 0x130, 10 },
> >> +    { 0x150, 10 }, { 0x170, 10 }, { 0x190, 10 }, { 0x1B0, 10 }, { 0x1D0, 10 },
> >> +    { 0x1F0, 10 }
> >>  };
> > 
> > would it be worth it to handle codes with length > the 8*sizeof in such a way
> > that this fits still in uint8 ?
> > 
> You seem to believe that the reason I switch to little-endian codes
> (which entails switching to uint16_t) in this array lies in the VLC API.
> This is not so. The reason for the switch is that the little endian
> values are now directly written by put_bits_le(). If the values were not
> reversed, one would have to reverse them at runtime in the encoder.

right, i missed that this was of course also used in the encoder

thx

[...]
diff mbox series

Patch

diff --git a/libavcodec/asv.c b/libavcodec/asv.c
index 14fdf73333..dcae90982a 100644
--- a/libavcodec/asv.c
+++ b/libavcodec/asv.c
@@ -53,31 +53,37 @@  const uint8_t ff_asv_level_tab[7][2] = {
 };
 
 const uint8_t ff_asv_dc_ccp_tab[8][2] = {
-    { 0x1, 2 }, { 0xD, 4 }, { 0xF, 4 }, { 0xC, 4 },
-    { 0x5, 3 }, { 0xE, 4 }, { 0x4, 3 }, { 0x0, 2 },
+    { 0x2, 2 }, { 0xB, 4 }, { 0xF, 4 }, { 0x3, 4 },
+    { 0x5, 3 }, { 0x7, 4 }, { 0x1, 3 }, { 0x0, 2 },
 };
 
 const uint8_t ff_asv_ac_ccp_tab[16][2] = {
-    { 0x00, 2 }, { 0x3B, 6 }, { 0x0A, 4 }, { 0x3A, 6 },
-    { 0x02, 3 }, { 0x39, 6 }, { 0x3C, 6 }, { 0x38, 6 },
-    { 0x03, 3 }, { 0x3D, 6 }, { 0x08, 4 }, { 0x1F, 5 },
-    { 0x09, 4 }, { 0x0B, 4 }, { 0x0D, 4 }, { 0x0C, 4 },
+    { 0x00, 2 }, { 0x37, 6 }, { 0x05, 4 }, { 0x17, 6 },
+    { 0x02, 3 }, { 0x27, 6 }, { 0x0F, 6 }, { 0x07, 6 },
+    { 0x06, 3 }, { 0x2F, 6 }, { 0x01, 4 }, { 0x1F, 5 },
+    { 0x09, 4 }, { 0x0D, 4 }, { 0x0B, 4 }, { 0x03, 4 },
 };
 
-const uint8_t ff_asv2_level_tab[63][2] = {
-    { 0x3F, 10 }, { 0x2F, 10 }, { 0x37, 10 }, { 0x27, 10 }, { 0x3B, 10 }, { 0x2B, 10 }, { 0x33, 10 }, { 0x23, 10 },
-    { 0x3D, 10 }, { 0x2D, 10 }, { 0x35, 10 }, { 0x25, 10 }, { 0x39, 10 }, { 0x29, 10 }, { 0x31, 10 }, { 0x21, 10 },
-    { 0x1F,  8 }, { 0x17,  8 }, { 0x1B,  8 }, { 0x13,  8 }, { 0x1D,  8 }, { 0x15,  8 }, { 0x19,  8 }, { 0x11,  8 },
-    { 0x0F,  6 }, { 0x0B,  6 }, { 0x0D,  6 }, { 0x09,  6 },
-    { 0x07,  4 }, { 0x05,  4 },
-    { 0x03,  2 },
-    { 0x00,  5 },
-    { 0x02,  2 },
-    { 0x04,  4 }, { 0x06,  4 },
-    { 0x08,  6 }, { 0x0C,  6 }, { 0x0A,  6 }, { 0x0E,  6 },
-    { 0x10,  8 }, { 0x18,  8 }, { 0x14,  8 }, { 0x1C,  8 }, { 0x12,  8 }, { 0x1A,  8 }, { 0x16,  8 }, { 0x1E,  8 },
-    { 0x20, 10 }, { 0x30, 10 }, { 0x28, 10 }, { 0x38, 10 }, { 0x24, 10 }, { 0x34, 10 }, { 0x2C, 10 }, { 0x3C, 10 },
-    { 0x22, 10 }, { 0x32, 10 }, { 0x2A, 10 }, { 0x3A, 10 }, { 0x26, 10 }, { 0x36, 10 }, { 0x2E, 10 }, { 0x3E, 10 },
+const uint16_t ff_asv2_level_tab[63][2] = {
+    { 0x3F0, 10 }, { 0x3D0, 10 }, { 0x3B0, 10 }, { 0x390, 10 }, { 0x370, 10 },
+    { 0x350, 10 }, { 0x330, 10 }, { 0x310, 10 }, { 0x2F0, 10 }, { 0x2D0, 10 },
+    { 0x2B0, 10 }, { 0x290, 10 }, { 0x270, 10 }, { 0x250, 10 }, { 0x230, 10 },
+    { 0x210, 10 },
+    { 0x0F8,  8 }, { 0x0E8,  8 }, { 0x0D8,  8 }, { 0x0C8,  8 }, { 0x0B8,  8 },
+    { 0x0A8,  8 }, { 0x098,  8 }, { 0x088,  8 },
+    { 0x03C,  6 }, { 0x034,  6 }, { 0x02C,  6 }, { 0x024,  6 },
+    { 0x00E,  4 }, { 0x00A,  4 },
+    { 0x003,  2 },
+    { 0x000,  5 },
+    { 0x001,  2 },
+    { 0x002,  4 }, { 0x006,  4 },
+    { 0x004,  6 }, { 0x00C,  6 }, { 0x014,  6 }, { 0x01C,  6 },
+    { 0x008,  8 }, { 0x018,  8 }, { 0x028,  8 }, { 0x038,  8 }, { 0x048,  8 },
+    { 0x058,  8 }, { 0x068,  8 }, { 0x078,  8 },
+    { 0x010, 10 }, { 0x030, 10 }, { 0x050, 10 }, { 0x070, 10 }, { 0x090, 10 },
+    { 0x0B0, 10 }, { 0x0D0, 10 }, { 0x0F0, 10 }, { 0x110, 10 }, { 0x130, 10 },
+    { 0x150, 10 }, { 0x170, 10 }, { 0x190, 10 }, { 0x1B0, 10 }, { 0x1D0, 10 },
+    { 0x1F0, 10 }
 };
 
 av_cold void ff_asv_common_init(AVCodecContext *avctx)
diff --git a/libavcodec/asv.h b/libavcodec/asv.h
index a1366b6fe4..e778c72d34 100644
--- a/libavcodec/asv.h
+++ b/libavcodec/asv.h
@@ -66,7 +66,7 @@  extern const uint8_t ff_asv_ccp_tab[17][2];
 extern const uint8_t ff_asv_level_tab[7][2];
 extern const uint8_t ff_asv_dc_ccp_tab[8][2];
 extern const uint8_t ff_asv_ac_ccp_tab[16][2];
-extern const uint8_t ff_asv2_level_tab[63][2];
+extern const uint16_t ff_asv2_level_tab[63][2];
 
 void ff_asv_common_init(AVCodecContext *avctx);
 
diff --git a/libavcodec/asvdec.c b/libavcodec/asvdec.c
index 78e53b6402..6b6d7b3fa7 100644
--- a/libavcodec/asvdec.c
+++ b/libavcodec/asvdec.c
@@ -55,21 +55,18 @@  static av_cold void init_vlcs(ASV1Context *a)
         INIT_VLC_STATIC(&ccp_vlc, CCP_VLC_BITS, 17,
                         &ff_asv_ccp_tab[0][1], 2, 1,
                         &ff_asv_ccp_tab[0][0], 2, 1, 32);
-        INIT_CUSTOM_VLC_STATIC(&dc_ccp_vlc, DC_CCP_VLC_BITS, 8,
-                               &ff_asv_dc_ccp_tab[0][1], 2, 1,
-                               &ff_asv_dc_ccp_tab[0][0], 2, 1,
-                               INIT_VLC_OUTPUT_LE, 16);
-        INIT_CUSTOM_VLC_STATIC(&ac_ccp_vlc, AC_CCP_VLC_BITS, 16,
-                               &ff_asv_ac_ccp_tab[0][1], 2, 1,
-                               &ff_asv_ac_ccp_tab[0][0], 2, 1,
-                               INIT_VLC_OUTPUT_LE, 64);
+        INIT_LE_VLC_STATIC(&dc_ccp_vlc, DC_CCP_VLC_BITS, 8,
+                           &ff_asv_dc_ccp_tab[0][1], 2, 1,
+                           &ff_asv_dc_ccp_tab[0][0], 2, 1, 16);
+        INIT_LE_VLC_STATIC(&ac_ccp_vlc, AC_CCP_VLC_BITS, 16,
+                           &ff_asv_ac_ccp_tab[0][1], 2, 1,
+                           &ff_asv_ac_ccp_tab[0][0], 2, 1, 64);
         INIT_VLC_STATIC(&level_vlc,      ASV1_LEVEL_VLC_BITS, 7,
                         &ff_asv_level_tab[0][1], 2, 1,
                         &ff_asv_level_tab[0][0], 2, 1, 16);
-        INIT_CUSTOM_VLC_STATIC(&asv2_level_vlc, ASV2_LEVEL_VLC_BITS, 63,
-                               &ff_asv2_level_tab[0][1], 2, 1,
-                               &ff_asv2_level_tab[0][0], 2, 1,
-                               INIT_VLC_OUTPUT_LE, 1024);
+        INIT_LE_VLC_STATIC(&asv2_level_vlc, ASV2_LEVEL_VLC_BITS, 63,
+                           &ff_asv2_level_tab[0][1], 4, 2,
+                           &ff_asv2_level_tab[0][0], 4, 2, 1024);
     }
 }
 
diff --git a/libavcodec/asvenc.c b/libavcodec/asvenc.c
index 49df3ffbe1..718ffa1836 100644
--- a/libavcodec/asvenc.c
+++ b/libavcodec/asvenc.c
@@ -32,14 +32,8 @@ 
 #include "dct.h"
 #include "fdctdsp.h"
 #include "internal.h"
-#include "mathops.h"
 #include "mpeg12data.h"
 
-static inline void asv2_put_bits(PutBitContext *pb, int n, int v)
-{
-    put_bits(pb, n, ff_reverse[v << (8 - n)]);
-}
-
 static inline void asv1_put_level(PutBitContext *pb, int level)
 {
     unsigned int index = level + 3;
@@ -57,14 +51,14 @@  static inline void asv2_put_level(ASV1Context *a, PutBitContext *pb, int level)
     unsigned int index = level + 31;
 
     if (index <= 62) {
-        put_bits(pb, ff_asv2_level_tab[index][1], ff_asv2_level_tab[index][0]);
+        put_bits_le(pb, ff_asv2_level_tab[index][1], ff_asv2_level_tab[index][0]);
     } else {
-        put_bits(pb, 5, 0); /* Escape code */
+        put_bits_le(pb, 5, 0); /* Escape code */
         if (level < -128 || level > 127) {
             av_log(a->avctx, AV_LOG_WARNING, "Clipping level %d, increase qscale\n", level);
             level = av_clip_int8(level);
         }
-        asv2_put_bits(pb, 8, level & 0xFF);
+        put_bits_le(pb, 8, level & 0xFF);
     }
 }
 
@@ -127,8 +121,8 @@  static inline void asv2_encode_block(ASV1Context *a, int16_t block[64])
 
     count >>= 2;
 
-    asv2_put_bits(&a->pb, 4, count);
-    asv2_put_bits(&a->pb, 8, (block[0] + 32) >> 6);
+    put_bits_le(&a->pb, 4, count);
+    put_bits_le(&a->pb, 8, (block[0] + 32) >> 6);
     block[0] = 0;
 
     for (i = 0; i <= count; i++) {
@@ -150,9 +144,9 @@  static inline void asv2_encode_block(ASV1Context *a, int16_t block[64])
 
         av_assert2(i || ccp < 8);
         if (i)
-            put_bits(&a->pb, ff_asv_ac_ccp_tab[ccp][1], ff_asv_ac_ccp_tab[ccp][0]);
+            put_bits_le(&a->pb, ff_asv_ac_ccp_tab[ccp][1], ff_asv_ac_ccp_tab[ccp][0]);
         else
-            put_bits(&a->pb, ff_asv_dc_ccp_tab[ccp][1], ff_asv_dc_ccp_tab[ccp][0]);
+            put_bits_le(&a->pb, ff_asv_dc_ccp_tab[ccp][1], ff_asv_dc_ccp_tab[ccp][0]);
 
         if (ccp) {
             if (ccp & 8)
@@ -291,17 +285,16 @@  static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
     }
     emms_c();
 
-    flush_put_bits(&a->pb);
+    if (avctx->codec_id == AV_CODEC_ID_ASV1)
+        flush_put_bits(&a->pb);
+    else
+        flush_put_bits_le(&a->pb);
     AV_WN32(put_bits_ptr(&a->pb), 0);
     size = (put_bits_count(&a->pb) + 31) / 32;
 
     if (avctx->codec_id == AV_CODEC_ID_ASV1) {
         a->bbdsp.bswap_buf((uint32_t *) pkt->data,
                            (uint32_t *) pkt->data, size);
-    } else {
-        int i;
-        for (i = 0; i < 4 * size; i++)
-            pkt->data[i] = ff_reverse[pkt->data[i]];
     }
 
     pkt->size   = size * 4;