mirror of
https://github.com/xiph/opus.git
synced 2025-06-05 23:10:54 +00:00
Moving FEC decision to the Opus encoder level (from SILK level)
This commit is contained in:
parent
099fc05ebf
commit
2b011b64d8
6 changed files with 57 additions and 27 deletions
|
@ -77,6 +77,9 @@ typedef struct {
|
|||
/* I: Flag to enable in-band Forward Error Correction (FEC); 0/1 */
|
||||
opus_int useInBandFEC;
|
||||
|
||||
/* I: Flag to actually code in-band Forward Error Correction (FEC) in the current packet; 0/1 */
|
||||
opus_int LBRR_coded;
|
||||
|
||||
/* I: Flag to enable discontinuous transmission (DTX); 0/1 */
|
||||
opus_int useDTX;
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ static opus_int silk_setup_complexity(
|
|||
|
||||
static OPUS_INLINE opus_int silk_setup_LBRR(
|
||||
silk_encoder_state *psEncC, /* I/O */
|
||||
const opus_int32 TargetRate_bps /* I */
|
||||
const silk_EncControlStruct *encControl /* I */
|
||||
);
|
||||
|
||||
|
||||
|
@ -65,7 +65,6 @@ static OPUS_INLINE opus_int silk_setup_LBRR(
|
|||
opus_int silk_control_encoder(
|
||||
silk_encoder_state_Fxx *psEnc, /* I/O Pointer to Silk encoder state */
|
||||
silk_EncControlStruct *encControl, /* I Control structure */
|
||||
const opus_int32 TargetRate_bps, /* I Target max bitrate (bps) */
|
||||
const opus_int allow_bw_switch, /* I Flag to allow switching audio bandwidth */
|
||||
const opus_int channelNb, /* I Channel number */
|
||||
const opus_int force_fs_kHz
|
||||
|
@ -125,7 +124,7 @@ opus_int silk_control_encoder(
|
|||
/********************************************/
|
||||
/* Set LBRR usage */
|
||||
/********************************************/
|
||||
ret += silk_setup_LBRR( &psEnc->sCmn, TargetRate_bps );
|
||||
ret += silk_setup_LBRR( &psEnc->sCmn, encControl );
|
||||
|
||||
psEnc->sCmn.controlled_since_last_payload = 1;
|
||||
|
||||
|
@ -403,25 +402,14 @@ static opus_int silk_setup_complexity(
|
|||
|
||||
static OPUS_INLINE opus_int silk_setup_LBRR(
|
||||
silk_encoder_state *psEncC, /* I/O */
|
||||
const opus_int32 TargetRate_bps /* I */
|
||||
const silk_EncControlStruct *encControl /* I */
|
||||
)
|
||||
{
|
||||
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 ) {
|
||||
LBRR_rate_thres_bps = LBRR_NB_MIN_RATE_BPS;
|
||||
} else if( psEncC->fs_kHz == 12 ) {
|
||||
LBRR_rate_thres_bps = LBRR_MB_MIN_RATE_BPS;
|
||||
} else {
|
||||
LBRR_rate_thres_bps = LBRR_WB_MIN_RATE_BPS;
|
||||
}
|
||||
LBRR_rate_thres_bps = silk_SMULWB( silk_MUL( LBRR_rate_thres_bps, 125 - silk_min( psEncC->PacketLoss_perc, 25 ) ), SILK_FIX_CONST( 0.01, 16 ) );
|
||||
|
||||
if( TargetRate_bps > LBRR_rate_thres_bps ) {
|
||||
psEncC->LBRR_enabled = encControl->LBRR_coded;
|
||||
if( psEncC->LBRR_enabled ) {
|
||||
/* 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 */
|
||||
|
@ -429,8 +417,6 @@ static OPUS_INLINE opus_int silk_setup_LBRR(
|
|||
} 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;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -237,7 +237,7 @@ opus_int silk_Encode( /* O Returns error co
|
|||
for( n = 0; n < encControl->nChannelsInternal; n++ ) {
|
||||
/* Force the side channel to the same rate as the mid */
|
||||
opus_int force_fs_kHz = (n==1) ? psEnc->state_Fxx[0].sCmn.fs_kHz : 0;
|
||||
if( ( ret = silk_control_encoder( &psEnc->state_Fxx[ n ], encControl, TargetRate_bps, psEnc->allowBandwidthSwitch, n, force_fs_kHz ) ) != 0 ) {
|
||||
if( ( ret = silk_control_encoder( &psEnc->state_Fxx[ n ], encControl, psEnc->allowBandwidthSwitch, n, force_fs_kHz ) ) != 0 ) {
|
||||
silk_assert( 0 );
|
||||
RESTORE_STACK;
|
||||
return ret;
|
||||
|
|
|
@ -81,7 +81,6 @@ opus_int silk_init_encoder(
|
|||
opus_int silk_control_encoder(
|
||||
silk_encoder_state_Fxx *psEnc, /* I/O Pointer to Silk encoder state */
|
||||
silk_EncControlStruct *encControl, /* I Control structure */
|
||||
const opus_int32 TargetRate_bps, /* I Target max bitrate (bps) */
|
||||
const opus_int allow_bw_switch, /* I Flag to allow switching audio bandwidth */
|
||||
const opus_int channelNb, /* I Channel number */
|
||||
const opus_int force_fs_kHz
|
||||
|
|
|
@ -79,7 +79,6 @@ opus_int silk_init_encoder(
|
|||
opus_int silk_control_encoder(
|
||||
silk_encoder_state_FLP *psEnc, /* I/O Pointer to Silk encoder state FLP */
|
||||
silk_EncControlStruct *encControl, /* I Control structure */
|
||||
const opus_int32 TargetRate_bps, /* I Target max bitrate (bps) */
|
||||
const opus_int allow_bw_switch, /* I Flag to allow switching audio bandwidth */
|
||||
const opus_int channelNb, /* I Channel number */
|
||||
const opus_int force_fs_kHz
|
||||
|
|
|
@ -156,6 +156,14 @@ static const opus_int32 mode_thresholds[2][2] = {
|
|||
{ 36000, 16000}, /* stereo */
|
||||
};
|
||||
|
||||
static const opus_int32 fec_thresholds[] = {
|
||||
12000, 1000, /* NB */
|
||||
14000, 1000, /* MB */
|
||||
16000, 1000, /* WB */
|
||||
20000, 1000, /* SWB */
|
||||
22000, 1000, /* FB */
|
||||
};
|
||||
|
||||
int opus_encoder_get_size(int channels)
|
||||
{
|
||||
int silkEncSizeBytes, celtEncSizeBytes;
|
||||
|
@ -943,6 +951,39 @@ opus_val16 compute_stereo_width(const opus_val16 *pcm, int frame_size, opus_int3
|
|||
return EXTRACT16(MIN32(Q15ONE, MULT16_16(20, mem->max_follower)));
|
||||
}
|
||||
|
||||
static int decide_fec(int useInBandFEC, int PacketLoss_perc, int last_fec, int mode, int *bandwidth, opus_int32 rate)
|
||||
{
|
||||
int orig_bandwidth;
|
||||
if (!useInBandFEC || PacketLoss_perc == 0 || mode == MODE_CELT_ONLY)
|
||||
return 0;
|
||||
orig_bandwidth = *bandwidth;
|
||||
for (;;)
|
||||
{
|
||||
opus_int32 hysteresis;
|
||||
opus_int32 LBRR_rate_thres_bps;
|
||||
/* Compute threshold for using FEC at the current bandwidth setting */
|
||||
LBRR_rate_thres_bps = fec_thresholds[2*(*bandwidth - OPUS_BANDWIDTH_NARROWBAND)];
|
||||
hysteresis = fec_thresholds[2*(*bandwidth - OPUS_BANDWIDTH_NARROWBAND) + 1];
|
||||
if (last_fec == 1) LBRR_rate_thres_bps -= hysteresis;
|
||||
if (last_fec == 0) LBRR_rate_thres_bps += hysteresis;
|
||||
LBRR_rate_thres_bps = silk_SMULWB( silk_MUL( LBRR_rate_thres_bps,
|
||||
125 - silk_min( PacketLoss_perc, 25 ) ), SILK_FIX_CONST( 0.01, 16 ) );
|
||||
/* If loss <= 5%, we look at whether we have enough rate to enable FEC.
|
||||
If loss > 5%, we decrease the bandwidth until we can enable FEC. */
|
||||
if (rate > LBRR_rate_thres_bps)
|
||||
return 1;
|
||||
else if (PacketLoss_perc <= 5)
|
||||
return 0;
|
||||
else if (*bandwidth > OPUS_BANDWIDTH_NARROWBAND)
|
||||
(*bandwidth)--;
|
||||
else
|
||||
break;
|
||||
}
|
||||
/* Couldn't find any bandwidth to enable FEC, keep original bandwidth. */
|
||||
*bandwidth = orig_bandwidth;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int compute_silk_rate_for_hybrid(int rate, int bandwidth, int frame20ms, int vbr) {
|
||||
int entry;
|
||||
int i;
|
||||
|
@ -1543,6 +1584,8 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
|
|||
st->bandwidth = IMIN(st->bandwidth, st->detected_bandwidth);
|
||||
}
|
||||
#endif
|
||||
st->silk_mode.LBRR_coded = decide_fec(st->silk_mode.useInBandFEC, st->silk_mode.packetLossPercentage,
|
||||
st->silk_mode.LBRR_coded, st->mode, &st->bandwidth, equiv_rate);
|
||||
celt_encoder_ctl(celt_enc, OPUS_SET_LSB_DEPTH(lsb_depth));
|
||||
|
||||
/* CELT mode doesn't support mediumband, use wideband instead */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue