API to control target delay in NetEq jitter buffer. NetEq maintains the given delay unless channel conditions require a higher delay.
TEST=unit-test, manual, trybots. R=henrik.lundin@webrtc.org, henrika@webrtc.org, mflodman@webrtc.org, mikhal@webrtc.org, stefan@webrtc.org, tina.legrand@webrtc.org Review URL: https://webrtc-codereview.appspot.com/1384005 git-svn-id: http://webrtc.googlecode.com/svn/trunk@4087 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
@ -216,6 +216,14 @@ int WebRtcNetEQ_UpdateIatStatistics(AutomodeInst_t *inst, int maxBufLen,
|
||||
streamingMode);
|
||||
if (tempvar > 0)
|
||||
{
|
||||
int high_lim_delay;
|
||||
/* Convert the minimum delay from milliseconds to packets in Q8.
|
||||
* |fsHz| is sampling rate in Hertz, and |inst->packetSpeechLenSamp|
|
||||
* is the number of samples per packet (according to the last
|
||||
* decoding).
|
||||
*/
|
||||
int32_t minimum_delay_q8 = ((inst->minimum_delay_ms *
|
||||
(fsHz / 1000)) << 8) / inst->packetSpeechLenSamp;
|
||||
inst->optBufLevel = tempvar;
|
||||
|
||||
if (streamingMode != 0)
|
||||
@ -224,6 +232,13 @@ int WebRtcNetEQ_UpdateIatStatistics(AutomodeInst_t *inst, int maxBufLen,
|
||||
inst->maxCSumIatQ8);
|
||||
}
|
||||
|
||||
/* The required delay. */
|
||||
inst->required_delay_q8 = inst->optBufLevel;
|
||||
|
||||
// Maintain the target delay.
|
||||
inst->optBufLevel = WEBRTC_SPL_MAX(inst->optBufLevel,
|
||||
minimum_delay_q8);
|
||||
|
||||
/*********/
|
||||
/* Limit */
|
||||
/*********/
|
||||
@ -238,8 +253,12 @@ int WebRtcNetEQ_UpdateIatStatistics(AutomodeInst_t *inst, int maxBufLen,
|
||||
maxBufLen = WEBRTC_SPL_LSHIFT_W32(maxBufLen, 8); /* shift to Q8 */
|
||||
|
||||
/* Enforce upper limit; 75% of maxBufLen */
|
||||
inst->optBufLevel = WEBRTC_SPL_MIN( inst->optBufLevel,
|
||||
(maxBufLen >> 1) + (maxBufLen >> 2) ); /* 1/2 + 1/4 = 75% */
|
||||
/* 1/2 + 1/4 = 75% */
|
||||
high_lim_delay = (maxBufLen >> 1) + (maxBufLen >> 2);
|
||||
inst->optBufLevel = WEBRTC_SPL_MIN(inst->optBufLevel,
|
||||
high_lim_delay);
|
||||
inst->required_delay_q8 = WEBRTC_SPL_MIN(inst->required_delay_q8,
|
||||
high_lim_delay);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -700,6 +719,7 @@ int WebRtcNetEQ_ResetAutomode(AutomodeInst_t *inst, int maxBufLenPackets)
|
||||
*/
|
||||
inst->optBufLevel = WEBRTC_SPL_MIN(4,
|
||||
(maxBufLenPackets >> 1) + (maxBufLenPackets >> 1)); /* 75% of maxBufLenPackets */
|
||||
inst->required_delay_q8 = inst->optBufLevel;
|
||||
inst->levelFiltFact = 253;
|
||||
|
||||
/*
|
||||
|
||||
@ -89,6 +89,12 @@ typedef struct
|
||||
reached 0 */
|
||||
int16_t extraDelayMs; /* extra delay for sync with video */
|
||||
|
||||
int minimum_delay_ms; /* Desired delay, NetEq maintains this amount of
|
||||
delay unless jitter statistics suggests a higher value. */
|
||||
int required_delay_q8; /* Smallest delay required. This is computed
|
||||
according to inter-arrival time and playout mode. It has the same unit
|
||||
as |optBufLevel|. */
|
||||
|
||||
/* Peak-detection */
|
||||
/* vector with the latest peak periods (peak spacing in samples) */
|
||||
uint32_t peakPeriodSamp[NUM_PEAKS];
|
||||
|
||||
@ -309,6 +309,19 @@ int WebRtcNetEQ_RecInSyncRTP(void* inst,
|
||||
WebRtcNetEQ_RTPInfo* rtp_info,
|
||||
uint32_t receive_timestamp);
|
||||
|
||||
/*
|
||||
* Set a minimum latency for the jitter buffer. The overall delay is the max of
|
||||
* |minimum_delay_ms| and the latency that is internally computed based on the
|
||||
* inter-arrival times.
|
||||
*/
|
||||
int WebRtcNetEQ_SetMinimumDelay(void *inst, int minimum_delay_ms);
|
||||
|
||||
/*
|
||||
* Get the least required delay in milliseconds given inter-arrival times
|
||||
* and playout mode.
|
||||
*/
|
||||
int WebRtcNetEQ_GetRequiredDelayMs(const void* inst);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -32,7 +32,9 @@ int WebRtcNetEQ_McuReset(MCUInst_t *inst)
|
||||
inst->main_inst = NULL;
|
||||
inst->one_desc = 0;
|
||||
inst->BufferStat_inst.Automode_inst.extraDelayMs = 0;
|
||||
inst->BufferStat_inst.Automode_inst.minimum_delay_ms = 0;
|
||||
inst->NetEqPlayoutMode = kPlayoutOn;
|
||||
inst->av_sync = 0;
|
||||
|
||||
WebRtcNetEQ_DbReset(&inst->codec_DB_inst);
|
||||
memset(&inst->PayloadSplit_inst, 0, sizeof(SplitInfo_t));
|
||||
|
||||
@ -437,6 +437,7 @@ int WebRtcNetEQ_Init(void *inst, uint16_t fs)
|
||||
NetEqMainInst->MCUinst.first_packet = 1;
|
||||
NetEqMainInst->MCUinst.one_desc = 0;
|
||||
NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.extraDelayMs = 0;
|
||||
NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.minimum_delay_ms = 0;
|
||||
NetEqMainInst->MCUinst.NoOfExpandCalls = 0;
|
||||
NetEqMainInst->MCUinst.fs = fs;
|
||||
|
||||
@ -529,6 +530,19 @@ int WebRtcNetEQ_SetExtraDelay(void *inst, int DelayInMs)
|
||||
return (0);
|
||||
}
|
||||
|
||||
int WebRtcNetEQ_SetMinimumDelay(void *inst, int minimum_delay_ms) {
|
||||
MainInst_t *NetEqMainInst = (MainInst_t*) inst;
|
||||
if (NetEqMainInst == NULL)
|
||||
return -1;
|
||||
if (minimum_delay_ms < 0 || minimum_delay_ms > 10000) {
|
||||
NetEqMainInst->ErrorCode = -FAULTY_DELAYVALUE;
|
||||
return -1;
|
||||
}
|
||||
NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.minimum_delay_ms =
|
||||
minimum_delay_ms;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WebRtcNetEQ_SetPlayoutMode(void *inst, enum WebRtcNetEQPlayoutMode playoutMode)
|
||||
{
|
||||
MainInst_t *NetEqMainInst = (MainInst_t*) inst;
|
||||
@ -1213,7 +1227,7 @@ int WebRtcNetEQ_GetNetworkStatistics(void *inst, WebRtcNetEQ_NetworkStatistics *
|
||||
/* Get optimal buffer size */
|
||||
/***************************/
|
||||
|
||||
if (NetEqMainInst->MCUinst.fs != 0 && NetEqMainInst->MCUinst.fs <= WEBRTC_SPL_WORD16_MAX)
|
||||
if (NetEqMainInst->MCUinst.fs != 0)
|
||||
{
|
||||
/* preferredBufferSize = Bopt * packSizeSamples / (fs/1000) */
|
||||
stats->preferredBufferSize
|
||||
@ -1693,3 +1707,25 @@ int WebRtcNetEQ_RecInSyncRTP(void* inst, WebRtcNetEQ_RTPInfo* rtp_info,
|
||||
}
|
||||
return SYNC_PAYLOAD_LEN_BYTES;
|
||||
}
|
||||
|
||||
int WebRtcNetEQ_GetRequiredDelayMs(const void* inst) {
|
||||
const MainInst_t* NetEqMainInst = (MainInst_t*)inst;
|
||||
const AutomodeInst_t* auto_mode = (NetEqMainInst == NULL) ? NULL :
|
||||
&NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst;
|
||||
|
||||
/* Instance sanity */
|
||||
if (NetEqMainInst == NULL || auto_mode == NULL)
|
||||
return 0;
|
||||
|
||||
if (NetEqMainInst->MCUinst.fs == 0)
|
||||
return 0; // Sampling rate not initialized.
|
||||
|
||||
/* |required_delay_q8| has the unit of packets in Q8 domain, therefore,
|
||||
* the corresponding delay is
|
||||
* required_delay_ms = (1000 * required_delay_q8 * samples_per_packet /
|
||||
* sample_rate_hz) / 256;
|
||||
*/
|
||||
return (auto_mode->required_delay_q8 *
|
||||
((auto_mode->packetSpeechLenSamp * 1000) / NetEqMainInst->MCUinst.fs) +
|
||||
128) >> 8;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user