aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJean-Marc Valin <jmvalin@jmvalin.ca>2016-06-21 12:38:25 -0400
committerJean-Marc Valin <jmvalin@jmvalin.ca>2016-07-19 16:11:50 -0400
commit2b011b64d8ca5f3f7b26806aeb77939ff7703c06 (patch)
tree35f394b019f3afd3b32e9ba1b9f21399ce1fc7f2 /src
parent099fc05ebf443e2bcc8c5ab9c627c86ec1e743e0 (diff)
downloadlibopus-2b011b64d8ca5f3f7b26806aeb77939ff7703c06.tar.gz
Moving FEC decision to the Opus encoder level (from SILK level)
Diffstat (limited to 'src')
-rw-r--r--src/opus_encoder.c43
1 files changed, 43 insertions, 0 deletions
diff --git a/src/opus_encoder.c b/src/opus_encoder.c
index 792fbf6b..93badd46 100644
--- a/src/opus_encoder.c
+++ b/src/opus_encoder.c
@@ -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 */