Skip to content

Commit

Permalink
Reduce redundancy when SILK uses too many bits
Browse files Browse the repository at this point in the history
Fix Hybrid redundancy assertion failure in ec_enc_shrink(), even
if SILK produces more than maxBits, by reducing or eliminating
redundancy when necessary.  Don't reserve space for redundancy that
is too small to be used for redundancy.  When there is not enough
space for redundancy, allow the regular frame to use all the bits.
  • Loading branch information
mark4o committed Nov 2, 2016
1 parent 1fd53f9 commit 20bf3b3
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 24 deletions.
36 changes: 12 additions & 24 deletions src/opus_encoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -1961,7 +1961,6 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
st->silk_mode.bitRate += 3*rate_offset/5;
else
st->silk_mode.bitRate += rate_offset;
bytes_target += rate_offset * frame_size / (8 * st->Fs);
}

st->silk_mode.payloadSize_ms = 1000 * frame_size / st->Fs;
Expand Down Expand Up @@ -2005,11 +2004,11 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
/* Call SILK encoder for the low band */

/* Max bits for SILK, counting ToC, redundancy bytes, and optionally redundancy. */
st->silk_mode.maxBits = IMIN(1275, max_data_bytes-1-redundancy_bytes)*8;
if (redundancy)
st->silk_mode.maxBits = (max_data_bytes-1)*8;
if (redundancy && redundancy_bytes >= 2)
{
/* Counting 1 bit for redundancy position and 20 bits for flag+size (only for hybrid). */
st->silk_mode.maxBits -= 1;
st->silk_mode.maxBits -= redundancy_bytes*8 + 1;
if (st->mode == MODE_HYBRID)
st->silk_mode.maxBits -= 20;
}
Expand Down Expand Up @@ -2134,18 +2133,9 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_

if (st->mode == MODE_HYBRID)
{
int len;

len = (ec_tell(&enc)+7)>>3;
if (redundancy)
len += st->mode == MODE_HYBRID ? 3 : 1;
if( st->use_vbr ) {
celt_encoder_ctl(celt_enc, OPUS_SET_BITRATE(st->bitrate_bps-st->silk_mode.bitRate));
nb_compr_bytes = max_data_bytes-1-redundancy_bytes;
celt_encoder_ctl(celt_enc, OPUS_SET_VBR_CONSTRAINT(0));
} else {
/* check if SILK used up too much */
nb_compr_bytes = len > bytes_target ? len : bytes_target;
}
} else {
if (st->use_vbr)
Expand All @@ -2162,14 +2152,8 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
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_BITRATE(st->bitrate_bps+bonus));
nb_compr_bytes = max_data_bytes-1-redundancy_bytes;
} else {
nb_compr_bytes = bytes_target;
}
}

} else {
nb_compr_bytes = 0;
}

ALLOC(tmp_prefill, st->channels*st->Fs/400, opus_val16);
Expand Down Expand Up @@ -2218,14 +2202,19 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
if ( st->mode != MODE_CELT_ONLY && ec_tell(&enc)+17+20*(st->mode == MODE_HYBRID) <= 8*(max_data_bytes-1))
{
/* For SILK mode, the redundancy is inferred from the length */
if (st->mode == MODE_HYBRID && (redundancy || ec_tell(&enc)+37 <= 8*nb_compr_bytes))
if (st->mode == MODE_HYBRID)
ec_enc_bit_logp(&enc, redundancy, 12);
if (redundancy)
{
int max_redundancy;
ec_enc_bit_logp(&enc, celt_to_silk, 1);
if (st->mode == MODE_HYBRID)
max_redundancy = (max_data_bytes-1)-nb_compr_bytes;
{
/* Reserve the 8 bits needed for the redundancy length,
and at least a few bits for CELT if possible */
max_redundancy = (max_data_bytes-1)-((ec_tell(&enc)+8+3+7)>>3);
max_redundancy = IMIN(max_redundancy, redundancy_bytes);
}
else
max_redundancy = (max_data_bytes-1)-((ec_tell(&enc)+7)>>3);
/* Target the same bit-rate for redundancy as for the rest,
Expand All @@ -2252,7 +2241,7 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
ec_enc_done(&enc);
nb_compr_bytes = ret;
} else {
nb_compr_bytes = IMIN((max_data_bytes-1)-redundancy_bytes, nb_compr_bytes);
nb_compr_bytes = (max_data_bytes-1)-redundancy_bytes;
ec_enc_shrink(&enc, nb_compr_bytes);
}

Expand Down Expand Up @@ -2299,7 +2288,7 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
celt_encode_with_ec(celt_enc, tmp_prefill, st->Fs/400, dummy, 2, NULL);
celt_encoder_ctl(celt_enc, CELT_SET_PREDICTION(0));
}
/* If false, we already busted the budget and we'll end up with a "PLC packet" */
/* If false, we already busted the budget and we'll end up with a "PLC frame" */
if (ec_tell(&enc) <= 8*nb_compr_bytes)
{
/* Set the bitrate again if it was overridden in the redundancy code above*/
Expand Down Expand Up @@ -2413,7 +2402,6 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
if (!st->use_vbr)
{
if (opus_packet_pad(data, ret, max_data_bytes) != OPUS_OK)

{
RESTORE_STACK;
return OPUS_INTERNAL_ERROR;
Expand Down
33 changes: 33 additions & 0 deletions tests/opus_encode_regressions.c
Original file line number Diff line number Diff line change
Expand Up @@ -951,6 +951,38 @@ static int ec_enc_shrink_assert(void)
return 0;
}

static int ec_enc_shrink_assert2(void)
{
OpusEncoder *enc;
int err;
int data_len;
unsigned char data[2000];

enc = opus_encoder_create(48000, 1, OPUS_APPLICATION_AUDIO, &err);
opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(6));
opus_encoder_ctl(enc, OPUS_SET_SIGNAL(OPUS_SIGNAL_VOICE));
opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND));
opus_encoder_ctl(enc, OPUS_SET_PACKET_LOSS_PERC(26));
opus_encoder_ctl(enc, OPUS_SET_BITRATE(27000));
{
static const short pcm[960] = { 0 };
data_len = opus_encode(enc, pcm, 960, data, 2000);
assert(data_len > 0);
}
opus_encoder_ctl(enc, OPUS_SET_SIGNAL(OPUS_SIGNAL_MUSIC));
{
static const short pcm[480] =
{
32767, 32767, 0, 0, 32767, 32767, 0, 0, 32767, 32767,
-32768, -32768, 0, 0, -32768, -32768, 0, 0, -32768, -32768
};
data_len = opus_encode(enc, pcm, 480, data, 19);
assert(data_len > 0);
}
opus_encoder_destroy(enc);
return 0;
}

void regression_test(void)
{
fprintf(stderr, "Running simple tests for bugs that have been fixed previously\n");
Expand All @@ -959,4 +991,5 @@ void regression_test(void)
mscbr_encode_fail();
surround_analysis_uninit();
ec_enc_shrink_assert();
ec_enc_shrink_assert2();
}

0 comments on commit 20bf3b3

Please sign in to comment.