[FFmpeg-devel] Implementation of Huffman codes for DCA encoder

Submitted by Даниил Чередник on Jan. 7, 2017, 10:22 p.m.

Details

Message ID CAJtH-nHxR6V+s++iOpCTNt5E+ywm2tdL2JJ_hfGrx2Soi-mt_Q@mail.gmail.com
State New
Headers show

Commit Message

Даниил Чередник Jan. 7, 2017, 10:22 p.m.
With real music and 256k bitrate encoding (the source was 44100, 16bit
stereo) I got:
Without Huffman: Best PSNR is  31.77 for shift 0
With: Best PSNR is  37.45 for shift 0

Current implementation of DCA encoder has minimal set of DTS features (no
ADPCM, no VQ, fixed amount of transmitted subbands, no transient control,
etc). So distortion is quite audible. Current set of patches introduces
Huffman encoding for quantized audio data which is equivalent of increasing
bitrate for 10-20%. Also bitstream allows to use Huffman for scale factor
indexes, and some other data. I am working on it too.

I have attached new split set of patches.

On Sat, Jan 7, 2017 at 11:50 PM, Carl Eugen Hoyos <ceffmpeg@gmail.com>
wrote:

> 2017-01-07 20:39 GMT+01:00 Rostislav Pehlivanov <atomnuker@gmail.com>:
> > On 7 January 2017 at 16:11, Carl Eugen Hoyos <ceffmpeg@gmail.com> wrote:
> >
> >> 2017-01-07 16:00 GMT+01:00 Даниил Чередник <dan.cherednik@gmail.com>:
> >>
> >> > Currently I am working on improvement quality of DTS encoder.
> Following
> >> > patches introduce Huffman coding.
> >>
> >> Is the quality improvement so obvious that no further tests are
> necessary?
> >> (Does psnr improve measurably?)
> >>
> > PSNR is pretty much useless for audio.
>
> > The ear's the only metric which works.
>
> Not everybody's;-))
>
> > From the 2 samples he posted I can tell there's a big difference, and the
> > encoder isn't very good right now and the patch definitely helps.
>
> Thank you!
>
> Carl Eugen
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>

Comments

Даниил Чередник Jan. 15, 2017, 3:14 p.m.
Hi.
Is there any issue in this patch?

On Sun, Jan 8, 2017 at 1:22 AM, Даниил Чередник <dan.cherednik@gmail.com>
wrote:

> With real music and 256k bitrate encoding (the source was 44100, 16bit
> stereo) I got:
> Without Huffman: Best PSNR is  31.77 for shift 0
> With: Best PSNR is  37.45 for shift 0
>
> Current implementation of DCA encoder has minimal set of DTS features (no
> ADPCM, no VQ, fixed amount of transmitted subbands, no transient control,
> etc). So distortion is quite audible. Current set of patches introduces
> Huffman encoding for quantized audio data which is equivalent of increasing
> bitrate for 10-20%. Also bitstream allows to use Huffman for scale factor
> indexes, and some other data. I am working on it too.
>
> I have attached new split set of patches.
>
> On Sat, Jan 7, 2017 at 11:50 PM, Carl Eugen Hoyos <ceffmpeg@gmail.com>
> wrote:
>
>> 2017-01-07 20:39 GMT+01:00 Rostislav Pehlivanov <atomnuker@gmail.com>:
>> > On 7 January 2017 at 16:11, Carl Eugen Hoyos <ceffmpeg@gmail.com>
>> wrote:
>> >
>> >> 2017-01-07 16:00 GMT+01:00 Даниил Чередник <dan.cherednik@gmail.com>:
>> >>
>> >> > Currently I am working on improvement quality of DTS encoder.
>> Following
>> >> > patches introduce Huffman coding.
>> >>
>> >> Is the quality improvement so obvious that no further tests are
>> necessary?
>> >> (Does psnr improve measurably?)
>> >>
>> > PSNR is pretty much useless for audio.
>>
>> > The ear's the only metric which works.
>>
>> Not everybody's;-))
>>
>> > From the 2 samples he posted I can tell there's a big difference, and
>> the
>> > encoder isn't very good right now and the patch definitely helps.
>>
>> Thank you!
>>
>> Carl Eugen
>> _______________________________________________
>> ffmpeg-devel mailing list
>> ffmpeg-devel@ffmpeg.org
>> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>>
>
>
>
> --
> Daniil Cherednik
>
Paul B Mahol Jan. 15, 2017, 3:58 p.m.
On 1/15/17, Daniil CHerednik <dan.cherednik@gmail.com> wrote:
> Hi.
> Is there any issue in this patch?

Do you plan to work more on this encoder?

Please do not top post.

>
> On Sun, Jan 8, 2017 at 1:22 AM, Daniil CHerednik <dan.cherednik@gmail.com>
> wrote:
>
>> With real music and 256k bitrate encoding (the source was 44100, 16bit
>> stereo) I got:
>> Without Huffman: Best PSNR is  31.77 for shift 0
>> With: Best PSNR is  37.45 for shift 0
>>
>> Current implementation of DCA encoder has minimal set of DTS features (no
>> ADPCM, no VQ, fixed amount of transmitted subbands, no transient control,
>> etc). So distortion is quite audible. Current set of patches introduces
>> Huffman encoding for quantized audio data which is equivalent of
>> increasing
>> bitrate for 10-20%. Also bitstream allows to use Huffman for scale factor
>> indexes, and some other data. I am working on it too.
>>
>> I have attached new split set of patches.
>>
>> On Sat, Jan 7, 2017 at 11:50 PM, Carl Eugen Hoyos <ceffmpeg@gmail.com>
>> wrote:
>>
>>> 2017-01-07 20:39 GMT+01:00 Rostislav Pehlivanov <atomnuker@gmail.com>:
>>> > On 7 January 2017 at 16:11, Carl Eugen Hoyos <ceffmpeg@gmail.com>
>>> wrote:
>>> >
>>> >> 2017-01-07 16:00 GMT+01:00 Daniil CHerednik <dan.cherednik@gmail.com>:
>>> >>
>>> >> > Currently I am working on improvement quality of DTS encoder.
>>> Following
>>> >> > patches introduce Huffman coding.
>>> >>
>>> >> Is the quality improvement so obvious that no further tests are
>>> necessary?
>>> >> (Does psnr improve measurably?)
>>> >>
>>> > PSNR is pretty much useless for audio.
>>>
>>> > The ear's the only metric which works.
>>>
>>> Not everybody's;-))
>>>
>>> > From the 2 samples he posted I can tell there's a big difference, and
>>> the
>>> > encoder isn't very good right now and the patch definitely helps.
>>>
>>> Thank you!
>>>
>>> Carl Eugen
>>> _______________________________________________
>>> ffmpeg-devel mailing list
>>> ffmpeg-devel@ffmpeg.org
>>> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>>>
>>
>>
>>
>> --
>> Daniil Cherednik
>>
>
>
>
> --
> Daniil Cherednik
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
Даниил Чередник Jan. 15, 2017, 5:34 p.m.
On Sun, Jan 15, 2017 at 6:58 PM, Paul B Mahol <onemda@gmail.com> wrote:

> On 1/15/17, Daniil CHerednik <dan.cherednik@gmail.com> wrote:
> > Hi.
> > Is there any issue in this patch?
>
> Do you plan to work more on this encoder?
>
Yes I do.

>
> Please do not top post.
>
Ok, sorry.

>
> >
> > On Sun, Jan 8, 2017 at 1:22 AM, Daniil CHerednik <
> dan.cherednik@gmail.com>
> > wrote:
> >
> >> With real music and 256k bitrate encoding (the source was 44100, 16bit
> >> stereo) I got:
> >> Without Huffman: Best PSNR is  31.77 for shift 0
> >> With: Best PSNR is  37.45 for shift 0
> >>
> >> Current implementation of DCA encoder has minimal set of DTS features
> (no
> >> ADPCM, no VQ, fixed amount of transmitted subbands, no transient
> control,
> >> etc). So distortion is quite audible. Current set of patches introduces
> >> Huffman encoding for quantized audio data which is equivalent of
> >> increasing
> >> bitrate for 10-20%. Also bitstream allows to use Huffman for scale
> factor
> >> indexes, and some other data. I am working on it too.
> >>
> >> I have attached new split set of patches.
> >>
> >> On Sat, Jan 7, 2017 at 11:50 PM, Carl Eugen Hoyos <ceffmpeg@gmail.com>
> >> wrote:
> >>
> >>> 2017-01-07 20:39 GMT+01:00 Rostislav Pehlivanov <atomnuker@gmail.com>:
> >>> > On 7 January 2017 at 16:11, Carl Eugen Hoyos <ceffmpeg@gmail.com>
> >>> wrote:
> >>> >
> >>> >> 2017-01-07 16:00 GMT+01:00 Daniil CHerednik <
> dan.cherednik@gmail.com>:
> >>> >>
> >>> >> > Currently I am working on improvement quality of DTS encoder.
> >>> Following
> >>> >> > patches introduce Huffman coding.
> >>> >>
> >>> >> Is the quality improvement so obvious that no further tests are
> >>> necessary?
> >>> >> (Does psnr improve measurably?)
> >>> >>
> >>> > PSNR is pretty much useless for audio.
> >>>
> >>> > The ear's the only metric which works.
> >>>
> >>> Not everybody's;-))
> >>>
> >>> > From the 2 samples he posted I can tell there's a big difference, and
> >>> the
> >>> > encoder isn't very good right now and the patch definitely helps.
> >>>
> >>> Thank you!
> >>>
> >>> Carl Eugen
> >>> _______________________________________________
> >>> ffmpeg-devel mailing list
> >>> ffmpeg-devel@ffmpeg.org
> >>> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> >>>
> >>
> >>
> >>
> >> --
> >> Daniil Cherednik
> >>
> >
> >
> >
> > --
> > Daniil Cherednik
> > _______________________________________________
> > ffmpeg-devel mailing list
> > ffmpeg-devel@ffmpeg.org
> > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> >
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
Rostislav Pehlivanov Jan. 15, 2017, 5:57 p.m.
On 15 January 2017 at 15:14, Даниил Чередник <dan.cherednik@gmail.com>
wrote:

> Hi.
> Is there any issue in this patch?
>
> On Sun, Jan 8, 2017 at 1:22 AM, Даниил Чередник <dan.cherednik@gmail.com>
> wrote:
>
> > With real music and 256k bitrate encoding (the source was 44100, 16bit
> > stereo) I got:
> > Without Huffman: Best PSNR is  31.77 for shift 0
> > With: Best PSNR is  37.45 for shift 0
> >
> > Current implementation of DCA encoder has minimal set of DTS features (no
> > ADPCM, no VQ, fixed amount of transmitted subbands, no transient control,
> > etc). So distortion is quite audible. Current set of patches introduces
> > Huffman encoding for quantized audio data which is equivalent of
> increasing
> > bitrate for 10-20%. Also bitstream allows to use Huffman for scale factor
> > indexes, and some other data. I am working on it too.
> >
> > I have attached new split set of patches.
> >
> > On Sat, Jan 7, 2017 at 11:50 PM, Carl Eugen Hoyos <ceffmpeg@gmail.com>
> > wrote:
> >
> >> 2017-01-07 20:39 GMT+01:00 Rostislav Pehlivanov <atomnuker@gmail.com>:
> >> > On 7 January 2017 at 16:11, Carl Eugen Hoyos <ceffmpeg@gmail.com>
> >> wrote:
> >> >
> >> >> 2017-01-07 16:00 GMT+01:00 Даниил Чередник <dan.cherednik@gmail.com
> >:
> >> >>
> >> >> > Currently I am working on improvement quality of DTS encoder.
> >> Following
> >> >> > patches introduce Huffman coding.
> >> >>
> >> >> Is the quality improvement so obvious that no further tests are
> >> necessary?
> >> >> (Does psnr improve measurably?)
> >> >>
> >> > PSNR is pretty much useless for audio.
> >>
> >> > The ear's the only metric which works.
> >>
> >> Not everybody's;-))
> >>
> >> > From the 2 samples he posted I can tell there's a big difference, and
> >> the
> >> > encoder isn't very good right now and the patch definitely helps.
> >>
> >> Thank you!
> >>
> >> Carl Eugen
> >> _______________________________________________
> >> ffmpeg-devel mailing list
> >> ffmpeg-devel@ffmpeg.org
> >> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> >>
> >
> >
> >
> > --
> > Daniil Cherednik
> >
>
>
>
> --
> Daniil Cherednik
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>

Hi,

Both patches look good to me, I'll push them later tonight unless someone
objects.
Rostislav Pehlivanov Jan. 16, 2017, 1:34 a.m.
On 15 January 2017 at 15:14, Даниил Чередник <dan.cherednik@gmail.com>
wrote:

> Hi.
> Is there any issue in this patch?
>
> On Sun, Jan 8, 2017 at 1:22 AM, Даниил Чередник <dan.cherednik@gmail.com>
> wrote:
>
> > With real music and 256k bitrate encoding (the source was 44100, 16bit
> > stereo) I got:
> > Without Huffman: Best PSNR is  31.77 for shift 0
> > With: Best PSNR is  37.45 for shift 0
> >
> > Current implementation of DCA encoder has minimal set of DTS features (no
> > ADPCM, no VQ, fixed amount of transmitted subbands, no transient control,
> > etc). So distortion is quite audible. Current set of patches introduces
> > Huffman encoding for quantized audio data which is equivalent of
> increasing
> > bitrate for 10-20%. Also bitstream allows to use Huffman for scale factor
> > indexes, and some other data. I am working on it too.
> >
> > I have attached new split set of patches.
> >
> > On Sat, Jan 7, 2017 at 11:50 PM, Carl Eugen Hoyos <ceffmpeg@gmail.com>
> > wrote:
> >
> >> 2017-01-07 20:39 GMT+01:00 Rostislav Pehlivanov <atomnuker@gmail.com>:
> >> > On 7 January 2017 at 16:11, Carl Eugen Hoyos <ceffmpeg@gmail.com>
> >> wrote:
> >> >
> >> >> 2017-01-07 16:00 GMT+01:00 Даниил Чередник <dan.cherednik@gmail.com
> >:
> >> >>
> >> >> > Currently I am working on improvement quality of DTS encoder.
> >> Following
> >> >> > patches introduce Huffman coding.
> >> >>
> >> >> Is the quality improvement so obvious that no further tests are
> >> necessary?
> >> >> (Does psnr improve measurably?)
> >> >>
> >> > PSNR is pretty much useless for audio.
> >>
> >> > The ear's the only metric which works.
> >>
> >> Not everybody's;-))
> >>
> >> > From the 2 samples he posted I can tell there's a big difference, and
> >> the
> >> > encoder isn't very good right now and the patch definitely helps.
> >>
> >> Thank you!
> >>
> >> Carl Eugen
> >> _______________________________________________
> >> ffmpeg-devel mailing list
> >> ffmpeg-devel@ffmpeg.org
> >> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> >>
> >
> >
> >
> > --
> > Daniil Cherednik
> >
>
>
>
> --
> Daniil Cherednik
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>

Thanks, pushed

Patch hide | download patch | download mbox

From e96c467499a26614bc7b5f79056ffb599ff616d7 Mon Sep 17 00:00:00 2001
From: Daniil Cherednik <dan.cherednik@gmail.com>
Date: Sun, 8 Jan 2017 00:16:49 +0300
Subject: [PATCH 3/3] avcodec/dcaenc: Implementation of Huffman codes for DCA
 encoder
To: ffmpeg-devel@ffmpeg.org

---
 libavcodec/Makefile   |   2 +-
 libavcodec/dca_core.c |  16 ++---
 libavcodec/dcadata.c  |   8 +++
 libavcodec/dcadata.h  |   5 ++
 libavcodec/dcaenc.c   | 159 ++++++++++++++++++++++++++++++++++++++------------
 libavcodec/dcaenc.h   |   1 -
 libavcodec/dcahuff.c  |  22 +++++++
 libavcodec/dcahuff.h  |   3 +
 tests/fate/acodec.mak |   2 +-
 9 files changed, 166 insertions(+), 52 deletions(-)

diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 58feb31..b81a275 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -234,7 +234,7 @@  OBJS-$(CONFIG_CYUV_DECODER)            += cyuv.o
 OBJS-$(CONFIG_DCA_DECODER)             += dcadec.o dca.o dcadata.o dcahuff.o \
                                           dca_core.o dca_exss.o dca_xll.o dca_lbr.o \
                                           dcadsp.o dcadct.o synth_filter.o
-OBJS-$(CONFIG_DCA_ENCODER)             += dcaenc.o dca.o dcadata.o
+OBJS-$(CONFIG_DCA_ENCODER)             += dcaenc.o dca.o dcadata.o dcahuff.o
 OBJS-$(CONFIG_DDS_DECODER)             += dds.o
 OBJS-$(CONFIG_DIRAC_DECODER)           += diracdec.o dirac.o diracdsp.o diractab.o \
                                           dirac_arith.o dirac_dwt.o dirac_vlc.o
diff --git a/libavcodec/dca_core.c b/libavcodec/dca_core.c
index 46825ed..d5e628e 100644
--- a/libavcodec/dca_core.c
+++ b/libavcodec/dca_core.c
@@ -92,14 +92,6 @@  static const uint8_t block_code_nbits[7] = {
     7, 10, 12, 13, 15, 17, 19
 };
 
-static const uint8_t quant_index_sel_nbits[DCA_CODE_BOOKS] = {
-    1, 2, 2, 2, 2, 3, 3, 3, 3, 3
-};
-
-static const uint8_t quant_index_group_size[DCA_CODE_BOOKS] = {
-    1, 3, 3, 3, 3, 7, 7, 7, 7, 7
-};
-
 static int dca_get_vlc(GetBitContext *s, DCAVLC *v, int i)
 {
     return get_vlc2(s, v->vlc[i].table, v->vlc[i].bits, v->max_depth) + v->offset;
@@ -400,12 +392,12 @@  static int parse_coding_header(DCACoreDecoder *s, enum HeaderType header, int xc
     // Quantization index codebook select
     for (n = 0; n < DCA_CODE_BOOKS; n++)
         for (ch = xch_base; ch < s->nchannels; ch++)
-            s->quant_index_sel[ch][n] = get_bits(&s->gb, quant_index_sel_nbits[n]);
+            s->quant_index_sel[ch][n] = get_bits(&s->gb, ff_dca_quant_index_sel_nbits[n]);
 
     // Scale factor adjustment index
     for (n = 0; n < DCA_CODE_BOOKS; n++)
         for (ch = xch_base; ch < s->nchannels; ch++)
-            if (s->quant_index_sel[ch][n] < quant_index_group_size[n])
+            if (s->quant_index_sel[ch][n] < ff_dca_quant_index_group_size[n])
                 s->scale_factor_adj[ch][n] = ff_dca_scale_factor_adj[get_bits(&s->gb, 2)];
 
     if (header == HEADER_XXCH) {
@@ -663,7 +655,7 @@  static inline int extract_audio(DCACoreDecoder *s, int32_t *audio, int abits, in
 
     if (abits <= DCA_CODE_BOOKS) {
         int sel = s->quant_index_sel[ch][abits - 1];
-        if (sel < quant_index_group_size[abits - 1]) {
+        if (sel < ff_dca_quant_index_group_size[abits - 1]) {
             // Huffman codes
             return parse_huffman_codes(s, audio, abits, sel);
         }
@@ -1562,7 +1554,7 @@  static int parse_x96_coding_header(DCACoreDecoder *s, int exss, int xch_base)
     // Quantization index codebook select
     for (n = 0; n < 6 + 4 * s->x96_high_res; n++)
         for (ch = xch_base; ch < s->x96_nchannels; ch++)
-            s->quant_index_sel[ch][n] = get_bits(&s->gb, quant_index_sel_nbits[n]);
+            s->quant_index_sel[ch][n] = get_bits(&s->gb, ff_dca_quant_index_sel_nbits[n]);
 
     if (exss) {
         // Reserved
diff --git a/libavcodec/dcadata.c b/libavcodec/dcadata.c
index b2e0f6c..193247b 100644
--- a/libavcodec/dcadata.c
+++ b/libavcodec/dcadata.c
@@ -50,6 +50,14 @@  const uint8_t ff_dca_dmix_primary_nch[8] = {
     1, 2, 2, 3, 3, 4, 4, 0
 };
 
+const uint8_t ff_dca_quant_index_sel_nbits[DCA_CODE_BOOKS] = {
+    1, 2, 2, 2, 2, 3, 3, 3, 3, 3
+};
+
+const uint8_t ff_dca_quant_index_group_size[DCA_CODE_BOOKS] = {
+    1, 3, 3, 3, 3, 7, 7, 7, 7, 7
+};
+
 /* ADPCM data */
 
 /* 16 bits signed fractional Q13 binary codes */
diff --git a/libavcodec/dcadata.h b/libavcodec/dcadata.h
index 17aa712..c838867 100644
--- a/libavcodec/dcadata.h
+++ b/libavcodec/dcadata.h
@@ -23,6 +23,8 @@ 
 
 #include <stdint.h>
 
+#include "dcahuff.h"
+
 extern const uint32_t ff_dca_bit_rates[32];
 
 extern const uint8_t ff_dca_channels[16];
@@ -31,6 +33,9 @@  extern const uint8_t ff_dca_bits_per_sample[8];
 
 extern const uint8_t ff_dca_dmix_primary_nch[8];
 
+extern const uint8_t ff_dca_quant_index_sel_nbits[DCA_CODE_BOOKS];
+extern const uint8_t ff_dca_quant_index_group_size[DCA_CODE_BOOKS];
+
 extern const int16_t ff_dca_adpcm_vb[4096][4];
 
 extern const uint32_t ff_dca_scale_factor_quant6[64];
diff --git a/libavcodec/dcaenc.c b/libavcodec/dcaenc.c
index e9c03ae..ff7b0eb 100644
--- a/libavcodec/dcaenc.c
+++ b/libavcodec/dcaenc.c
@@ -70,6 +70,7 @@  typedef struct DCAEncContext {
     int abits[MAX_CHANNELS][DCAENC_SUBBANDS];
     int scale_factor[MAX_CHANNELS][DCAENC_SUBBANDS];
     softfloat quant[MAX_CHANNELS][DCAENC_SUBBANDS];
+    int32_t quant_index_sel[MAX_CHANNELS][DCA_CODE_BOOKS];
     int32_t eff_masking_curve_cb[256];
     int32_t band_masking_cb[32];
     int32_t worst_quantization_noise;
@@ -109,7 +110,7 @@  static int encode_init(AVCodecContext *avctx)
 {
     DCAEncContext *c = avctx->priv_data;
     uint64_t layout = avctx->channel_layout;
-    int i, min_frame_bits;
+    int i, j, min_frame_bits;
 
     c->fullband_channels = c->channels = avctx->channels;
     c->lfe_channel = (avctx->channels == 3 || avctx->channels == 6);
@@ -142,6 +143,12 @@  static int encode_init(AVCodecContext *avctx)
         c->channel_order_tab = channel_reorder_nolfe[c->channel_config];
     }
 
+    for (i = 0; i < MAX_CHANNELS; i++) {
+        for (j = 0; j < DCA_CODE_BOOKS; j++) {
+            c->quant_index_sel[i][j] = ff_dca_quant_index_group_size[j];
+        }
+    }
+
     for (i = 0; i < 9; i++) {
         if (sample_rates[i] == avctx->sample_rate)
             break;
@@ -619,9 +626,58 @@  static void quantize_all(DCAEncContext *c)
                 c->quantized[ch][band][sample] = quantize_value(c->subband[ch][band][sample], c->quant[ch][band]);
 }
 
+static void accumulate_huff_bit_consumption(int abits, int32_t *quantized, uint32_t *result)
+{
+    uint8_t sel, id = abits - 1;
+    for (sel = 0; sel < ff_dca_quant_index_group_size[id]; sel++)
+        result[sel] += ff_dca_vlc_calc_quant_bits(quantized, SUBBAND_SAMPLES, sel, id);
+}
+
+static uint32_t set_best_code(uint32_t vlc_bits[DCA_CODE_BOOKS][7], uint32_t clc_bits[DCA_CODE_BOOKS], int32_t res[DCA_CODE_BOOKS])
+{
+    uint8_t i, sel;
+    uint32_t best_sel_bits[DCA_CODE_BOOKS];
+    int32_t best_sel_id[DCA_CODE_BOOKS];
+    uint32_t t, bits = 0;
+
+    for (i = 0; i < DCA_CODE_BOOKS; i++) {
+
+        av_assert0(!((!!vlc_bits[i][0]) ^ (!!clc_bits[i])));
+        if (vlc_bits[i][0] == 0) {
+            /* do not transmit adjustment index for empty codebooks */
+            res[i] = ff_dca_quant_index_group_size[i];
+            /* and skip it */
+            continue;
+        }
+
+        best_sel_bits[i] = vlc_bits[i][0];
+        best_sel_id[i] = 0;
+        for (sel = 0; sel < ff_dca_quant_index_group_size[i]; sel++) {
+            if (best_sel_bits[i] > vlc_bits[i][sel] && vlc_bits[i][sel]) {
+                best_sel_bits[i] = vlc_bits[i][sel];
+                best_sel_id[i] = sel;
+            }
+        }
+
+        /* 2 bits to transmit scale factor adjustment index */
+        t = best_sel_bits[i] + 2;
+        if (t < clc_bits[i]) {
+            res[i] = best_sel_id[i];
+            bits += t;
+        } else {
+            res[i] = ff_dca_quant_index_group_size[i];
+            bits += clc_bits[i];
+        }
+    }
+    return bits;
+}
+
 static int init_quantization_noise(DCAEncContext *c, int noise)
 {
     int ch, band, ret = 0;
+    uint32_t huff_bit_count_accum[MAX_CHANNELS][DCA_CODE_BOOKS][7];
+    uint32_t clc_bit_count_accum[MAX_CHANNELS][DCA_CODE_BOOKS];
+    uint32_t bits_counter = 0;
 
     c->consumed_bits = 132 + 493 * c->fullband_channels;
     if (c->lfe_channel)
@@ -648,10 +704,36 @@  static int init_quantization_noise(DCAEncContext *c, int noise)
         }
     }
 
-    for (ch = 0; ch < c->fullband_channels; ch++)
+    /* Recalc scale_factor each time to get bits consumption in case of Huffman coding.
+       It is suboptimal solution */
+    /* TODO: May be cache scaled values */
+    for (ch = 0; ch < c->fullband_channels; ch++) {
+        for (band = 0; band < 32; band++) {
+            c->scale_factor[ch][band] = calc_one_scale(c->peak_cb[ch][band],
+                                                       c->abits[ch][band],
+                                                       &c->quant[ch][band]);
+        }
+    }
+    quantize_all(c);
+
+    memset(huff_bit_count_accum, 0, MAX_CHANNELS * DCA_CODE_BOOKS * 7 * sizeof(uint32_t));
+    memset(clc_bit_count_accum, 0, MAX_CHANNELS * DCA_CODE_BOOKS * sizeof(uint32_t));
+    for (ch = 0; ch < c->fullband_channels; ch++) {
         for (band = 0; band < 32; band++) {
-            c->consumed_bits += bit_consumption[c->abits[ch][band]];
+            if (c->abits[ch][band] && c->abits[ch][band] <= DCA_CODE_BOOKS) {
+                accumulate_huff_bit_consumption(c->abits[ch][band], c->quantized[ch][band], huff_bit_count_accum[ch][c->abits[ch][band] - 1]);
+                clc_bit_count_accum[ch][c->abits[ch][band] - 1] += bit_consumption[c->abits[ch][band]];
+            } else {
+                bits_counter += bit_consumption[c->abits[ch][band]];
+            }
         }
+    }
+
+    for (ch = 0; ch < c->fullband_channels; ch++) {
+        bits_counter += set_best_code(huff_bit_count_accum[ch], clc_bit_count_accum[ch], c->quant_index_sel[ch]);
+    }
+
+    c->consumed_bits += bits_counter;
 
     return ret;
 }
@@ -706,16 +788,8 @@  static void shift_history(DCAEncContext *c, const int32_t *input)
         }
 }
 
-static void calc_scales(DCAEncContext *c)
+static void calc_lfe_scales(DCAEncContext *c)
 {
-    int band, ch;
-
-    for (ch = 0; ch < c->fullband_channels; ch++)
-        for (band = 0; band < 32; band++)
-            c->scale_factor[ch][band] = calc_one_scale(c->peak_cb[ch][band],
-                                                       c->abits[ch][band],
-                                                       &c->quant[ch][band]);
-
     if (c->lfe_channel)
         c->lfe_scale_factor = calc_one_scale(c->lfe_peak_cb, 11, &c->lfe_quant);
 }
@@ -805,9 +879,6 @@  static void put_frame_header(DCAEncContext *c)
 
 static void put_primary_audio_header(DCAEncContext *c)
 {
-    static const int bitlen[11] = { 0, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3 };
-    static const int thr[11]    = { 0, 1, 3, 3, 3, 3, 7, 7, 7, 7, 7 };
-
     int ch, i;
     /* Number of subframes */
     put_bits(&c->pb, 4, SUBFRAMES - 1);
@@ -839,36 +910,51 @@  static void put_primary_audio_header(DCAEncContext *c)
     for (ch = 0; ch < c->fullband_channels; ch++)
         put_bits(&c->pb, 3, 6);
 
-    /* Quantization index codebook select: dummy data
-       to avoid transmission of scale factor adjustment */
-    for (i = 1; i < 11; i++)
+    /* Quantization index codebook select */
+    for (i = 0; i < DCA_CODE_BOOKS; i++)
         for (ch = 0; ch < c->fullband_channels; ch++)
-            put_bits(&c->pb, bitlen[i], thr[i]);
+            put_bits(&c->pb, ff_dca_quant_index_sel_nbits[i], c->quant_index_sel[ch][i]);
+
+    /* Scale factor adjustment index: transmitted in case of Huffman coding */
+    for (i = 0; i < DCA_CODE_BOOKS; i++)
+        for (ch = 0; ch < c->fullband_channels; ch++)
+            if (c->quant_index_sel[ch][i] < ff_dca_quant_index_group_size[i])
+                put_bits(&c->pb, 2, 0);
 
-    /* Scale factor adjustment index: not transmitted */
     /* Audio header CRC check word: not transmitted */
 }
 
 static void put_subframe_samples(DCAEncContext *c, int ss, int band, int ch)
 {
-    if (c->abits[ch][band] <= 7) {
-        int sum, i, j;
-        for (i = 0; i < 8; i += 4) {
-            sum = 0;
-            for (j = 3; j >= 0; j--) {
-                sum *= ff_dca_quant_levels[c->abits[ch][band]];
-                sum += c->quantized[ch][band][ss * 8 + i + j];
-                sum += (ff_dca_quant_levels[c->abits[ch][band]] - 1) / 2;
-            }
-            put_bits(&c->pb, bit_consumption[c->abits[ch][band]] / 4, sum);
+    int i, j, sum, bits, sel;
+    if (c->abits[ch][band] <= DCA_CODE_BOOKS) {
+        av_assert0(c->abits[ch][band] > 0);
+        sel = c->quant_index_sel[ch][c->abits[ch][band] - 1];
+        // Huffman codes
+        if (sel < ff_dca_quant_index_group_size[c->abits[ch][band] - 1]) {
+            ff_dca_vlc_enc_quant(&c->pb, &c->quantized[ch][band][ss * 8], 8, sel, c->abits[ch][band] - 1);
+            return;
         }
-    } else {
-        int i;
-        for (i = 0; i < 8; i++) {
-            int bits = bit_consumption[c->abits[ch][band]] / 16;
-            put_sbits(&c->pb, bits, c->quantized[ch][band][ss * 8 + i]);
+
+        // Block codes
+        if (c->abits[ch][band] <= 7) {
+            for (i = 0; i < 8; i += 4) {
+                sum = 0;
+                for (j = 3; j >= 0; j--) {
+                    sum *= ff_dca_quant_levels[c->abits[ch][band]];
+                    sum += c->quantized[ch][band][ss * 8 + i + j];
+                    sum += (ff_dca_quant_levels[c->abits[ch][band]] - 1) / 2;
+                }
+                put_bits(&c->pb, bit_consumption[c->abits[ch][band]] / 4, sum);
+            }
+            return;
         }
     }
+
+    for (i = 0; i < 8; i++) {
+        bits = bit_consumption[c->abits[ch][band]] / 16;
+        put_sbits(&c->pb, bits, c->quantized[ch][band][ss * 8 + i]);
+    }
 }
 
 static void put_subframe(DCAEncContext *c, int subframe)
@@ -947,8 +1033,7 @@  static int encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
     calc_masking(c, samples);
     find_peaks(c);
     assign_bits(c);
-    calc_scales(c);
-    quantize_all(c);
+    calc_lfe_scales(c);
     shift_history(c, samples);
 
     init_put_bits(&c->pb, avpkt->data, avpkt->size);
diff --git a/libavcodec/dcaenc.h b/libavcodec/dcaenc.h
index eccfb42..06816c2 100644
--- a/libavcodec/dcaenc.h
+++ b/libavcodec/dcaenc.h
@@ -95,7 +95,6 @@  static const softfloat scalefactor_inv[128] = {
 
 /* manually derived from
  * Table B.5: Selection of quantization levels and codebooks
- * FIXME: will become invalid when Huffman codes are introduced.
  */
 static const int bit_consumption[27] = {
     -8, 28, 40, 48, 52, 60, 68, 76, 80, 96,
diff --git a/libavcodec/dcahuff.c b/libavcodec/dcahuff.c
index bea3530..9fb42a6 100644
--- a/libavcodec/dcahuff.c
+++ b/libavcodec/dcahuff.c
@@ -1335,3 +1335,25 @@  av_cold void ff_dca_init_vlcs(void)
 
     vlcs_initialized = 1;
 }
+
+uint32_t ff_dca_vlc_calc_quant_bits(int *values, uint8_t n, uint8_t sel, uint8_t table)
+{
+    uint8_t i, id;
+    uint32_t sum = 0;
+    for (i = 0; i < n; i++) {
+        id = values[i] - bitalloc_offsets[table];
+        av_assert0(id < bitalloc_sizes[table]);
+        sum += bitalloc_bits[table][sel][id];
+    }
+    return sum;
+}
+
+void ff_dca_vlc_enc_quant(PutBitContext *pb, int *values, uint8_t n, uint8_t sel, uint8_t table)
+{
+    uint8_t i, id;
+    for (i = 0; i < n; i++) {
+        id = values[i] - bitalloc_offsets[table];
+        av_assert0(id < bitalloc_sizes[table]);
+        put_bits(pb, bitalloc_bits[table][sel][id], bitalloc_codes[table][sel][id]);
+    }
+}
diff --git a/libavcodec/dcahuff.h b/libavcodec/dcahuff.h
index b1d5735..c017622 100644
--- a/libavcodec/dcahuff.h
+++ b/libavcodec/dcahuff.h
@@ -27,6 +27,7 @@ 
 
 #include "avcodec.h"
 #include "get_bits.h"
+#include "put_bits.h"
 
 #define DCA_CODE_BOOKS      10
 
@@ -55,5 +56,7 @@  extern VLC  ff_dca_vlc_grid_3;
 extern VLC  ff_dca_vlc_rsd;
 
 av_cold void ff_dca_init_vlcs(void);
+uint32_t ff_dca_vlc_calc_quant_bits(int *values, uint8_t n, uint8_t sel, uint8_t abits);
+void ff_dca_vlc_enc_quant(PutBitContext *pb, int *values, uint8_t n, uint8_t sel, uint8_t abits);
 
 #endif /* AVCODEC_DCAHUFF_H */
diff --git a/tests/fate/acodec.mak b/tests/fate/acodec.mak
index c7d4d26..5c3fea9 100644
--- a/tests/fate/acodec.mak
+++ b/tests/fate/acodec.mak
@@ -104,7 +104,7 @@  fate-acodec-dca: tests/data/asynth-44100-2.wav
 fate-acodec-dca: SRC = tests/data/asynth-44100-2.wav
 fate-acodec-dca: CMD = md5 -i $(TARGET_PATH)/$(SRC) -c:a dca -strict -2 -f dts -flags +bitexact
 fate-acodec-dca: CMP = oneline
-fate-acodec-dca: REF = 7ffdefdf47069289990755c79387cc90
+fate-acodec-dca: REF = 7cd79a3717943a06b217f1130223a86f
 
 FATE_ACODEC-$(call ENCDEC, DCA, WAV) += fate-acodec-dca2
 fate-acodec-dca2: CMD = enc_dec_pcm dts wav s16le $(SRC) -c:a dca -strict -2 -flags +bitexact
-- 
2.1.4