Changeset 5590


Ignore:
Timestamp:
05/08/17 21:39:08 (20 months ago)
Author:
ming
Message:

Fixed #2015: Add multicast option in streamutil sample app

Location:
pjproject/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjlib/src/pj/sock_bsd.c

    r5544 r5590  
    6363#ifdef SOL_IP 
    6464const pj_uint16_t PJ_SOL_IP     = SOL_IP; 
    65 #elif (defined(PJ_WIN32) && PJ_WIN32) || (defined(PJ_WIN64) && PJ_WIN64)  
     65#elif (defined(PJ_WIN32) && PJ_WIN32) || (defined(PJ_WIN64) && PJ_WIN64) || \ 
     66      (defined (IPPROTO_IP)) 
    6667const pj_uint16_t PJ_SOL_IP     = IPPROTO_IP; 
    6768#else 
  • pjproject/trunk/pjsip-apps/src/samples/streamutil.c

    r5311 r5590  
    4242#include "util.h" 
    4343 
     44/* An experimental feature to add multicast option to this app for providing 
     45 * the capability to send IP datagrams from a single source to more than 
     46 * one receivers. 
     47 */ 
     48#define HAVE_MULTICAST 1 
    4449 
    4550static const char *desc =  
     
    6166 "                        the program will transmit RTP audio to the    \n" 
    6267 "                        specified address. (default: recv only)       \n" 
     68#if HAVE_MULTICAST 
     69 "  --mcast-add=IP        Joins the multicast group as specified by     \n" 
     70 "                        the address. Sample usage:                    \n" 
     71 "                        Sender:                                       \n" 
     72 "                        streamutil --remote=[multicast_addr]:[port]   \n" 
     73 "                        Receivers:                                    \n" 
     74 "                        streamutil --local-port=[port]                \n" 
     75 "                                   --mcast-add=[multicast_addr]       \n" 
     76#endif 
    6377 "  --play-file=WAV       Send audio from the WAV file instead of from  \n" 
    6478 "                        the sound device.                             \n" 
     
    114128                                  pj_uint16_t local_port, 
    115129                                  const pj_sockaddr_in *rem_addr, 
     130                                  pj_bool_t mcast, 
     131                                  const pj_sockaddr_in *mcast_addr, 
    116132#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0) 
    117133                                  pj_bool_t use_srtp, 
     
    158174    } 
    159175 
    160     /* Create media transport */ 
    161     status = pjmedia_transport_udp_create(med_endpt, NULL, local_port, 
    162                                           0, &transport); 
    163     if (status != PJ_SUCCESS) 
    164         return status; 
     176    pj_sockaddr_cp(&info.rem_rtcp, &info.rem_addr); 
     177    pj_sockaddr_set_port(&info.rem_rtcp, 
     178                         pj_sockaddr_get_port(&info.rem_rtcp)+1); 
     179 
     180    if (mcast) { 
     181        pjmedia_sock_info si; 
     182        int reuse = 1; 
     183 
     184        pj_bzero(&si, sizeof(pjmedia_sock_info)); 
     185        si.rtp_sock = si.rtcp_sock = PJ_INVALID_SOCKET; 
     186 
     187        /* Create RTP socket */ 
     188        status = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, 
     189                                &si.rtp_sock); 
     190        if (status != PJ_SUCCESS) 
     191            return status; 
     192 
     193        status = pj_sock_setsockopt(si.rtp_sock, pj_SOL_SOCKET(), 
     194                                    pj_SO_REUSEADDR(), &reuse, sizeof(reuse)); 
     195        if (status != PJ_SUCCESS) 
     196            return status; 
     197 
     198        /* Bind RTP socket */ 
     199        status = pj_sockaddr_init(pj_AF_INET(), &si.rtp_addr_name, 
     200                                  NULL, local_port); 
     201        if (status != PJ_SUCCESS) 
     202            return status; 
     203     
     204        status = pj_sock_bind(si.rtp_sock, &si.rtp_addr_name, 
     205                              pj_sockaddr_get_len(&si.rtp_addr_name)); 
     206        if (status != PJ_SUCCESS) 
     207            return status; 
     208 
     209        /* Create RTCP socket */ 
     210        status = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, 
     211                                &si.rtcp_sock); 
     212        if (status != PJ_SUCCESS) 
     213            return status; 
     214 
     215        status = pj_sock_setsockopt(si.rtcp_sock, pj_SOL_SOCKET(), 
     216                                    pj_SO_REUSEADDR(), &reuse, sizeof(reuse)); 
     217        if (status != PJ_SUCCESS) 
     218            return status; 
     219 
     220        /* Bind RTCP socket */ 
     221        status = pj_sockaddr_init(pj_AF_INET(), &si.rtcp_addr_name, 
     222                                  NULL, local_port+1); 
     223        if (status != PJ_SUCCESS) 
     224            return status; 
     225     
     226        status = pj_sock_bind(si.rtcp_sock, &si.rtcp_addr_name, 
     227                              pj_sockaddr_get_len(&si.rtcp_addr_name)); 
     228        if (status != PJ_SUCCESS) 
     229            return status; 
     230 
     231#ifdef HAVE_MULTICAST 
     232        { 
     233            unsigned char loop; 
     234            struct pj_ip_mreq imr; 
     235         
     236            pj_memset(&imr, 0, sizeof(struct pj_ip_mreq)); 
     237            imr.imr_multiaddr.s_addr = mcast_addr->sin_addr.s_addr; 
     238            imr.imr_interface.s_addr = pj_htonl(PJ_INADDR_ANY); 
     239            status = pj_sock_setsockopt(si.rtp_sock, pj_SOL_IP(), 
     240                                        pj_IP_ADD_MEMBERSHIP(), 
     241                                        &imr, sizeof(struct pj_ip_mreq)); 
     242            if (status != PJ_SUCCESS) 
     243                return status; 
     244 
     245            status = pj_sock_setsockopt(si.rtcp_sock, pj_SOL_IP(), 
     246                                        pj_IP_ADD_MEMBERSHIP(), 
     247                                        &imr, sizeof(struct pj_ip_mreq)); 
     248            if (status != PJ_SUCCESS) 
     249                return status; 
     250 
     251            /* Disable local reception of local sent packets */ 
     252            loop = 0; 
     253            pj_sock_setsockopt(si.rtp_sock, pj_SOL_IP(), 
     254                               pj_IP_MULTICAST_LOOP(), &loop, sizeof(loop)); 
     255            pj_sock_setsockopt(si.rtcp_sock, pj_SOL_IP(), 
     256                               pj_IP_MULTICAST_LOOP(), &loop, sizeof(loop)); 
     257        } 
     258#endif 
     259         
     260        /* Create media transport from existing sockets */ 
     261        status = pjmedia_transport_udp_attach( med_endpt, NULL, &si,  
     262                                PJMEDIA_UDP_NO_SRC_ADDR_CHECKING, &transport); 
     263        if (status != PJ_SUCCESS) 
     264            return status;       
     265         
     266    } else { 
     267        /* Create media transport */ 
     268        status = pjmedia_transport_udp_create(med_endpt, NULL, local_port, 
     269                                              0, &transport); 
     270        if (status != PJ_SUCCESS) 
     271            return status; 
     272    } 
    165273 
    166274#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0) 
     
    250358    pjmedia_dir dir = PJMEDIA_DIR_DECODING; 
    251359    pj_sockaddr_in remote_addr; 
     360    pj_sockaddr_in mcast_addr; 
    252361    pj_uint16_t local_port = 4000; 
    253362    char *codec_id = NULL; 
    254363    char *rec_file = NULL; 
    255364    char *play_file = NULL; 
     365    int mcast = 0; 
    256366 
    257367    enum { 
     
    259369        OPT_LOCAL_PORT  = 'p', 
    260370        OPT_REMOTE      = 'r', 
     371        OPT_MCAST       = 'm', 
    261372        OPT_PLAY_FILE   = 'w', 
    262373        OPT_RECORD_FILE = 'R', 
     
    276387        { "local-port",     1, 0, OPT_LOCAL_PORT }, 
    277388        { "remote",         1, 0, OPT_REMOTE }, 
     389        { "mcast-add",      1, 0, OPT_MCAST }, 
    278390        { "play-file",      1, 0, OPT_PLAY_FILE }, 
    279391        { "record-file",    1, 0, OPT_RECORD_FILE }, 
     
    332444            break; 
    333445 
     446        case OPT_MCAST: 
     447            { 
     448                pj_str_t ip = pj_str(pj_optarg); 
     449 
     450                mcast = 1; 
     451                status = pj_sockaddr_in_init(&mcast_addr, &ip, 0); 
     452                if (status != PJ_SUCCESS) { 
     453                    app_perror(THIS_FILE, "Invalid mcast address", status); 
     454                    return 1; 
     455                } 
     456            } 
     457            break; 
     458 
    334459        case OPT_PLAY_FILE: 
    335460            play_file = pj_optarg; 
     
    455580    /* Create stream based on program arguments */ 
    456581    status = create_stream(pool, med_endpt, codec_info, dir, local_port,  
    457                            &remote_addr,  
     582                           &remote_addr, mcast, &mcast_addr, 
    458583#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0) 
    459584                           use_srtp, &srtp_crypto_suite,  
Note: See TracChangeset for help on using the changeset viewer.