Changeset 568 for pjproject


Ignore:
Timestamp:
Jun 29, 2006 2:45:17 PM (18 years ago)
Author:
bennylp
Message:

Improvements in PJMEDIA to support RFC 3605 (RTCP attribute in SDP) and other changes to improve RTCP communication behind NAT. Also fixed bug related to RTCP reporting changes in revision 565

Location:
pjproject/trunk
Files:
15 edited

Legend:

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

    r518 r568  
    156156 
    157157/** 
     158 * Support for sending and decoding RTCP port in SDP (RFC 3605). 
     159 * Default is yes. 
     160 */ 
     161#ifndef PJMEDIA_HAS_RTCP_IN_SDP 
     162#   define PJMEDIA_HAS_RTCP_IN_SDP              1 
     163#endif 
     164 
     165 
     166 
     167/** 
    158168 * @} 
    159169 */ 
  • pjproject/trunk/pjmedia/include/pjmedia/errno.h

    r518 r568  
    141141/** 
    142142 * @hideinitializer 
    143  * Invalid fmtp attribute. 
     143 * Invalid SDP "fmtp" attribute. 
    144144 */ 
    145145#define PJMEDIA_SDP_EINFMTP         (PJMEDIA_ERRNO_START+34)    /* 220034 */ 
     146/** 
     147 * @hideinitializer 
     148 * Invalid SDP "rtcp" attribute. 
     149 */ 
     150#define PJMEDIA_SDP_EINRTCP         (PJMEDIA_ERRNO_START+35)    /* 220035 */ 
    146151 
    147152 
  • pjproject/trunk/pjmedia/include/pjmedia/sdp.h

    r518 r568  
    292292PJ_DECL(pj_status_t) pjmedia_sdp_attr_get_fmtp(const pjmedia_sdp_attr *attr, 
    293293                                               pjmedia_sdp_fmtp *fmtp); 
     294 
     295 
     296/** 
     297 * This structure describes SDP \a rtcp attribute. 
     298 */ 
     299typedef struct pjmedia_sdp_rtcp_attr 
     300{ 
     301    unsigned    port;       /**< RTCP port number.          */ 
     302    pj_str_t    net_type;   /**< Optional network type.     */ 
     303    pj_str_t    addr_type;  /**< Optional address type.     */ 
     304    pj_str_t    addr;       /**< Optional address.          */ 
     305} pjmedia_sdp_rtcp_attr; 
     306 
     307 
     308/** 
     309 * Parse a generic SDP attribute to get SDP rtcp attribute values. 
     310 * 
     311 * @param attr          Generic attribute to be converted to rtcp, which 
     312 *                      name must be "rtcp". 
     313 * @param rtcp          SDP rtcp attribute to be initialized. 
     314 * 
     315 * @return              PJ_SUCCESS on success. 
     316 */ 
     317PJ_DECL(pj_status_t) pjmedia_sdp_attr_get_rtcp(const pjmedia_sdp_attr *attr, 
     318                                               pjmedia_sdp_rtcp_attr *rtcp); 
     319 
    294320 
    295321 
  • pjproject/trunk/pjmedia/include/pjmedia/stream.h

    r518 r568  
    9292    pjmedia_dir         dir;        /**< Media direction.                   */ 
    9393    pj_sockaddr_in      rem_addr;   /**< Remote RTP address                 */ 
     94    pj_sockaddr_in      rem_rtcp;   /**< Optional remote RTCP address. If 
     95                                         sin_family is zero, the RTP address 
     96                                         will be calculated from RTP.       */ 
    9497    pjmedia_codec_info  fmt;        /**< Incoming codec format info.        */ 
    9598    pjmedia_codec_param *param;     /**< Optional codec param.              */ 
  • pjproject/trunk/pjmedia/include/pjmedia/transport.h

    r539 r568  
    7474                          void *user_data, 
    7575                          const pj_sockaddr_t *rem_addr, 
     76                          const pj_sockaddr_t *rem_rtcp, 
    7677                          unsigned addr_len, 
    7778                          void (*rtp_cb)(void *user_data, 
     
    155156 *                  called. 
    156157 * @param rem_addr  Remote RTP address to send RTP packet to. 
     158 * @param rem_rtcp  Optional remote RTCP address. If the argument is NULL 
     159 *                  or if the address is zero, the RTCP address will be 
     160 *                  calculated from the RTP address (which is RTP port 
     161 *                  plus one). 
    157162 * @param addr_len  Length of the remote address. 
    158163 * @param rtp_cb    Callback to be called when RTP packet is received on 
     
    166171                                                void *user_data, 
    167172                                                const pj_sockaddr_t *rem_addr, 
     173                                                const pj_sockaddr_t *rem_rtcp, 
    168174                                                unsigned addr_len, 
    169175                                                void (*rtp_cb)(void *user_data, 
     
    174180                                                                pj_ssize_t)) 
    175181{ 
    176     return tp->op->attach(tp, user_data, rem_addr, addr_len, rtp_cb, rtcp_cb); 
     182    return tp->op->attach(tp, user_data, rem_addr, rem_rtcp, addr_len,  
     183                          rtp_cb, rtcp_cb); 
    177184} 
    178185 
  • pjproject/trunk/pjmedia/src/pjmedia/endpoint.c

    r438 r568  
    328328    pj_strdup (pool, &m->desc.transport, &STR_RTP_AVP); 
    329329 
    330     /* Add format and rtpmap for each codec. */ 
     330    /* Init media line and attribute list. */ 
    331331    m->desc.fmt_count = 0; 
    332332    m->attr_count = 0; 
    333333 
     334    /* Add "rtcp" attribute */ 
     335#if 1 
     336    { 
     337        attr = pj_pool_alloc(pool, sizeof(pjmedia_sdp_attr)); 
     338        attr->name = pj_str("rtcp"); 
     339        attr->value.ptr = pj_pool_alloc(pool, 80); 
     340        attr->value.slen =  
     341            pj_ansi_snprintf(attr->value.ptr, 80, 
     342                            ":%u IN IP4 %s", 
     343                            pj_ntohs(sock_info[0].rtp_addr_name.sin_port), 
     344                            pj_inet_ntoa(sock_info[0].rtp_addr_name.sin_addr)); 
     345        pjmedia_sdp_attr_add(&m->attr_count, m->attr, attr); 
     346    } 
     347#endif 
     348 
     349    /* Add format and rtpmap for each codec */ 
    334350    for (i=0; i<endpt->codec_mgr.codec_cnt; ++i) { 
    335351 
  • pjproject/trunk/pjmedia/src/pjmedia/errno.c

    r534 r568  
    5656    PJ_BUILD_ERR( PJMEDIA_SDP_EINPT,        "Invalid SDP payload type in media line" ), 
    5757    PJ_BUILD_ERR( PJMEDIA_SDP_EINFMTP,      "Invalid SDP fmtp attribute" ), 
     58    PJ_BUILD_ERR( PJMEDIA_SDP_EINRTCP,      "Invalid SDP rtcp attribyte" ), 
    5859 
    5960    /* SDP negotiator errors. */ 
  • pjproject/trunk/pjmedia/src/pjmedia/sdp.c

    r366 r568  
    6060static void parse_media(pj_scanner *scanner, pjmedia_sdp_media *med, 
    6161                        parse_context *ctx); 
    62  
     62static void on_scanner_error(pj_scanner *scanner); 
    6363 
    6464/* 
     
    242242                                                 pjmedia_sdp_rtpmap *rtpmap) 
    243243{ 
    244     const char *p = attr->value.ptr; 
    245     const char *end = attr->value.ptr + attr->value.slen; 
     244    pj_scanner scanner; 
    246245    pj_str_t token; 
     246    pj_status_t status = -1; 
     247    PJ_USE_EXCEPTION; 
    247248 
    248249    PJ_ASSERT_RETURN(pj_strcmp2(&attr->name, "rtpmap")==0, PJ_EINVALIDOP); 
     250 
     251    pj_scan_init(&scanner, (char*)attr->value.ptr, attr->value.slen, 
     252                 PJ_SCAN_AUTOSKIP_WS, &on_scanner_error); 
    249253 
    250254    /* rtpmap sample: 
     
    252256     */ 
    253257 
    254     /* Eat the first ':' */ 
    255     if (*p != ':') return PJMEDIA_SDP_EINRTPMAP; 
    256  
    257     /* Get ':' */ 
    258     ++p; 
    259  
    260     /* Get payload type. */ 
    261     token.ptr = (char*)p; 
    262     while (pj_isdigit(*p) && p!=end) 
    263         ++p; 
    264     token.slen = p - token.ptr; 
    265     if (token.slen == 0) 
    266         return PJMEDIA_SDP_EINRTPMAP; 
    267  
    268     rtpmap->pt = token; 
    269  
    270     /* Expecting space after payload type. */ 
    271     if (*p != ' ') return PJMEDIA_SDP_EINRTPMAP; 
    272  
    273     /* Get space. */ 
    274     ++p; 
    275  
    276     /* Get encoding name. */ 
    277     token.ptr = (char*)p; 
    278     while (*p != '/' && p != end) 
    279         ++p; 
    280     token.slen = p - token.ptr; 
    281     if (token.slen == 0) 
    282         return PJMEDIA_SDP_EINRTPMAP; 
    283     rtpmap->enc_name = token; 
    284  
    285     /* Expecting '/' after encoding name. */ 
    286     if (*p != '/') return PJMEDIA_SDP_EINRTPMAP; 
    287  
    288     /* Get '/' */ 
    289     ++p; 
    290  
    291     /* Get the clock rate. */ 
    292     token.ptr = (char*)p; 
    293     while (p != end && pj_isdigit(*p)) 
    294         ++p; 
    295     token.slen = p - token.ptr; 
    296     if (token.slen == 0) 
    297         return PJMEDIA_SDP_EINRTPMAP; 
    298  
    299     rtpmap->clock_rate = pj_strtoul(&token); 
    300  
    301     /* Expecting either '/' or EOF */ 
    302     if (p != end && *p != '/') 
    303         return PJMEDIA_SDP_EINRTPMAP; 
    304  
    305     if (p != end) { 
    306         ++p; 
    307         token.ptr = (char*)p; 
    308         token.slen = end-p; 
    309         rtpmap->param = token; 
    310     } else { 
    311         rtpmap->param.ptr = NULL; 
    312         rtpmap->param.slen = 0; 
    313     } 
    314  
    315     return PJ_SUCCESS; 
    316  
     258    /* Init */ 
     259    rtpmap->pt.slen = rtpmap->param.slen = rtpmap->enc_name.slen = 0; 
     260 
     261    /* Parse */ 
     262    PJ_TRY { 
     263        /* Eat the first ':' */ 
     264        if (pj_scan_get_char(&scanner) != ':') { 
     265            status = PJMEDIA_SDP_EINRTPMAP; 
     266            goto on_return; 
     267        } 
     268 
     269 
     270        /* Get payload type. */ 
     271        pj_scan_get(&scanner, &cs_token, &rtpmap->pt); 
     272 
     273 
     274        /* Get encoding name. */ 
     275        pj_scan_get(&scanner, &cs_token, &rtpmap->enc_name); 
     276 
     277        /* Expecting '/' after encoding name. */ 
     278        if (pj_scan_get_char(&scanner) != '/') { 
     279            status = PJMEDIA_SDP_EINRTPMAP; 
     280            goto on_return; 
     281        } 
     282 
     283 
     284        /* Get the clock rate. */ 
     285        pj_scan_get(&scanner, &cs_token, &token); 
     286        rtpmap->clock_rate = pj_strtoul(&token); 
     287 
     288        /* Expecting either '/' or EOF */ 
     289        if (*scanner.curptr == '/') { 
     290            pj_scan_get_char(&scanner); 
     291            rtpmap->param.ptr = scanner.curptr; 
     292            rtpmap->param.slen = scanner.end - scanner.curptr; 
     293        } else { 
     294            rtpmap->param.slen = 0; 
     295        } 
     296 
     297        status = PJ_SUCCESS; 
     298    } 
     299    PJ_CATCH(SYNTAX_ERROR) { 
     300        status = PJMEDIA_SDP_EINRTPMAP; 
     301    } 
     302    PJ_END; 
     303 
     304 
     305on_return: 
     306    pj_scan_fini(&scanner); 
     307    return status; 
    317308} 
    318309 
     
    359350} 
    360351 
     352 
     353PJ_DEF(pj_status_t) pjmedia_sdp_attr_get_rtcp(const pjmedia_sdp_attr *attr, 
     354                                              pjmedia_sdp_rtcp_attr *rtcp) 
     355{ 
     356    pj_scanner scanner; 
     357    pj_str_t token; 
     358    pj_status_t status = -1; 
     359    PJ_USE_EXCEPTION; 
     360 
     361    PJ_ASSERT_RETURN(pj_strcmp2(&attr->name, "rtcp")==0, PJ_EINVALIDOP); 
     362 
     363    /* fmtp BNF: 
     364     *  a=rtcp:<port> [nettype addrtype address] 
     365     */ 
     366 
     367    pj_scan_init(&scanner, (char*)attr->value.ptr, attr->value.slen, 
     368                 PJ_SCAN_AUTOSKIP_WS, &on_scanner_error); 
     369 
     370    /* Init */ 
     371    rtcp->net_type.slen = rtcp->addr_type.slen = rtcp->addr.slen = 0; 
     372 
     373    /* Parse */ 
     374    PJ_TRY { 
     375 
     376        /* Get the first ":" */ 
     377        if (pj_scan_get_char(&scanner) != ':') 
     378        { 
     379            status = PJMEDIA_SDP_EINRTCP; 
     380            goto on_return; 
     381        } 
     382 
     383        /* Get the port */ 
     384        pj_scan_get(&scanner, &cs_token, &token); 
     385        rtcp->port = pj_strtoul(&token); 
     386 
     387        /* Have address? */ 
     388        if (!pj_scan_is_eof(&scanner)) { 
     389 
     390            /* Get network type */ 
     391            pj_scan_get(&scanner, &cs_token, &rtcp->net_type); 
     392 
     393            /* Get address type */ 
     394            pj_scan_get(&scanner, &cs_token, &rtcp->addr_type); 
     395 
     396            /* Get the address */ 
     397            pj_scan_get(&scanner, &cs_token, &rtcp->addr); 
     398 
     399        } 
     400 
     401        status = PJ_SUCCESS; 
     402 
     403    } 
     404    PJ_CATCH(SYNTAX_ERROR) { 
     405        status = PJMEDIA_SDP_EINRTCP; 
     406    } 
     407    PJ_END; 
     408 
     409on_return: 
     410    pj_scan_fini(&scanner); 
     411    return status; 
     412} 
     413 
     414 
     415 
    361416PJ_DEF(pj_status_t) pjmedia_sdp_attr_to_rtpmap(pj_pool_t *pool, 
    362417                                               const pjmedia_sdp_attr *attr, 
     
    377432{ 
    378433    pjmedia_sdp_attr *attr; 
    379     char tempbuf[64], *p, *endbuf; 
    380     int i; 
     434    char tempbuf[64]; 
     435    int len; 
    381436 
    382437    /* Check arguments. */ 
     
    387442                     PJMEDIA_SDP_EINRTPMAP); 
    388443 
    389     /* Check size. */ 
    390     i = rtpmap->enc_name.slen + rtpmap->param.slen + 32; 
    391     if (i >= sizeof(tempbuf)-1) { 
    392         pj_assert(!"rtpmap attribute is too long"); 
    393         return PJMEDIA_SDP_ERTPMAPTOOLONG; 
    394     } 
    395444 
    396445    attr = pj_pool_alloc(pool, sizeof(pjmedia_sdp_attr)); 
     
    400449    attr->name.slen = 6; 
    401450 
    402     p = tempbuf; 
    403     endbuf = tempbuf+sizeof(tempbuf); 
    404  
    405     /* Add colon */ 
    406     *p++ = ':'; 
    407  
    408     /* Add payload type. */ 
    409     pj_memcpy(p, rtpmap->pt.ptr, rtpmap->pt.slen); 
    410     p += rtpmap->pt.slen; 
    411     *p++ = ' '; 
    412  
    413     /* Add encoding name. */ 
    414     for (i=0; i<rtpmap->enc_name.slen; ++i) 
    415         p[i] = rtpmap->enc_name.ptr[i]; 
    416     p += rtpmap->enc_name.slen; 
    417     *p++ = '/'; 
    418  
    419     /* Add clock rate. */ 
    420     p += pj_utoa(rtpmap->clock_rate, p); 
    421  
    422     /* Add parameter if necessary. */ 
    423     if (rtpmap->param.slen > 0) { 
    424         *p++ = '/'; 
    425         for (i=0; i<rtpmap->param.slen; ++i) 
    426             p[i] = rtpmap->param.ptr[i]; 
    427         p += rtpmap->param.slen; 
    428     } 
    429  
    430     *p = '\0'; 
    431  
    432     attr->value.slen = p-tempbuf; 
     451    /* Format: ":pt enc_name/clock_rate[/param]" */ 
     452    len = pj_ansi_snprintf(tempbuf, sizeof(tempbuf),  
     453                           ":%.*s %.*s/%u%s%.*s", 
     454                           (int)rtpmap->pt.slen, 
     455                           rtpmap->pt.ptr, 
     456                           (int)rtpmap->enc_name.slen, 
     457                           rtpmap->enc_name.ptr, 
     458                           rtpmap->clock_rate, 
     459                           (rtpmap->param.slen ? "/" : ""), 
     460                           rtpmap->param.slen, 
     461                           rtpmap->param.ptr); 
     462 
     463    if (len < 1 || len > sizeof(tempbuf)) 
     464        return PJMEDIA_SDP_ERTPMAPTOOLONG; 
     465 
     466    attr->value.slen = len; 
    433467    attr->value.ptr = pj_pool_alloc(pool, attr->value.slen); 
    434468    pj_memcpy(attr->value.ptr, tempbuf, attr->value.slen); 
     
    441475static int print_connection_info( pjmedia_sdp_conn *c, char *buf, int len) 
    442476{ 
    443     char *p = buf; 
    444  
    445     if (len < 8+c->net_type.slen+c->addr_type.slen+c->addr.slen) { 
     477    int printed; 
     478 
     479    printed = pj_ansi_snprintf(buf, len, "c=%.*s %.*s %.*s\r\n", 
     480                               (int)c->net_type.slen, 
     481                               c->net_type.ptr, 
     482                               (int)c->addr_type.slen, 
     483                               c->addr_type.ptr, 
     484                               (int)c->addr.slen, 
     485                               c->addr.ptr); 
     486    if (printed < 1 || printed > len) 
    446487        return -1; 
    447     } 
    448     *p++ = 'c'; 
    449     *p++ = '='; 
    450     pj_memcpy(p, c->net_type.ptr, c->net_type.slen); 
    451     p += c->net_type.slen; 
    452     *p++ = ' '; 
    453     pj_memcpy(p, c->addr_type.ptr, c->addr_type.slen); 
    454     p += c->addr_type.slen; 
    455     *p++ = ' '; 
    456     pj_memcpy(p, c->addr.ptr, c->addr.slen); 
    457     p += c->addr.slen; 
    458     *p++ = '\r'; 
    459     *p++ = '\n'; 
    460  
    461     return p-buf; 
    462 } 
     488 
     489    return printed; 
     490} 
     491 
    463492 
    464493PJ_DEF(pjmedia_sdp_conn*) pjmedia_sdp_conn_clone (pj_pool_t *pool,  
  • pjproject/trunk/pjmedia/src/pjmedia/session.c

    r452 r568  
    7979    pj_status_t status; 
    8080 
    81  
    8281     
    8382    /* Validate arguments: */ 
     
    156155 
    157156    /* Set remote address: */ 
    158  
    159     si->rem_addr.sin_family = PJ_AF_INET; 
    160     si->rem_addr.sin_port = pj_htons(rem_m->desc.port); 
    161     if (pj_inet_aton(&rem_conn->addr, &si->rem_addr.sin_addr) == 0) { 
    162  
     157    status = pj_sockaddr_in_init(&si->rem_addr, &rem_conn->addr,  
     158                                 rem_m->desc.port); 
     159    if (status != PJ_SUCCESS) { 
    163160        /* Invalid IP address. */ 
    164161        return PJMEDIA_EINVALIDIP; 
    165162    } 
     163 
     164    /* If "rtcp" attribute is present in the SDP, set the RTCP address 
     165     * from that attribute. Otherwise, calculate from RTP address. 
     166     */ 
     167    attr = pjmedia_sdp_attr_find2(rem_m->attr_count, rem_m->attr, 
     168                                  "rtcp", NULL); 
     169    if (attr) { 
     170        pjmedia_sdp_rtcp_attr rtcp; 
     171        status = pjmedia_sdp_attr_get_rtcp(attr, &rtcp); 
     172        if (status == PJ_SUCCESS) { 
     173            if (rtcp.addr.slen) { 
     174                status = pj_sockaddr_in_init(&si->rem_rtcp, &rtcp.addr, 
     175                                             (pj_uint16_t)rtcp.port); 
     176            } else { 
     177                pj_sockaddr_in_init(&si->rem_rtcp, NULL,  
     178                                    (pj_uint16_t)rtcp.port); 
     179                si->rem_rtcp.sin_addr.s_addr = si->rem_addr.sin_addr.s_addr; 
     180            } 
     181        } 
     182    } 
     183     
     184    if (si->rem_rtcp.sin_addr.s_addr == 0) { 
     185        int rtcp_port; 
     186 
     187        pj_memcpy(&si->rem_rtcp, &si->rem_addr, sizeof(pj_sockaddr_in)); 
     188        rtcp_port = pj_ntohs(si->rem_addr.sin_port) + 1; 
     189        si->rem_rtcp.sin_port = pj_htons((pj_uint16_t)rtcp_port); 
     190    } 
     191 
    166192 
    167193    /* And codec must be numeric! */ 
  • pjproject/trunk/pjmedia/src/pjmedia/stream.c

    r538 r568  
    10681068 
    10691069    /* Only attach transport when stream is ready. */ 
    1070     status = (*tp->op->attach)(tp, stream, &info->rem_addr,  
     1070    status = (*tp->op->attach)(tp, stream, &info->rem_addr, &info->rem_rtcp, 
    10711071                               sizeof(info->rem_addr), &on_rx_rtp, 
    10721072                               &on_rx_rtcp); 
  • pjproject/trunk/pjmedia/src/pjmedia/transport_udp.c

    r558 r568  
    7272    pj_sock_t           rtcp_sock;      /**< RTCP socket                    */ 
    7373    pj_sockaddr_in      rtcp_addr_name; /**< Published RTCP address.        */ 
     74    pj_sockaddr_in      rtcp_src_addr;  /**< Actual source RTCP address.    */ 
     75    int                 rtcp_addr_len;  /**< Length of RTCP src address.    */ 
    7476    pj_ioqueue_key_t   *rtcp_key;       /**< RTCP socket key in ioqueue     */ 
    7577    pj_ioqueue_op_key_t rtcp_read_op;   /**< Pending read operation         */ 
     
    9092                                       void *user_data, 
    9193                                       const pj_sockaddr_t *rem_addr, 
     94                                       const pj_sockaddr_t *rem_rtcp, 
    9295                                       unsigned addr_len, 
    9396                                       void (*rtp_cb)(void*, 
     
    276279    /* Kick of pending RTCP read from the ioqueue */ 
    277280    size = sizeof(tp->rtcp_pkt); 
    278     status = pj_ioqueue_recv(tp->rtcp_key, &tp->rtcp_read_op, 
    279                              tp->rtcp_pkt, &size, PJ_IOQUEUE_ALWAYS_ASYNC); 
     281    tp->rtcp_addr_len = sizeof(tp->rtcp_src_addr); 
     282    status = pj_ioqueue_recvfrom( tp->rtcp_key, &tp->rtcp_read_op, 
     283                                  tp->rtcp_pkt, &size, PJ_IOQUEUE_ALWAYS_ASYNC, 
     284                                  &tp->rtcp_src_addr, &tp->rtcp_addr_len); 
    280285    if (status != PJ_EPENDING) 
    281286        goto on_error; 
     
    385390                if (udp->rtp_src_cnt >= PJMEDIA_RTP_NAT_PROBATION_CNT) { 
    386391                 
    387                     pj_uint16_t port; 
    388  
    389392                    /* Set remote RTP address to source address */ 
    390393                    udp->rem_rtp_addr = udp->rtp_src_addr; 
    391  
    392                     /* Also update remote RTCP address */ 
    393                     pj_memcpy(&udp->rem_rtcp_addr, &udp->rem_rtp_addr,  
    394                               sizeof(pj_sockaddr_in)); 
    395                     port = (pj_uint16_t) 
    396                            (pj_ntohs(udp->rem_rtp_addr.sin_port)+1); 
    397                     udp->rem_rtcp_addr.sin_port = pj_htons(port); 
    398394 
    399395                    /* Reset counter */ 
     
    404400                              pj_inet_ntoa(udp->rtp_src_addr.sin_addr), 
    405401                              pj_ntohs(udp->rtp_src_addr.sin_port))); 
     402 
     403                    /* Also update remote RTCP address if actual RTCP source 
     404                     * address is not heard yet. 
     405                     */ 
     406                    if (udp->rtcp_src_addr.sin_addr.s_addr == 0) { 
     407                        pj_uint16_t port; 
     408 
     409                        pj_memcpy(&udp->rem_rtcp_addr, &udp->rem_rtp_addr,  
     410                                  sizeof(pj_sockaddr_in)); 
     411                        port = (pj_uint16_t) 
     412                               (pj_ntohs(udp->rem_rtp_addr.sin_port)+1); 
     413                        udp->rem_rtcp_addr.sin_port = pj_htons(port); 
     414 
     415                        pj_memcpy(&udp->rtcp_src_addr, &udp->rem_rtcp_addr,  
     416                                  sizeof(pj_sockaddr_in)); 
     417 
     418                        PJ_LOG(4,(udp->base.name, 
     419                                  "Remote RTCP address switched to %s:%d", 
     420                                  pj_inet_ntoa(udp->rtcp_src_addr.sin_addr), 
     421                                  pj_ntohs(udp->rtcp_src_addr.sin_port))); 
     422 
     423                    } 
    406424                } 
    407425            } 
     
    441459            (*cb)(user_data, udp->rtcp_pkt, bytes_read); 
    442460 
     461        /* Check if RTCP source address is the same as the configured 
     462         * remote address, and switch the address when they are 
     463         * different. 
     464         */ 
     465        if ((udp->options & PJMEDIA_UDP_NO_SRC_ADDR_CHECKING)==0 && 
     466            ((udp->rem_rtcp_addr.sin_addr.s_addr !=  
     467               udp->rtcp_src_addr.sin_addr.s_addr) || 
     468             (udp->rem_rtcp_addr.sin_port !=  
     469               udp->rtcp_src_addr.sin_port))) 
     470        { 
     471            pj_memcpy(&udp->rem_rtcp_addr, &udp->rtcp_src_addr, 
     472                      sizeof(pj_sockaddr_in)); 
     473            PJ_LOG(4,(udp->base.name, 
     474                      "Remote RTCP address switched to %s:%d", 
     475                      pj_inet_ntoa(udp->rtcp_src_addr.sin_addr), 
     476                      pj_ntohs(udp->rtcp_src_addr.sin_port))); 
     477        } 
     478 
    443479        bytes_read = sizeof(udp->rtcp_pkt); 
    444         status = pj_ioqueue_recv(udp->rtcp_key, &udp->rtcp_read_op, 
    445                                      udp->rtcp_pkt, &bytes_read, 0); 
     480        udp->rtcp_addr_len = sizeof(udp->rtcp_src_addr); 
     481        status = pj_ioqueue_recvfrom(udp->rtcp_key, &udp->rtcp_read_op, 
     482                                     udp->rtcp_pkt, &bytes_read, 0, 
     483                                     &udp->rtcp_src_addr,  
     484                                     &udp->rtcp_addr_len); 
    446485 
    447486    } while (status == PJ_SUCCESS); 
     
    453492                                       void *user_data, 
    454493                                       const pj_sockaddr_t *rem_addr, 
     494                                       const pj_sockaddr_t *rem_rtcp, 
    455495                                       unsigned addr_len, 
    456496                                       void (*rtp_cb)(void*, 
     
    462502{ 
    463503    struct transport_udp *udp = (struct transport_udp*) tp; 
     504    const pj_sockaddr_in *rtcp_addr; 
    464505 
    465506    /* Validate arguments */ 
     
    474515    pj_memcpy(&udp->rem_rtp_addr, rem_addr, sizeof(pj_sockaddr_in)); 
    475516 
    476     /* Guess RTCP address from RTP address */ 
    477     pj_memcpy(&udp->rem_rtcp_addr, rem_addr, sizeof(pj_sockaddr_in)); 
    478     udp->rem_rtcp_addr.sin_port = (pj_uint16_t) pj_htons((pj_uint16_t)( 
    479                                     pj_ntohs(udp->rem_rtp_addr.sin_port)+1)); 
     517    /* Copy remote RTP address, if one is specified. */ 
     518    rtcp_addr = rem_rtcp; 
     519    if (rtcp_addr && rtcp_addr->sin_addr.s_addr != 0) { 
     520        pj_memcpy(&udp->rem_rtcp_addr, rem_rtcp, sizeof(pj_sockaddr_in)); 
     521 
     522    } else { 
     523        int rtcp_port; 
     524 
     525        /* Otherwise guess the RTCP address from the RTP address */ 
     526        pj_memcpy(&udp->rem_rtcp_addr, rem_addr, sizeof(pj_sockaddr_in)); 
     527        rtcp_port = pj_ntohs(udp->rem_rtp_addr.sin_port) + 1; 
     528        udp->rem_rtcp_addr.sin_port = pj_htons((pj_uint16_t)rtcp_port); 
     529    } 
    480530 
    481531    /* Save the callbacks */ 
  • pjproject/trunk/pjsip-apps/src/samples/siprtp.c

    r546 r568  
    12851285    status = pjmedia_transport_attach(audio->transport, audio,  
    12861286                                      &audio->si.rem_addr,  
     1287                                      &audio->si.rem_rtcp, 
    12871288                                      sizeof(pj_sockaddr_in), 
    12881289                                      &on_rx_rtp, 
  • pjproject/trunk/pjsip-apps/src/samples/siprtp_report.c

    r565 r568  
    162162           audio->rtcp.stat.rx.loss * 100.0 / (audio->rtcp.stat.rx.pkt + audio->rtcp.stat.rx.loss), 
    163163           audio->rtcp.stat.rx.dup,  
    164            audio->rtcp.stat.rx.dup * 100.0 / (audio->rtcp.stat.rx.pkt + audio->rtcp.stat.rx.dup), 
     164           audio->rtcp.stat.rx.dup * 100.0 / (audio->rtcp.stat.rx.pkt + audio->rtcp.stat.rx.loss), 
    165165           audio->rtcp.stat.rx.reorder,  
    166            audio->rtcp.stat.rx.reorder * 100.0 / (audio->rtcp.stat.rx.pkt + audio->rtcp.stat.rx.reorder), 
     166           audio->rtcp.stat.rx.reorder * 100.0 / (audio->rtcp.stat.rx.pkt + audio->rtcp.stat.rx.loss), 
    167167           "", 
    168168           audio->rtcp.stat.rx.loss_period.min / 1000.0,  
     
    205205           audio->rtcp.stat.tx.loss * 100.0 / (audio->rtcp.stat.tx.pkt + audio->rtcp.stat.tx.loss), 
    206206           audio->rtcp.stat.tx.dup,  
    207            audio->rtcp.stat.tx.dup * 100.0 / (audio->rtcp.stat.tx.pkt + audio->rtcp.stat.tx.dup), 
     207           audio->rtcp.stat.tx.dup * 100.0 / (audio->rtcp.stat.tx.pkt + audio->rtcp.stat.tx.loss), 
    208208           audio->rtcp.stat.tx.reorder,  
    209            audio->rtcp.stat.tx.reorder * 100.0 / (audio->rtcp.stat.tx.pkt + audio->rtcp.stat.tx.reorder), 
     209           audio->rtcp.stat.tx.reorder * 100.0 / (audio->rtcp.stat.tx.pkt + audio->rtcp.stat.tx.loss), 
    210210           "", 
    211211           audio->rtcp.stat.tx.loss_period.min / 1000.0,  
  • pjproject/trunk/pjsip-apps/src/samples/streamutil.c

    r565 r568  
    607607           stat.rx.loss * 100.0 / (stat.rx.pkt + stat.rx.loss), 
    608608           stat.rx.dup,  
    609            stat.rx.dup * 100.0 / (stat.rx.pkt + stat.rx.dup), 
     609           stat.rx.dup * 100.0 / (stat.rx.pkt + stat.rx.loss), 
    610610           stat.rx.reorder,  
    611            stat.rx.reorder * 100.0 / (stat.rx.pkt + stat.rx.reorder), 
     611           stat.rx.reorder * 100.0 / (stat.rx.pkt + stat.rx.loss), 
    612612           "", 
    613613           stat.rx.loss_period.min / 1000.0,  
     
    650650           stat.tx.loss * 100.0 / (stat.tx.pkt + stat.tx.loss), 
    651651           stat.tx.dup,  
    652            stat.tx.dup * 100.0 / (stat.tx.pkt + stat.tx.dup), 
     652           stat.tx.dup * 100.0 / (stat.tx.pkt + stat.tx.loss), 
    653653           stat.tx.reorder,  
    654            stat.tx.reorder * 100.0 / (stat.tx.pkt + stat.tx.reorder), 
     654           stat.tx.reorder * 100.0 / (stat.tx.pkt + stat.tx.loss), 
    655655           "", 
    656656           stat.tx.loss_period.min / 1000.0,  
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c

    r565 r568  
    13051305               stat.rx.loss * 100.0 / (stat.rx.pkt + stat.rx.loss), 
    13061306               stat.rx.dup,  
    1307                stat.rx.dup * 100.0 / (stat.rx.pkt + stat.rx.dup), 
     1307               stat.rx.dup * 100.0 / (stat.rx.pkt + stat.rx.loss), 
    13081308               stat.rx.reorder,  
    1309                stat.rx.reorder * 100.0 / (stat.rx.pkt + stat.rx.reorder), 
     1309               stat.rx.reorder * 100.0 / (stat.rx.pkt + stat.rx.loss), 
    13101310               indent, indent, 
    13111311               stat.rx.loss_period.min / 1000.0,  
     
    13641364               stat.tx.loss * 100.0 / (stat.tx.pkt + stat.tx.loss), 
    13651365               stat.tx.dup,  
    1366                stat.tx.dup * 100.0 / (stat.tx.pkt + stat.tx.dup), 
     1366               stat.tx.dup * 100.0 / (stat.tx.pkt + stat.tx.loss), 
    13671367               stat.tx.reorder,  
    1368                stat.tx.reorder * 100.0 / (stat.tx.pkt + stat.tx.reorder), 
     1368               stat.tx.reorder * 100.0 / (stat.tx.pkt + stat.tx.loss), 
    13691369 
    13701370               indent, indent, 
Note: See TracChangeset for help on using the changeset viewer.