Changeset 3450


Ignore:
Timestamp:
Mar 15, 2011 11:28:24 AM (9 years ago)
Author:
bennylp
Message:

Re #1186 (SDP works); added few more APIs for SDP generation:

  • pjmedia_endpt_create_base_sdp(): create blank SDP
  • pjmedia_endpt_create_audio_sdp(): create m=audio SDP media
  • pjmedia_endpt_create_video_sdp(): create m=video SDP media
Location:
pjproject/branches/projects/2.0-dev/pjmedia
Files:
2 edited

Legend:

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

    r3392 r3450  
    181181 *                      also denotes the maximum number of streams (i.e. 
    182182 *                      the "m=" lines) that will be created in the SDP. 
     183 *                      By convention, if this value is greater than one, 
     184 *                      the first media will be audio and the remaining 
     185 *                      media is video. 
    183186 * @param sock_info     Array of socket transport information. One  
    184187 *                      transport is needed for each media stream, and 
     
    195198                                               pjmedia_sdp_session **p_sdp ); 
    196199 
     200/** 
     201 * Create a "blank" SDP session description. The SDP will contain basic SDP 
     202 * fields such as origin, time, and name, but without any media lines. 
     203 * 
     204 * @param endpt         The media endpoint. 
     205 * @param pool          Pool to allocate memory from. 
     206 * @param sess_name     Optional SDP session name, or NULL to use default 
     207 *                      value. 
     208 * @param origin        Address to put in the origin field. 
     209 * @param p_sdp         Pointer to receive the created SDP session. 
     210 * 
     211 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     212 */ 
     213PJ_DECL(pj_status_t) pjmedia_endpt_create_base_sdp(pjmedia_endpt *endpt, 
     214                                                   pj_pool_t *pool, 
     215                                                   const pj_str_t *sess_name, 
     216                                                   const pj_sockaddr *origin, 
     217                                                   pjmedia_sdp_session **p_sdp); 
     218 
     219/** 
     220 * Create SDP media line for audio media. 
     221 * 
     222 * @param endpt         The media endpoint. 
     223 * @param pool          Pool to allocate memory from. 
     224 * @param si            Socket information. 
     225 * @param options       Option flags, must be zero for now. 
     226 * @param p_m           Pointer to receive the created SDP media. 
     227 * 
     228 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     229 */ 
     230PJ_DECL(pj_status_t) pjmedia_endpt_create_audio_sdp(pjmedia_endpt *endpt, 
     231                                                    pj_pool_t *pool, 
     232                                                    const pjmedia_sock_info*si, 
     233                                                    unsigned options, 
     234                                                    pjmedia_sdp_media **p_m); 
     235 
     236/** 
     237 * Create SDP media line for video media. 
     238 * 
     239 * @param endpt         The media endpoint. 
     240 * @param pool          Pool to allocate memory from. 
     241 * @param si            Socket information. 
     242 * @param options       Option flags, must be zero for now. 
     243 * @param p_m           Pointer to receive the created SDP media. 
     244 * 
     245 * @return              PJ_SUCCESS on success, or the appropriate error code. 
     246 */ 
     247PJ_DECL(pj_status_t) pjmedia_endpt_create_video_sdp(pjmedia_endpt *endpt, 
     248                                                    pj_pool_t *pool, 
     249                                                    const pjmedia_sock_info*si, 
     250                                                    unsigned options, 
     251                                                    pjmedia_sdp_media **p_m); 
    197252 
    198253/** 
  • pjproject/branches/projects/2.0-dev/pjmedia/src/pjmedia/endpoint.c

    r3419 r3450  
    321321} 
    322322 
    323  
    324 static pj_status_t init_sdp_media_audio_format(pj_pool_t *pool, 
    325                                                pjmedia_endpt *endpt, 
    326                                                pjmedia_sdp_media *m) 
    327 { 
     323/* Common initialization for both audio and video SDP media line */ 
     324static pj_status_t init_sdp_media(pjmedia_sdp_media *m, 
     325                                  pj_pool_t *pool, 
     326                                  const pj_str_t *media_type, 
     327                                  const pjmedia_sock_info *sock_info) 
     328{ 
     329    char tmp_addr[PJ_INET6_ADDRSTRLEN]; 
     330    pjmedia_sdp_attr *attr; 
     331    const pj_sockaddr *addr; 
     332 
     333    pj_strdup(pool, &m->desc.media, media_type); 
     334 
     335    addr = &sock_info->rtp_addr_name; 
     336 
     337    /* Validate address family */ 
     338    PJ_ASSERT_RETURN(addr->addr.sa_family == pj_AF_INET() || 
     339                     addr->addr.sa_family == pj_AF_INET6(), 
     340                     PJ_EAFNOTSUP); 
     341 
     342    /* SDP connection line */ 
     343    m->conn = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_conn); 
     344    m->conn->net_type = STR_IN; 
     345    m->conn->addr_type = (addr->addr.sa_family==pj_AF_INET())? STR_IP4:STR_IP6; 
     346    pj_sockaddr_print(addr, tmp_addr, sizeof(tmp_addr), 0); 
     347    pj_strdup2(pool, &m->conn->addr, tmp_addr); 
     348 
     349    /* Port and transport in media description */ 
     350    m->desc.port = pj_sockaddr_get_port(addr); 
     351    m->desc.port_count = 1; 
     352    pj_strdup (pool, &m->desc.transport, &STR_RTP_AVP); 
     353 
     354    /* Add "rtcp" attribute */ 
     355#if defined(PJMEDIA_HAS_RTCP_IN_SDP) && PJMEDIA_HAS_RTCP_IN_SDP!=0 
     356    if (sock_info->rtcp_addr_name.addr.sa_family != 0) { 
     357        attr = pjmedia_sdp_attr_create_rtcp(pool, &sock_info->rtcp_addr_name); 
     358        if (attr) 
     359            pjmedia_sdp_attr_add(&m->attr_count, m->attr, attr); 
     360    } 
     361#endif 
     362 
     363    /* Add sendrecv attribute. */ 
     364    attr = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_attr); 
     365    attr->name = STR_SENDRECV; 
     366    m->attr[m->attr_count++] = attr; 
     367 
     368    return PJ_SUCCESS; 
     369} 
     370 
     371/* Create m=audio SDP media line */ 
     372PJ_DEF(pj_status_t) pjmedia_endpt_create_audio_sdp(pjmedia_endpt *endpt, 
     373                                                   pj_pool_t *pool, 
     374                                                   const pjmedia_sock_info *si, 
     375                                                   unsigned options, 
     376                                                   pjmedia_sdp_media **p_m) 
     377{ 
     378    const pj_str_t STR_AUDIO = { "audio", 5 }; 
     379    pjmedia_sdp_media *m; 
    328380    pjmedia_sdp_attr *attr; 
    329381    unsigned i; 
     382    pj_status_t status; 
     383 
     384    PJ_UNUSED_ARG(options); 
    330385 
    331386    /* Check that there are not too many codecs */ 
    332387    PJ_ASSERT_RETURN(endpt->codec_mgr.codec_cnt <= PJMEDIA_MAX_SDP_FMT, 
    333388                     PJ_ETOOMANY); 
     389 
     390    /* Create and init basic SDP media */ 
     391    m = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_media); 
     392    status = init_sdp_media(m, pool, &STR_AUDIO, si); 
     393    if (status != PJ_SUCCESS) 
     394        return status; 
    334395 
    335396    /* Add format, rtpmap, and fmtp (when applicable) for each codec */ 
     
    466527#endif 
    467528 
    468     return PJ_SUCCESS; 
    469 } 
    470  
    471  
    472 static pj_status_t init_sdp_media_video_format(pj_pool_t *pool, 
    473                                                pjmedia_endpt *endpt, 
    474                                                pjmedia_sdp_media *m) 
    475 { 
     529    *p_m = m; 
     530    return PJ_SUCCESS; 
     531} 
     532 
     533/* Create m=video SDP media line */ 
     534PJ_DEF(pj_status_t) pjmedia_endpt_create_video_sdp(pjmedia_endpt *endpt, 
     535                                                   pj_pool_t *pool, 
     536                                                   const pjmedia_sock_info *si, 
     537                                                   unsigned options, 
     538                                                   pjmedia_sdp_media **p_m) 
     539{ 
     540    const pj_str_t STR_VIDEO = { "video", 5 }; 
     541    pjmedia_sdp_media *m; 
    476542    pjmedia_vid_codec_info codec_info[PJMEDIA_VID_CODEC_MGR_MAX_CODECS]; 
    477543    unsigned codec_prio[PJMEDIA_VID_CODEC_MGR_MAX_CODECS]; 
     
    484550        pjmedia_vid_codec_mgr_create(endpt->pool, NULL); 
    485551 
     552    /* Create and init basic SDP media */ 
     553    m = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_media); 
     554    status = init_sdp_media(m, pool, &STR_VIDEO, si); 
     555    if (status != PJ_SUCCESS) 
     556        return status; 
     557 
    486558    cnt = PJ_ARRAY_SIZE(codec_info); 
    487559    status = pjmedia_vid_codec_mgr_enum_codecs(NULL, &cnt,  
     
    494566    /* Add format, rtpmap, and fmtp (when applicable) for each codec */ 
    495567    for (i=0; i<cnt; ++i) { 
    496  
    497         pjmedia_sdp_rtpmap rtpmap = {0}; 
     568        pjmedia_sdp_rtpmap rtpmap; 
    498569        pjmedia_vid_codec_param codec_param; 
    499570        pj_str_t *fmt; 
     571 
     572        pj_bzero(&rtpmap, sizeof(rtpmap)); 
    500573 
    501574        if (codec_prio[i] == PJMEDIA_CODEC_PRIO_DISABLED) 
     
    506579             * returning appropriate status code. 
    507580             */ 
    508             PJ_LOG(3, (THIS_FILE, "Too many video codecs")); 
     581            PJ_PERROR(3,(THIS_FILE, PJ_ETOOMANY, 
     582                        "Skipping some video codecs")); 
    509583            break; 
    510584        } 
     
    588662    } 
    589663 
    590     return PJ_SUCCESS; 
    591 } 
    592  
    593  
    594 static 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); 
     664    *p_m = m; 
     665    return PJ_SUCCESS; 
     666} 
     667 
     668 
     669/** 
     670 * Create a "blank" SDP session description. The SDP will contain basic SDP 
     671 * fields such as origin, time, and name, but without any media lines. 
     672 */ 
     673PJ_DEF(pj_status_t) pjmedia_endpt_create_base_sdp( pjmedia_endpt *endpt, 
     674                                                   pj_pool_t *pool, 
     675                                                   const pj_str_t *sess_name, 
     676                                                   const pj_sockaddr *origin, 
     677                                                   pjmedia_sdp_session **p_sdp) 
     678{ 
     679    pj_time_val tv; 
     680    pjmedia_sdp_session *sdp; 
     681 
     682    /* Sanity check arguments */ 
     683    PJ_ASSERT_RETURN(endpt && pool && p_sdp, PJ_EINVAL); 
     684 
     685    sdp = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_session); 
     686 
     687    pj_gettimeofday(&tv); 
     688    sdp->origin.user = pj_str("-"); 
     689    sdp->origin.version = sdp->origin.id = tv.sec + 2208988800UL; 
     690    sdp->origin.net_type = STR_IN; 
     691 
     692    if (origin->addr.sa_family == pj_AF_INET()) { 
     693        sdp->origin.addr_type = STR_IP4; 
     694        pj_strdup2(pool, &sdp->origin.addr, 
     695                   pj_inet_ntoa(origin->ipv4.sin_addr)); 
     696    } else if (origin->addr.sa_family == pj_AF_INET6()) { 
     697        char tmp_addr[PJ_INET6_ADDRSTRLEN]; 
     698 
     699        sdp->origin.addr_type = STR_IP6; 
     700        pj_strdup2(pool, &sdp->origin.addr, 
     701                   pj_sockaddr_print(origin, tmp_addr, sizeof(tmp_addr), 0)); 
     702 
    647703    } 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; 
     704        pj_assert(!"Invalid address family"); 
     705        return PJ_EAFNOTSUP; 
     706    } 
     707 
     708    if (sess_name) 
     709        pj_strdup(pool, &sdp->name, sess_name); 
     710    else 
     711        sdp->name = STR_SDP_NAME; 
     712 
     713    /* SDP time and attributes. */ 
     714    sdp->time.start = sdp->time.stop = 0; 
     715    sdp->attr_count = 0; 
    667716 
    668717    /* Done */ 
    669     sdp->media[sdp->media_count++] = m; 
     718    *p_sdp = sdp; 
    670719 
    671720    return PJ_SUCCESS; 
     
    682731                                              pjmedia_sdp_session **p_sdp ) 
    683732{ 
    684     pj_time_val tv; 
    685     unsigned i; 
    686733    const pj_sockaddr *addr0; 
    687734    pjmedia_sdp_session *sdp; 
    688     pjmedia_type media_types[] = {PJMEDIA_TYPE_AUDIO, PJMEDIA_TYPE_VIDEO}; 
     735    pjmedia_sdp_media *m; 
     736    unsigned i; 
     737    pj_status_t status; 
    689738 
    690739    /* Sanity check arguments */ 
    691740    PJ_ASSERT_RETURN(endpt && pool && p_sdp && stream_cnt, PJ_EINVAL); 
    692     PJ_ASSERT_RETURN(stream_cnt <= PJ_ARRAY_SIZE(media_types), PJ_ETOOMANY); 
     741    PJ_ASSERT_RETURN(stream_cnt < PJMEDIA_MAX_SDP_MEDIA, PJ_ETOOMANY); 
     742 
     743    addr0 = &sock_info[0].rtp_addr_name; 
    693744 
    694745    /* 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); 
     746    status = pjmedia_endpt_create_base_sdp(endpt, pool, NULL, addr0, &sdp); 
     747    if (status != PJ_SUCCESS) 
     748        return status; 
     749 
     750    /* Audio is first, by convention */ 
     751    status = pjmedia_endpt_create_audio_sdp(endpt, pool, 
     752                                            &sock_info[0], 0, &m); 
     753    if (status != PJ_SUCCESS) 
     754        return status; 
     755    sdp->media[sdp->media_count++] = m; 
     756 
     757    /* The remaining stream, if any, are videos (by convention as well) */ 
     758    for (i=1; i<stream_cnt; ++i) { 
     759        status = pjmedia_endpt_create_video_sdp(endpt, pool, 
     760                                                &sock_info[i], 0, &m); 
    739761        if (status != PJ_SUCCESS) 
    740762            return status; 
     763        sdp->media[sdp->media_count++] = m; 
    741764    } 
    742765 
     
    745768 
    746769    return PJ_SUCCESS; 
    747  
    748770} 
    749771 
Note: See TracChangeset for help on using the changeset viewer.