diff options
author | Benny Prijono <bennylp@teluu.com> | 2006-12-26 21:56:38 +0000 |
---|---|---|
committer | Benny Prijono <bennylp@teluu.com> | 2006-12-26 21:56:38 +0000 |
commit | f6ff4e00da1d8bd928f16378c8d6c99a92c6d364 (patch) | |
tree | e1c039f27690141632bf01fbbbc982a1af2a19aa /pjmedia | |
parent | 47d417ed5eb941ec7bdde985a05340ae184d6fc7 (diff) |
Implement ticket #53: Disable silence detector during the first few seconds of RTP transmission to assist NAT traversal
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@868 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjmedia')
-rw-r--r-- | pjmedia/include/pjmedia/config.h | 14 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/stream.c | 65 |
2 files changed, 73 insertions, 6 deletions
diff --git a/pjmedia/include/pjmedia/config.h b/pjmedia/include/pjmedia/config.h index b705e6f4..ea84baa5 100644 --- a/pjmedia/include/pjmedia/config.h +++ b/pjmedia/include/pjmedia/config.h @@ -172,6 +172,20 @@ /** + * Specify how long (in miliseconds) the stream should suspend the + * silence detector/voice activity detector (VAD) during the initial + * period of the session. + * + * Specify zero to disable this feature. + * + * Default: 600 msec + */ +#ifndef PJMEDIA_STREAM_VAD_SUSPEND_MSEC +# define PJMEDIA_STREAM_VAD_SUSPEND_MSEC 600 +#endif + + +/** * Suggested or default threshold to be set for fixed silence detection * or as starting threshold for adaptive silence detection. The threshold * has the range from zero to 255. diff --git a/pjmedia/src/pjmedia/stream.c b/pjmedia/src/pjmedia/stream.c index 0c67a15c..9c032bbf 100644 --- a/pjmedia/src/pjmedia/stream.c +++ b/pjmedia/src/pjmedia/stream.c @@ -88,10 +88,13 @@ struct pjmedia_stream pjmedia_codec *codec; /**< Codec instance being used. */ pjmedia_codec_param codec_param; /**< Codec param. */ + unsigned vad_enabled; /**< VAD enabled in param. */ unsigned frame_size; /**< Size of encoded base frame.*/ pj_bool_t is_streaming; /**< Currently streaming?. This is used to put RTP marker bit. */ + pj_uint32_t ts_vad_disabled;/**< TS when VAD was disabled. */ + pj_uint32_t tx_duration; /**< TX duration in timestamp. */ pj_mutex_t *jb_mutex; pjmedia_jbuf *jb; /**< Jitter buffer. */ @@ -126,6 +129,11 @@ static const char digitmap[16] = { '0', '1', '2', '3', '8', '9', '*', '#', 'A', 'B', 'C', 'D'}; +/* Zero PCM frame */ +#define ZERO_PCM_MAX_SIZE 1920 /* 40ms worth of PCM @ 48KHz */ +static pj_int16_t zero_frame[ZERO_PCM_MAX_SIZE]; + + /* * Print error. */ @@ -447,7 +455,8 @@ static pj_status_t put_frame( pjmedia_port *port, pjmedia_channel *channel = stream->enc; pj_status_t status = 0; struct pjmedia_frame frame_out; - unsigned ts_len; + unsigned ts_len, samples_per_frame; + pjmedia_frame tmp_in_frame; void *rtphdr; int rtphdrlen; @@ -461,10 +470,35 @@ static pj_status_t put_frame( pjmedia_port *port, //ts_len = frame->size / 2; ts_len = port->info.samples_per_frame; + /* Increment transmit duration */ + stream->tx_duration += ts_len; + /* Init frame_out buffer. */ frame_out.buf = ((char*)channel->out_pkt) + sizeof(pjmedia_rtp_hdr); frame_out.size = 0; + /* Calculate number of samples per frame */ + samples_per_frame = stream->codec_param.info.frm_ptime * + stream->codec_param.info.clock_rate * + stream->codec_param.info.channel_cnt / + 1000; + + /* If VAD is temporarily disabled during creation, feed zero PCM frame + * to the codec. + */ + if (stream->vad_enabled != stream->codec_param.setting.vad && + stream->vad_enabled != 0 && + frame->type == PJMEDIA_FRAME_TYPE_NONE && + samples_per_frame <= ZERO_PCM_MAX_SIZE) + { + pj_memcpy(&tmp_in_frame, frame, sizeof(pjmedia_frame)); + frame = &tmp_in_frame; + + tmp_in_frame.buf = zero_frame; + tmp_in_frame.size = samples_per_frame * 2; + tmp_in_frame.type = PJMEDIA_FRAME_TYPE_AUDIO; + } + /* If we have DTMF digits in the queue, transmit the digits. * Otherwise encode the PCM buffer. @@ -481,15 +515,11 @@ static pj_status_t put_frame( pjmedia_port *port, &rtphdrlen); } else if (frame->type != PJMEDIA_FRAME_TYPE_NONE) { - unsigned ts, samples_per_frame; + unsigned ts; /* Repeatedly call encode if there are multiple frames to be * sent. */ - samples_per_frame = stream->codec_param.info.frm_ptime * - stream->codec_param.info.clock_rate * - stream->codec_param.info.channel_cnt / - 1000; for (ts=0; ts<ts_len; ts += samples_per_frame) { pjmedia_frame tmp_out_frame, tmp_in_frame; @@ -569,6 +599,7 @@ static pj_status_t put_frame( pjmedia_port *port, PJ_LOG(5,(stream->port.info.name.ptr,"Starting silence")); stream->is_streaming = PJ_FALSE; } + return PJ_SUCCESS; } @@ -597,6 +628,19 @@ static pj_status_t put_frame( pjmedia_port *port, /* Update stat */ pjmedia_rtcp_tx_rtp(&stream->rtcp, frame_out.size); + /* If VAD is temporarily disabled during creation, enable it + * after transmitting for VAD_SUSPEND_SEC seconds. + */ + if (stream->vad_enabled != stream->codec_param.setting.vad && + (stream->tx_duration - stream->ts_vad_disabled) > + stream->port.info.clock_rate * PJMEDIA_STREAM_VAD_SUSPEND_MSEC / 1000) + { + stream->codec_param.setting.vad = stream->vad_enabled; + stream->codec->op->modify(stream->codec, &stream->codec_param); + PJ_LOG(4,(stream->port.info.name.ptr,"VAD re-enabled")); + } + + return PJ_SUCCESS; } @@ -1028,6 +1072,15 @@ PJ_DEF(pj_status_t) pjmedia_stream_create( pjmedia_endpt *endpt, goto err_cleanup; + /* Initially disable the VAD in the stream, to help traverse NAT better */ + stream->vad_enabled = stream->codec_param.setting.vad; + if (stream->vad_enabled) { + stream->codec_param.setting.vad = 0; + stream->ts_vad_disabled = 0; + stream->codec->op->modify(stream->codec, &stream->codec_param); + PJ_LOG(4,(stream->port.info.name.ptr,"VAD temporarily disabled")); + } + /* Get the frame size: */ stream->frame_size = (stream->codec_param.info.avg_bps / 8) * |