Changeset 5590 for pjproject/trunk/pjsip-apps/src/samples/streamutil.c
- Timestamp:
- May 9, 2017 2:39:08 AM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjsip-apps/src/samples/streamutil.c
r5311 r5590 42 42 #include "util.h" 43 43 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 44 49 45 50 static const char *desc = … … 61 66 " the program will transmit RTP audio to the \n" 62 67 " 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 63 77 " --play-file=WAV Send audio from the WAV file instead of from \n" 64 78 " the sound device. \n" … … 114 128 pj_uint16_t local_port, 115 129 const pj_sockaddr_in *rem_addr, 130 pj_bool_t mcast, 131 const pj_sockaddr_in *mcast_addr, 116 132 #if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0) 117 133 pj_bool_t use_srtp, … … 158 174 } 159 175 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 } 165 273 166 274 #if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0) … … 250 358 pjmedia_dir dir = PJMEDIA_DIR_DECODING; 251 359 pj_sockaddr_in remote_addr; 360 pj_sockaddr_in mcast_addr; 252 361 pj_uint16_t local_port = 4000; 253 362 char *codec_id = NULL; 254 363 char *rec_file = NULL; 255 364 char *play_file = NULL; 365 int mcast = 0; 256 366 257 367 enum { … … 259 369 OPT_LOCAL_PORT = 'p', 260 370 OPT_REMOTE = 'r', 371 OPT_MCAST = 'm', 261 372 OPT_PLAY_FILE = 'w', 262 373 OPT_RECORD_FILE = 'R', … … 276 387 { "local-port", 1, 0, OPT_LOCAL_PORT }, 277 388 { "remote", 1, 0, OPT_REMOTE }, 389 { "mcast-add", 1, 0, OPT_MCAST }, 278 390 { "play-file", 1, 0, OPT_PLAY_FILE }, 279 391 { "record-file", 1, 0, OPT_RECORD_FILE }, … … 332 444 break; 333 445 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 334 459 case OPT_PLAY_FILE: 335 460 play_file = pj_optarg; … … 455 580 /* Create stream based on program arguments */ 456 581 status = create_stream(pool, med_endpt, codec_info, dir, local_port, 457 &remote_addr, 582 &remote_addr, mcast, &mcast_addr, 458 583 #if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0) 459 584 use_srtp, &srtp_crypto_suite,
Note: See TracChangeset
for help on using the changeset viewer.