shithub: opus

Download patch

ref: fac6c98ce15f4ad68edb7c20bf61652bc6bb4364
parent: a9411472cd82b466dc786d71a10120e919f4d8c6
author: Gregory Maxwell <[email protected]>
date: Thu Oct 28 11:00:37 EDT 2010

Fix crashes with VBR for short duration frames and very low bitrates. This may, however, cause the encoder to violate the rate target at insanely low rates.

This also generally improves VBR behavior by more carefully accounting
for rounding.

--- a/libcelt/celt.c
+++ b/libcelt/celt.c
@@ -132,7 +132,7 @@
    st->end = st->mode->effEBands;
 
    st->vbr_rate_norm = 0;
-   st->vbr_offset = -140<<BITRES;
+   st->vbr_offset = -(64<<BITRES);
    st->force_intra  = 0;
    st->delayedIntra = 1;
    st->tonal_average = 256;
@@ -800,18 +800,9 @@
      celt_int32 target;
      celt_int32 vbr_bound, max_allowed;
 
-     vbr_rate = M*st->vbr_rate_norm;
+     target = vbr_rate = M*st->vbr_rate_norm;
 
-     /* Computes the max bit-rate allowed in VBR more to avoid busting the budget */
-     vbr_bound = vbr_rate;
-     max_allowed = (vbr_rate + vbr_bound - st->vbr_reservoir)>>(BITRES+3);
-     if (max_allowed < 4)
-        max_allowed = 4;
-     if (max_allowed < nbAvailableBytes)
-        nbAvailableBytes = max_allowed;
-     target=vbr_rate;
-
-     /* Shortblocks get a large boost in bitrate, but since they 
+     /* Shortblocks get a large boost in bitrate, but since they
         are uncommon long blocks are not greatly affected */
      if (shortBlocks || tf_sum < -2*(st->end-st->start))
         target*=2;
@@ -824,8 +815,15 @@
         so far is added*/
      target=target+st->vbr_offset+ec_enc_tell(enc, BITRES);
 
-     /* In VBR mode the frame size must not be reduced so much that it would result in the coarse energy busting its budget */
-     target=IMIN(nbAvailableBytes<<(BITRES+3),target);
+     /* Computes the max bit-rate allowed in VBR more to avoid violating the target rate and buffering */
+     vbr_bound = vbr_rate;
+     max_allowed = IMIN(vbr_rate+vbr_bound-st->vbr_reservoir>>(BITRES+3),nbAvailableBytes);
+
+     /* In VBR mode the frame size must not be reduced so much that it would result in the encoder running out of bits */
+     nbAvailableBytes = target+(1<<(BITRES+2))>>(BITRES+3);
+     nbAvailableBytes=IMAX(16,IMIN(max_allowed,nbAvailableBytes));
+     target=nbAvailableBytes<<(BITRES+3);
+
      if (st->vbr_count < 970)
      {
         st->vbr_count++;
@@ -832,7 +830,6 @@
         alpha = celt_rcp(SHL32(EXTEND32(st->vbr_count+20),16));
      } else
         alpha = QCONST16(.001f,15);
-
      /* By how much did we "miss" the target on that frame */
      delta = (celt_int32)target - vbr_rate;
      /* How many bits have we used in excess of what we're allowed */
@@ -848,14 +845,12 @@
      if (st->vbr_reservoir < 0)
      {
         /* We're under the min value -- increase rate */
-        int adjust = 1-(st->vbr_reservoir-1)/(8<<BITRES);
-        st->vbr_reservoir += adjust*(8<<BITRES);
-        target += adjust;
+        int adjust = (-st->vbr_reservoir)/(8<<BITRES);
+        nbAvailableBytes += adjust;
+        st->vbr_reservoir = 0;
         /*printf ("+%d\n", adjust);*/
      }
-     if (nbAvailableBytes > target>>(BITRES+3))
-        nbAvailableBytes = target>>(BITRES+3);
-     nbCompressedBytes = nbAvailableBytes + nbFilledBytes;
+     nbCompressedBytes = IMIN(nbCompressedBytes,nbAvailableBytes+nbFilledBytes);
 
      /* This moves the raw bits to take into account the new compressed size */
      ec_byte_shrink(&buf, nbCompressedBytes);
@@ -1110,6 +1105,7 @@
          CELT_MEMSET((char*)&st->ENCODER_RESET_START, 0,
                celt_encoder_get_size(st->mode, st->channels)-
                ((char*)&st->ENCODER_RESET_START - (char*)st));
+         st->vbr_offset = -(64<<BITRES);
          st->delayedIntra = 1;
          st->fold_decision = 1;
          st->tonal_average = QCONST16(1.f,8);