mirror of
https://github.com/xiph/opus.git
synced 2025-06-03 00:57:43 +00:00
Fix for flutter with FEC
The bug was caused by an improper feedback of the per-frame bitrate, causing the bitrate to jump up and down from frame to frame, within a packet. The patch avoids this, and also gives a slight improvement in general for multi-frame packets, even without FEC. Signed-off-by: Jean-Marc Valin <jmvalin@jmvalin.ca>
This commit is contained in:
parent
8adff0bb31
commit
3499e78bd5
5 changed files with 21 additions and 11 deletions
|
@ -70,11 +70,6 @@ opus_int silk_control_SNR(
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Reduce coding quality whenever LBRR is enabled, to free up some bits */
|
||||
if( psEncC->LBRR_enabled ) {
|
||||
psEncC->SNR_dB_Q7 = silk_SMLABB( psEncC->SNR_dB_Q7, 12 - psEncC->LBRR_GainIncreases, SILK_FIX_CONST( -0.25, 7 ) );
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -397,9 +397,10 @@ static OPUS_INLINE opus_int silk_setup_LBRR(
|
|||
const opus_int32 TargetRate_bps /* I */
|
||||
)
|
||||
{
|
||||
opus_int ret = SILK_NO_ERROR;
|
||||
opus_int LBRR_in_previous_packet, ret = SILK_NO_ERROR;
|
||||
opus_int32 LBRR_rate_thres_bps;
|
||||
|
||||
LBRR_in_previous_packet = psEncC->LBRR_enabled;
|
||||
psEncC->LBRR_enabled = 0;
|
||||
if( psEncC->useInBandFEC && psEncC->PacketLoss_perc > 0 ) {
|
||||
if( psEncC->fs_kHz == 8 ) {
|
||||
|
@ -413,8 +414,13 @@ static OPUS_INLINE opus_int silk_setup_LBRR(
|
|||
|
||||
if( TargetRate_bps > LBRR_rate_thres_bps ) {
|
||||
/* Set gain increase for coding LBRR excitation */
|
||||
if( LBRR_in_previous_packet == 0 ) {
|
||||
/* Previous packet did not have LBRR, and was therefore coded at a higher bitrate */
|
||||
psEncC->LBRR_GainIncreases = 7;
|
||||
} else {
|
||||
psEncC->LBRR_GainIncreases = silk_max_int( 7 - silk_SMULWB( (opus_int32)psEncC->PacketLoss_perc, SILK_FIX_CONST( 0.4, 16 ) ), 2 );
|
||||
}
|
||||
psEncC->LBRR_enabled = 1;
|
||||
psEncC->LBRR_GainIncreases = silk_max_int( 7 - silk_SMULWB( (opus_int32)psEncC->PacketLoss_perc, SILK_FIX_CONST( 0.4, 16 ) ), 2 );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -376,26 +376,33 @@ opus_int silk_Encode( /* O Returns error co
|
|||
for( n = 0; n < encControl->nChannelsInternal; n++ ) {
|
||||
silk_memset( psEnc->state_Fxx[ n ].sCmn.LBRR_flags, 0, sizeof( psEnc->state_Fxx[ n ].sCmn.LBRR_flags ) );
|
||||
}
|
||||
|
||||
psEnc->nBitsUsedLBRR = ec_tell( psRangeEnc );
|
||||
}
|
||||
|
||||
silk_HP_variable_cutoff( psEnc->state_Fxx );
|
||||
|
||||
/* Total target bits for packet */
|
||||
nBits = silk_DIV32_16( silk_MUL( encControl->bitRate, encControl->payloadSize_ms ), 1000 );
|
||||
/* Subtract half of the bits already used */
|
||||
/* Subtract bits used for LBRR */
|
||||
if( !prefillFlag ) {
|
||||
nBits -= ec_tell( psRangeEnc ) >> 1;
|
||||
nBits -= psEnc->nBitsUsedLBRR;
|
||||
}
|
||||
/* Divide by number of uncoded frames left in packet */
|
||||
nBits = silk_DIV32_16( nBits, psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket - psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded );
|
||||
nBits = silk_DIV32_16( nBits, psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket );
|
||||
/* Convert to bits/second */
|
||||
if( encControl->payloadSize_ms == 10 ) {
|
||||
TargetRate_bps = silk_SMULBB( nBits, 100 );
|
||||
} else {
|
||||
TargetRate_bps = silk_SMULBB( nBits, 50 );
|
||||
}
|
||||
/* Subtract fraction of bits in excess of target in previous packets */
|
||||
/* Subtract fraction of bits in excess of target in previous frames and packets */
|
||||
TargetRate_bps -= silk_DIV32_16( silk_MUL( psEnc->nBitsExceeded, 1000 ), BITRESERVOIR_DECAY_TIME_MS );
|
||||
if( !prefillFlag && psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded > 0 ) {
|
||||
/* Compare actual vs target bits so far in this packet */
|
||||
opus_int32 bitsBalance = ec_tell( psRangeEnc ) - psEnc->nBitsUsedLBRR - nBits * psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded;
|
||||
TargetRate_bps -= silk_DIV32_16( silk_MUL( bitsBalance, 1000 ), BITRESERVOIR_DECAY_TIME_MS );
|
||||
}
|
||||
/* Never exceed input bitrate */
|
||||
TargetRate_bps = silk_LIMIT( TargetRate_bps, encControl->bitRate, 5000 );
|
||||
|
||||
|
|
|
@ -116,6 +116,7 @@ typedef struct {
|
|||
typedef struct {
|
||||
silk_encoder_state_FIX state_Fxx[ ENCODER_NUM_CHANNELS ];
|
||||
stereo_enc_state sStereo;
|
||||
opus_int32 nBitsUsedLBRR;
|
||||
opus_int32 nBitsExceeded;
|
||||
opus_int nChannelsAPI;
|
||||
opus_int nChannelsInternal;
|
||||
|
|
|
@ -115,6 +115,7 @@ typedef struct {
|
|||
typedef struct {
|
||||
silk_encoder_state_FLP state_Fxx[ ENCODER_NUM_CHANNELS ];
|
||||
stereo_enc_state sStereo;
|
||||
opus_int32 nBitsUsedLBRR;
|
||||
opus_int32 nBitsExceeded;
|
||||
opus_int nChannelsAPI;
|
||||
opus_int nChannelsInternal;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue