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:
turaj@webrtc.org
2013-05-22 20:39:43 +00:00
parent 561990fd73
commit e46c8d3875
19 changed files with 405 additions and 74 deletions

View File

@ -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;
/*

View File

@ -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];

View File

@ -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

View File

@ -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));

View File

@ -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;
}