Changeset 868


Ignore:
Timestamp:
Dec 26, 2006 9:56:38 PM (17 years ago)
Author:
bennylp
Message:

Implement ticket #53: Disable silence detector during the first few seconds of RTP transmission to assist NAT traversal

Location:
pjproject/trunk/pjmedia
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/include/pjmedia/config.h

    r838 r868  
    173173 
    174174/** 
     175 * Specify how long (in miliseconds) the stream should suspend the 
     176 * silence detector/voice activity detector (VAD) during the initial 
     177 * period of the session. 
     178 * 
     179 * Specify zero to disable this feature. 
     180 * 
     181 * Default: 600 msec 
     182 */ 
     183#ifndef PJMEDIA_STREAM_VAD_SUSPEND_MSEC 
     184#   define PJMEDIA_STREAM_VAD_SUSPEND_MSEC      600 
     185#endif 
     186 
     187 
     188/** 
    175189 * Suggested or default threshold to be set for fixed silence detection 
    176190 * or as starting threshold for adaptive silence detection. The threshold 
  • pjproject/trunk/pjmedia/src/pjmedia/stream.c

    r863 r868  
    8989    pjmedia_codec           *codec;         /**< Codec instance being used. */ 
    9090    pjmedia_codec_param      codec_param;   /**< Codec param.               */ 
     91    unsigned                 vad_enabled;   /**< VAD enabled in param.      */ 
    9192    unsigned                 frame_size;    /**< Size of encoded base frame.*/ 
    9293    pj_bool_t                is_streaming;  /**< Currently streaming?. This 
    9394                                                 is used to put RTP marker 
    9495                                                 bit.                       */ 
     96    pj_uint32_t              ts_vad_disabled;/**< TS when VAD was disabled. */ 
     97    pj_uint32_t              tx_duration;   /**< TX duration in timestamp.  */ 
    9598 
    9699    pj_mutex_t              *jb_mutex; 
     
    126129                                   '8', '9', '*', '#', 
    127130                                   'A', 'B', 'C', 'D'}; 
     131 
     132/* Zero PCM frame */ 
     133#define ZERO_PCM_MAX_SIZE   1920    /* 40ms worth of PCM @ 48KHz */ 
     134static pj_int16_t zero_frame[ZERO_PCM_MAX_SIZE]; 
     135 
    128136 
    129137/* 
     
    448456    pj_status_t status = 0; 
    449457    struct pjmedia_frame frame_out; 
    450     unsigned ts_len; 
     458    unsigned ts_len, samples_per_frame; 
     459    pjmedia_frame tmp_in_frame; 
    451460    void *rtphdr; 
    452461    int rtphdrlen; 
     
    462471    ts_len = port->info.samples_per_frame; 
    463472 
     473    /* Increment transmit duration */ 
     474    stream->tx_duration += ts_len; 
     475 
    464476    /* Init frame_out buffer. */ 
    465477    frame_out.buf = ((char*)channel->out_pkt) + sizeof(pjmedia_rtp_hdr); 
    466478    frame_out.size = 0; 
     479 
     480    /* Calculate number of samples per frame */ 
     481    samples_per_frame = stream->codec_param.info.frm_ptime * 
     482                        stream->codec_param.info.clock_rate * 
     483                        stream->codec_param.info.channel_cnt / 
     484                        1000; 
     485 
     486    /* If VAD is temporarily disabled during creation, feed zero PCM frame 
     487     * to the codec. 
     488     */ 
     489    if (stream->vad_enabled != stream->codec_param.setting.vad && 
     490        stream->vad_enabled != 0 && 
     491        frame->type == PJMEDIA_FRAME_TYPE_NONE && 
     492        samples_per_frame <= ZERO_PCM_MAX_SIZE) 
     493    { 
     494        pj_memcpy(&tmp_in_frame, frame, sizeof(pjmedia_frame)); 
     495        frame = &tmp_in_frame; 
     496 
     497        tmp_in_frame.buf = zero_frame; 
     498        tmp_in_frame.size = samples_per_frame * 2; 
     499        tmp_in_frame.type = PJMEDIA_FRAME_TYPE_AUDIO; 
     500    } 
    467501 
    468502 
     
    482516 
    483517    } else if (frame->type != PJMEDIA_FRAME_TYPE_NONE) { 
    484         unsigned ts, samples_per_frame; 
     518        unsigned ts; 
    485519 
    486520        /* Repeatedly call encode if there are multiple frames to be 
    487521         * sent. 
    488522         */ 
    489         samples_per_frame = stream->codec_param.info.frm_ptime * 
    490                             stream->codec_param.info.clock_rate * 
    491                             stream->codec_param.info.channel_cnt / 
    492                             1000; 
    493523 
    494524        for (ts=0; ts<ts_len; ts += samples_per_frame) { 
     
    570600            stream->is_streaming = PJ_FALSE; 
    571601        } 
     602 
    572603        return PJ_SUCCESS; 
    573604    } 
     
    597628    /* Update stat */ 
    598629    pjmedia_rtcp_tx_rtp(&stream->rtcp, frame_out.size); 
     630 
     631    /* If VAD is temporarily disabled during creation, enable it 
     632     * after transmitting for VAD_SUSPEND_SEC seconds. 
     633     */ 
     634    if (stream->vad_enabled != stream->codec_param.setting.vad && 
     635        (stream->tx_duration - stream->ts_vad_disabled) >  
     636        stream->port.info.clock_rate * PJMEDIA_STREAM_VAD_SUSPEND_MSEC / 1000) 
     637    { 
     638        stream->codec_param.setting.vad = stream->vad_enabled; 
     639        stream->codec->op->modify(stream->codec, &stream->codec_param); 
     640        PJ_LOG(4,(stream->port.info.name.ptr,"VAD re-enabled")); 
     641    } 
     642 
    599643 
    600644    return PJ_SUCCESS; 
     
    10281072        goto err_cleanup; 
    10291073 
     1074 
     1075    /* Initially disable the VAD in the stream, to help traverse NAT better */ 
     1076    stream->vad_enabled = stream->codec_param.setting.vad; 
     1077    if (stream->vad_enabled) { 
     1078        stream->codec_param.setting.vad = 0; 
     1079        stream->ts_vad_disabled = 0; 
     1080        stream->codec->op->modify(stream->codec, &stream->codec_param); 
     1081        PJ_LOG(4,(stream->port.info.name.ptr,"VAD temporarily disabled")); 
     1082    } 
    10301083 
    10311084    /* Get the frame size: */ 
Note: See TracChangeset for help on using the changeset viewer.