Skip to content
Snippets Groups Projects
Commit 6b45974f authored by Jean-Marc Valin's avatar Jean-Marc Valin
Browse files

Reduces rate/max rate to make room for redundancy

This fixes a problem where we could end up starving the redundancy
frame, especially for CBR. The solution is to make sure that some
bits are left available -- assuming we use the same rate for redundancy
as for the rest of the frame.
parent ff16ab09
No related branches found
No related tags found
No related merge requests found
...@@ -80,6 +80,8 @@ opus_int silk_control_audio_bandwidth( ...@@ -80,6 +80,8 @@ opus_int silk_control_audio_bandwidth(
} else { } else {
if( psEncC->sLP.transition_frame_no <= 0 ) { if( psEncC->sLP.transition_frame_no <= 0 ) {
encControl->switchReady = 1; encControl->switchReady = 1;
/* Make room for redundancy */
encControl->maxBits -= encControl->maxBits * 5 / ( encControl->payloadSize_ms + 5 );
} else { } else {
/* Direction: down (at double speed) */ /* Direction: down (at double speed) */
psEncC->sLP.mode = -2; psEncC->sLP.mode = -2;
...@@ -106,6 +108,8 @@ opus_int silk_control_audio_bandwidth( ...@@ -106,6 +108,8 @@ opus_int silk_control_audio_bandwidth(
} else { } else {
if( psEncC->sLP.mode == 0 ) { if( psEncC->sLP.mode == 0 ) {
encControl->switchReady = 1; encControl->switchReady = 1;
/* Make room for redundancy */
encControl->maxBits -= encControl->maxBits * 5 / ( encControl->payloadSize_ms + 5 );
} else { } else {
/* Direction: up */ /* Direction: up */
psEncC->sLP.mode = 1; psEncC->sLP.mode = 1;
......
...@@ -458,20 +458,20 @@ opus_int32 opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_s ...@@ -458,20 +458,20 @@ opus_int32 opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_s
int prefill=0; int prefill=0;
int start_band = 0; int start_band = 0;
int redundancy = 0; int redundancy = 0;
int redundancy_bytes = 0; int redundancy_bytes = 0; /* Number of bytes to use for redundancy frame */
int celt_to_silk = 0; int celt_to_silk = 0;
VARDECL(opus_val16, pcm_buf); VARDECL(opus_val16, pcm_buf);
int nb_compr_bytes; int nb_compr_bytes;
int to_celt = 0; int to_celt = 0;
opus_uint32 redundant_rng = 0; opus_uint32 redundant_rng = 0;
int cutoff_Hz, hp_freq_smth1; int cutoff_Hz, hp_freq_smth1;
int voice_est; int voice_est; /* Probability of voice in Q7 */
opus_int32 equiv_rate; opus_int32 equiv_rate;
int delay_compensation; int delay_compensation;
int frame_rate; int frame_rate;
opus_int32 max_rate; opus_int32 max_rate; /* Max bitrate we're allowed to use */
int curr_bandwidth; int curr_bandwidth;
opus_int32 max_data_bytes; opus_int32 max_data_bytes; /* Max number of bytes we're allowed to use */
VARDECL(opus_val16, tmp_prefill); VARDECL(opus_val16, tmp_prefill);
ALLOC_STACK; ALLOC_STACK;
...@@ -652,6 +652,7 @@ opus_int32 opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_s ...@@ -652,6 +652,7 @@ opus_int32 opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_s
} }
} }
} }
/* For the first frame at a new SILK bandwidth */
if (st->silk_bw_switch) if (st->silk_bw_switch)
{ {
redundancy = 1; redundancy = 1;
...@@ -659,6 +660,15 @@ opus_int32 opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_s ...@@ -659,6 +660,15 @@ opus_int32 opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_s
st->silk_bw_switch = 0; st->silk_bw_switch = 0;
} }
if (redundancy)
{
/* Fair share of the max size allowed */
redundancy_bytes = IMIN(257, max_data_bytes*(opus_int32)(st->Fs/200)/(frame_size+st->Fs/200));
/* For VBR, target the actual bitrate (subject to the limit above) */
if (st->use_vbr)
redundancy_bytes = IMIN(redundancy_bytes, st->bitrate_bps/1600);
}
if (st->mode != MODE_CELT_ONLY && st->prev_mode == MODE_CELT_ONLY) if (st->mode != MODE_CELT_ONLY && st->prev_mode == MODE_CELT_ONLY)
{ {
silk_EncControlStruct dummy; silk_EncControlStruct dummy;
...@@ -823,7 +833,7 @@ opus_int32 opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_s ...@@ -823,7 +833,7 @@ opus_int32 opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_s
st->mode = MODE_SILK_ONLY; st->mode = MODE_SILK_ONLY;
/* printf("%d %d %d %d\n", st->bitrate_bps, st->stream_channels, st->mode, curr_bandwidth); */ /* printf("%d %d %d %d\n", st->bitrate_bps, st->stream_channels, st->mode, curr_bandwidth); */
bytes_target = IMIN(max_data_bytes, st->bitrate_bps * frame_size / (st->Fs * 8)) - 1; bytes_target = IMIN(max_data_bytes-redundancy_bytes, st->bitrate_bps * frame_size / (st->Fs * 8)) - 1;
data += 1; data += 1;
...@@ -929,7 +939,7 @@ opus_int32 opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_s ...@@ -929,7 +939,7 @@ opus_int32 opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_s
st->silk_mode.useCBR = !st->use_vbr; st->silk_mode.useCBR = !st->use_vbr;
/* Call SILK encoder for the low band */ /* Call SILK encoder for the low band */
nBytes = IMIN(1275, max_data_bytes-1); nBytes = IMIN(1275, max_data_bytes-1-redundancy_bytes);
st->silk_mode.maxBits = nBytes*8; st->silk_mode.maxBits = nBytes*8;
/* Only allow up to 90% of the bits for hybrid mode*/ /* Only allow up to 90% of the bits for hybrid mode*/
...@@ -941,8 +951,6 @@ opus_int32 opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_s ...@@ -941,8 +951,6 @@ opus_int32 opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_s
/* Reduce the initial target to make it easier to reach the CBR rate */ /* Reduce the initial target to make it easier to reach the CBR rate */
st->silk_mode.bitRate = IMAX(1, st->silk_mode.bitRate-2000); st->silk_mode.bitRate = IMAX(1, st->silk_mode.bitRate-2000);
} }
if (redundancy)
st->silk_mode.maxBits -= st->silk_mode.maxBits/(1 + frame_size/(st->Fs/200));
if (prefill) if (prefill)
{ {
...@@ -990,6 +998,7 @@ opus_int32 opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_s ...@@ -990,6 +998,7 @@ opus_int32 opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_s
} }
st->silk_mode.opusCanSwitch = st->silk_mode.switchReady; st->silk_mode.opusCanSwitch = st->silk_mode.switchReady;
/* FIXME: How do we allocate the redundancy for CBR? */
if (st->silk_mode.opusCanSwitch) if (st->silk_mode.opusCanSwitch)
{ {
redundancy = 1; redundancy = 1;
...@@ -1047,7 +1056,7 @@ opus_int32 opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_s ...@@ -1047,7 +1056,7 @@ opus_int32 opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_s
celt_encoder_ctl(celt_enc, OPUS_SET_VBR(1)); celt_encoder_ctl(celt_enc, OPUS_SET_VBR(1));
celt_encoder_ctl(celt_enc, OPUS_SET_VBR_CONSTRAINT(st->vbr_constraint)); celt_encoder_ctl(celt_enc, OPUS_SET_VBR_CONSTRAINT(st->vbr_constraint));
celt_encoder_ctl(celt_enc, OPUS_SET_BITRATE(st->bitrate_bps)); celt_encoder_ctl(celt_enc, OPUS_SET_BITRATE(st->bitrate_bps));
nb_compr_bytes = max_data_bytes-1; nb_compr_bytes = max_data_bytes-1-redundancy_bytes;
} else { } else {
nb_compr_bytes = bytes_target; nb_compr_bytes = bytes_target;
} }
...@@ -1119,8 +1128,10 @@ opus_int32 opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_s ...@@ -1119,8 +1128,10 @@ opus_int32 opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_s
} }
if (!redundancy) if (!redundancy)
{
st->silk_bw_switch = 0; st->silk_bw_switch = 0;
redundancy_bytes = 0;
}
if (st->mode != MODE_CELT_ONLY)start_band=17; if (st->mode != MODE_CELT_ONLY)start_band=17;
if (st->mode == MODE_SILK_ONLY) if (st->mode == MODE_SILK_ONLY)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment