---
 libavcodec/ac3enc.c       |  226 ++++++++++++++++++++++++++-------------------
 libavcodec/ac3enc_float.c |    2 +-
 libavcodec/ac3tab.c       |    5 +
 libavcodec/ac3tab.h       |    1 +
 4 files changed, 139 insertions(+), 95 deletions(-)

diff --git a/libavcodec/ac3enc.c b/libavcodec/ac3enc.c
index 8cc6c3d..c938b87 100644
--- a/libavcodec/ac3enc.c
+++ b/libavcodec/ac3enc.c
@@ -140,6 +140,7 @@ typedef struct AC3Block {
 typedef struct AC3EncodeContext {
     AVClass *av_class;                      ///< AVClass used for AVOption
     AC3EncOptions options;                  ///< encoding options
+    AVCodecContext *avctx;                  ///< parent AVCodecContext;
     PutBitContext pb;                       ///< bitstream writer context
     DSPContext dsp;
     AC3DSPContext ac3dsp;                   ///< AC-3 optimized functions
@@ -154,6 +155,8 @@ typedef struct AC3EncodeContext {
     int bit_rate;                           ///< target bit rate, in bits-per-second
     int sample_rate;                        ///< sampling frequency, in Hz
 
+    int num_blks_code;                      ///< number of blocks code                  (numblkscod)
+    int num_blocks;                         ///< number of blocks per frame
     int frame_size_min;                     ///< minimum frame size in case rounding is necessary
     int frame_size;                         ///< current frame size in bytes
     int frame_size_code;                    ///< frame size code                        (frmsizecod)
@@ -413,7 +416,7 @@ static void adjust_frame_size(AC3EncodeContext *s)
     s->frame_size = s->frame_size_min +
                     2 * (s->bits_written * s->sample_rate < s->samples_written * s->bit_rate);
     s->bits_written    += s->frame_size * 8;
-    s->samples_written += AC3_FRAME_SIZE;
+    s->samples_written += AC3_BLOCK_SIZE * s->num_blocks;
 }
 
 
@@ -432,13 +435,13 @@ static void deinterleave_input_samples(AC3EncodeContext *s,
         int sinc;
 
         /* copy last 256 samples of previous frame to the start of the current frame */
-        memcpy(&s->planar_samples[ch][0], &s->planar_samples[ch][AC3_FRAME_SIZE],
+        memcpy(&s->planar_samples[ch][0], &s->planar_samples[ch][AC3_BLOCK_SIZE*s->num_blocks],
                AC3_BLOCK_SIZE * sizeof(s->planar_samples[0][0]));
 
         /* deinterleave */
         sinc = s->channels;
         sptr = samples + s->channel_map[ch];
-        for (i = AC3_BLOCK_SIZE; i < AC3_FRAME_SIZE+AC3_BLOCK_SIZE; i++) {
+        for (i = AC3_BLOCK_SIZE; i < AC3_BLOCK_SIZE*s->num_blocks+AC3_BLOCK_SIZE; i++) {
             s->planar_samples[ch][i] = *sptr;
             sptr += sinc;
         }
@@ -456,7 +459,7 @@ static void apply_mdct(AC3EncodeContext *s)
     int blk, ch;
 
     for (ch = 0; ch < s->channels; ch++) {
-        for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) {
+        for (blk = 0; blk < s->num_blocks; blk++) {
             AC3Block *block = &s->blocks[blk];
             const SampleType *input_samples = &s->planar_samples[ch][blk * AC3_BLOCK_SIZE];
 
@@ -479,7 +482,7 @@ static void compute_coupling_strategy(AC3EncodeContext *s)
 
     /* set coupling use flags for each block/channel */
     /* TODO: turn coupling on/off and adjust start band based on bit usage */
-    for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) {
+    for (blk = 0; blk < s->num_blocks; blk++) {
         AC3Block *block = &s->blocks[blk];
         for (ch = 1; ch <= s->fbw_channels; ch++)
             block->channel_in_cpl[ch] = s->cpl_on;
@@ -489,7 +492,7 @@ static void compute_coupling_strategy(AC3EncodeContext *s)
        enabled for that block */
     got_cpl_snr = 0;
     num_cpl_blocks = 0;
-    for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) {
+    for (blk = 0; blk < s->num_blocks; blk++) {
         AC3Block *block = &s->blocks[blk];
         block->num_cpl_channels = 0;
         for (ch = 1; ch <= s->fbw_channels; ch++)
@@ -525,7 +528,7 @@ static void compute_coupling_strategy(AC3EncodeContext *s)
         s->cpl_on = 0;
 
     /* set bandwidth for each channel */
-    for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) {
+    for (blk = 0; blk < s->num_blocks; blk++) {
         AC3Block *block = &s->blocks[blk];
         for (ch = 1; ch <= s->fbw_channels; ch++) {
             if (block->channel_in_cpl[ch])
@@ -567,7 +570,7 @@ static void apply_channel_coupling(AC3EncodeContext *s)
     int num_cpl_coefs = s->num_cpl_subbands * 12;
 
     /* calculate coupling channel from fbw channels */
-    for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) {
+    for (blk = 0; blk < s->num_blocks; blk++) {
         AC3Block *block = &s->blocks[blk];
         CoefType *cpl_coef = &block->mdct_coef[CPL_CH][s->start_freq[CPL_CH]];
         if (!block->cpl_in_use)
@@ -600,7 +603,7 @@ static void apply_channel_coupling(AC3EncodeContext *s)
     while (i < s->cpl_end_freq) {
         int band_size = s->cpl_band_sizes[bnd];
         for (ch = CPL_CH; ch <= s->fbw_channels; ch++) {
-            for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) {
+            for (blk = 0; blk < s->num_blocks; blk++) {
                 AC3Block *block = &s->blocks[blk];
                 if (!block->cpl_in_use || (ch > CPL_CH && !block->channel_in_cpl[ch]))
                     continue;
@@ -615,7 +618,7 @@ static void apply_channel_coupling(AC3EncodeContext *s)
     }
 
     /* determine which blocks to send new coupling coordinates for */
-    for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) {
+    for (blk = 0; blk < s->num_blocks; blk++) {
         AC3Block *block  = &s->blocks[blk];
         AC3Block *block0 = blk ? &s->blocks[blk-1] : NULL;
         int new_coords = 0;
@@ -673,7 +676,7 @@ static void apply_channel_coupling(AC3EncodeContext *s)
        coordinates in successive blocks */
     for (bnd = 0; bnd < s->num_cpl_bands; bnd++) {
         blk = 0;
-        while (blk < AC3_MAX_BLOCKS) {
+        while (blk < s->num_blocks) {
             int blk1;
             CoefSumType energy_cpl;
             AC3Block *block  = &s->blocks[blk];
@@ -685,7 +688,7 @@ static void apply_channel_coupling(AC3EncodeContext *s)
 
             energy_cpl = energy[blk][CPL_CH][bnd];
             blk1 = blk+1;
-            while (!s->blocks[blk1].new_cpl_coords && blk1 < AC3_MAX_BLOCKS) {
+            while (blk1 < s->num_blocks && !s->blocks[blk1].new_cpl_coords) {
                 if (s->blocks[blk1].cpl_in_use)
                     energy_cpl += energy[blk1][CPL_CH][bnd];
                 blk1++;
@@ -697,7 +700,7 @@ static void apply_channel_coupling(AC3EncodeContext *s)
                     continue;
                 energy_ch = energy[blk][ch][bnd];
                 blk1 = blk+1;
-                while (!s->blocks[blk1].new_cpl_coords && blk1 < AC3_MAX_BLOCKS) {
+                while (blk1 < s->num_blocks && !s->blocks[blk1].new_cpl_coords) {
                     if (s->blocks[blk1].cpl_in_use)
                         energy_ch += energy[blk1][ch][bnd];
                     blk1++;
@@ -709,7 +712,7 @@ static void apply_channel_coupling(AC3EncodeContext *s)
     }
 
     /* calculate exponents/mantissas for coupling coordinates */
-    for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) {
+    for (blk = 0; blk < s->num_blocks; blk++) {
         AC3Block *block = &s->blocks[blk];
         if (!block->cpl_in_use || !block->new_cpl_coords)
             continue;
@@ -760,7 +763,7 @@ static void apply_channel_coupling(AC3EncodeContext *s)
         int first_cpl_coords[AC3_MAX_CHANNELS];
         for (ch = 1; ch <= s->fbw_channels; ch++)
             first_cpl_coords[ch] = 1;
-        for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) {
+        for (blk = 0; blk < s->num_blocks; blk++) {
             AC3Block *block = &s->blocks[blk];
             for (ch = 1; ch <= s->fbw_channels; ch++) {
                 if (block->channel_in_cpl[ch]) {
@@ -775,7 +778,7 @@ static void apply_channel_coupling(AC3EncodeContext *s)
         }
 
         /* set first cpl leak */
-        for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) {
+        for (blk = 0; blk < s->num_blocks; blk++) {
             AC3Block *block = &s->blocks[blk];
             if (block->cpl_in_use) {
                 block->new_cpl_leak = 2;
@@ -799,7 +802,7 @@ static void compute_rematrixing_strategy(AC3EncodeContext *s)
     if (s->channel_mode != AC3_CHMODE_STEREO)
         return;
 
-    for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) {
+    for (blk = 0; blk < s->num_blocks; blk++) {
         block = &s->blocks[blk];
         block->new_rematrixing_strategy = !blk;
 
@@ -863,7 +866,7 @@ static void apply_rematrixing(AC3EncodeContext *s)
     if (!s->rematrixing_enabled)
         return;
 
-    for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) {
+    for (blk = 0; blk < s->num_blocks; blk++) {
         AC3Block *block = &s->blocks[blk];
         if (block->new_rematrixing_strategy)
             flags = block->rematrixing_flags;
@@ -923,7 +926,7 @@ static void extract_exponents(AC3EncodeContext *s)
     int blk, ch;
 
     for (ch = !s->cpl_on; ch <= s->channels; ch++) {
-        for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) {
+        for (blk = 0; blk < s->num_blocks; blk++) {
             AC3Block *block = &s->blocks[blk];
             s->ac3dsp.extract_exponents(block->exp[ch], block->fixed_coef[ch],
                                         AC3_MAX_COEFS);
@@ -938,6 +941,12 @@ static void extract_exponents(AC3EncodeContext *s)
  */
 #define EXP_DIFF_THRESHOLD 500
 
+static const uint8_t exp_strategy_reuse_tab[4][6] = {
+    { EXP_D15, EXP_D15, EXP_D15, EXP_D15, EXP_D15, EXP_D15 },
+    { EXP_D15, EXP_D15, EXP_D15, EXP_D15, EXP_D15, EXP_D15 },
+    { EXP_D25, EXP_D25, EXP_D15, EXP_D15, EXP_D15, EXP_D15 },
+    { EXP_D45, EXP_D25, EXP_D25, EXP_D15, EXP_D15, EXP_D15 }
+};
 
 /**
  * Calculate exponent strategies for all channels.
@@ -956,7 +965,7 @@ static void compute_exp_strategy(AC3EncodeContext *s)
            reused in the next frame */
         exp_strategy[0] = EXP_NEW;
         exp += AC3_MAX_COEFS;
-        for (blk = 1; blk < AC3_MAX_BLOCKS; blk++, exp += AC3_MAX_COEFS) {
+        for (blk = 1; blk < s->num_blocks; blk++, exp += AC3_MAX_COEFS) {
             if (ch == CPL_CH) {
                 if (!s->blocks[blk-1].cpl_in_use) {
                     exp_strategy[blk] = EXP_NEW;
@@ -980,28 +989,23 @@ static void compute_exp_strategy(AC3EncodeContext *s)
         /* now select the encoding strategy type : if exponents are often
            recoded, we use a coarse encoding */
         blk = 0;
-        while (blk < AC3_MAX_BLOCKS) {
+        while (blk < s->num_blocks) {
             blk1 = blk + 1;
-            while (blk1 < AC3_MAX_BLOCKS && exp_strategy[blk1] == EXP_REUSE)
+            while (blk1 < s->num_blocks && exp_strategy[blk1] == EXP_REUSE)
                 blk1++;
-            switch (blk1 - blk) {
-            case 1:  exp_strategy[blk] = EXP_D45; break;
-            case 2:
-            case 3:  exp_strategy[blk] = EXP_D25; break;
-            default: exp_strategy[blk] = EXP_D15; break;
-            }
+            exp_strategy[blk] = exp_strategy_reuse_tab[s->num_blks_code][blk1-blk-1];
             blk = blk1;
         }
     }
     if (s->lfe_on) {
         ch = s->lfe_channel;
         s->exp_strategy[ch][0] = EXP_D15;
-        for (blk = 1; blk < AC3_MAX_BLOCKS; blk++)
+        for (blk = 1; blk < s->num_blocks; blk++)
             s->exp_strategy[ch][blk] = EXP_REUSE;
     }
 
     /* determine frame exponent strategy use for E-AC-3 */
-    if (s->eac3) {
+    if (s->eac3 && s->num_blocks == 6) {
         s->use_frame_exp_strategy = 1;
         for (ch = !s->cpl_on; ch <= s->fbw_channels; ch++) {
             int expstr = frame_expstr_search_tab[s->exp_strategy[ch][0]-1]
@@ -1016,6 +1020,8 @@ static void compute_exp_strategy(AC3EncodeContext *s)
             }
             s->frame_exp_strategy[ch] = expstr;
         }
+    } else {
+        s->use_frame_exp_strategy = 0;
     }
 }
 
@@ -1108,7 +1114,7 @@ static void encode_exponents(AC3EncodeContext *s)
 
         cpl = (ch == CPL_CH);
         blk = 0;
-        while (blk < AC3_MAX_BLOCKS) {
+        while (blk < s->num_blocks) {
             AC3Block *block = &s->blocks[blk];
             if (cpl && !block->cpl_in_use) {
                 exp += AC3_MAX_COEFS;
@@ -1121,7 +1127,7 @@ static void encode_exponents(AC3EncodeContext *s)
             /* count the number of EXP_REUSE blocks after the current block
                and set exponent reference block pointers */
             block->exp_ref_block[ch] = block;
-            while (blk1 < AC3_MAX_BLOCKS && exp_strategy[blk1] == EXP_REUSE) {
+            while (blk1 < s->num_blocks && exp_strategy[blk1] == EXP_REUSE) {
                 s->blocks[blk1].exp_ref_block[ch] = block;
                 blk1++;
             }
@@ -1154,7 +1160,7 @@ static void group_exponents(AC3EncodeContext *s)
     int exp0, exp1;
 
     bit_count = 0;
-    for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) {
+    for (blk = 0; blk < s->num_blocks; blk++) {
         AC3Block *block = &s->blocks[blk];
         for (ch = !block->cpl_in_use; ch <= s->channels; ch++) {
             int exp_strategy = s->exp_strategy[ch][blk];
@@ -1243,30 +1249,38 @@ static void count_frame_bits_fixed(AC3EncodeContext *s)
     if (s->eac3) {
         /* bitstream info header */
         frame_bits += 35;
-        frame_bits += 1 + 1 + 1;
+        frame_bits += 1 + 1;
+        if (s->num_blks_code != 0x3)
+            frame_bits++;
+        frame_bits++;
         /* audio frame header */
-        frame_bits += 2;
+        if (s->num_blks_code == 0x3)
+            frame_bits += 2;
         frame_bits += 10;
         /* exponent strategy */
         if (s->use_frame_exp_strategy)
             frame_bits += 5 * s->fbw_channels;
         else
-            frame_bits += 2 * AC3_MAX_BLOCKS * s->fbw_channels;
+            frame_bits += 2 * s->num_blocks * s->fbw_channels;
         /* lfe exponent strategy */
-        frame_bits += s->lfe_on;
+        frame_bits += s->num_blocks * s->lfe_on;
         /* converter exponent strategy */
-        frame_bits += s->fbw_channels * 5;
+        if (s->num_blks_code != 0x3)
+            frame_bits++;
+        else
+            frame_bits += s->fbw_channels * 5;
         /* snr offsets */
         frame_bits += 10;
         /* block start info */
-        frame_bits++;
+        if (s->num_blks_code != 0x0)
+            frame_bits++;
     } else {
         frame_bits += 49;
         frame_bits += frame_bits_inc[s->channel_mode];
     }
 
     /* audio blocks */
-    for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) {
+    for (blk = 0; blk < s->num_blocks; blk++) {
         if (!s->eac3) {
             /* block switch flags */
             frame_bits += s->fbw_channels;
@@ -1368,7 +1382,7 @@ static void count_frame_bits(AC3EncodeContext *s)
         /* coupling */
         if (s->channel_mode > AC3_CHMODE_MONO) {
             frame_bits++;
-            for (blk = 1; blk < AC3_MAX_BLOCKS; blk++) {
+            for (blk = 1; blk < s->num_blocks; blk++) {
                 AC3Block *block = &s->blocks[blk];
                 frame_bits++;
                 if (block->new_cpl_strategy)
@@ -1379,7 +1393,7 @@ static void count_frame_bits(AC3EncodeContext *s)
         if (s->use_frame_exp_strategy) {
             frame_bits += 5 * s->cpl_on;
         } else {
-            for (blk = 0; blk < AC3_MAX_BLOCKS; blk++)
+            for (blk = 0; blk < s->num_blocks; blk++)
                 frame_bits += 2 * s->blocks[blk].cpl_in_use;
         }
     } else {
@@ -1394,7 +1408,7 @@ static void count_frame_bits(AC3EncodeContext *s)
     }
 
     /* audio blocks */
-    for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) {
+    for (blk = 0; blk < s->num_blocks; blk++) {
         AC3Block *block = &s->blocks[blk];
 
         /* coupling strategy */
@@ -1497,7 +1511,7 @@ static void bit_alloc_masking(AC3EncodeContext *s)
 {
     int blk, ch;
 
-    for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) {
+    for (blk = 0; blk < s->num_blocks; blk++) {
         AC3Block *block = &s->blocks[blk];
         for (ch = !block->cpl_in_use; ch <= s->channels; ch++) {
             /* We only need psd and mask for calculating bap.
@@ -1529,7 +1543,7 @@ static void reset_block_bap(AC3EncodeContext *s)
     int channels = s->channels + 1;
     if (s->blocks[0].bap[0] == s->bap_buffer)
         return;
-    for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) {
+    for (blk = 0; blk < s->num_blocks; blk++) {
         for (ch = 0; ch < channels; ch++) {
             s->blocks[blk].bap[ch] = &s->bap_buffer[AC3_MAX_COEFS * (blk * channels + ch)];
         }
@@ -1554,7 +1568,7 @@ static int bit_alloc(AC3EncodeContext *s, int snr_offset)
 
     reset_block_bap(s);
     mantissa_bits = 0;
-    for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) {
+    for (blk = 0; blk < s->num_blocks; blk++) {
         AC3Block *block = &s->blocks[blk];
         AC3Block *ref_block;
         int av_uninit(ch0);
@@ -1655,7 +1669,7 @@ static int downgrade_exponents(AC3EncodeContext *s)
 {
     int ch, blk;
 
-    for (blk = AC3_MAX_BLOCKS-1; blk >= 0; blk--) {
+    for (blk = s->num_blocks-1; blk >= 0; blk--) {
         for (ch = !s->blocks[blk].cpl_in_use; ch <= s->fbw_channels; ch++) {
             if (s->exp_strategy[ch][blk] == EXP_D15) {
                 s->exp_strategy[ch][blk] = EXP_D25;
@@ -1663,7 +1677,7 @@ static int downgrade_exponents(AC3EncodeContext *s)
             }
         }
     }
-    for (blk = AC3_MAX_BLOCKS-1; blk >= 0; blk--) {
+    for (blk = s->num_blocks-1; blk >= 0; blk--) {
         for (ch = !s->blocks[blk].cpl_in_use; ch <= s->fbw_channels; ch++) {
             if (s->exp_strategy[ch][blk] == EXP_D25) {
                 s->exp_strategy[ch][blk] = EXP_D45;
@@ -1673,7 +1687,7 @@ static int downgrade_exponents(AC3EncodeContext *s)
     }
     /* block 0 cannot reuse exponents, so only downgrade D45 to REUSE if
        the block number > 0 */
-    for (blk = AC3_MAX_BLOCKS-1; blk > 0; blk--) {
+    for (blk = s->num_blocks-1; blk > 0; blk--) {
         for (ch = !s->blocks[blk].cpl_in_use; ch <= s->fbw_channels; ch++) {
             if (s->exp_strategy[ch][blk] > EXP_REUSE) {
                 s->exp_strategy[ch][blk] = EXP_REUSE;
@@ -1864,7 +1878,7 @@ static void quantize_mantissas(AC3EncodeContext *s)
 {
     int blk, ch, ch0=0, got_cpl;
 
-    for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) {
+    for (blk = 0; blk < s->num_blocks; blk++) {
         AC3Block *block = &s->blocks[blk];
         AC3Block *ref_block;
         AC3Mant m = { 0 };
@@ -1963,7 +1977,7 @@ static void eac3_output_frame_header(AC3EncodeContext *s)
         put_bits(&s->pb, 2, s->bit_alloc.sr_code);  /* sample rate code */
     } else {
         put_bits(&s->pb, 2, s->bit_alloc.sr_code);  /* sample rate code */
-        put_bits(&s->pb, 2, 0x3);                   /* number of blocks = 6 */
+        put_bits(&s->pb, 2, s->num_blks_code);      /* number of blocks */
     }
     put_bits(&s->pb, 3, s->channel_mode);           /* audio coding mode */
     put_bits(&s->pb, 1, s->lfe_on);                 /* LFE channel indicator */
@@ -1974,11 +1988,15 @@ static void eac3_output_frame_header(AC3EncodeContext *s)
     /* TODO: mixing metadata */
     put_bits(&s->pb, 1, 0);                         /* no info metadata */
     /* TODO: info metadata */
+    if (s->num_blks_code != 0x3)
+        put_bits(&s->pb, 1, !(s->avctx->frame_number % 6)); /* converter sync flag */
     put_bits(&s->pb, 1, 0);                         /* no additional bit stream info */
 
     /* frame header */
-    put_bits(&s->pb, 1, !s->use_frame_exp_strategy); /* exponent strategy syntax */
-    put_bits(&s->pb, 1, 0);                         /* aht enabled = no */
+    if (s->num_blks_code == 0x3) {
+        put_bits(&s->pb, 1, !s->use_frame_exp_strategy); /* exponent strategy syntax */
+        put_bits(&s->pb, 1, 0);                          /* aht enabled = no */
+    }
     put_bits(&s->pb, 2, 0);                         /* snr offset strategy = 1 */
     put_bits(&s->pb, 1, 0);                         /* transient pre-noise processing enabled = no */
     put_bits(&s->pb, 1, 0);                         /* block switch syntax enabled = no */
@@ -1991,7 +2009,7 @@ static void eac3_output_frame_header(AC3EncodeContext *s)
     /* coupling strategy use flags */
     if (s->channel_mode > AC3_CHMODE_MONO) {
         put_bits(&s->pb, 1, s->blocks[0].cpl_in_use);
-        for (blk = 1; blk < AC3_MAX_BLOCKS; blk++) {
+        for (blk = 1; blk < s->num_blocks; blk++) {
             AC3Block *block = &s->blocks[blk];
             put_bits(&s->pb, 1, block->new_cpl_strategy);
             if (block->new_cpl_strategy)
@@ -2003,26 +2021,31 @@ static void eac3_output_frame_header(AC3EncodeContext *s)
         for (ch = !s->cpl_on; ch <= s->fbw_channels; ch++)
             put_bits(&s->pb, 5, s->frame_exp_strategy[ch]);
     } else {
-        for (blk = 0; blk < AC3_MAX_BLOCKS; blk++)
+        for (blk = 0; blk < s->num_blocks; blk++)
             for (ch = !s->blocks[blk].cpl_in_use; ch <= s->fbw_channels; ch++)
                 put_bits(&s->pb, 2, s->exp_strategy[ch][blk]);
     }
     if (s->lfe_on) {
-        for (blk = 0; blk < AC3_MAX_BLOCKS; blk++)
+        for (blk = 0; blk < s->num_blocks; blk++)
             put_bits(&s->pb, 1, s->exp_strategy[s->lfe_channel][blk]);
     }
-    /* E-AC-3 to AC-3 converter exponent strategy (unfortunately not optional...) */
-    for (ch = 1; ch <= s->fbw_channels; ch++) {
-        if (s->use_frame_exp_strategy)
-            put_bits(&s->pb, 5, s->frame_exp_strategy[ch]);
-        else
-            put_bits(&s->pb, 5, 0);
+    /* E-AC-3 to AC-3 converter exponent strategy */
+    if (s->num_blks_code != 0x3) {
+        put_bits(&s->pb, 1, 0);
+    } else {
+        for (ch = 1; ch <= s->fbw_channels; ch++) {
+            if (s->use_frame_exp_strategy)
+                put_bits(&s->pb, 5, s->frame_exp_strategy[ch]);
+            else
+                put_bits(&s->pb, 5, 0);
+        }
     }
     /* snr offsets */
     put_bits(&s->pb, 6, s->coarse_snr_offset);
     put_bits(&s->pb, 4, s->fine_snr_offset[1]);
     /* block start info */
-    put_bits(&s->pb, 1, 0);
+    if (s->num_blks_code != 0x0)
+        put_bits(&s->pb, 1, 0);
 }
 
 
@@ -2316,7 +2339,7 @@ static void output_frame(AC3EncodeContext *s, unsigned char *frame)
     else
         ac3_output_frame_header(s);
 
-    for (blk = 0; blk < AC3_MAX_BLOCKS; blk++)
+    for (blk = 0; blk < s->num_blocks; blk++)
         output_audio_block(s, blk);
 
     output_frame_end(s);
@@ -2658,7 +2681,7 @@ static av_cold int ac3_encode_close(AVCodecContext *avctx)
     av_freep(&s->band_psd_buffer);
     av_freep(&s->mask_buffer);
     av_freep(&s->qmant_buffer);
-    for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) {
+    for (blk = 0; blk < s->num_blocks; blk++) {
         AC3Block *block = &s->blocks[blk];
         av_freep(&block->bap);
         av_freep(&block->mdct_coef);
@@ -2763,18 +2786,30 @@ static av_cold int validate_options(AVCodecContext *avctx, AC3EncodeContext *s)
     /* validate bit rate */
     if (s->eac3) {
         int max_br, min_br, wpf, min_br_dist, min_br_code;
+        int num_blks_code, num_blocks, frame_samples;
 
         /* calculate min/max bitrate */
-        max_br = 2048 * s->sample_rate / AC3_FRAME_SIZE * 16;
-        min_br = ((s->sample_rate + (AC3_FRAME_SIZE-1)) / AC3_FRAME_SIZE) * 16;
+        /* TODO: More tests with 3 and 2 blocks. All E-AC-3 samples I've found
+                 use either 6 blocks or 1 block, even though 2 or 3 blocks
+                 would work as far as the bit rate is concerned. */
+        for (num_blks_code = 3; num_blks_code >= 0; num_blks_code--) {
+            num_blocks = ff_eac3_num_blocks_tab[num_blks_code];
+            frame_samples  = AC3_BLOCK_SIZE * num_blocks;
+            max_br = 2048 * s->sample_rate / frame_samples * 16;
+            min_br = ((s->sample_rate + (frame_samples-1)) / frame_samples) * 16;
+            if (avctx->bit_rate <= max_br)
+                break;
+        }
         if (avctx->bit_rate < min_br || avctx->bit_rate > max_br) {
             av_log(avctx, AV_LOG_ERROR, "invalid bit rate. must be %d to %d "
                    "for this sample rate\n", min_br, max_br);
             return AVERROR(EINVAL);
         }
+        s->num_blks_code = num_blks_code;
+        s->num_blocks    = num_blocks;
 
         /* calculate words-per-frame for the selected bitrate */
-        wpf = (avctx->bit_rate / 16) * AC3_FRAME_SIZE / s->sample_rate;
+        wpf = (avctx->bit_rate / 16) * frame_samples / s->sample_rate;
         av_assert1(wpf > 0 && wpf <= 2048);
 
         /* find the closest AC-3 bitrate code to the selected bitrate.
@@ -2792,7 +2827,7 @@ static av_cold int validate_options(AVCodecContext *avctx, AC3EncodeContext *s)
 
         /* make sure the minimum frame size is below the average frame size */
         s->frame_size_code = min_br_code << 1;
-        while (wpf > 1 && wpf * s->sample_rate / AC3_FRAME_SIZE * 16 > avctx->bit_rate)
+        while (wpf > 1 && wpf * s->sample_rate / frame_samples * 16 > avctx->bit_rate)
             wpf--;
         s->frame_size_min = 2 * wpf;
     } else {
@@ -2806,6 +2841,8 @@ static av_cold int validate_options(AVCodecContext *avctx, AC3EncodeContext *s)
         }
         s->frame_size_code = i << 1;
         s->frame_size_min  = 2 * ff_ac3_frame_size_tab[s->frame_size_code][s->bit_alloc.sr_code];
+        s->num_blks_code   = 0x3;
+        s->num_blocks      = 6;
     }
     s->bit_rate   = avctx->bit_rate;
     s->frame_size = s->frame_size_min;
@@ -2871,13 +2908,13 @@ static av_cold void set_bandwidth(AC3EncodeContext *s)
     /* set number of coefficients for each channel */
     for (ch = 1; ch <= s->fbw_channels; ch++) {
         s->start_freq[ch] = 0;
-        for (blk = 0; blk < AC3_MAX_BLOCKS; blk++)
+        for (blk = 0; blk < s->num_blocks; blk++)
             s->blocks[blk].end_freq[ch] = s->bandwidth_code * 3 + 73;
     }
     /* LFE channel always has 7 coefs */
     if (s->lfe_on) {
         s->start_freq[s->lfe_channel] = 0;
-        for (blk = 0; blk < AC3_MAX_BLOCKS; blk++)
+        for (blk = 0; blk < s->num_blocks; blk++)
             s->blocks[blk].end_freq[ch] = 7;
     }
 
@@ -2914,7 +2951,7 @@ static av_cold void set_bandwidth(AC3EncodeContext *s)
 
         s->start_freq[CPL_CH] = cpl_start_band * 12 + 37;
         s->cpl_end_freq       = cpl_end_band   * 12 + 37;
-        for (blk = 0; blk < AC3_MAX_BLOCKS; blk++)
+        for (blk = 0; blk < s->num_blocks; blk++)
             s->blocks[blk].end_freq[CPL_CH] = s->cpl_end_freq;
     }
 }
@@ -2930,34 +2967,34 @@ static av_cold int allocate_buffers(AVCodecContext *avctx)
                      alloc_fail);
     for (ch = 0; ch < s->channels; ch++) {
         FF_ALLOCZ_OR_GOTO(avctx, s->planar_samples[ch],
-                          (AC3_FRAME_SIZE+AC3_BLOCK_SIZE) * sizeof(**s->planar_samples),
-                          alloc_fail);
+                          (AC3_BLOCK_SIZE * s->num_blocks + AC3_BLOCK_SIZE) *
+                          sizeof(**s->planar_samples), alloc_fail);
     }
-    FF_ALLOC_OR_GOTO(avctx, s->bap_buffer,  AC3_MAX_BLOCKS * channels *
+    FF_ALLOC_OR_GOTO(avctx, s->bap_buffer,  s->num_blocks * channels *
                      AC3_MAX_COEFS * sizeof(*s->bap_buffer),  alloc_fail);
-    FF_ALLOC_OR_GOTO(avctx, s->bap1_buffer, AC3_MAX_BLOCKS * channels *
+    FF_ALLOC_OR_GOTO(avctx, s->bap1_buffer, s->num_blocks * channels *
                      AC3_MAX_COEFS * sizeof(*s->bap1_buffer), alloc_fail);
-    FF_ALLOCZ_OR_GOTO(avctx, s->mdct_coef_buffer, AC3_MAX_BLOCKS * channels *
+    FF_ALLOCZ_OR_GOTO(avctx, s->mdct_coef_buffer, s->num_blocks * channels *
                       AC3_MAX_COEFS * sizeof(*s->mdct_coef_buffer), alloc_fail);
-    FF_ALLOC_OR_GOTO(avctx, s->exp_buffer, AC3_MAX_BLOCKS * channels *
+    FF_ALLOC_OR_GOTO(avctx, s->exp_buffer, s->num_blocks * channels *
                      AC3_MAX_COEFS * sizeof(*s->exp_buffer), alloc_fail);
-    FF_ALLOC_OR_GOTO(avctx, s->grouped_exp_buffer, AC3_MAX_BLOCKS * channels *
+    FF_ALLOC_OR_GOTO(avctx, s->grouped_exp_buffer, s->num_blocks * channels *
                      128 * sizeof(*s->grouped_exp_buffer), alloc_fail);
-    FF_ALLOC_OR_GOTO(avctx, s->psd_buffer, AC3_MAX_BLOCKS * channels *
+    FF_ALLOC_OR_GOTO(avctx, s->psd_buffer, s->num_blocks * channels *
                      AC3_MAX_COEFS * sizeof(*s->psd_buffer), alloc_fail);
-    FF_ALLOC_OR_GOTO(avctx, s->band_psd_buffer, AC3_MAX_BLOCKS * channels *
+    FF_ALLOC_OR_GOTO(avctx, s->band_psd_buffer, s->num_blocks * channels *
                      64 * sizeof(*s->band_psd_buffer), alloc_fail);
-    FF_ALLOC_OR_GOTO(avctx, s->mask_buffer, AC3_MAX_BLOCKS * channels *
+    FF_ALLOC_OR_GOTO(avctx, s->mask_buffer, s->num_blocks * channels *
                      64 * sizeof(*s->mask_buffer), alloc_fail);
-    FF_ALLOC_OR_GOTO(avctx, s->qmant_buffer, AC3_MAX_BLOCKS * channels *
+    FF_ALLOC_OR_GOTO(avctx, s->qmant_buffer, s->num_blocks * channels *
                      AC3_MAX_COEFS * sizeof(*s->qmant_buffer), alloc_fail);
     if (s->cpl_enabled) {
-        FF_ALLOC_OR_GOTO(avctx, s->cpl_coord_exp_buffer, AC3_MAX_BLOCKS * channels *
+        FF_ALLOC_OR_GOTO(avctx, s->cpl_coord_exp_buffer, s->num_blocks * channels *
                          16 * sizeof(*s->cpl_coord_exp_buffer), alloc_fail);
-        FF_ALLOC_OR_GOTO(avctx, s->cpl_coord_mant_buffer, AC3_MAX_BLOCKS * channels *
+        FF_ALLOC_OR_GOTO(avctx, s->cpl_coord_mant_buffer, s->num_blocks * channels *
                          16 * sizeof(*s->cpl_coord_mant_buffer), alloc_fail);
     }
-    for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) {
+    for (blk = 0; blk < s->num_blocks; blk++) {
         AC3Block *block = &s->blocks[blk];
         FF_ALLOC_OR_GOTO(avctx, block->bap, channels * sizeof(*block->bap),
                          alloc_fail);
@@ -2996,23 +3033,23 @@ static av_cold int allocate_buffers(AVCodecContext *avctx)
             }
 
             /* arrangement: channel, block, coeff */
-            block->exp[ch]         = &s->exp_buffer        [AC3_MAX_COEFS * (AC3_MAX_BLOCKS * ch + blk)];
-            block->mdct_coef[ch]   = &s->mdct_coef_buffer  [AC3_MAX_COEFS * (AC3_MAX_BLOCKS * ch + blk)];
+            block->exp[ch]         = &s->exp_buffer        [AC3_MAX_COEFS * (s->num_blocks * ch + blk)];
+            block->mdct_coef[ch]   = &s->mdct_coef_buffer  [AC3_MAX_COEFS * (s->num_blocks * ch + blk)];
         }
     }
 
     if (CONFIG_AC3ENC_FLOAT) {
-        FF_ALLOCZ_OR_GOTO(avctx, s->fixed_coef_buffer, AC3_MAX_BLOCKS * channels *
+        FF_ALLOCZ_OR_GOTO(avctx, s->fixed_coef_buffer, s->num_blocks * channels *
                           AC3_MAX_COEFS * sizeof(*s->fixed_coef_buffer), alloc_fail);
-        for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) {
+        for (blk = 0; blk < s->num_blocks; blk++) {
             AC3Block *block = &s->blocks[blk];
             FF_ALLOCZ_OR_GOTO(avctx, block->fixed_coef, channels *
                               sizeof(*block->fixed_coef), alloc_fail);
             for (ch = 0; ch < channels; ch++)
-                block->fixed_coef[ch] = &s->fixed_coef_buffer[AC3_MAX_COEFS * (AC3_MAX_BLOCKS * ch + blk)];
+                block->fixed_coef[ch] = &s->fixed_coef_buffer[AC3_MAX_COEFS * (s->num_blocks * ch + blk)];
         }
     } else {
-        for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) {
+        for (blk = 0; blk < s->num_blocks; blk++) {
             AC3Block *block = &s->blocks[blk];
             FF_ALLOCZ_OR_GOTO(avctx, block->fixed_coef, channels *
                               sizeof(*block->fixed_coef), alloc_fail);
@@ -3035,16 +3072,17 @@ static av_cold int ac3_encode_init(AVCodecContext *avctx)
     AC3EncodeContext *s = avctx->priv_data;
     int ret, frame_size_58;
 
+    s->avctx = avctx;
     s->eac3 = avctx->codec_id == CODEC_ID_EAC3;
 
-    avctx->frame_size = AC3_FRAME_SIZE;
-
     ff_ac3_common_init();
 
     ret = validate_options(avctx, s);
     if (ret)
         return ret;
 
+    avctx->frame_size = AC3_BLOCK_SIZE * s->num_blocks;
+
     s->bitstream_mode = avctx->audio_service_type;
     if (s->bitstream_mode == AV_AUDIO_SERVICE_TYPE_KARAOKE)
         s->bitstream_mode = 0x7;
diff --git a/libavcodec/ac3enc_float.c b/libavcodec/ac3enc_float.c
index 012c31d..09c452b 100644
--- a/libavcodec/ac3enc_float.c
+++ b/libavcodec/ac3enc_float.c
@@ -93,7 +93,7 @@ static int normalize_samples(AC3EncodeContext *s)
  */
 static void scale_coefficients(AC3EncodeContext *s)
 {
-    int chan_size = AC3_MAX_COEFS * AC3_MAX_BLOCKS;
+    int chan_size = AC3_MAX_COEFS * s->num_blocks;
     s->ac3dsp.float_to_fixed24(s->fixed_coef_buffer + chan_size,
                                s->mdct_coef_buffer  + chan_size,
                                chan_size * s->channels);
diff --git a/libavcodec/ac3tab.c b/libavcodec/ac3tab.c
index 327f953..0ab0604 100644
--- a/libavcodec/ac3tab.c
+++ b/libavcodec/ac3tab.c
@@ -133,6 +133,11 @@ const uint16_t ff_ac3_bitrate_tab[19] = {
 };
 
 /**
+ * Table E2.9 Number of Audio Blocks Per Syncframe
+ */
+const uint8_t ff_eac3_num_blocks_tab[4] = { 1, 2, 3, 6 };
+
+/**
  * Table of bin locations for rematrixing bands
  * reference: Section 7.5.2 Rematrixing : Frequency Band Definitions
  */
diff --git a/libavcodec/ac3tab.h b/libavcodec/ac3tab.h
index 35ee5a8..27711be 100644
--- a/libavcodec/ac3tab.h
+++ b/libavcodec/ac3tab.h
@@ -38,6 +38,7 @@ extern const uint8_t  ff_ac3_enc_channel_map[8][2][6];
 extern const uint8_t  ff_ac3_dec_channel_map[8][2][6];
 extern const uint16_t ff_ac3_sample_rate_tab[3];
 extern const uint16_t ff_ac3_bitrate_tab[19];
+extern const uint8_t  ff_eac3_num_blocks_tab[4];
 extern const uint8_t  ff_ac3_rematrix_band_tab[5];
 extern const uint8_t  ff_eac3_default_cpl_band_struct[18];
 extern const int16_t  ff_ac3_window[AC3_WINDOW_SIZE/2];
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to