blob: a274b6671ee752f71ce5fa74f145fabf12ef9f62 [file] [log] [blame]
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/*
* bandwidth_estimator.c
*
* This file contains the code for the Bandwidth Estimator designed
* for iSAC.
*
* NOTE! Castings needed for C55, do not remove!
*
*/
#include "bandwidth_estimator.h"
#include "settings.h"
/* array of quantization levels for bottle neck info; Matlab code: */
/* sprintf('%4.1ff, ', logspace(log10(5000), log10(40000), 12)) */
static const WebRtc_Word16 kQRateTable[12] = {
10000, 11115, 12355, 13733, 15265, 16967,
18860, 20963, 23301, 25900, 28789, 32000
};
/* 0.1 times the values in the table kQRateTable */
/* values are in Q16 */
static const WebRtc_Word32 KQRate01[12] = {
65536000, 72843264, 80969728, 90000589, 100040704, 111194931,
123600896, 137383117, 152705434, 169738240, 188671590, 209715200
};
/* Bits per Bytes Seconds
* 8 bits/byte * 1000 msec/sec * 1/framelength (in msec)->bits/byte*sec
* frame length will either be 30 or 60 msec. 8738 is 1/60 in Q19 and 1/30 in Q18
* The following number is either in Q15 or Q14 depending on the current frame length */
static const WebRtc_Word32 kBitsByteSec = 4369000;
/* Received header rate. First value is for 30 ms packets and second for 60 ms */
static const WebRtc_Word16 kRecHeaderRate[2] = {
9333, 4666
};
/* Inverted minimum and maximum bandwidth in Q30.
minBwInv 30 ms, maxBwInv 30 ms,
minBwInv 60 ms, maxBwInv 69 ms
*/
static const WebRtc_Word32 kInvBandwidth[4] = {
55539, 25978,
73213, 29284
};
/* Number of samples in 25 msec */
static const WebRtc_Word32 kSamplesIn25msec = 400;
/****************************************************************************
* WebRtcIsacfix_InitBandwidthEstimator(...)
*
* This function initializes the struct for the bandwidth estimator
*
* Input/Output:
* - bweStr : Struct containing bandwidth information.
*
* Return value : 0
*/
WebRtc_Word32 WebRtcIsacfix_InitBandwidthEstimator(BwEstimatorstr *bweStr)
{
bweStr->prevFrameSizeMs = INIT_FRAME_LEN;
bweStr->prevRtpNumber = 0;
bweStr->prevSendTime = 0;
bweStr->prevArrivalTime = 0;
bweStr->prevRtpRate = 1;
bweStr->lastUpdate = 0;
bweStr->lastReduction = 0;
bweStr->countUpdates = -9;
/* INIT_BN_EST = 20000
* INIT_BN_EST_Q7 = 2560000
* INIT_HDR_RATE = 4666
* INIT_REC_BN_EST_Q5 = 789312
*
* recBwInv = 1/(INIT_BN_EST + INIT_HDR_RATE) in Q30
* recBwAvg = INIT_BN_EST + INIT_HDR_RATE in Q5
*/
bweStr->recBwInv = 43531;
bweStr->recBw = INIT_BN_EST;
bweStr->recBwAvgQ = INIT_BN_EST_Q7;
bweStr->recBwAvg = INIT_REC_BN_EST_Q5;
bweStr->recJitter = (WebRtc_Word32) 327680; /* 10 in Q15 */
bweStr->recJitterShortTerm = 0;
bweStr->recJitterShortTermAbs = (WebRtc_Word32) 40960; /* 5 in Q13 */
bweStr->recMaxDelay = (WebRtc_Word32) 10;
bweStr->recMaxDelayAvgQ = (WebRtc_Word32) 5120; /* 10 in Q9 */
bweStr->recHeaderRate = INIT_HDR_RATE;
bweStr->countRecPkts = 0;
bweStr->sendBwAvg = INIT_BN_EST_Q7;
bweStr->sendMaxDelayAvg = (WebRtc_Word32) 5120; /* 10 in Q9 */
bweStr->countHighSpeedRec = 0;
bweStr->highSpeedRec = 0;
bweStr->countHighSpeedSent = 0;
bweStr->highSpeedSend = 0;
bweStr->inWaitPeriod = 0;
/* Find the inverse of the max bw and min bw in Q30
* (1 / (MAX_ISAC_BW + INIT_HDR_RATE) in Q30
* (1 / (MIN_ISAC_BW + INIT_HDR_RATE) in Q30
*/
bweStr->maxBwInv = kInvBandwidth[3];
bweStr->minBwInv = kInvBandwidth[2];
return 0;
}
/****************************************************************************
* WebRtcIsacfix_UpdateUplinkBwImpl(...)
*
* This function updates bottle neck rate received from other side in payload
* and calculates a new bottle neck to send to the other side.
*
* Input/Output:
* - bweStr : struct containing bandwidth information.
* - rtpNumber : value from RTP packet, from NetEq
* - frameSize : length of signal frame in ms, from iSAC decoder
* - sendTime : value in RTP header giving send time in samples
* - arrivalTime : value given by timeGetTime() time of arrival in
* samples of packet from NetEq
* - pksize : size of packet in bytes, from NetEq
* - Index : integer (range 0...23) indicating bottle neck &
* jitter as estimated by other side
*
* Return value : 0 if everything went fine,
* -1 otherwise
*/
WebRtc_Word32 WebRtcIsacfix_UpdateUplinkBwImpl(BwEstimatorstr *bweStr,
const WebRtc_UWord16 rtpNumber,
const WebRtc_Word16 frameSize,
const WebRtc_UWord32 sendTime,
const WebRtc_UWord32 arrivalTime,
const WebRtc_Word16 pksize,
const WebRtc_UWord16 Index)
{
WebRtc_UWord16 weight = 0;
WebRtc_UWord32 currBwInv = 0;
WebRtc_UWord16 recRtpRate;
WebRtc_UWord32 arrTimeProj;
WebRtc_Word32 arrTimeDiff;
WebRtc_Word32 arrTimeNoise;
WebRtc_Word32 arrTimeNoiseAbs;
WebRtc_Word32 sendTimeDiff;
WebRtc_Word32 delayCorrFactor = DELAY_CORRECTION_MED;
WebRtc_Word32 lateDiff = 0;
WebRtc_Word16 immediateSet = 0;
WebRtc_Word32 frameSizeSampl;
WebRtc_Word32 temp;
WebRtc_Word32 msec;
WebRtc_UWord32 exponent;
WebRtc_UWord32 reductionFactor;
WebRtc_UWord32 numBytesInv;
WebRtc_Word32 sign;
WebRtc_UWord32 byteSecondsPerBit;
WebRtc_UWord32 tempLower;
WebRtc_UWord32 tempUpper;
WebRtc_Word32 recBwAvgInv;
WebRtc_Word32 numPktsExpected;
WebRtc_Word16 errCode;
/* UPDATE ESTIMATES FROM OTHER SIDE */
/* The function also checks if Index has a valid value */
errCode = WebRtcIsacfix_UpdateUplinkBwRec(bweStr, Index);
if (errCode <0) {
return(errCode);
}
/* UPDATE ESTIMATES ON THIS SIDE */
/* Bits per second per byte * 1/30 or 1/60 */
if (frameSize == 60) {
/* If frameSize changed since last call, from 30 to 60, recalculate some values */
if ( (frameSize != bweStr->prevFrameSizeMs) && (bweStr->countUpdates > 0)) {
bweStr->countUpdates = 10;
bweStr->recHeaderRate = kRecHeaderRate[1];
bweStr->maxBwInv = kInvBandwidth[3];
bweStr->minBwInv = kInvBandwidth[2];
bweStr->recBwInv = WEBRTC_SPL_UDIV(1073741824, (bweStr->recBw + bweStr->recHeaderRate));
}
/* kBitsByteSec is in Q15 */
recRtpRate = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(kBitsByteSec,
(WebRtc_Word32)pksize), 15) + bweStr->recHeaderRate;
} else {
/* If frameSize changed since last call, from 60 to 30, recalculate some values */
if ( (frameSize != bweStr->prevFrameSizeMs) && (bweStr->countUpdates > 0)) {
bweStr->countUpdates = 10;
bweStr->recHeaderRate = kRecHeaderRate[0];
bweStr->maxBwInv = kInvBandwidth[1];
bweStr->minBwInv = kInvBandwidth[0];
bweStr->recBwInv = WEBRTC_SPL_UDIV(1073741824, (bweStr->recBw + bweStr->recHeaderRate));
}
/* kBitsByteSec is in Q14 */
recRtpRate = (WebRtc_UWord16)WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(kBitsByteSec,
(WebRtc_Word32)pksize), 14) + bweStr->recHeaderRate;
}
/* Check for timer wrap-around */
if (arrivalTime < bweStr->prevArrivalTime) {
bweStr->prevArrivalTime = arrivalTime;
bweStr->lastUpdate = arrivalTime;
bweStr->lastReduction = arrivalTime + FS3;
bweStr->countRecPkts = 0;
/* store frame size */
bweStr->prevFrameSizeMs = frameSize;
/* store far-side transmission rate */
bweStr->prevRtpRate = recRtpRate;
/* store far-side RTP time stamp */
bweStr->prevRtpNumber = rtpNumber;
return 0;
}
bweStr->countRecPkts++;
/* Calculate framesize in msec */
frameSizeSampl = WEBRTC_SPL_MUL_16_16((WebRtc_Word16)SAMPLES_PER_MSEC, frameSize);
/* Check that it's not one of the first 9 packets */
if ( bweStr->countUpdates > 0 ) {
/* Stay in Wait Period for 1.5 seconds (no updates in wait period) */
if(bweStr->inWaitPeriod) {
if ((arrivalTime - bweStr->startWaitPeriod)> FS_1_HALF) {
bweStr->inWaitPeriod = 0;
}
}
/* If not been updated for a long time, reduce the BN estimate */
/* Check send time difference between this packet and previous received */
sendTimeDiff = sendTime - bweStr->prevSendTime;
if (sendTimeDiff <= WEBRTC_SPL_LSHIFT_W32(frameSizeSampl, 1)) {
/* Only update if 3 seconds has past since last update */
if ((arrivalTime - bweStr->lastUpdate) > FS3) {
/* Calculate expected number of received packets since last update */
numPktsExpected = WEBRTC_SPL_UDIV(arrivalTime - bweStr->lastUpdate, frameSizeSampl);
/* If received number of packets is more than 90% of expected (922 = 0.9 in Q10): */
/* do the update, else not */
if(WEBRTC_SPL_LSHIFT_W32(bweStr->countRecPkts, 10) > WEBRTC_SPL_MUL_16_16(922, numPktsExpected)) {
/* Q4 chosen to approx dividing by 16 */
msec = (arrivalTime - bweStr->lastReduction);
/* the number below represents 13 seconds, highly unlikely
but to insure no overflow when reduction factor is multiplied by recBw inverse */
if (msec > 208000) {
msec = 208000;
}
/* Q20 2^(negative number: - 76/1048576) = .99995
product is Q24 */
exponent = WEBRTC_SPL_UMUL(0x0000004C, msec);
/* do the approx with positive exponent so that value is actually rf^-1
and multiply by bw inverse */
reductionFactor = WEBRTC_SPL_RSHIFT_U32(0x01000000 | (exponent & 0x00FFFFFF),
WEBRTC_SPL_RSHIFT_U32(exponent, 24));
/* reductionFactor in Q13 */
reductionFactor = WEBRTC_SPL_RSHIFT_U32(reductionFactor, 11);
if ( reductionFactor != 0 ) {
bweStr->recBwInv = WEBRTC_SPL_MUL((WebRtc_Word32)bweStr->recBwInv, (WebRtc_Word32)reductionFactor);
bweStr->recBwInv = WEBRTC_SPL_RSHIFT_W32((WebRtc_Word32)bweStr->recBwInv, 13);
} else {
/* recBwInv = 1 / (INIT_BN_EST + INIT_HDR_RATE) in Q26 (Q30??)*/
bweStr->recBwInv = WEBRTC_SPL_DIV((1073741824 +
WEBRTC_SPL_LSHIFT_W32(((WebRtc_Word32)INIT_BN_EST + INIT_HDR_RATE), 1)), INIT_BN_EST + INIT_HDR_RATE);
}
/* reset time-since-update counter */
bweStr->lastReduction = arrivalTime;
} else {
/* Delay last reduction with 3 seconds */
bweStr->lastReduction = arrivalTime + FS3;
bweStr->lastUpdate = arrivalTime;
bweStr->countRecPkts = 0;
}
}
} else {
bweStr->lastReduction = arrivalTime + FS3;
bweStr->lastUpdate = arrivalTime;
bweStr->countRecPkts = 0;
}
/* update only if previous packet was not lost */
if ( rtpNumber == bweStr->prevRtpNumber + 1 ) {
arrTimeDiff = arrivalTime - bweStr->prevArrivalTime;
if (!(bweStr->highSpeedSend && bweStr->highSpeedRec)) {
if (arrTimeDiff > frameSizeSampl) {
if (sendTimeDiff > 0) {
lateDiff = arrTimeDiff - sendTimeDiff -
WEBRTC_SPL_LSHIFT_W32(frameSizeSampl, 1);
} else {
lateDiff = arrTimeDiff - frameSizeSampl;
}
/* 8000 is 1/2 second (in samples at FS) */
if (lateDiff > 8000) {
delayCorrFactor = (WebRtc_Word32) DELAY_CORRECTION_MAX;
bweStr->inWaitPeriod = 1;
bweStr->startWaitPeriod = arrivalTime;
immediateSet = 1;
} else if (lateDiff > 5120) {
delayCorrFactor = (WebRtc_Word32) DELAY_CORRECTION_MED;
immediateSet = 1;
bweStr->inWaitPeriod = 1;
bweStr->startWaitPeriod = arrivalTime;
}
}
}
if ((bweStr->prevRtpRate > WEBRTC_SPL_RSHIFT_W32((WebRtc_Word32) bweStr->recBwAvg, 5)) &&
(recRtpRate > WEBRTC_SPL_RSHIFT_W32((WebRtc_Word32)bweStr->recBwAvg, 5)) &&
!bweStr->inWaitPeriod) {
/* test if still in initiation period and increment counter */
if (bweStr->countUpdates++ > 99) {
/* constant weight after initiation part, 0.01 in Q13 */
weight = (WebRtc_UWord16) 82;
} else {
/* weight decreases with number of updates, 1/countUpdates in Q13 */
weight = (WebRtc_UWord16) WebRtcSpl_DivW32W16(
(WebRtc_Word32)(8192 + WEBRTC_SPL_RSHIFT_W32((WebRtc_Word32) bweStr->countUpdates, 1)),
(WebRtc_Word16)bweStr->countUpdates);
}
/* Bottle Neck Estimation */
/* limit outliers, if more than 25 ms too much */
if (arrTimeDiff > frameSizeSampl + kSamplesIn25msec) {
arrTimeDiff = frameSizeSampl + kSamplesIn25msec;
}
/* don't allow it to be less than frame rate - 10 ms */
if (arrTimeDiff < frameSizeSampl - FRAMESAMPLES_10ms) {
arrTimeDiff = frameSizeSampl - FRAMESAMPLES_10ms;
}
/* compute inverse receiving rate for last packet, in Q19 */
numBytesInv = (WebRtc_UWord16) WebRtcSpl_DivW32W16(
(WebRtc_Word32)(524288 + WEBRTC_SPL_RSHIFT_W32(((WebRtc_Word32)pksize + HEADER_SIZE), 1)),
(WebRtc_Word16)(pksize + HEADER_SIZE));
/* 8389 is ~ 1/128000 in Q30 */
byteSecondsPerBit = WEBRTC_SPL_MUL_16_16(arrTimeDiff, 8389);
/* get upper N bits */
tempUpper = WEBRTC_SPL_RSHIFT_U32(byteSecondsPerBit, 15);
/* get lower 15 bits */
tempLower = byteSecondsPerBit & 0x00007FFF;
tempUpper = WEBRTC_SPL_MUL(tempUpper, numBytesInv);
tempLower = WEBRTC_SPL_MUL(tempLower, numBytesInv);
tempLower = WEBRTC_SPL_RSHIFT_U32(tempLower, 15);
currBwInv = tempUpper + tempLower;
currBwInv = WEBRTC_SPL_RSHIFT_U32(currBwInv, 4);
/* Limit inv rate. Note that minBwInv > maxBwInv! */
if(currBwInv < bweStr->maxBwInv) {
currBwInv = bweStr->maxBwInv;
} else if(currBwInv > bweStr->minBwInv) {
currBwInv = bweStr->minBwInv;
}
/* update bottle neck rate estimate */
bweStr->recBwInv = WEBRTC_SPL_UMUL(weight, currBwInv) +
WEBRTC_SPL_UMUL((WebRtc_UWord32) 8192 - weight, bweStr->recBwInv);
/* Shift back to Q30 from Q40 (actual used bits shouldn't be more than 27 based on minBwInv)
up to 30 bits used with Q13 weight */
bweStr->recBwInv = WEBRTC_SPL_RSHIFT_U32(bweStr->recBwInv, 13);
/* reset time-since-update counter */
bweStr->lastUpdate = arrivalTime;
bweStr->lastReduction = arrivalTime + FS3;
bweStr->countRecPkts = 0;
/* to save resolution compute the inverse of recBwAvg in Q26 by left shifting numerator to 2^31
and NOT right shifting recBwAvg 5 bits to an integer
At max 13 bits are used
shift to Q5 */
recBwAvgInv = WEBRTC_SPL_UDIV((WebRtc_UWord32)(0x80000000 + WEBRTC_SPL_RSHIFT_U32(bweStr->recBwAvg, 1)),
bweStr->recBwAvg);
/* Calculate Projected arrival time difference */
/* The numerator of the quotient can be 22 bits so right shift inv by 4 to avoid overflow
result in Q22 */
arrTimeProj = WEBRTC_SPL_MUL((WebRtc_Word32)8000, recBwAvgInv);
/* shift to Q22 */
arrTimeProj = WEBRTC_SPL_RSHIFT_U32(arrTimeProj, 4);
/* complete calulation */
arrTimeProj = WEBRTC_SPL_MUL(((WebRtc_Word32)pksize + HEADER_SIZE), arrTimeProj);
/* shift to Q10 */
arrTimeProj = WEBRTC_SPL_RSHIFT_U32(arrTimeProj, 12);
/* difference between projected and actual arrival time differences */
/* Q9 (only shift arrTimeDiff by 5 to simulate divide by 16 (need to revisit if change sampling rate) DH */
if (WEBRTC_SPL_LSHIFT_W32(arrTimeDiff, 6) > (WebRtc_Word32)arrTimeProj) {
arrTimeNoise = WEBRTC_SPL_LSHIFT_W32(arrTimeDiff, 6) - arrTimeProj;
sign = 1;
} else {
arrTimeNoise = arrTimeProj - WEBRTC_SPL_LSHIFT_W32(arrTimeDiff, 6);
sign = -1;
}
/* Q9 */
arrTimeNoiseAbs = arrTimeNoise;
/* long term averaged absolute jitter, Q15 */
weight = WEBRTC_SPL_RSHIFT_W32(weight, 3);
bweStr->recJitter = WEBRTC_SPL_MUL(weight, WEBRTC_SPL_LSHIFT_W32(arrTimeNoiseAbs, 5))
+ WEBRTC_SPL_MUL(1024 - weight, bweStr->recJitter);
/* remove the fractional portion */
bweStr->recJitter = WEBRTC_SPL_RSHIFT_W32(bweStr->recJitter, 10);
/* Maximum jitter is 10 msec in Q15 */
if (bweStr->recJitter > (WebRtc_Word32)327680) {
bweStr->recJitter = (WebRtc_Word32)327680;
}
/* short term averaged absolute jitter */
/* Calculation in Q13 products in Q23 */
bweStr->recJitterShortTermAbs = WEBRTC_SPL_MUL(51, WEBRTC_SPL_LSHIFT_W32(arrTimeNoiseAbs, 3)) +
WEBRTC_SPL_MUL(973, bweStr->recJitterShortTermAbs);
bweStr->recJitterShortTermAbs = WEBRTC_SPL_RSHIFT_W32(bweStr->recJitterShortTermAbs , 10);
/* short term averaged jitter */
/* Calculation in Q13 products in Q23 */
bweStr->recJitterShortTerm = WEBRTC_SPL_MUL(205, WEBRTC_SPL_LSHIFT_W32(arrTimeNoise, 3)) * sign +
WEBRTC_SPL_MUL(3891, bweStr->recJitterShortTerm);
if (bweStr->recJitterShortTerm < 0) {
temp = -bweStr->recJitterShortTerm;
temp = WEBRTC_SPL_RSHIFT_W32(temp, 12);
bweStr->recJitterShortTerm = -temp;
} else {
bweStr->recJitterShortTerm = WEBRTC_SPL_RSHIFT_W32(bweStr->recJitterShortTerm, 12);
}
}
}
} else {
/* reset time-since-update counter when receiving the first 9 packets */
bweStr->lastUpdate = arrivalTime;
bweStr->lastReduction = arrivalTime + FS3;
bweStr->countRecPkts = 0;
bweStr->countUpdates++;
}
/* Limit to minimum or maximum bottle neck rate (in Q30) */
if (bweStr->recBwInv > bweStr->minBwInv) {
bweStr->recBwInv = bweStr->minBwInv;
} else if (bweStr->recBwInv < bweStr->maxBwInv) {
bweStr->recBwInv = bweStr->maxBwInv;
}
/* store frame length */
bweStr->prevFrameSizeMs = frameSize;
/* store far-side transmission rate */
bweStr->prevRtpRate = recRtpRate;
/* store far-side RTP time stamp */
bweStr->prevRtpNumber = rtpNumber;
/* Replace bweStr->recMaxDelay by the new value (atomic operation) */
if (bweStr->prevArrivalTime != 0xffffffff) {
bweStr->recMaxDelay = WEBRTC_SPL_MUL(3, bweStr->recJitter);
}
/* store arrival time stamp */
bweStr->prevArrivalTime = arrivalTime;
bweStr->prevSendTime = sendTime;
/* Replace bweStr->recBw by the new value */
bweStr->recBw = WEBRTC_SPL_UDIV(1073741824, bweStr->recBwInv) - bweStr->recHeaderRate;
if (immediateSet) {
/* delay correction factor is in Q10 */
bweStr->recBw = WEBRTC_SPL_UMUL(delayCorrFactor, bweStr->recBw);
bweStr->recBw = WEBRTC_SPL_RSHIFT_U32(bweStr->recBw, 10);
if (bweStr->recBw < (WebRtc_Word32) MIN_ISAC_BW) {
bweStr->recBw = (WebRtc_Word32) MIN_ISAC_BW;
}
bweStr->recBwAvg = WEBRTC_SPL_LSHIFT_U32(bweStr->recBw + bweStr->recHeaderRate, 5);
bweStr->recBwAvgQ = WEBRTC_SPL_LSHIFT_U32(bweStr->recBw, 7);
bweStr->recJitterShortTerm = 0;
bweStr->recBwInv = WEBRTC_SPL_UDIV(1073741824, bweStr->recBw + bweStr->recHeaderRate);
immediateSet = 0;
}
return 0;
}
/* This function updates the send bottle neck rate */
/* Index - integer (range 0...23) indicating bottle neck & jitter as estimated by other side */
/* returns 0 if everything went fine, -1 otherwise */
WebRtc_Word16 WebRtcIsacfix_UpdateUplinkBwRec(BwEstimatorstr *bweStr,
const WebRtc_Word16 Index)
{
WebRtc_UWord16 RateInd;
if ( (Index < 0) || (Index > 23) ) {
return -ISAC_RANGE_ERROR_BW_ESTIMATOR;
}
/* UPDATE ESTIMATES FROM OTHER SIDE */
if ( Index > 11 ) {
RateInd = Index - 12;
/* compute the jitter estimate as decoded on the other side in Q9 */
/* sendMaxDelayAvg = 0.9 * sendMaxDelayAvg + 0.1 * MAX_ISAC_MD */
bweStr->sendMaxDelayAvg = WEBRTC_SPL_MUL(461, bweStr->sendMaxDelayAvg) +
WEBRTC_SPL_MUL(51, WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)MAX_ISAC_MD, 9));
bweStr->sendMaxDelayAvg = WEBRTC_SPL_RSHIFT_W32(bweStr->sendMaxDelayAvg, 9);
} else {
RateInd = Index;
/* compute the jitter estimate as decoded on the other side in Q9 */
/* sendMaxDelayAvg = 0.9 * sendMaxDelayAvg + 0.1 * MIN_ISAC_MD */
bweStr->sendMaxDelayAvg = WEBRTC_SPL_MUL(461, bweStr->sendMaxDelayAvg) +
WEBRTC_SPL_MUL(51, WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)MIN_ISAC_MD,9));
bweStr->sendMaxDelayAvg = WEBRTC_SPL_RSHIFT_W32(bweStr->sendMaxDelayAvg, 9);
}
/* compute the BN estimate as decoded on the other side */
/* sendBwAvg = 0.9 * sendBwAvg + 0.1 * kQRateTable[RateInd]; */
bweStr->sendBwAvg = WEBRTC_SPL_UMUL(461, bweStr->sendBwAvg) +
WEBRTC_SPL_UMUL(51, WEBRTC_SPL_LSHIFT_U32(kQRateTable[RateInd], 7));
bweStr->sendBwAvg = WEBRTC_SPL_RSHIFT_U32(bweStr->sendBwAvg, 9);
if (WEBRTC_SPL_RSHIFT_U32(bweStr->sendBwAvg, 7) > 28000 && !bweStr->highSpeedSend) {
bweStr->countHighSpeedSent++;
/* approx 2 seconds with 30ms frames */
if (bweStr->countHighSpeedSent >= 66) {
bweStr->highSpeedSend = 1;
}
} else if (!bweStr->highSpeedSend) {
bweStr->countHighSpeedSent = 0;
}
return 0;
}
/****************************************************************************
* WebRtcIsacfix_GetDownlinkBwIndexImpl(...)
*
* This function calculates and returns the bandwidth/jitter estimation code
* (integer 0...23) to put in the sending iSAC payload.
*
* Input:
* - bweStr : BWE struct
*
* Return:
* bandwith and jitter index (0..23)
*/
WebRtc_UWord16 WebRtcIsacfix_GetDownlinkBwIndexImpl(BwEstimatorstr *bweStr)
{
WebRtc_Word32 rate;
WebRtc_Word32 maxDelay;
WebRtc_UWord16 rateInd;
WebRtc_UWord16 maxDelayBit;
WebRtc_Word32 tempTerm1;
WebRtc_Word32 tempTerm2;
WebRtc_Word32 tempTermX;
WebRtc_Word32 tempTermY;
WebRtc_Word32 tempMin;
WebRtc_Word32 tempMax;
/* Get Rate Index */
/* Get unquantized rate. Always returns 10000 <= rate <= 32000 */
rate = WebRtcIsacfix_GetDownlinkBandwidth(bweStr);
/* Compute the averaged BN estimate on this side */
/* recBwAvg = 0.9 * recBwAvg + 0.1 * (rate + bweStr->recHeaderRate), 0.9 and 0.1 in Q9 */
bweStr->recBwAvg = WEBRTC_SPL_UMUL(922, bweStr->recBwAvg) +
WEBRTC_SPL_UMUL(102, WEBRTC_SPL_LSHIFT_U32((WebRtc_UWord32)rate + bweStr->recHeaderRate, 5));
bweStr->recBwAvg = WEBRTC_SPL_RSHIFT_U32(bweStr->recBwAvg, 10);
/* find quantization index that gives the closest rate after averaging */
for (rateInd = 1; rateInd < 12; rateInd++) {
if (rate <= kQRateTable[rateInd]){
break;
}
}
/* find closest quantization index, and update quantized average by taking: */
/* 0.9*recBwAvgQ + 0.1*kQRateTable[rateInd] */
/* 0.9 times recBwAvgQ in Q16 */
/* 461/512 - 25/65536 =0.900009 */
tempTerm1 = WEBRTC_SPL_MUL(bweStr->recBwAvgQ, 25);
tempTerm1 = WEBRTC_SPL_RSHIFT_W32(tempTerm1, 7);
tempTermX = WEBRTC_SPL_UMUL(461, bweStr->recBwAvgQ) - tempTerm1;
/* rate in Q16 */
tempTermY = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)rate, 16);
/* 0.1 * kQRateTable[rateInd] = KQRate01[rateInd] */
tempTerm1 = tempTermX + KQRate01[rateInd] - tempTermY;
tempTerm2 = tempTermY - tempTermX - KQRate01[rateInd-1];
/* Compare (0.9 * recBwAvgQ + 0.1 * kQRateTable[rateInd] - rate) >
(rate - 0.9 * recBwAvgQ - 0.1 * kQRateTable[rateInd-1]) */
if (tempTerm1 > tempTerm2) {
rateInd--;
}
/* Update quantized average by taking: */
/* 0.9*recBwAvgQ + 0.1*kQRateTable[rateInd] */
/* Add 0.1 times kQRateTable[rateInd], in Q16 */
tempTermX += KQRate01[rateInd];
/* Shift back to Q7 */
bweStr->recBwAvgQ = WEBRTC_SPL_RSHIFT_W32(tempTermX, 9);
/* Count consecutive received bandwidth above 28000 kbps (28000 in Q7 = 3584000) */
/* If 66 high estimates in a row, set highSpeedRec to one */
/* 66 corresponds to ~2 seconds in 30 msec mode */
if ((bweStr->recBwAvgQ > 3584000) && !bweStr->highSpeedRec) {
bweStr->countHighSpeedRec++;
if (bweStr->countHighSpeedRec >= 66) {
bweStr->highSpeedRec = 1;
}
} else if (!bweStr->highSpeedRec) {
bweStr->countHighSpeedRec = 0;
}
/* Get Max Delay Bit */
/* get unquantized max delay */
maxDelay = WebRtcIsacfix_GetDownlinkMaxDelay(bweStr);
/* Update quantized max delay average */
tempMax = 652800; /* MAX_ISAC_MD * 0.1 in Q18 */
tempMin = 130560; /* MIN_ISAC_MD * 0.1 in Q18 */
tempTermX = WEBRTC_SPL_MUL((WebRtc_Word32)bweStr->recMaxDelayAvgQ, (WebRtc_Word32)461);
tempTermY = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)maxDelay, 18);
tempTerm1 = tempTermX + tempMax - tempTermY;
tempTerm2 = tempTermY - tempTermX - tempMin;
if ( tempTerm1 > tempTerm2) {
maxDelayBit = 0;
tempTerm1 = tempTermX + tempMin;
/* update quantized average, shift back to Q9 */
bweStr->recMaxDelayAvgQ = WEBRTC_SPL_RSHIFT_W32(tempTerm1, 9);
} else {
maxDelayBit = 12;
tempTerm1 = tempTermX + tempMax;
/* update quantized average, shift back to Q9 */
bweStr->recMaxDelayAvgQ = WEBRTC_SPL_RSHIFT_W32(tempTerm1, 9);
}
/* Return bandwitdh and jitter index (0..23) */
return (WebRtc_UWord16)(rateInd + maxDelayBit);
}
/* get the bottle neck rate from far side to here, as estimated on this side */
WebRtc_UWord16 WebRtcIsacfix_GetDownlinkBandwidth(const BwEstimatorstr *bweStr)
{
WebRtc_UWord32 recBw;
WebRtc_Word32 jitter_sign; /* Q8 */
WebRtc_Word32 bw_adjust; /* Q16 */
WebRtc_Word32 rec_jitter_short_term_abs_inv; /* Q18 */
WebRtc_Word32 temp;
/* Q18 rec jitter short term abs is in Q13, multiply it by 2^13 to save precision
2^18 then needs to be shifted 13 bits to 2^31 */
rec_jitter_short_term_abs_inv = WEBRTC_SPL_UDIV(0x80000000, bweStr->recJitterShortTermAbs);
/* Q27 = 9 + 18 */
jitter_sign = WEBRTC_SPL_MUL(WEBRTC_SPL_RSHIFT_W32(bweStr->recJitterShortTerm, 4), (WebRtc_Word32)rec_jitter_short_term_abs_inv);
if (jitter_sign < 0) {
temp = -jitter_sign;
temp = WEBRTC_SPL_RSHIFT_W32(temp, 19);
jitter_sign = -temp;
} else {
jitter_sign = WEBRTC_SPL_RSHIFT_W32(jitter_sign, 19);
}
/* adjust bw proportionally to negative average jitter sign */
//bw_adjust = 1.0f - jitter_sign * (0.15f + 0.15f * jitter_sign * jitter_sign);
//Q8 -> Q16 .15 +.15 * jitter^2 first term is .15 in Q16 latter term is Q8*Q8*Q8
//38 in Q8 ~.15 9830 in Q16 ~.15
temp = 9830 + WEBRTC_SPL_RSHIFT_W32((WEBRTC_SPL_MUL(38, WEBRTC_SPL_MUL(jitter_sign, jitter_sign))), 8);
if (jitter_sign < 0) {
temp = WEBRTC_SPL_MUL(jitter_sign, temp);
temp = -temp;
temp = WEBRTC_SPL_RSHIFT_W32(temp, 8);
bw_adjust = (WebRtc_UWord32)65536 + temp; /* (1 << 16) + temp; */
} else {
bw_adjust = (WebRtc_UWord32)65536 - WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(jitter_sign, temp), 8);/* (1 << 16) - ((jitter_sign * temp) >> 8); */
}
//make sure following multiplication won't overflow
//bw adjust now Q14
bw_adjust = WEBRTC_SPL_RSHIFT_W32(bw_adjust, 2);//see if good resolution is maintained
/* adjust Rate if jitter sign is mostly constant */
recBw = WEBRTC_SPL_UMUL(bweStr->recBw, bw_adjust);
recBw = WEBRTC_SPL_RSHIFT_W32(recBw, 14);
/* limit range of bottle neck rate */
if (recBw < MIN_ISAC_BW) {
recBw = MIN_ISAC_BW;
} else if (recBw > MAX_ISAC_BW) {
recBw = MAX_ISAC_BW;
}
return (WebRtc_UWord16) recBw;
}
/* Returns the mmax delay (in ms) */
WebRtc_Word16 WebRtcIsacfix_GetDownlinkMaxDelay(const BwEstimatorstr *bweStr)
{
WebRtc_Word16 recMaxDelay;
recMaxDelay = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(bweStr->recMaxDelay, 15);
/* limit range of jitter estimate */
if (recMaxDelay < MIN_ISAC_MD) {
recMaxDelay = MIN_ISAC_MD;
} else if (recMaxDelay > MAX_ISAC_MD) {
recMaxDelay = MAX_ISAC_MD;
}
return recMaxDelay;
}
/* get the bottle neck rate from here to far side, as estimated by far side */
WebRtc_Word16 WebRtcIsacfix_GetUplinkBandwidth(const BwEstimatorstr *bweStr)
{
WebRtc_Word16 send_bw;
send_bw = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_U32(bweStr->sendBwAvg, 7);
/* limit range of bottle neck rate */
if (send_bw < MIN_ISAC_BW) {
send_bw = MIN_ISAC_BW;
} else if (send_bw > MAX_ISAC_BW) {
send_bw = MAX_ISAC_BW;
}
return send_bw;
}
/* Returns the max delay value from the other side in ms */
WebRtc_Word16 WebRtcIsacfix_GetUplinkMaxDelay(const BwEstimatorstr *bweStr)
{
WebRtc_Word16 send_max_delay;
send_max_delay = (WebRtc_Word16) WEBRTC_SPL_RSHIFT_W32(bweStr->sendMaxDelayAvg, 9);
/* limit range of jitter estimate */
if (send_max_delay < MIN_ISAC_MD) {
send_max_delay = MIN_ISAC_MD;
} else if (send_max_delay > MAX_ISAC_MD) {
send_max_delay = MAX_ISAC_MD;
}
return send_max_delay;
}
/*
* update long-term average bitrate and amount of data in buffer
* returns minimum payload size (bytes)
*/
WebRtc_UWord16 WebRtcIsacfix_GetMinBytes(RateModel *State,
WebRtc_Word16 StreamSize, /* bytes in bitstream */
const WebRtc_Word16 FrameSamples, /* samples per frame */
const WebRtc_Word16 BottleNeck, /* bottle neck rate; excl headers (bps) */
const WebRtc_Word16 DelayBuildUp) /* max delay from bottle neck buffering (ms) */
{
WebRtc_Word32 MinRate = 0;
WebRtc_UWord16 MinBytes;
WebRtc_Word16 TransmissionTime;
WebRtc_Word32 inv_Q12;
WebRtc_Word32 den;
/* first 10 packets @ low rate, then INIT_BURST_LEN packets @ fixed rate of INIT_RATE bps */
if (State->InitCounter > 0) {
if (State->InitCounter-- <= INIT_BURST_LEN) {
MinRate = INIT_RATE;
} else {
MinRate = 0;
}
} else {
/* handle burst */
if (State->BurstCounter) {
if (State->StillBuffered < WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL((512 - WEBRTC_SPL_DIV(512, BURST_LEN)), DelayBuildUp), 9)) {
/* max bps derived from BottleNeck and DelayBuildUp values */
inv_Q12 = WEBRTC_SPL_DIV(4096, WEBRTC_SPL_MUL(BURST_LEN, FrameSamples));
MinRate = WEBRTC_SPL_MUL(512 + WEBRTC_SPL_MUL(SAMPLES_PER_MSEC, WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(DelayBuildUp, inv_Q12), 3)), BottleNeck);
} else {
/* max bps derived from StillBuffered and DelayBuildUp values */
inv_Q12 = WEBRTC_SPL_DIV(4096, FrameSamples);
if (DelayBuildUp > State->StillBuffered) {
MinRate = WEBRTC_SPL_MUL(512 + WEBRTC_SPL_MUL(SAMPLES_PER_MSEC, WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(DelayBuildUp - State->StillBuffered, inv_Q12), 3)), BottleNeck);
} else if ((den = WEBRTC_SPL_MUL(SAMPLES_PER_MSEC, (State->StillBuffered - DelayBuildUp))) >= FrameSamples) {
/* MinRate will be negative here */
MinRate = 0;
} else {
MinRate = WEBRTC_SPL_MUL((512 - WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(den, inv_Q12), 3)), BottleNeck);
}
//if (MinRate < 1.04 * BottleNeck)
// MinRate = 1.04 * BottleNeck;
//Q9
if (MinRate < WEBRTC_SPL_MUL(532, BottleNeck)) {
MinRate += WEBRTC_SPL_MUL(22, BottleNeck);
}
}
State->BurstCounter--;
}
}
/* convert rate from bits/second to bytes/packet */
//round and shift before conversion
MinRate += 256;
MinRate = WEBRTC_SPL_RSHIFT_W32(MinRate, 9);
MinBytes = (WebRtc_UWord16)WEBRTC_SPL_UDIV(WEBRTC_SPL_MUL(MinRate, FrameSamples), FS8);
/* StreamSize will be adjusted if less than MinBytes */
if (StreamSize < MinBytes) {
StreamSize = MinBytes;
}
/* keep track of when bottle neck was last exceeded by at least 1% */
//517/512 ~ 1.01
if (WEBRTC_SPL_DIV(WEBRTC_SPL_MUL(StreamSize, FS8), FrameSamples) > (WEBRTC_SPL_MUL(517, BottleNeck) >> 9)) {
if (State->PrevExceed) {
/* bottle_neck exceded twice in a row, decrease ExceedAgo */
State->ExceedAgo -= WEBRTC_SPL_DIV(BURST_INTERVAL, BURST_LEN - 1);
if (State->ExceedAgo < 0) {
State->ExceedAgo = 0;
}
} else {
State->ExceedAgo += (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W16(FrameSamples, 4); /* ms */
State->PrevExceed = 1;
}
} else {
State->PrevExceed = 0;
State->ExceedAgo += (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W16(FrameSamples, 4); /* ms */
}
/* set burst flag if bottle neck not exceeded for long time */
if ((State->ExceedAgo > BURST_INTERVAL) && (State->BurstCounter == 0)) {
if (State->PrevExceed) {
State->BurstCounter = BURST_LEN - 1;
} else {
State->BurstCounter = BURST_LEN;
}
}
/* Update buffer delay */
TransmissionTime = (WebRtc_Word16)WEBRTC_SPL_DIV(WEBRTC_SPL_MUL(StreamSize, 8000), BottleNeck); /* ms */
State->StillBuffered += TransmissionTime;
State->StillBuffered -= (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W16(FrameSamples, 4); //>>4 = SAMPLES_PER_MSEC /* ms */
if (State->StillBuffered < 0) {
State->StillBuffered = 0;
}
if (State->StillBuffered > 2000) {
State->StillBuffered = 2000;
}
return MinBytes;
}
/*
* update long-term average bitrate and amount of data in buffer
*/
void WebRtcIsacfix_UpdateRateModel(RateModel *State,
WebRtc_Word16 StreamSize, /* bytes in bitstream */
const WebRtc_Word16 FrameSamples, /* samples per frame */
const WebRtc_Word16 BottleNeck) /* bottle neck rate; excl headers (bps) */
{
WebRtc_Word16 TransmissionTime;
/* avoid the initial "high-rate" burst */
State->InitCounter = 0;
/* Update buffer delay */
TransmissionTime = (WebRtc_Word16)WEBRTC_SPL_DIV(WEBRTC_SPL_MUL(WEBRTC_SPL_MUL(StreamSize, 8), 1000), BottleNeck); /* ms */
State->StillBuffered += TransmissionTime;
State->StillBuffered -= (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W16(FrameSamples, 4); /* ms */
if (State->StillBuffered < 0) {
State->StillBuffered = 0;
}
}
void WebRtcIsacfix_InitRateModel(RateModel *State)
{
State->PrevExceed = 0; /* boolean */
State->ExceedAgo = 0; /* ms */
State->BurstCounter = 0; /* packets */
State->InitCounter = INIT_BURST_LEN + 10; /* packets */
State->StillBuffered = 1; /* ms */
}
WebRtc_Word16 WebRtcIsacfix_GetNewFrameLength(WebRtc_Word16 bottle_neck, WebRtc_Word16 current_framesamples)
{
WebRtc_Word16 new_framesamples;
new_framesamples = current_framesamples;
/* find new framelength */
switch(current_framesamples) {
case 480:
if (bottle_neck < Thld_30_60) {
new_framesamples = 960;
}
break;
case 960:
if (bottle_neck >= Thld_60_30) {
new_framesamples = 480;
}
break;
default:
new_framesamples = -1; /* Error */
}
return new_framesamples;
}
WebRtc_Word16 WebRtcIsacfix_GetSnr(WebRtc_Word16 bottle_neck, WebRtc_Word16 framesamples)
{
WebRtc_Word16 s2nr = 0;
/* find new SNR value */
//consider BottleNeck to be in Q10 ( * 1 in Q10)
switch(framesamples) {
case 480:
/*s2nr = -1*(a_30 << 10) + ((b_30 * bottle_neck) >> 10);*/
s2nr = -22500 + (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(500, bottle_neck, 10); //* 0.001; //+ c_30 * bottle_neck * bottle_neck * 0.000001;
break;
case 960:
/*s2nr = -1*(a_60 << 10) + ((b_60 * bottle_neck) >> 10);*/
s2nr = -22500 + (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(500, bottle_neck, 10); //* 0.001; //+ c_30 * bottle_neck * bottle_neck * 0.000001;
break;
default:
s2nr = -1; /* Error */
}
return s2nr; //return in Q10
}