Hi, On 14.07.17 09:45, Lele wrote:
Hi guys, I should create two pj socket connected with two different multicast Ip. I'm wrote the following source code but It's only working for the first multicast connection. When I call multicastConnection2 function memory pool reference is lost. I don't known why this reference is lost when I run pj_sock_socket function to instantiate a new sock. Following, when I create a new transport for the new stream, application crash. In my application first I call multicastConnection function that initialize pjsip library and create a media_endpt, and after I run multicastConnection2 to connect the other stream to the same sound port. The following source code is wrote starting from streamutil.c sample. How can I implement this feature in my application? Thanks in advice /* Global variables for all opened streams */ bool isMcastEnabled = true; pjmedia_snd_port *snd_port = NULL; pjmedia_port *stream_port; bool isMcastEnabled; pjmedia_dir dir = PJMEDIA_DIR_DECODING; pjmedia_audio_codec_config codec_cfg; const pjmedia_codec_info *codec_info; pj_pool_t *poolMc; pjmedia_endpt *med_endpt; pj_status_t MainWindow::multicastConnection() { if (!isMcastEnabled) { pj_bool_t mcast = true; pj_caching_pool cp; pjmedia_stream *stream = NULL; pj_status_t status; pjmedia_codec_param codec_param; pj_sockaddr_in remote_addr; pj_sockaddr_in mcast_addr; pj_uint16_t local_port = 4000; char *codec_id = new char[4]; strcpy(codec_id, "PCMA"); /* Reset defined remote address */ pj_bzero(&remote_addr, sizeof(remote_addr)); /* Init PJLIB */ status = pj_init(); if (status != PJ_SUCCESS) { return status; } /* Set multicast ip */ const pj_str_t multicastAddrIpv4 = Utils::toPj_str("239.0.0.1"); /* Defined multicast IpV4 address */ status = pj_sockaddr_in_init(&mcast_addr, &multicastAddrIpv4, 0); dir = PJMEDIA_DIR_DECODING; /* Must create a pool factory before we can allocate any memory. */ pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0); /* * Initialize media endpoint. * This will implicitly initialize PJMEDIA too. */ status = pjmedia_endpt_create(&cp.factory, NULL, 1, &med_endpt); if (status != PJ_SUCCESS) { return status; } /* Create memory pool for application purpose */ poolMc = pj_pool_create(&cp.factory, /* pool factory */ "app", /* pool factory */ 4000, /* init size */ 4000, /* increment size */ NULL /* callback on error */ ); /* Register all codecs */ pjmedia_audio_codec_config_default(&codec_cfg); /* Register all supported codecs (register all known audio codecs implemented in PJMEDA-CODEC library to the specified media endpoint) */ status = pjmedia_codec_register_audio_codecs(med_endpt, &codec_cfg); if (status != PJ_SUCCESS) { return status; } /* Find which codec to use */ if (codec_id) { unsigned count = 1; pj_str_t str_codec_id = pj_str(codec_id); //PCMA is configured as codec_id pjmedia_codec_mgr *codec_mgr = pjmedia_endpt_get_codec_mgr(med_endpt); status = pjmedia_codec_mgr_find_codecs_by_id(codec_mgr, &str_codec_id, &count, &codec_info, NULL); if (status != PJ_SUCCESS) { return status; } } else { /* Default to pcmu */ status = pjmedia_codec_mgr_get_codec_info(pjmedia_endpt_get_codec_mgr(med_endpt), 0, &codec_info); if (status != PJ_SUCCESS) { return status; } } /* ============ Create stream based on program arguments ============ */ pjmedia_stream_info info; pjmedia_transport *transport = NULL; //Reset stream info pj_bzero(&info, sizeof(info)); /* Initialize stream info formats */ info.type = PJMEDIA_TYPE_AUDIO; info.dir = dir; pj_memcpy(&info.fmt, codec_info, sizeof(pjmedia_codec_info)); info.tx_pt = codec_info->pt; info.rx_pt = codec_info->pt; info.ssrc = pj_rand(); /* each source have different ssrc on multicast channel */ /* Copy remote address */ pj_memcpy(&info.rem_addr, &remote_addr, sizeof(pj_sockaddr_in)); if (status != PJ_SUCCESS) { return status; } /* If remote address is not set, set to an arbitrary address (otherwise stream will assert) */ if (info.rem_addr.addr.sa_family == 0) { const pj_str_t addr = Utils::toPj_str("127.0.0.1"); pj_sockaddr_in_init(&info.rem_addr.ipv4, &addr, 0); } pj_sockaddr_cp(&info.rem_rtcp, &info.rem_addr); /* I think when rtcp is enabled, this function copy remote_addr ip in rtcp_addr ip */ pj_sockaddr_set_port(&info.rem_rtcp, pj_sockaddr_get_port(&info.rem_rtcp) + 1); /* I think when rtcp is enabled, this function assign rtcp port */ if (mcast) { pjmedia_sock_info si; int reuse = 1; pj_bzero(&si, sizeof(pjmedia_sock_info)); si.rtp_sock = si.rtcp_sock = PJ_INVALID_SOCKET; /* Create RTP socket */ status = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &si.rtp_sock); if (status != PJ_SUCCESS) { return status; } status = pj_sock_setsockopt(si.rtp_sock, pj_SOL_SOCKET(), pj_SO_REUSEADDR(), &reuse, sizeof(reuse)); if (status != PJ_SUCCESS) { return status; } /* Bind RTP socket */ status = pj_sockaddr_init(pj_AF_INET(), &si.rtp_addr_name, NULL, local_port); if (status != PJ_SUCCESS) { return status; } status = pj_sock_bind(si.rtp_sock, &si.rtp_addr_name, pj_sockaddr_get_len(&si.rtp_addr_name)); if (status != PJ_SUCCESS) { return status; } /* Create RTCP socket */ status = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &si.rtcp_sock); if (status != PJ_SUCCESS) { return status; } status = pj_sock_setsockopt(si.rtcp_sock, pj_SOL_SOCKET(), pj_SO_REUSEADDR(), &reuse, sizeof(reuse)); if (status != PJ_SUCCESS) { return status; } /* Bind RTCP socket */ status = pj_sockaddr_init(pj_AF_INET(), &si.rtcp_addr_name, NULL, local_port + 1); if (status != PJ_SUCCESS) { return status; } status = pj_sock_bind(si.rtcp_sock, &si.rtcp_addr_name, pj_sockaddr_get_len(&si.rtcp_addr_name)); if (status != PJ_SUCCESS) { return status; } /* If have multicast */ unsigned char loop; struct pj_ip_mreq imr; pj_memset(&imr, 0, sizeof(struct pj_ip_mreq)); imr.imr_multiaddr.s_addr = mcast_addr.sin_addr.s_addr; imr.imr_interface.s_addr = pj_htonl(PJ_INADDR_ANY); status = pj_sock_setsockopt(si.rtp_sock, pj_SOL_IP(), pj_IP_ADD_MEMBERSHIP(), &imr, sizeof(struct pj_ip_mreq)); if (status != PJ_SUCCESS) { return status; } /* To manage rtcp */ status = pj_sock_setsockopt(si.rtcp_sock, pj_SOL_IP(), pj_IP_ADD_MEMBERSHIP(), &imr, sizeof(struct pj_ip_mreq)); if (status != PJ_SUCCESS) { return status; } /* Disable local reception of local sent packets */ loop = 0; pj_sock_setsockopt(si.rtp_sock, pj_SOL_IP(), pj_IP_MULTICAST_LOOP(), &loop, sizeof(loop)); pj_sock_setsockopt(si.rtcp_sock, pj_SOL_IP(), pj_IP_MULTICAST_LOOP(), &loop, sizeof(loop)); /* Create media transport from existing sockets */ status = pjmedia_transport_udp_attach(med_endpt, "mcast2", &si, PJMEDIA_UDP_NO_SRC_ADDR_CHECKING, &transport); if (status != PJ_SUCCESS) { return status; } } else { /* Create media transport from existing sockets */ status = pjmedia_transport_udp_create(med_endpt, NULL, local_port, 0, &transport); if (status != PJ_SUCCESS) { return status; } } /* Now that the stream info is initialized, we can create the stream */ status = pjmedia_stream_create(med_endpt, poolMc, &info, transport, NULL, &stream); if (status != PJ_SUCCESS) { pjmedia_transport_close(transport); return status; } else { /* Get codec default param for info */ status = pjmedia_codec_mgr_get_default_param(pjmedia_endpt_get_codec_mgr(med_endpt), codec_info, &codec_param); if (status != PJ_SUCCESS) { return status; } /* Get the port interface of the stream */ status = pjmedia_stream_get_port(stream, &stream_port); if (status != PJ_SUCCESS) { return status; } /* Create sound device port. */ if (dir == PJMEDIA_DIR_ENCODING_DECODING) status = pjmedia_snd_port_create(poolMc, -1, -1, PJMEDIA_PIA_SRATE(&stream_port->info), PJMEDIA_PIA_CCNT(&stream_port->info), PJMEDIA_PIA_SPF(&stream_port->info), PJMEDIA_PIA_BITS(&stream_port->info), 0, &snd_port); else if (dir == PJMEDIA_DIR_ENCODING) status = pjmedia_snd_port_create_rec(poolMc, -1, PJMEDIA_PIA_SRATE(&stream_port->info), PJMEDIA_PIA_CCNT(&stream_port->info), PJMEDIA_PIA_SPF(&stream_port->info), PJMEDIA_PIA_BITS(&stream_port->info), 0, &snd_port); else status = pjmedia_snd_port_create_player(poolMc, -1, PJMEDIA_PIA_SRATE(&stream_port->info), PJMEDIA_PIA_CCNT(&stream_port->info), PJMEDIA_PIA_SPF(&stream_port->info), PJMEDIA_PIA_BITS(&stream_port->info), 0, &snd_port); if (status != PJ_SUCCESS) { return status; } /* Connect sound port to stream */ status = pjmedia_snd_port_connect(snd_port, stream_port); if (status != PJ_SUCCESS) { return status; } /* Start streaming */ pjmedia_stream_start(stream); } } return PJ_SUCCESS; } pj_status_t MainWindow::multicastConnection2() { if (!isMcastEnabled) { pj_pool_t *memoryPool; pj_bool_t mcast = true; pj_sockaddr_in mcast_addr; pj_uint16_t local_port = 5000; pj_status_t status; pjmedia_stream *stream = NULL; /* Set multicast ip */ const pj_str_t multicastAddrIpv4 = Utils::toPj_str("239.0.0.2"); /* Defined multicast IpV4 address */ status = pj_sockaddr_in_init(&mcast_addr, &multicastAddrIpv4, 0); /* ============ Create stream based on program arguments ============ */ pjmedia_stream_info info; pjmedia_transport *transport = NULL; //Reset stream info pj_bzero(&info, sizeof(info)); /* Initialize stream info formats */ info.type = PJMEDIA_TYPE_AUDIO; info.dir = dir; pj_memcpy(&info.fmt, codec_info, sizeof(pjmedia_codec_info)); info.tx_pt = codec_info->pt; info.rx_pt = codec_info->pt; info.ssrc = pj_rand(); /* each source have different ssrc on multicast channel */ /* If remote address is not set, set to an arbitrary address (otherwise stream will assert) */ if (info.rem_addr.addr.sa_family == 0) { const pj_str_t addr = Utils::toPj_str("127.0.0.1"); pj_sockaddr_in_init(&info.rem_addr.ipv4, &addr, 0); } pj_sockaddr_cp(&info.rem_rtcp, &info.rem_addr); pj_sockaddr_set_port(&info.rem_rtcp, pj_sockaddr_get_port(&info.rem_rtcp) + 1); if (mcast) { pjmedia_sock_info si; int reuse = 1; pj_bzero(&si, sizeof(pjmedia_sock_info)); si.rtp_sock = si.rtcp_sock = PJ_INVALID_SOCKET; /* Create RTP socket */ status = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &si.rtp_sock); if (status != PJ_SUCCESS) { return status; } status = pj_sock_setsockopt(si.rtp_sock, pj_SOL_SOCKET(), pj_SO_REUSEADDR(), &reuse, sizeof(reuse)); if (status != PJ_SUCCESS) { return status; } /* Bind RTP socket */ status = pj_sockaddr_init(pj_AF_INET(), &si.rtp_addr_name, NULL, local_port); if (status != PJ_SUCCESS) { return status; } status = pj_sock_bind(si.rtp_sock, &si.rtp_addr_name, pj_sockaddr_get_len(&si.rtp_addr_name)); if (status != PJ_SUCCESS) { return status; } /* Create RTCP socket */ status = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &si.rtcp_sock); if (status != PJ_SUCCESS) { return status; } status = pj_sock_setsockopt(si.rtcp_sock, pj_SOL_SOCKET(), pj_SO_REUSEADDR(), &reuse, sizeof(reuse)); if (status != PJ_SUCCESS) { return status; } /* Bind RTCP socket */ status = pj_sockaddr_init(pj_AF_INET(), &si.rtcp_addr_name, NULL, local_port + 1); if (status != PJ_SUCCESS) { return status; } status = pj_sock_bind(si.rtcp_sock, &si.rtcp_addr_name, pj_sockaddr_get_len(&si.rtcp_addr_name)); if (status != PJ_SUCCESS) { return status; } /* If have multicast */ unsigned char loop; struct pj_ip_mreq imr; pj_memset(&imr, 0, sizeof(struct pj_ip_mreq)); imr.imr_multiaddr.s_addr = mcast_addr.sin_addr.s_addr; imr.imr_interface.s_addr = pj_htonl(PJ_INADDR_ANY); status = pj_sock_setsockopt(si.rtp_sock, pj_SOL_IP(), pj_IP_ADD_MEMBERSHIP(), &imr, sizeof(struct pj_ip_mreq)); if (status != PJ_SUCCESS) { return status; } /* To manage rtcp */ status = pj_sock_setsockopt(si.rtcp_sock, pj_SOL_IP(), pj_IP_ADD_MEMBERSHIP(), &imr, sizeof(struct pj_ip_mreq)); if (status != PJ_SUCCESS) { return status; } /* Disable local reception of local sent packets */ loop = 0; pj_sock_setsockopt(si.rtp_sock, pj_SOL_IP(), pj_IP_MULTICAST_LOOP(), &loop, sizeof(loop)); pj_sock_setsockopt(si.rtcp_sock, pj_SOL_IP(), pj_IP_MULTICAST_LOOP(), &loop, sizeof(loop)); /* Create media transport from existing sockets */ status = pjmedia_transport_udp_attach(med_endpt, "mcast2", &si, PJMEDIA_UDP_NO_SRC_ADDR_CHECKING, &transport); if (status != PJ_SUCCESS) { return status; } } /* Now that the stream info is initialized, we can create the stream */ status = pjmedia_stream_create(med_endpt, poolMc, &info, transport, NULL, &stream); if (status != PJ_SUCCESS) { pjmedia_transport_close(transport); return status; } else { /* Connect sound port to stream */ status = pjmedia_snd_port_connect(snd_port, stream_port); if (status != PJ_SUCCESS) { return status; } /* Start streaming */ pjmedia_stream_start(stream); } } return PJ_SUCCESS; } Best Regards LL -- 1024D/A9F85A52 2000-01-18 Alain Totouom <totouom@xxxxxx> PGP Fingerprint DA18 0DF2 FBD2 5F67 0656 452D E3A2 7531 A9F8 5A52 |
_______________________________________________ Visit our blog: http://blog.pjsip.org pjsip mailing list pjsip@xxxxxxxxxxxxxxx http://lists.pjsip.org/mailman/listinfo/pjsip_lists.pjsip.org