When bit allocation fails more drastic steps can be taken to reduce the 
bitrate. For now, downgrade exponents first, then reduce bandwidth. This may 
change later as bandwidth and exponent handling becomes more advanced.
---
 libavcodec/ac3enc.c |   73 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 71 insertions(+), 2 deletions(-)

diff --git libavcodec/ac3enc.c libavcodec/ac3enc.c
index 1652e0e..bc9a28c 100644
--- libavcodec/ac3enc.c
+++ libavcodec/ac3enc.c
@@ -1296,6 +1296,59 @@ static void adjust_frame_size(AC3EncodeContext *s)
     s->frame_size       = s->frame_size_min + (s->bits_written * s->sample_rate < s->samples_written * s->bit_rate);
 }
 
+/**
+ * Downgrade exponent strategies to reduce the bits used by the exponents.
+ * This is a fallback for when bit allocation fails with the normal exponent
+ * strategies.  Each time this function is run it only downgrades the
+ * strategy in 1 channel of 1 block.
+ * @return non-zero if downgrade was successful
+ */
+static int downgrade_exponents(AC3EncodeContext *s,
+                               uint8_t exp_strategy[AC3_MAX_BLOCKS][AC3_MAX_CHANNELS])
+{
+    int ch, blk;
+
+    for (ch = 0; ch < s->channels; ch++) {
+        for (blk = AC3_MAX_BLOCKS-1; blk >= 0; blk--) {
+            if (exp_strategy[blk][ch] == EXP_D15) {
+                exp_strategy[blk][ch] = EXP_D25;
+                return 1;
+            }
+            if (exp_strategy[blk][ch] == EXP_D25) {
+                exp_strategy[blk][ch] = EXP_D45;
+                return 1;
+            }
+            /* block 0 cannot reuse exponents, so only downgrade D45 to REUSE
+               if the block number > 0 */
+            if (exp_strategy[blk][ch] == EXP_D45 && blk) {
+                exp_strategy[blk][ch] = EXP_REUSE;
+                return 1;
+            }
+        }
+    }
+    return 0;
+}
+
+/**
+ * Reduce the bandwidth to reduce the number of bits used for a given SNR offset.
+ * This is a second fallback for when bit allocation still fails after exponents
+ * have been downgraded.
+ * @return non-zero if bitrate reduction was successful
+ */
+static int reduce_bandwidth(AC3EncodeContext *s, int min_bw_code)
+{
+    int ch;
+
+    if (s->bandwidth_code[0] > min_bw_code) {
+        for (ch = 0; ch < s->fbw_channels; ch++) {
+            s->bandwidth_code[ch]--;
+            s->nb_coefs[ch] = s->bandwidth_code[ch] * 3 + 73;
+        }
+        return 1;
+    }
+    return 0;
+}
+
 static int AC3_encode_frame(AVCodecContext *avctx,
                             unsigned char *frame, int buf_size, void *data)
 {
@@ -1306,7 +1359,7 @@ static int AC3_encode_frame(AVCodecContext *avctx,
     uint8_t exp_strategy[AC3_MAX_BLOCKS][AC3_MAX_CHANNELS];
     uint8_t bap[AC3_MAX_BLOCKS][AC3_MAX_CHANNELS][AC3_MAX_COEFS];
     int8_t exp_shift[AC3_MAX_BLOCKS][AC3_MAX_CHANNELS];
-    int frame_bits, frame_size;
+    int frame_bits, frame_size, err;
 
     adjust_frame_size(s);
 
@@ -1316,7 +1369,23 @@ static int AC3_encode_frame(AVCodecContext *avctx,
 
     process_exponents(s, mdct_coef, exp, exp_strategy, exp_shift, &frame_bits);
 
-    if (compute_bit_allocation(s, bap, exp, exp_strategy, frame_bits)) {
+    err = compute_bit_allocation(s, bap, exp, exp_strategy, frame_bits);
+    while (err) {
+        /* fallback 1: downgrade exponents */
+        if (downgrade_exponents(s, exp_strategy)) {
+            calculate_exponents(s, mdct_coef, exp, exp_shift);
+            encode_exponents(s, exp, exp_strategy, &frame_bits);
+            err = compute_bit_allocation(s, bap, exp, exp_strategy, frame_bits);
+            continue;
+        }
+
+        /* fallback 2: reduce bandwidth code down to 0 */
+        if (reduce_bandwidth(s, 0)) {
+            process_exponents(s, mdct_coef, exp, exp_strategy, exp_shift, &frame_bits);
+            err = compute_bit_allocation(s, bap, exp, exp_strategy, frame_bits);
+            continue;
+        }
+
         av_log(avctx, AV_LOG_ERROR, "Bit allocation failed. Try increasing the bitrate.\n");
         return AVERROR(EINVAL);
     }
_______________________________________________
FFmpeg-soc mailing list
[email protected]
https://lists.mplayerhq.hu/mailman/listinfo/ffmpeg-soc

Reply via email to