Changeset 2020


Ignore:
Timestamp:
Jun 14, 2008 4:52:04 PM (16 years ago)
Author:
bennylp
Message:

Implement ticket #546 and revisit ticket #439:

  • ticket #546 implements RTCP SDES and CNAME
  • re-enable periodic RTP TX which was disabled by #439
  • fixed bug in RTCP TX interval
  • changed PJMEDIA_CODEC_MAX_SILENCE_PERIOD value from ts to msec
Location:
pjproject/trunk/pjmedia
Files:
6 edited

Legend:

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

    r2007 r2020  
    395395 
    396396/** 
    397  * Specify the maximum duration of silence period in the codec.  
     397 * Specify the maximum duration of silence period in the codec, in msec.  
    398398 * This is useful for example to keep NAT binding open in the firewall 
    399399 * and to prevent server from disconnecting the call because no  
     
    406406 * Use (-1) to disable this feature. 
    407407 * 
    408  * Default: 8000 (one second on 8KHz). 
     408 * Default: 500 ms 
    409409 * 
    410410 */ 
    411411#ifndef PJMEDIA_CODEC_MAX_SILENCE_PERIOD 
    412 #   define PJMEDIA_CODEC_MAX_SILENCE_PERIOD     8000 
     412#   define PJMEDIA_CODEC_MAX_SILENCE_PERIOD     500 
    413413#endif 
    414414 
  • pjproject/trunk/pjmedia/src/pjmedia-codec/g722.c

    r1985 r2020  
    553553        if (is_silence && 
    554554            PJMEDIA_CODEC_MAX_SILENCE_PERIOD != -1 && 
    555             silence_duration < PJMEDIA_CODEC_MAX_SILENCE_PERIOD)  
     555            silence_duration < PJMEDIA_CODEC_MAX_SILENCE_PERIOD*16000/1000)  
    556556        { 
    557557            output->type = PJMEDIA_FRAME_TYPE_NONE; 
  • pjproject/trunk/pjmedia/src/pjmedia-codec/gsm.c

    r2015 r2020  
    543543        if (is_silence && 
    544544            PJMEDIA_CODEC_MAX_SILENCE_PERIOD != -1 && 
    545             silence_duration < PJMEDIA_CODEC_MAX_SILENCE_PERIOD)  
     545            silence_duration < PJMEDIA_CODEC_MAX_SILENCE_PERIOD*8000/1000)  
    546546        { 
    547547            output->type = PJMEDIA_FRAME_TYPE_NONE; 
  • pjproject/trunk/pjmedia/src/pjmedia-codec/ilbc.c

    r1985 r2020  
    540540        if (is_silence && 
    541541            PJMEDIA_CODEC_MAX_SILENCE_PERIOD != -1 && 
    542             silence_period < PJMEDIA_CODEC_MAX_SILENCE_PERIOD) 
     542            silence_period < PJMEDIA_CODEC_MAX_SILENCE_PERIOD*8000/1000) 
    543543        { 
    544544            output->type = PJMEDIA_FRAME_TYPE_NONE; 
  • pjproject/trunk/pjmedia/src/pjmedia/g711.c

    r1985 r2020  
    503503        if (is_silence &&  
    504504            PJMEDIA_CODEC_MAX_SILENCE_PERIOD != -1 && 
    505             silence_period < PJMEDIA_CODEC_MAX_SILENCE_PERIOD)  
     505            silence_period < PJMEDIA_CODEC_MAX_SILENCE_PERIOD*8000/1000)  
    506506        { 
    507507            output->type = PJMEDIA_FRAME_TYPE_NONE; 
  • pjproject/trunk/pjmedia/src/pjmedia/stream.c

    r1985 r2020  
    8484    pjmedia_dir              dir;           /**< Stream direction.          */ 
    8585    void                    *user_data;     /**< User data.                 */ 
     86    pj_str_t                 cname;         /**< SDES CNAME                 */ 
    8687 
    8788    pjmedia_transport       *transport;     /**< Stream transport.          */ 
     
    116117    pj_uint32_t              rtcp_last_tx;  /**< RTCP tx time in timestamp  */ 
    117118    pj_uint32_t              rtcp_interval; /**< Interval, in timestamp.    */ 
     119    pj_bool_t                initial_rr;    /**< Initial RTCP RR sent       */ 
    118120 
    119121    /* RFC 2833 DTMF transmission queue: */ 
     
    177179                                   'A', 'B', 'C', 'D'}; 
    178180 
     181/* Zero audio frame samples */ 
     182static pj_int16_t zero_frame[30 * 16000 / 1000]; 
     183 
    179184/* 
    180185 * Print error. 
     
    535540} 
    536541 
     542/* Build RTCP SDES packet */ 
     543static unsigned create_rtcp_sdes(pjmedia_stream *stream, pj_uint8_t *pkt, 
     544                                 unsigned max_len) 
     545{ 
     546    pjmedia_rtcp_common hdr; 
     547    pj_uint8_t *p = pkt; 
     548 
     549    /* SDES header */ 
     550    hdr.version = 2; 
     551    hdr.p = 0; 
     552    hdr.count = 1; 
     553    hdr.pt = 202; 
     554    hdr.length = 2 + (4+stream->cname.slen+3)/4 - 1; 
     555    if (max_len < (hdr.length << 2)) { 
     556        pj_assert(!"Not enough buffer for SDES packet"); 
     557        return 0; 
     558    } 
     559    hdr.length = pj_htons((pj_uint16_t)hdr.length); 
     560    hdr.ssrc = stream->enc->rtp.out_hdr.ssrc; 
     561    pj_memcpy(p, &hdr, sizeof(hdr)); 
     562    p += sizeof(hdr); 
     563 
     564    /* CNAME item */ 
     565    *p++ = 1; 
     566    *p++ = (pj_uint8_t)stream->cname.slen; 
     567    pj_memcpy(p, stream->cname.ptr, stream->cname.slen); 
     568    p += stream->cname.slen; 
     569 
     570    /* END */ 
     571    *p++ = '\0'; 
     572    *p++ = '\0'; 
     573 
     574    /* Pad to 32bit */ 
     575    while ((p-pkt) % 4) 
     576        *p++ = '\0'; 
     577 
     578    return (p - pkt); 
     579} 
     580 
     581/* Build RTCP BYE packet */ 
     582static unsigned create_rtcp_bye(pjmedia_stream *stream, pj_uint8_t *pkt, 
     583                                unsigned max_len) 
     584{ 
     585    pjmedia_rtcp_common hdr; 
     586 
     587    /* BYE header */ 
     588    hdr.version = 2; 
     589    hdr.p = 0; 
     590    hdr.count = 1; 
     591    hdr.pt = 203; 
     592    hdr.length = 1; 
     593    if (max_len < (hdr.length << 2)) { 
     594        pj_assert(!"Not enough buffer for SDES packet"); 
     595        return 0; 
     596    } 
     597    hdr.length = pj_htons((pj_uint16_t)hdr.length); 
     598    hdr.ssrc = stream->enc->rtp.out_hdr.ssrc; 
     599    pj_memcpy(pkt, &hdr, sizeof(hdr)); 
     600 
     601    return sizeof(hdr); 
     602} 
     603 
    537604 
    538605/** 
     
    674741        } 
    675742 
    676         /* No need to encode if this is a zero frame. 
    677          * See http://www.pjsip.org/trac/ticket/439  
    678          */ 
     743 
     744    /* 
     745     * Special treatment for FRAME_TYPE_AUDIO but with frame->buf==NULL. 
     746     * This happens when stream input is disconnected from the bridge. 
     747     * In this case we periodically transmit RTP frame to keep NAT binding 
     748     * open, by giving zero PCM frame to the codec. 
     749     * 
     750     * This was originally done in http://trac.pjsip.org/repos/ticket/56, 
     751     * but then disabled in http://trac.pjsip.org/repos/ticket/439, but 
     752     * now it's enabled again. 
     753     */ 
     754    } else if (frame->type == PJMEDIA_FRAME_TYPE_AUDIO && 
     755               frame->buf == NULL && 
     756               (stream->dir & PJMEDIA_DIR_ENCODING) && 
     757               stream->codec_param.info.frm_ptime * 
     758                stream->codec_param.info.clock_rate/1000 < 
     759                  PJ_ARRAY_SIZE(zero_frame))  
     760    { 
     761        pjmedia_frame silence_frame; 
     762 
     763        pj_bzero(&silence_frame, sizeof(silence_frame)); 
     764        silence_frame.buf = zero_frame; 
     765        silence_frame.size = stream->codec_param.info.frm_ptime * 2 * 
     766                              stream->codec_param.info.clock_rate / 1000; 
     767        silence_frame.type = PJMEDIA_FRAME_TYPE_AUDIO; 
     768        silence_frame.timestamp.u32.lo = pj_ntohl(stream->enc->rtp.out_hdr.ts); 
     769         
     770        /* Encode! */ 
     771        status = stream->codec->op->encode( stream->codec, &silence_frame, 
     772                                            channel->out_pkt_size -  
     773                                            sizeof(pjmedia_rtp_hdr), 
     774                                            &frame_out); 
     775        if (status != PJ_SUCCESS) { 
     776            LOGERR_((stream->port.info.name.ptr,  
     777                    "Codec encode() error", status)); 
     778            return status; 
     779        } 
     780 
     781        /* Encapsulate. */ 
     782        status = pjmedia_rtp_encode_rtp( &channel->rtp,  
     783                                         channel->pt, 0,  
     784                                         frame_out.size, rtp_ts_len,  
     785                                         (const void**)&rtphdr,  
     786                                         &rtphdrlen); 
     787 
     788 
     789    /* Encode audio frame */ 
    679790    } else if (frame->type != PJMEDIA_FRAME_TYPE_NONE && 
    680791               frame->buf != NULL)  
     
    697808                                         (const void**)&rtphdr,  
    698809                                         &rtphdrlen); 
     810 
    699811    } else { 
    700812 
     
    12051317    pjmedia_rtcp_rx_rtp2(&stream->rtcp, pj_ntohs(hdr->seq), 
    12061318                         pj_ntohl(hdr->ts), payloadlen, pkt_discarded); 
     1319 
     1320    /* Send RTCP RR and SDES after we receive some RTP packets */ 
     1321    if (stream->rtcp.received >= 10 && !stream->initial_rr) { 
     1322        void *sr_rr_pkt; 
     1323        pj_uint8_t *pkt; 
     1324        int len; 
     1325 
     1326        /* Build RR or SR */ 
     1327        pjmedia_rtcp_build_rtcp(&stream->rtcp, &sr_rr_pkt, &len); 
     1328        pkt = (pj_uint8_t*) stream->enc->out_pkt; 
     1329        pj_memcpy(pkt, sr_rr_pkt, len); 
     1330        pkt += len; 
     1331 
     1332        /* Append SDES */ 
     1333        len = create_rtcp_sdes(stream, (pj_uint8_t*)pkt,  
     1334                               stream->enc->out_pkt_size - len); 
     1335        if (len > 0) { 
     1336            pkt += len; 
     1337            len = ((pj_uint8_t*)pkt) - ((pj_uint8_t*)stream->enc->out_pkt); 
     1338            pjmedia_transport_send_rtcp(stream->transport,  
     1339                                        stream->enc->out_pkt, len); 
     1340        } 
     1341 
     1342        stream->initial_rr = PJ_TRUE; 
     1343    } 
    12071344} 
    12081345 
     
    13021439    pjmedia_stream *stream; 
    13031440    pj_str_t name; 
    1304     unsigned jb_init, jb_max, jb_min_pre, jb_max_pre; 
     1441    unsigned jb_init, jb_max, jb_min_pre, jb_max_pre, len; 
     1442    char *p; 
    13051443    pj_status_t status; 
    13061444 
     
    13401478    stream->dir = info->dir; 
    13411479    stream->user_data = user_data; 
    1342     stream->rtcp_interval = (PJMEDIA_RTCP_INTERVAL + (pj_rand() % 8000)) *  
     1480    stream->rtcp_interval = (PJMEDIA_RTCP_INTERVAL-500 + (pj_rand()%1000)) * 
    13431481                            info->fmt.clock_rate / 1000; 
    13441482 
     
    13461484    stream->rx_event_pt = info->rx_event_pt ? info->rx_event_pt : -1; 
    13471485    stream->last_dtmf = -1; 
     1486 
     1487    /* Build random RTCP CNAME. CNAME has user@host format */ 
     1488    stream->cname.ptr = p = (char*) pj_pool_alloc(pool, 20); 
     1489    pj_create_random_string(p, 5); 
     1490    p += 5; 
     1491    *p++ = '@'; *p++ = 'p'; *p++ = 'j'; 
     1492    pj_create_random_string(p, 6); 
     1493    p += 6; 
     1494    *p++ = '.'; *p++ = 'o'; *p++ = 'r'; *p++ = 'g'; 
     1495    stream->cname.slen = p - stream->cname.ptr; 
    13481496 
    13491497 
     
    16101758#endif 
    16111759 
     1760    /* Send RTCP SDES */ 
     1761    len = create_rtcp_sdes(stream, stream->enc->out_pkt,  
     1762                           stream->enc->out_pkt_size); 
     1763    if (len != 0) { 
     1764        pjmedia_transport_send_rtcp(stream->transport,  
     1765                                    stream->enc->out_pkt, len); 
     1766    } 
     1767 
    16121768    /* Success! */ 
    16131769    *p_stream = stream; 
     
    16291785PJ_DEF(pj_status_t) pjmedia_stream_destroy( pjmedia_stream *stream ) 
    16301786{ 
    1631  
     1787    unsigned len; 
    16321788    PJ_ASSERT_RETURN(stream != NULL, PJ_EINVAL); 
    16331789 
     
    16691825    } 
    16701826#endif 
     1827 
     1828    /* Send RTCP BYE */ 
     1829    len = create_rtcp_bye(stream, stream->enc->out_pkt,  
     1830                          stream->enc->out_pkt_size); 
     1831    if (len != 0) { 
     1832        pjmedia_transport_send_rtcp(stream->transport,  
     1833                                    stream->enc->out_pkt, len); 
     1834    } 
    16711835 
    16721836    /* Detach from transport  
Note: See TracChangeset for help on using the changeset viewer.