Changeset 3419


Ignore:
Timestamp:
Feb 24, 2011 7:16:31 AM (14 years ago)
Author:
nanang
Message:

Re #1186:

  • Added API pjmedia_sdp_conn_cmp() to compare SDP connection.
  • Added internal API pjmedia_stream_info_parse_fmtp() to parse SDP format parameter of specified payload as a helper function for generating stream info from SDP.
  • Modified pjmedia_endpt_create_sdp() to be able to generate SDP media line for video.
Location:
pjproject/branches/projects/2.0-dev/pjmedia
Files:
2 added
3 edited

Legend:

Unmodified
Added
Removed
  • pjproject/branches/projects/2.0-dev/pjmedia/include/pjmedia/sdp.h

    r3392 r3419  
    366366                                                  const pjmedia_sdp_conn *rhs); 
    367367 
     368 
     369/**  
     370 * Compare connection info.  
     371 *  
     372 * @param conn1     The first connection info to compare. 
     373 * @param conn1     The second connection info to compare. 
     374 * @param option    Comparison option, which should be zero for now. 
     375 * 
     376 * @return          PJ_SUCCESS when both connection info are equal, otherwise 
     377 *                  returns PJMEDIA_SDP_ECONNNOTEQUAL. 
     378 */ 
     379PJ_DECL(pj_status_t) pjmedia_sdp_conn_cmp(const pjmedia_sdp_conn *conn1,  
     380                                          const pjmedia_sdp_conn *conn2, 
     381                                          unsigned option); 
    368382 
    369383 
  • pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/endpoint.c

    r3360 r3419  
    2121#include <pjmedia/errno.h> 
    2222#include <pjmedia/sdp.h> 
     23#include <pjmedia/vid_codec.h> 
    2324#include <pjmedia-audiodev/audiodev.h> 
    2425#include <pj/assert.h> 
     
    320321} 
    321322 
    322 /** 
    323  * Create a SDP session description that describes the endpoint 
    324  * capability. 
    325  */ 
    326 PJ_DEF(pj_status_t) pjmedia_endpt_create_sdp( pjmedia_endpt *endpt, 
    327                                               pj_pool_t *pool, 
    328                                               unsigned stream_cnt, 
    329                                               const pjmedia_sock_info sock_info[], 
    330                                               pjmedia_sdp_session **p_sdp ) 
    331 { 
    332     pj_time_val tv; 
     323 
     324static pj_status_t init_sdp_media_audio_format(pj_pool_t *pool, 
     325                                               pjmedia_endpt *endpt, 
     326                                               pjmedia_sdp_media *m) 
     327{ 
     328    pjmedia_sdp_attr *attr; 
    333329    unsigned i; 
    334     const pj_sockaddr *addr0; 
    335     pjmedia_sdp_session *sdp; 
    336     pjmedia_sdp_media *m; 
    337     pjmedia_sdp_attr *attr; 
    338  
    339     /* Sanity check arguments */ 
    340     PJ_ASSERT_RETURN(endpt && pool && p_sdp && stream_cnt, PJ_EINVAL); 
    341330 
    342331    /* Check that there are not too many codecs */ 
     
    344333                     PJ_ETOOMANY); 
    345334 
    346     /* Create and initialize basic SDP session */ 
    347     sdp = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_session); 
    348  
    349     addr0 = &sock_info[0].rtp_addr_name; 
    350  
    351     pj_gettimeofday(&tv); 
    352     sdp->origin.user = pj_str("-"); 
    353     sdp->origin.version = sdp->origin.id = tv.sec + 2208988800UL; 
    354     sdp->origin.net_type = STR_IN; 
    355  
    356     if (addr0->addr.sa_family == pj_AF_INET()) { 
    357         sdp->origin.addr_type = STR_IP4; 
    358         pj_strdup2(pool, &sdp->origin.addr,  
    359                    pj_inet_ntoa(addr0->ipv4.sin_addr)); 
    360     } else if (addr0->addr.sa_family == pj_AF_INET6()) { 
    361         char tmp_addr[PJ_INET6_ADDRSTRLEN]; 
    362  
    363         sdp->origin.addr_type = STR_IP6; 
    364         pj_strdup2(pool, &sdp->origin.addr,  
    365                    pj_sockaddr_print(addr0, tmp_addr, sizeof(tmp_addr), 0)); 
    366  
    367     } else { 
    368         pj_assert(!"Invalid address family"); 
    369         return PJ_EAFNOTSUP; 
    370     } 
    371  
    372     sdp->name = STR_SDP_NAME; 
    373  
    374     /* Since we only support one media stream at present, put the 
    375      * SDP connection line in the session level. 
    376      */ 
    377     sdp->conn = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_conn); 
    378     sdp->conn->net_type = sdp->origin.net_type; 
    379     sdp->conn->addr_type = sdp->origin.addr_type; 
    380     sdp->conn->addr = sdp->origin.addr; 
    381  
    382  
    383     /* SDP time and attributes. */ 
    384     sdp->time.start = sdp->time.stop = 0; 
    385     sdp->attr_count = 0; 
    386  
    387     /* Create media stream 0: */ 
    388  
    389     sdp->media_count = 1; 
    390     m = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_media); 
    391     sdp->media[0] = m; 
    392  
    393     /* Standard media info: */ 
    394     pj_strdup(pool, &m->desc.media, &STR_AUDIO); 
    395     m->desc.port = pj_sockaddr_get_port(addr0); 
    396     m->desc.port_count = 1; 
    397     pj_strdup (pool, &m->desc.transport, &STR_RTP_AVP); 
    398  
    399     /* Init media line and attribute list. */ 
    400     m->desc.fmt_count = 0; 
    401     m->attr_count = 0; 
    402  
    403     /* Add "rtcp" attribute */ 
    404 #if defined(PJMEDIA_HAS_RTCP_IN_SDP) && PJMEDIA_HAS_RTCP_IN_SDP!=0 
    405     if (sock_info->rtcp_addr_name.addr.sa_family != 0) { 
    406         attr = pjmedia_sdp_attr_create_rtcp(pool, &sock_info->rtcp_addr_name); 
    407         if (attr) 
    408             pjmedia_sdp_attr_add(&m->attr_count, m->attr, attr); 
    409     } 
    410 #endif 
    411  
    412335    /* Add format, rtpmap, and fmtp (when applicable) for each codec */ 
    413336    for (i=0; i<endpt->codec_mgr.codec_cnt; ++i) { 
     
    416339        pjmedia_sdp_rtpmap rtpmap; 
    417340        char tmp_param[3]; 
    418         pjmedia_sdp_attr *attr; 
    419341        pjmedia_codec_param codec_param; 
    420342        pj_str_t *fmt; 
     
    520442    } 
    521443 
    522     /* Add sendrecv attribute. */ 
    523     attr = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_attr); 
    524     attr->name = STR_SENDRECV; 
    525     m->attr[m->attr_count++] = attr; 
    526  
    527444#if defined(PJMEDIA_RTP_PT_TELEPHONE_EVENTS) && \ 
    528445    PJMEDIA_RTP_PT_TELEPHONE_EVENTS != 0 
     
    548465    } 
    549466#endif 
     467 
     468    return PJ_SUCCESS; 
     469} 
     470 
     471 
     472static pj_status_t init_sdp_media_video_format(pj_pool_t *pool, 
     473                                               pjmedia_endpt *endpt, 
     474                                               pjmedia_sdp_media *m) 
     475{ 
     476    pjmedia_vid_codec_info codec_info[PJMEDIA_VID_CODEC_MGR_MAX_CODECS]; 
     477    unsigned codec_prio[PJMEDIA_VID_CODEC_MGR_MAX_CODECS]; 
     478    pjmedia_sdp_attr *attr; 
     479    unsigned cnt, i; 
     480    pj_status_t status; 
     481 
     482    /* Make sure video codec manager is instantiated */ 
     483    if (!pjmedia_vid_codec_mgr_instance()) 
     484        pjmedia_vid_codec_mgr_create(endpt->pool, NULL); 
     485 
     486    cnt = PJ_ARRAY_SIZE(codec_info); 
     487    status = pjmedia_vid_codec_mgr_enum_codecs(NULL, &cnt,  
     488                                               codec_info, codec_prio); 
     489 
     490    /* Check that there are not too many codecs */ 
     491    PJ_ASSERT_RETURN(0 <= PJMEDIA_MAX_SDP_FMT, 
     492                     PJ_ETOOMANY); 
     493 
     494    /* Add format, rtpmap, and fmtp (when applicable) for each codec */ 
     495    for (i=0; i<cnt; ++i) { 
     496 
     497        pjmedia_sdp_rtpmap rtpmap = {0}; 
     498        pjmedia_vid_codec_param codec_param; 
     499        pj_str_t *fmt; 
     500 
     501        if (codec_prio[i] == PJMEDIA_CODEC_PRIO_DISABLED) 
     502            break; 
     503 
     504        if (i > PJMEDIA_MAX_SDP_FMT) { 
     505            /* Too many codecs, perhaps it is better to tell application by 
     506             * returning appropriate status code. 
     507             */ 
     508            PJ_LOG(3, (THIS_FILE, "Too many video codecs")); 
     509            break; 
     510        } 
     511 
     512        /* Payload type */ 
     513        if (codec_info[i].pt == 255) { 
     514            PJ_TODO(ALLOCATE_DYNAMIC_PAYLOAD_TYPE); 
     515            continue; 
     516        } 
     517 
     518        pjmedia_vid_codec_mgr_get_default_param(NULL, &codec_info[i], 
     519                                                &codec_param); 
     520 
     521        fmt = &m->desc.fmt[m->desc.fmt_count++]; 
     522        fmt->ptr = (char*) pj_pool_alloc(pool, 8); 
     523        fmt->slen = pj_utoa(codec_info[i].pt, fmt->ptr); 
     524        rtpmap.pt = *fmt; 
     525 
     526        /* Encoding name */ 
     527        rtpmap.enc_name = codec_info[i].encoding_name; 
     528 
     529        /* Clock rate */ 
     530        rtpmap.clock_rate = codec_info[i].clock_rate; 
     531 
     532        if (codec_info[i].pt >= 96 || pjmedia_add_rtpmap_for_static_pt) { 
     533            pjmedia_sdp_rtpmap_to_attr(pool, &rtpmap, &attr); 
     534            m->attr[m->attr_count++] = attr; 
     535        } 
     536 
     537        /* Add fmtp params */ 
     538        if (codec_param.dec_fmtp.cnt > 0) { 
     539            enum { MAX_FMTP_STR_LEN = 160 }; 
     540            char buf[MAX_FMTP_STR_LEN]; 
     541            unsigned buf_len = 0, j; 
     542            pjmedia_codec_fmtp *dec_fmtp = &codec_param.dec_fmtp; 
     543 
     544            /* Print codec PT */ 
     545            buf_len += pj_ansi_snprintf(buf,  
     546                                        MAX_FMTP_STR_LEN - buf_len,  
     547                                        "%d",  
     548                                        codec_info[i].pt); 
     549 
     550            for (j = 0; j < dec_fmtp->cnt; ++j) { 
     551                unsigned test_len = 2; 
     552 
     553                /* Check if buf still available */ 
     554                test_len = dec_fmtp->param[j].val.slen +  
     555                           dec_fmtp->param[j].name.slen; 
     556                if (test_len + buf_len >= MAX_FMTP_STR_LEN) 
     557                    return PJ_ETOOBIG; 
     558 
     559                /* Print delimiter */ 
     560                buf_len += pj_ansi_snprintf(&buf[buf_len],  
     561                                            MAX_FMTP_STR_LEN - buf_len, 
     562                                            (j == 0?" ":";")); 
     563 
     564                /* Print an fmtp param */ 
     565                if (dec_fmtp->param[j].name.slen) 
     566                    buf_len += pj_ansi_snprintf( 
     567                                            &buf[buf_len], 
     568                                            MAX_FMTP_STR_LEN - buf_len, 
     569                                            "%.*s=%.*s", 
     570                                            (int)dec_fmtp->param[j].name.slen, 
     571                                            dec_fmtp->param[j].name.ptr, 
     572                                            (int)dec_fmtp->param[j].val.slen, 
     573                                            dec_fmtp->param[j].val.ptr); 
     574                else 
     575                    buf_len += pj_ansi_snprintf(&buf[buf_len],  
     576                                            MAX_FMTP_STR_LEN - buf_len, 
     577                                            "%.*s",  
     578                                            (int)dec_fmtp->param[j].val.slen, 
     579                                            dec_fmtp->param[j].val.ptr); 
     580            } 
     581 
     582            attr = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_attr); 
     583 
     584            attr->name = pj_str("fmtp"); 
     585            attr->value = pj_strdup3(pool, buf); 
     586            m->attr[m->attr_count++] = attr; 
     587        } 
     588    } 
     589 
     590    return PJ_SUCCESS; 
     591} 
     592 
     593 
     594static pj_status_t add_sdp_media(pjmedia_endpt *endpt, 
     595                                 pj_pool_t *pool, 
     596                                 pjmedia_type type, 
     597                                 const pjmedia_sock_info *sock_info, 
     598                                 pjmedia_sdp_session *sdp) 
     599{ 
     600    pjmedia_sdp_media *m; 
     601    pjmedia_sdp_attr *attr; 
     602    pjmedia_sdp_conn conn; 
     603    const pj_sockaddr *addr; 
     604    pj_status_t status; 
     605 
     606    addr = &sock_info->rtp_addr_name; 
     607 
     608    /* Validate address family */ 
     609    if (addr->addr.sa_family != pj_AF_INET() && 
     610        addr->addr.sa_family != pj_AF_INET6()) 
     611    { 
     612        pj_assert(!"Invalid address family"); 
     613        return PJ_EAFNOTSUP; 
     614    } 
     615 
     616    /* Validate media type */ 
     617    if (type != PJMEDIA_TYPE_AUDIO && type != PJMEDIA_TYPE_VIDEO) { 
     618        pj_assert(!"Invalid mediay type"); 
     619        return PJMEDIA_EINVALIMEDIATYPE; 
     620    } 
     621 
     622    /* Allocate SDP media */ 
     623    m = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_media); 
     624 
     625    /* Connection data, if not the same to one in the session level */ 
     626    { 
     627        char tmp_addr[PJ_INET6_ADDRSTRLEN]; 
     628        pj_bzero(&conn, sizeof(conn)); 
     629        conn.net_type = STR_IN; 
     630        conn.addr_type = (addr->addr.sa_family==pj_AF_INET())? STR_IP4:STR_IP6; 
     631        pj_sockaddr_print(addr, tmp_addr, sizeof(tmp_addr), 0); 
     632        pj_strset2(&conn.addr, tmp_addr); 
     633 
     634        if (pjmedia_sdp_conn_cmp(&conn, sdp->conn, 0) != PJ_SUCCESS) 
     635            m->conn = pjmedia_sdp_conn_clone(pool, &conn); 
     636    } 
     637 
     638    /* Port and transport in media description */ 
     639    m->desc.port = pj_sockaddr_get_port(addr); 
     640    m->desc.port_count = 1; 
     641    pj_strdup (pool, &m->desc.transport, &STR_RTP_AVP); 
     642 
     643    /* Media formats and parameters */ 
     644    if (type == PJMEDIA_TYPE_AUDIO) { 
     645        pj_strdup(pool, &m->desc.media, &STR_AUDIO); 
     646        status = init_sdp_media_audio_format(pool, endpt, m); 
     647    } else { 
     648        pj_strdup(pool, &m->desc.media, &STR_VIDEO); 
     649        status = init_sdp_media_video_format(pool, endpt, m); 
     650    } 
     651    if (status != PJ_SUCCESS) 
     652        return status; 
     653 
     654    /* Add "rtcp" attribute */ 
     655#if defined(PJMEDIA_HAS_RTCP_IN_SDP) && PJMEDIA_HAS_RTCP_IN_SDP!=0 
     656    if (sock_info->rtcp_addr_name.addr.sa_family != 0) { 
     657        attr = pjmedia_sdp_attr_create_rtcp(pool, &sock_info->rtcp_addr_name); 
     658        if (attr) 
     659            pjmedia_sdp_attr_add(&m->attr_count, m->attr, attr); 
     660    } 
     661#endif 
     662 
     663    /* Add sendrecv attribute. */ 
     664    attr = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_attr); 
     665    attr->name = STR_SENDRECV; 
     666    m->attr[m->attr_count++] = attr; 
     667 
     668    /* Done */ 
     669    sdp->media[sdp->media_count++] = m; 
     670 
     671    return PJ_SUCCESS; 
     672} 
     673 
     674/** 
     675 * Create a SDP session description that describes the endpoint 
     676 * capability. 
     677 */ 
     678PJ_DEF(pj_status_t) pjmedia_endpt_create_sdp( pjmedia_endpt *endpt, 
     679                                              pj_pool_t *pool, 
     680                                              unsigned stream_cnt, 
     681                                              const pjmedia_sock_info sock_info[], 
     682                                              pjmedia_sdp_session **p_sdp ) 
     683{ 
     684    pj_time_val tv; 
     685    unsigned i; 
     686    const pj_sockaddr *addr0; 
     687    pjmedia_sdp_session *sdp; 
     688    pjmedia_type media_types[] = {PJMEDIA_TYPE_AUDIO, PJMEDIA_TYPE_VIDEO}; 
     689 
     690    /* Sanity check arguments */ 
     691    PJ_ASSERT_RETURN(endpt && pool && p_sdp && stream_cnt, PJ_EINVAL); 
     692    PJ_ASSERT_RETURN(stream_cnt <= PJ_ARRAY_SIZE(media_types), PJ_ETOOMANY); 
     693 
     694    /* Create and initialize basic SDP session */ 
     695    sdp = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_session); 
     696 
     697    addr0 = &sock_info[0].rtp_addr_name; 
     698 
     699    pj_gettimeofday(&tv); 
     700    sdp->origin.user = pj_str("-"); 
     701    sdp->origin.version = sdp->origin.id = tv.sec + 2208988800UL; 
     702    sdp->origin.net_type = STR_IN; 
     703 
     704    if (addr0->addr.sa_family == pj_AF_INET()) { 
     705        sdp->origin.addr_type = STR_IP4; 
     706        pj_strdup2(pool, &sdp->origin.addr,  
     707                   pj_inet_ntoa(addr0->ipv4.sin_addr)); 
     708    } else if (addr0->addr.sa_family == pj_AF_INET6()) { 
     709        char tmp_addr[PJ_INET6_ADDRSTRLEN]; 
     710 
     711        sdp->origin.addr_type = STR_IP6; 
     712        pj_strdup2(pool, &sdp->origin.addr,  
     713                   pj_sockaddr_print(addr0, tmp_addr, sizeof(tmp_addr), 0)); 
     714 
     715    } else { 
     716        pj_assert(!"Invalid address family"); 
     717        return PJ_EAFNOTSUP; 
     718    } 
     719 
     720    sdp->name = STR_SDP_NAME; 
     721 
     722    /* SDP connection line in the session level. */ 
     723    sdp->conn = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_conn); 
     724    sdp->conn->net_type = sdp->origin.net_type; 
     725    sdp->conn->addr_type = sdp->origin.addr_type; 
     726    sdp->conn->addr = sdp->origin.addr; 
     727 
     728 
     729    /* SDP time and attributes. */ 
     730    sdp->time.start = sdp->time.stop = 0; 
     731    sdp->attr_count = 0; 
     732 
     733    /* Add SDP media. */ 
     734    for (i = 0; i < stream_cnt; ++i) { 
     735        pj_status_t status; 
     736 
     737        status = add_sdp_media(endpt, pool, media_types[i],  
     738                               &sock_info[i], sdp); 
     739        if (status != PJ_SUCCESS) 
     740            return status; 
     741    } 
    550742 
    551743    /* Done */ 
  • pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/sdp_cmp.c

    r3198 r3419  
    296296 
    297297 
     298PJ_DEF(pj_status_t) pjmedia_sdp_conn_cmp(const pjmedia_sdp_conn *conn1,  
     299                                         const pjmedia_sdp_conn *conn2, 
     300                                         unsigned option) 
     301{ 
     302    PJ_UNUSED_ARG(option); 
     303    return compare_conn(conn1, conn2); 
     304} 
Note: See TracChangeset for help on using the changeset viewer.