Changeset 452 for pjproject/trunk
- Timestamp:
- May 17, 2006 5:17:39 PM (19 years ago)
- Location:
- pjproject/trunk
- Files:
-
- 2 added
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/build/Makefile
r431 r452 70 70 port.o resample.o \ 71 71 resample_port.o rtcp.o rtp.o sdp.o sdp_cmp.o sdp_neg.o \ 72 session.o silencedet.o sound_port.o stream.o wave.o \ 72 session.o silencedet.o sound_port.o stream.o \ 73 transport_udp.o wave.o \ 73 74 $(SOUND_OBJS) $(NULLSOUND_OBJS) 74 75 -
pjproject/trunk/pjmedia/build/os-win32.mak
r355 r452 11 11 $(PA_DIR)/pa_win_wmme.o 12 12 13 export OS_CFLAGS += -DPA_NO_ASIO -DPA_NO_DS 13 export OS_CFLAGS += -DPA_NO_ASIO -DPA_NO_DS \ 14 -DPJMEDIA_SOUND_IMPLEMENTATION=PJMEDIA_SOUND_PORTAUDIO_SOUND 14 15 15 16 # Example: -
pjproject/trunk/pjmedia/build/pjmedia.dsp
r417 r452 192 192 # Begin Source File 193 193 194 SOURCE=..\src\pjmedia\transport_udp.c 195 # End Source File 196 # Begin Source File 197 194 198 SOURCE=..\src\pjmedia\wav_player.c 195 199 # End Source File … … 301 305 302 306 SOURCE=..\include\pjmedia\stream.h 307 # End Source File 308 # Begin Source File 309 310 SOURCE=..\include\pjmedia\transport_udp.h 303 311 # End Source File 304 312 # Begin Source File -
pjproject/trunk/pjmedia/include/pjmedia.h
r417 r452 44 44 #include <pjmedia/silencedet.h> 45 45 #include <pjmedia/session.h> 46 #include <pjmedia/transport_udp.h> 46 47 #include <pjmedia/sound.h> 47 48 #include <pjmedia/sound_port.h> -
pjproject/trunk/pjmedia/include/pjmedia/session.h
r438 r452 89 89 * @param max_streams Maximum number of stream infos to be created. 90 90 * @param si Session info structure to be initialized. 91 * @param skinfo Optional array of media socket info to be copied92 * to the stream info. If this argument is specified,93 * the array must contain sufficient elements for94 * each stream to be initialized.95 91 * @param local Local SDP session descriptor. 96 92 * @param remote Remote SDP session descriptor. … … 104 100 unsigned max_streams, 105 101 pjmedia_session_info *si, 106 const pjmedia_sock_info skinfo[],107 102 const pjmedia_sdp_session *local, 108 103 const pjmedia_sdp_session *remote); … … 119 114 * @param pool Pool to allocate memory. 120 115 * @param endpt PJMEDIA endpoint instance. 121 * @param skinfo Optional socket info to be copied to the stream info.122 116 * @param local Local SDP session descriptor. 123 117 * @param remote Remote SDP session descriptor. … … 130 124 pj_pool_t *pool, 131 125 pjmedia_endpt *endpt, 132 const pjmedia_sock_info *skinfo,133 126 const pjmedia_sdp_session *local, 134 127 const pjmedia_sdp_session *remote, … … 146 139 * 147 140 * @param endpt The PJMEDIA endpoint instance. 148 * @param s tream_cnt Maximum number of streams to be created. This149 * also denotes the number of elements in the150 * s ocket information.151 * @param local_sdp The SDP describing local capability.152 * @param rem_sdp The SDP describing remote capability.141 * @param si Session info containing stream count and array of 142 * stream info. The stream count indicates how many 143 * streams to be created in the session. 144 * @param transports Array of media stream transports, with 145 * sufficient number of elements (one for each stream). 153 146 * @param user_data Arbitrary user data to be kept in the session. 154 147 * @param p_session Pointer to receive the media session. … … 160 153 pjmedia_session_create( pjmedia_endpt *endpt, 161 154 const pjmedia_session_info *si, 155 pjmedia_transport *transports[], 162 156 void *user_data, 163 157 pjmedia_session **p_session ); -
pjproject/trunk/pjmedia/include/pjmedia/stream.h
r438 r452 70 70 pjmedia_type type; /**< Media type (audio, video) */ 71 71 pjmedia_dir dir; /**< Media direction. */ 72 pjmedia_sock_info sock_info; /**< Media transport (RTP/RTCP sockets) */73 72 pj_sockaddr_in rem_addr; /**< Remote RTP address */ 74 73 pjmedia_codec_info fmt; /**< Incoming codec format info. */ … … 101 100 102 101 /** 102 * @see pjmedia_transport_op. 103 */ 104 typedef struct pjmedia_transport pjmedia_transport; 105 106 107 /** 108 * This structure describes the operations for the stream transport. 109 */ 110 struct pjmedia_transport_op 111 { 112 /** 113 * This function is called by the stream when the transport is about 114 * to be used by the stream for the first time, and it tells the transport 115 * about remote RTP address to send the packet and some callbacks to be 116 * called for incoming packets. 117 */ 118 pj_status_t (*attach)(pjmedia_transport *tp, 119 pjmedia_stream *strm, 120 const pj_sockaddr_t *rem_addr, 121 unsigned addr_len, 122 void (*rtp_cb)(pjmedia_stream*, 123 const void*, 124 pj_ssize_t), 125 void (*rtcp_cb)(pjmedia_stream*, 126 const void*, 127 pj_ssize_t)); 128 129 /** 130 * This function is called by the stream when the stream is no longer 131 * need the transport (normally when the stream is about to be closed). 132 */ 133 void (*detach)(pjmedia_transport *tp, 134 pjmedia_stream *strm); 135 136 /** 137 * This function is called by the stream to send RTP packet using the 138 * transport. 139 */ 140 pj_status_t (*send_rtp)(pjmedia_transport *tp, 141 const void *pkt, 142 pj_size_t size); 143 144 /** 145 * This function is called by the stream to send RTCP packet using the 146 * transport. 147 */ 148 pj_status_t (*send_rtcp)(pjmedia_transport *tp, 149 const void *pkt, 150 pj_size_t size); 151 152 }; 153 154 155 /** 156 * @see pjmedia_transport_op. 157 */ 158 typedef struct pjmedia_transport_op pjmedia_transport_op; 159 160 161 /** 162 * This structure declares stream transport. A stream transport is called 163 * by the stream to transmit a packet, and will notify stream when 164 * incoming packet is arrived. 165 */ 166 struct pjmedia_transport 167 { 168 char name[PJ_MAX_OBJ_NAME]; 169 170 pjmedia_transport_op *op; 171 }; 172 173 174 175 /** 103 176 * Create a media stream based on the specified parameter. After the stream 104 177 * has been created, application normally would want to get the media port … … 115 188 * buffer needs to preallocate some storage. 116 189 * @param info Stream information. 190 * @param tp Stream transport instance used to transmit 191 * and receive RTP/RTCP packets to/from the underlying 192 * transport. 117 193 * @param user_data Arbitrary user data (for future callback feature). 118 194 * @param p_stream Pointer to receive the media stream. … … 123 199 pj_pool_t *pool, 124 200 const pjmedia_stream_info *info, 201 pjmedia_transport *tp, 125 202 void *user_data, 126 203 pjmedia_stream **p_stream); … … 152 229 153 230 /** 231 * Get the media transport object associated with this stream. 232 * 233 * @param st The media stream. 234 * 235 * @return The transport object being used by the stream. 236 */ 237 PJ_DECL(pjmedia_transport*) pjmedia_stream_get_transport(pjmedia_stream *st); 238 239 240 /** 154 241 * Start the media stream. This will start the appropriate channels 155 242 * in the media stream, depending on the media direction that was set … … 225 312 226 313 /** 227 * Retrieve the incoming DTMF digits from the stream. Note that the digits 228 * buffer will not be NULL terminated. 314 * Retrieve the incoming DTMF digits from the stream, and remove the digits 315 * from stream's DTMF buffer. Note that the digits buffer will not be NULL 316 * terminated. 229 317 * 230 318 * @param stream The media stream. -
pjproject/trunk/pjmedia/src/pjmedia/session.c
r438 r452 65 65 pj_pool_t *pool, 66 66 pjmedia_endpt *endpt, 67 const pjmedia_sock_info *skinfo,68 67 const pjmedia_sdp_session *local, 69 68 const pjmedia_sdp_session *remote, … … 343 342 } 344 343 345 /* Copy skinfo */346 if (skinfo)347 si->sock_info = *skinfo;348 349 344 /* Leave SSRC to random. */ 350 345 si->ssrc = pj_rand(); … … 365 360 unsigned max_streams, 366 361 pjmedia_session_info *si, 367 const pjmedia_sock_info skinfo[],368 362 const pjmedia_sdp_session *local, 369 363 const pjmedia_sdp_session *remote) … … 382 376 status = pjmedia_stream_info_from_sdp( &si->stream_info[i], pool, 383 377 endpt, 384 (skinfo ? &skinfo[i] : NULL),385 378 local, remote, i); 386 379 if (status != PJ_SUCCESS) … … 398 391 PJ_DEF(pj_status_t) pjmedia_session_create( pjmedia_endpt *endpt, 399 392 const pjmedia_session_info *si, 393 pjmedia_transport *transports[], 400 394 void *user_data, 401 395 pjmedia_session **p_session ) … … 433 427 status = pjmedia_stream_create(endpt, session->pool, 434 428 &session->stream_info[i], 429 (transports?transports[i]:NULL), 435 430 session, 436 431 &session->stream[i]); -
pjproject/trunk/pjmedia/src/pjmedia/stream.c
r450 r452 86 86 void *user_data; /**< User data. */ 87 87 88 pjmedia_transport *transport; /**< Stream transport. */ 89 88 90 pjmedia_codec *codec; /**< Codec instance being used. */ 89 91 pjmedia_codec_param codec_param; /**< Codec param. */ … … 92 94 pjmedia_jbuf *jb; /**< Jitter buffer. */ 93 95 94 pjmedia_sock_info skinfo; /**< Transport info. */95 pj_sockaddr_in rem_rtp_addr; /**< Remote RTP address. */96 pj_sockaddr_in rem_rtcp_addr; /**< Remote RTCP address. */97 98 99 96 pjmedia_rtcp_session rtcp; /**< RTCP for incoming RTP. */ 100 97 101 pj_ioqueue_key_t *rtp_key; /**< RTP ioqueue key. */102 pj_ioqueue_op_key_t rtp_op_key; /**< The pending read op key. */103 pj_sockaddr_in rtp_src_addr; /**< addr of src pkt from remote*/104 unsigned rtp_src_cnt; /**< if different, # of pkt rcv */105 int rtp_addrlen; /**< Address length. */106 107 pj_ioqueue_key_t *rtcp_key; /**< RTCP ioqueue key. */108 pj_ioqueue_op_key_t rtcp_op_key; /**< The pending read op key. */109 pj_size_t rtcp_pkt_size; /**< Size of RTCP packet buf. */110 char rtcp_pkt[512]; /**< RTCP packet buffer. */111 98 pj_uint32_t rtcp_last_tx; /**< RTCP tx time in timestamp */ 112 99 pj_uint32_t rtcp_interval; /**< Interval, in timestamp. */ 113 int rtcp_addrlen; /**< Address length. */114 100 115 101 /* RFC 2833 DTMF transmission queue: */ … … 424 410 425 411 pjmedia_rtcp_pkt *rtcp_pkt; 426 pj_ssize_t size;427 412 int len; 428 pj_status_t status;429 413 430 414 pjmedia_rtcp_build_rtcp(&stream->rtcp, &rtcp_pkt, &len); 431 size = len; 432 status = pj_sock_sendto(stream->skinfo.rtcp_sock, rtcp_pkt, &size, 0, 433 &stream->rem_rtcp_addr, 434 sizeof(stream->rem_rtcp_addr)); 435 #if 0 436 if (status != PJ_SUCCESS) { 437 char errmsg[PJ_ERR_MSG_SIZE]; 438 439 pj_strerror(status, errmsg, sizeof(errmsg)); 440 PJ_LOG(4,(port->info.name.ptr, "Error sending RTCP: %s [%d]", 441 errmsg, status)); 442 } 443 #endif 415 416 (*stream->transport->op->send_rtcp)(stream->transport, 417 rtcp_pkt, len); 444 418 445 419 stream->rtcp_last_tx = timestamp; … … 587 561 /* Send. */ 588 562 sent = frame_out.size+sizeof(pjmedia_rtp_hdr); 589 status = pj_sock_sendto(stream->skinfo.rtp_sock, channel->out_pkt, 590 &sent, 0, &stream->rem_rtp_addr, 591 sizeof(stream->rem_rtp_addr)); 592 if (status != PJ_SUCCESS) 593 return status; 563 564 (*stream->transport->op->send_rtp)(stream->transport, 565 channel->out_pkt, sent); 566 594 567 595 568 /* Update stat */ … … 683 656 684 657 /* 685 * This callback is called by ioqueue frameworkon receipt of packets658 * This callback is called by stream transport on receipt of packets 686 659 * in the RTP socket. 687 660 */ 688 static void on_rx_rtp( pj _ioqueue_key_t *key,689 pj_ioqueue_op_key_t *op_key, 661 static void on_rx_rtp( pjmedia_stream *stream, 662 const void *pkt, 690 663 pj_ssize_t bytes_read) 691 664 692 665 { 693 pjmedia_stream *stream = pj_ioqueue_get_user_data(key);694 666 pjmedia_channel *channel = stream->dec; 667 const pjmedia_rtp_hdr *hdr; 668 const void *payload; 669 unsigned payloadlen; 670 pjmedia_rtp_status seq_st; 695 671 pj_status_t status; 696 672 697 698 PJ_UNUSED_ARG(op_key); 699 700 701 /* 702 * Loop while we have packet. 673 674 /* Update RTP and RTCP session. */ 675 status = pjmedia_rtp_decode_rtp(&channel->rtp, pkt, bytes_read, 676 &hdr, &payload, &payloadlen); 677 if (status != PJ_SUCCESS) { 678 LOGERR_((stream->port.info.name.ptr, "RTP decode error", status)); 679 return; 680 } 681 682 683 /* Inform RTCP session */ 684 pjmedia_rtcp_rx_rtp(&stream->rtcp, pj_ntohs(hdr->seq), 685 pj_ntohl(hdr->ts), payloadlen); 686 687 /* Handle incoming DTMF. */ 688 if (hdr->pt == stream->rx_event_pt) { 689 handle_incoming_dtmf(stream, payload, payloadlen); 690 return; 691 } 692 693 694 /* Update RTP session (also checks if RTP session can accept 695 * the incoming packet. 703 696 */ 704 do { 705 const pjmedia_rtp_hdr *hdr; 706 const void *payload; 707 unsigned payloadlen; 708 pjmedia_rtp_status seq_st; 709 710 /* Go straight to read next packet if bytes_read == 0. 697 pjmedia_rtp_session_update(&channel->rtp, hdr, &seq_st); 698 if (seq_st.status.value) { 699 TRC_ ((stream->port.info.name.ptr, 700 "RTP status: badpt=%d, badssrc=%d, dup=%d, " 701 "outorder=%d, probation=%d, restart=%d", 702 seq_st.status.flag.badpt, 703 seq_st.status.flag.badssrc, 704 seq_st.status.flag.dup, 705 seq_st.status.flag.outorder, 706 seq_st.status.flag.probation, 707 seq_st.status.flag.restart)); 708 709 if (seq_st.status.flag.badpt) { 710 PJ_LOG(4,(stream->port.info.name.ptr, 711 "Bad RTP pt %d (expecting %d)", 712 hdr->pt, channel->rtp.out_pt)); 713 } 714 } 715 716 /* Skip bad RTP packet */ 717 if (seq_st.status.flag.bad) 718 return; 719 720 721 /* Put "good" packet to jitter buffer, or reset the jitter buffer 722 * when RTP session is restarted. 723 */ 724 pj_mutex_lock( stream->jb_mutex ); 725 if (seq_st.status.flag.restart) { 726 status = pjmedia_jbuf_reset(stream->jb); 727 PJ_LOG(4,(stream->port.info.name.ptr, "Jitter buffer reset")); 728 729 } else { 730 /* 731 * Packets may contain more than one frames, while the jitter 732 * buffer can only take one frame per "put" operation. So we need 733 * to ask the codec to "parse" the payload into multiple frames. 711 734 */ 712 if (bytes_read == 0) 713 goto read_next_packet; 714 715 if (bytes_read < 0) 716 goto read_next_packet; 717 718 /* Update RTP and RTCP session. */ 719 status = pjmedia_rtp_decode_rtp(&channel->rtp, 720 channel->in_pkt, bytes_read, 721 &hdr, &payload, &payloadlen); 735 enum { MAX = 16 }; 736 pj_timestamp ts; 737 unsigned i, count = MAX; 738 unsigned samples_per_frame; 739 pjmedia_frame frames[MAX]; 740 741 /* Get the timestamp of the first sample */ 742 ts.u64 = pj_ntohl(hdr->ts); 743 744 /* Parse the payload. */ 745 status = (*stream->codec->op->parse)(stream->codec, 746 (void*)payload, 747 payloadlen, 748 &ts, 749 &count, 750 frames); 722 751 if (status != PJ_SUCCESS) { 723 LOGERR_((stream->port.info.name.ptr, "RTP decode error", status)); 724 goto read_next_packet; 752 LOGERR_((stream->port.info.name.ptr, 753 "Codec parse() error", 754 status)); 755 count = 0; 725 756 } 726 757 727 728 /* Inform RTCP session */ 729 pjmedia_rtcp_rx_rtp(&stream->rtcp, pj_ntohs(hdr->seq), 730 pj_ntohl(hdr->ts), payloadlen); 731 732 /* Handle incoming DTMF. */ 733 if (hdr->pt == stream->rx_event_pt) { 734 handle_incoming_dtmf(stream, payload, payloadlen); 735 goto read_next_packet; 758 /* Put each frame to jitter buffer. */ 759 samples_per_frame = stream->codec_param.info.frm_ptime * 760 stream->codec_param.info.clock_rate * 761 stream->codec_param.info.channel_cnt / 762 1000; 763 764 for (i=0; i<count; ++i) { 765 unsigned ext_seq; 766 767 ext_seq = (unsigned)(frames[i].timestamp.u64 / 768 samples_per_frame); 769 pjmedia_jbuf_put_frame(stream->jb, frames[i].buf, 770 frames[i].size, ext_seq); 771 736 772 } 737 738 739 /* Update RTP session (also checks if RTP session can accept 740 * the incoming packet. 741 */ 742 pjmedia_rtp_session_update(&channel->rtp, hdr, &seq_st); 743 if (seq_st.status.value) { 744 TRC_ ((stream->port.info.name.ptr, 745 "RTP status: badpt=%d, badssrc=%d, dup=%d, " 746 "outorder=%d, probation=%d, restart=%d", 747 seq_st.status.flag.badpt, 748 seq_st.status.flag.badssrc, 749 seq_st.status.flag.dup, 750 seq_st.status.flag.outorder, 751 seq_st.status.flag.probation, 752 seq_st.status.flag.restart)); 753 754 if (seq_st.status.flag.badpt) { 755 PJ_LOG(4,(stream->port.info.name.ptr, 756 "Bad RTP pt %d (expecting %d)", 757 hdr->pt, channel->rtp.out_pt)); 758 } 759 } 760 761 /* Skip bad RTP packet */ 762 if (seq_st.status.flag.bad) 763 goto read_next_packet; 764 765 766 /* See if source address of RTP packet is different than the 767 * configured address. 768 */ 769 if ((stream->rem_rtp_addr.sin_addr.s_addr != 770 stream->rtp_src_addr.sin_addr.s_addr) || 771 (stream->rem_rtp_addr.sin_port != stream->rtp_src_addr.sin_port)) 772 { 773 stream->rtp_src_cnt++; 774 775 if (stream->rtp_src_cnt >= PJMEDIA_RTP_NAT_PROBATION_CNT) { 776 777 stream->rem_rtp_addr = stream->rtp_src_addr; 778 stream->rtp_src_cnt = 0; 779 780 PJ_LOG(4,(stream->port.info.name.ptr, 781 "Remote RTP address switched to %s:%d", 782 pj_inet_ntoa(stream->rtp_src_addr.sin_addr), 783 pj_ntohs(stream->rtp_src_addr.sin_port))); 784 } 785 } 786 787 788 789 /* Put "good" packet to jitter buffer, or reset the jitter buffer 790 * when RTP session is restarted. 791 */ 792 pj_mutex_lock( stream->jb_mutex ); 793 if (seq_st.status.flag.restart) { 794 status = pjmedia_jbuf_reset(stream->jb); 795 PJ_LOG(4,(stream->port.info.name.ptr, "Jitter buffer reset")); 796 797 } else { 798 /* 799 * Packets may contain more than one frames, while the jitter 800 * buffer can only take one frame per "put" operation. So we need 801 * to ask the codec to "parse" the payload into multiple frames. 802 */ 803 enum { MAX = 16 }; 804 pj_timestamp ts; 805 unsigned i, count = MAX; 806 unsigned samples_per_frame; 807 pjmedia_frame frames[MAX]; 808 809 /* Get the timestamp of the first sample */ 810 ts.u64 = pj_ntohl(hdr->ts); 811 812 /* Parse the payload. */ 813 status = (*stream->codec->op->parse)(stream->codec, 814 (void*)payload, 815 payloadlen, 816 &ts, 817 &count, 818 frames); 819 if (status != PJ_SUCCESS) { 820 LOGERR_((stream->port.info.name.ptr, 821 "Codec parse() error", 822 status)); 823 count = 0; 824 } 825 826 /* Put each frame to jitter buffer. */ 827 samples_per_frame = stream->codec_param.info.frm_ptime * 828 stream->codec_param.info.clock_rate * 829 stream->codec_param.info.channel_cnt / 830 1000; 831 832 for (i=0; i<count; ++i) { 833 unsigned ext_seq; 834 835 ext_seq = (unsigned)(frames[i].timestamp.u64 / 836 samples_per_frame); 837 pjmedia_jbuf_put_frame(stream->jb, frames[i].buf, 838 frames[i].size, ext_seq); 839 840 } 841 } 842 pj_mutex_unlock( stream->jb_mutex ); 843 844 845 /* Check if now is the time to transmit RTCP SR/RR report. 846 * We only do this when stream direction is "decoding only", 847 * because otherwise check_tx_rtcp() will be handled by put_frame() 848 */ 849 if (stream->dir == PJMEDIA_DIR_DECODING) { 850 check_tx_rtcp(stream, pj_ntohl(hdr->ts)); 851 } 852 853 if (status != 0) { 854 LOGERR_((stream->port.info.name.ptr, "Jitter buffer put() error", 855 status)); 856 goto read_next_packet; 857 } 858 859 860 read_next_packet: 861 bytes_read = channel->in_pkt_size; 862 stream->rtp_addrlen = sizeof(stream->rtp_src_addr); 863 status = pj_ioqueue_recvfrom( stream->rtp_key, 864 &stream->rtp_op_key, 865 channel->in_pkt, 866 &bytes_read, 0, 867 &stream->rtp_src_addr, 868 &stream->rtp_addrlen); 869 870 if (status != PJ_SUCCESS) { 871 bytes_read = -status; 872 } 873 874 } while (status == PJ_SUCCESS || 875 status == PJ_STATUS_FROM_OS(OSERR_ECONNRESET)); 876 877 if (status != PJ_SUCCESS && status != PJ_EPENDING) { 878 char errmsg[PJ_ERR_MSG_SIZE]; 879 880 pj_strerror(status, errmsg, sizeof(errmsg)); 881 PJ_LOG(4,(stream->port.info.name.ptr, 882 "Error reading RTP packet: %s [status=%d]. " 883 "RTP stream thread quitting!", 884 errmsg, status)); 885 } 886 } 887 888 889 /* 890 * This callback is called by ioqueue framework on receipt of packets 773 } 774 pj_mutex_unlock( stream->jb_mutex ); 775 776 777 /* Check if now is the time to transmit RTCP SR/RR report. 778 * We only do this when stream direction is "decoding only", 779 * because otherwise check_tx_rtcp() will be handled by put_frame() 780 */ 781 if (stream->dir == PJMEDIA_DIR_DECODING) { 782 check_tx_rtcp(stream, pj_ntohl(hdr->ts)); 783 } 784 785 if (status != 0) { 786 LOGERR_((stream->port.info.name.ptr, "Jitter buffer put() error", 787 status)); 788 return; 789 } 790 } 791 792 793 /* 794 * This callback is called by stream transport on receipt of packets 891 795 * in the RTCP socket. 892 796 */ 893 static void on_rx_rtcp( pj _ioqueue_key_t *key,894 pj_ioqueue_op_key_t *op_key,797 static void on_rx_rtcp( pjmedia_stream *stream, 798 const void *pkt, 895 799 pj_ssize_t bytes_read) 896 800 { 897 pjmedia_stream *stream = pj_ioqueue_get_user_data(key); 898 pj_status_t status; 899 900 PJ_UNUSED_ARG(op_key); 901 902 do { 903 if (bytes_read > 0) { 904 pjmedia_rtcp_rx_rtcp(&stream->rtcp, stream->rtcp_pkt, 905 bytes_read); 906 } 907 908 bytes_read = stream->rtcp_pkt_size; 909 stream->rtcp_addrlen = sizeof(stream->rem_rtcp_addr); 910 status = pj_ioqueue_recvfrom( stream->rtcp_key, 911 &stream->rtcp_op_key, 912 stream->rtcp_pkt, 913 &bytes_read, 0, 914 &stream->rem_rtcp_addr, 915 &stream->rtcp_addrlen); 916 917 } while (status == PJ_SUCCESS); 918 919 if (status != PJ_SUCCESS && status != PJ_EPENDING) { 920 char errmsg[PJ_ERR_MSG_SIZE]; 921 922 pj_strerror(status, errmsg, sizeof(errmsg)); 923 PJ_LOG(4,(stream->port.info.name.ptr, 924 "Error reading RTCP packet: %s [status=%d]", 925 errmsg, status)); 926 } 927 801 pjmedia_rtcp_rx_rtcp(&stream->rtcp, pkt, bytes_read); 928 802 } 929 803 … … 994 868 pj_pool_t *pool, 995 869 const pjmedia_stream_info *info, 870 pjmedia_transport *tp, 996 871 void *user_data, 997 872 pjmedia_stream **p_stream) … … 999 874 { 1000 875 pjmedia_stream *stream; 1001 pj_ioqueue_callback ioqueue_cb;1002 pj_uint16_t rtcp_port;1003 876 unsigned jb_init, jb_max, jb_min_pre, jb_max_pre; 1004 877 pj_status_t status; … … 1037 910 stream->dir = info->dir; 1038 911 stream->user_data = user_data; 1039 stream->skinfo = info->sock_info;1040 stream->rem_rtp_addr = info->rem_addr;1041 rtcp_port = (pj_uint16_t) (pj_ntohs(info->rem_addr.sin_port)+1);1042 stream->rem_rtcp_addr = stream->rem_rtp_addr;1043 stream->rem_rtcp_addr.sin_port = pj_htons(rtcp_port);1044 912 stream->rtcp_interval = (PJMEDIA_RTCP_INTERVAL + (pj_rand() % 8000)) * 1045 913 info->fmt.clock_rate / 1000; … … 1048 916 stream->rx_event_pt = info->rx_event_pt ? info->rx_event_pt : -1; 1049 917 stream->last_dtmf = -1; 918 919 /* Attach transport */ 920 status = (*tp->op->attach)(tp, stream, &info->rem_addr, 921 sizeof(info->rem_addr), &on_rx_rtp, 922 &on_rx_rtcp); 923 if (status != PJ_SUCCESS) 924 goto err_cleanup; 925 926 stream->transport = tp; 1050 927 1051 928 … … 1161 1038 goto err_cleanup; 1162 1039 1163 /* Register RTP socket to ioqueue */ 1164 pj_memset(&ioqueue_cb, 0, sizeof(ioqueue_cb)); 1165 ioqueue_cb.on_read_complete = &on_rx_rtp; 1166 1167 status = pj_ioqueue_register_sock( pool, 1168 pjmedia_endpt_get_ioqueue(endpt), 1169 stream->skinfo.rtp_sock, 1170 stream, &ioqueue_cb, &stream->rtp_key); 1171 if (status != PJ_SUCCESS) 1172 goto err_cleanup; 1173 1174 /* Init pending operation key. */ 1175 pj_ioqueue_op_key_init(&stream->rtp_op_key, sizeof(stream->rtp_op_key)); 1176 1177 /* Bootstrap the first recvfrom() operation. */ 1178 on_rx_rtp( stream->rtp_key, &stream->rtp_op_key, 0); 1179 1180 1181 /* Register RTCP socket to ioqueue. */ 1182 if (stream->skinfo.rtcp_sock != PJ_INVALID_SOCKET) { 1183 pj_memset(&ioqueue_cb, 0, sizeof(ioqueue_cb)); 1184 ioqueue_cb.on_read_complete = &on_rx_rtcp; 1185 1186 status = pj_ioqueue_register_sock( pool, 1187 pjmedia_endpt_get_ioqueue(endpt), 1188 stream->skinfo.rtcp_sock, 1189 stream, &ioqueue_cb, 1190 &stream->rtcp_key); 1191 if (status != PJ_SUCCESS) 1192 goto err_cleanup; 1193 } 1194 1195 /* Init pending operation key. */ 1196 pj_ioqueue_op_key_init(&stream->rtcp_op_key, sizeof(stream->rtcp_op_key)); 1197 1198 stream->rtcp_pkt_size = sizeof(stream->rtcp_pkt); 1199 1200 /* Bootstrap the first recvfrom() operation. */ 1201 on_rx_rtcp( stream->rtcp_key, &stream->rtcp_op_key, 0); 1040 1202 1041 1203 1042 /* Success! */ … … 1228 1067 1229 1068 1230 /* Unregister from ioqueue. */ 1231 if (stream->rtp_key) { 1232 pj_ioqueue_unregister(stream->rtp_key); 1233 stream->rtp_key = NULL; 1234 } 1235 if (stream->rtcp_key) { 1236 pj_ioqueue_unregister(stream->rtcp_key); 1237 stream->rtcp_key = NULL; 1069 /* Detach from transport */ 1070 if (stream->transport) { 1071 (*stream->transport->op->detach)(stream->transport, stream); 1072 stream->transport = NULL; 1238 1073 } 1239 1074 … … 1266 1101 *p_port = &stream->port; 1267 1102 return PJ_SUCCESS; 1103 } 1104 1105 1106 /* 1107 * Get the transport object 1108 */ 1109 PJ_DEF(pjmedia_transport*) pjmedia_stream_get_transport(pjmedia_stream *st) 1110 { 1111 return st->transport; 1268 1112 } 1269 1113 -
pjproject/trunk/pjsip-apps/src/samples/simpleua.c
r438 r452 74 74 static pjmedia_endpt *g_med_endpt; /* Media endpoint. */ 75 75 static pjmedia_sock_info g_med_skinfo; /* Socket info for media */ 76 static pjmedia_transport *g_med_transport;/* Media stream transport */ 76 77 77 78 /* Call variables: */ … … 281 282 282 283 284 /* Create media transport */ 285 status = pjmedia_transport_udp_attach(g_med_endpt, NULL, &g_med_skinfo, 286 &g_med_transport); 287 if (status != PJ_SUCCESS) { 288 app_perror(THIS_FILE, "Unable to create media transport", status); 289 return 1; 290 } 291 283 292 /* 284 293 * If URL is specified, then make call immediately. … … 612 621 * We only support one stream per session for now. 613 622 */ 614 status = pjmedia_session_info_from_sdp(inv->dlg->pool, g_med_endpt, 1,615 &sess_info, &g_med_skinfo,623 status = pjmedia_session_info_from_sdp(inv->dlg->pool, g_med_endpt, 624 1, &sess_info, 616 625 local_sdp, remote_sdp); 617 626 if (status != PJ_SUCCESS) { … … 630 639 */ 631 640 status = pjmedia_session_create( g_med_endpt, &sess_info, 632 NULL, &g_med_session );641 &g_med_transport, NULL, &g_med_session ); 633 642 if (status != PJ_SUCCESS) { 634 643 app_perror( THIS_FILE, "Unable to create media session", status); -
pjproject/trunk/pjsip-apps/src/samples/siprtp.c
r444 r452 1277 1277 1278 1278 status = pjmedia_stream_info_from_sdp(&audio->si, inv->pool, app.med_endpt, 1279 NULL,local_sdp, remote_sdp, 0);1279 local_sdp, remote_sdp, 0); 1280 1280 if (status != PJ_SUCCESS) { 1281 1281 app_perror(THIS_FILE, "Error creating stream info from SDP", status); -
pjproject/trunk/pjsip-apps/src/samples/streamutil.c
r448 r452 111 111 { 112 112 pjmedia_stream_info info; 113 pjmedia_transport *transport; 113 114 pj_status_t status; 114 115 … … 130 131 131 132 132 /* Create RTP socket */ 133 status = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, 134 &info.sock_info.rtp_sock); 135 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); 136 137 138 /* Bind RTP socket to local port */ 139 info.sock_info.rtp_addr_name.sin_family = PJ_AF_INET; 140 info.sock_info.rtp_addr_name.sin_port = pj_htons(local_port); 141 142 status = pj_sock_bind(info.sock_info.rtp_sock, 143 &info.sock_info.rtp_addr_name, 144 sizeof(pj_sockaddr_in)); 145 if (status != PJ_SUCCESS) { 146 app_perror(THIS_FILE, "Unable to bind RTP socket", status); 147 pj_sock_close(info.sock_info.rtp_sock); 133 /* Create media transport */ 134 status = pjmedia_transport_udp_create(med_endpt, NULL, local_port, 135 &transport); 136 if (status != PJ_SUCCESS) 148 137 return status; 149 }150 151 152 /* Create RTCP socket */153 status = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0,154 &info.sock_info.rtcp_sock);155 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);156 157 158 /* Bind RTP socket to local port + 1 */159 ++local_port;160 info.sock_info.rtcp_addr_name.sin_family = PJ_AF_INET;161 info.sock_info.rtcp_addr_name.sin_port = pj_htons(local_port);162 163 status = pj_sock_bind(info.sock_info.rtcp_sock,164 &info.sock_info.rtcp_addr_name,165 sizeof(pj_sockaddr_in));166 if (status != PJ_SUCCESS) {167 app_perror(THIS_FILE, "Unable to bind RTCP socket", status);168 pj_sock_close(info.sock_info.rtp_sock);169 pj_sock_close(info.sock_info.rtcp_sock);170 return status;171 }172 138 173 139 … … 176 142 */ 177 143 178 status = pjmedia_stream_create( med_endpt, pool, &info, NULL, p_stream); 144 status = pjmedia_stream_create( med_endpt, pool, &info, 145 transport, NULL, p_stream); 179 146 180 147 if (status != PJ_SUCCESS) { 181 148 app_perror(THIS_FILE, "Error creating stream", status); 182 pj_sock_close(info.sock_info.rtp_sock); 183 pj_sock_close(info.sock_info.rtcp_sock); 149 pjmedia_transport_udp_close(transport); 184 150 return status; 185 151 } … … 212 178 pjmedia_port *stream_port; 213 179 char tmp[10]; 214 pj_status_t status; 180 pj_status_t status; 215 181 216 182 … … 514 480 /* Destroy stream */ 515 481 if (stream) { 482 pjmedia_transport *tp; 483 484 tp = pjmedia_stream_get_transport(stream); 516 485 pjmedia_stream_destroy(stream); 486 pjmedia_transport_udp_close(tp); 517 487 } 518 488 -
pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h
r438 r452 103 103 call was triggered by xfer. */ 104 104 pjmedia_sock_info skinfo; /**< Preallocated media sockets. */ 105 pjmedia_transport *med_tp; /**< Media transport. */ 105 106 void *app_data; /**< Application data. */ 106 107 pj_timer_entry refresh_tm;/**< Timer to send re-INVITE. */ -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c
r438 r452 98 98 99 99 100 /* Close and reopen socket. */101 static pj_status_t reopen_sock( pj_sock_t *sock, pj_sockaddr_in *addr)102 {103 pj_status_t status;104 105 status = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, sock);106 if (status != PJ_SUCCESS) {107 pjsua_perror(THIS_FILE, "Unable to create socket", status);108 return status;109 }110 111 status = pj_sock_bind(*sock, addr, sizeof(pj_sockaddr_in));112 if (status != PJ_SUCCESS) {113 pjsua_perror(THIS_FILE, "Unable to re-bind RTP/RTCP socket", status);114 return status;115 }116 117 return PJ_SUCCESS;118 }119 120 100 /* 121 101 * Destroy the call's media … … 131 111 132 112 if (call->session) { 133 pj_sockaddr_in rtp_addr, rtcp_addr;134 int addrlen;135 136 addrlen = sizeof(rtp_addr);137 pj_sock_getsockname(call->skinfo.rtp_sock, &rtp_addr, &addrlen);138 139 addrlen = sizeof(rtcp_addr);140 pj_sock_getsockname(call->skinfo.rtcp_sock, &rtcp_addr, &addrlen);141 142 113 /* Destroy session (this will also close RTP/RTCP sockets). */ 143 114 pjmedia_session_destroy(call->session); 144 145 /* Close and reopen RTP socket.146 * This is necessary to get the socket unregistered from ioqueue,147 * when IOCompletionPort is used.148 */149 reopen_sock(&call->skinfo.rtp_sock, &rtp_addr);150 151 /* Close and reopen RTCP socket too. */152 reopen_sock(&call->skinfo.rtcp_sock, &rtcp_addr);153 154 115 call->session = NULL; 155 116 … … 1012 973 */ 1013 974 status = pjmedia_session_info_from_sdp( call->inv->dlg->pool, 1014 pjsua.med_endpt, 1,1015 &sess_info, &call->skinfo,975 pjsua.med_endpt, 976 1,&sess_info, 1016 977 local_sdp, remote_sdp); 1017 978 if (status != PJ_SUCCESS) { … … 1036 997 /* Create session based on session info. */ 1037 998 status = pjmedia_session_create( pjsua.med_endpt, &sess_info, 999 &call->med_tp, 1038 1000 call, &call->session ); 1039 1001 if (status != PJ_SUCCESS) { -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c
r443 r452 321 321 pj_inet_ntoa(skinfo->rtp_addr_name.sin_addr), 322 322 pj_ntohs(skinfo->rtp_addr_name.sin_port))); 323 PJ_LOG(4,(THIS_FILE, "RTCP UDPsocket reachable at %s:%d",323 PJ_LOG(4,(THIS_FILE, "RTCP socket reachable at %s:%d", 324 324 pj_inet_ntoa(skinfo->rtcp_addr_name.sin_addr), 325 325 pj_ntohs(skinfo->rtcp_addr_name.sin_port))); … … 780 780 for (i=0; i<(int)pjsua.max_calls; ++i) { 781 781 status = init_sockets(i==0, &pjsua.calls[i].skinfo); 782 if (status == PJ_SUCCESS) 783 status = pjmedia_transport_udp_attach(pjsua.med_endpt, NULL, 784 &pjsua.calls[i].skinfo, 785 &pjsua.calls[i].med_tp); 782 786 if (status != PJ_SUCCESS) { 783 787 pjsua_perror(THIS_FILE, "init_sockets() has returned error", … … 787 791 pj_sock_close(pjsua.sip_sock); 788 792 while (i >= 0) { 789 pj_sock_close(pjsua.calls[i].skinfo.rtp_sock); 790 pj_sock_close(pjsua.calls[i].skinfo.rtcp_sock); 793 pjmedia_transport_udp_close(pjsua.calls[i].med_tp); 791 794 } 792 795 return status; … … 1049 1052 #endif /* PJMEDIA_HAS_L16_CODEC */ 1050 1053 1054 1055 /* Close transports */ 1056 for (i=0; i<pjsua.call_cnt; ++i) { 1057 pjmedia_transport_udp_close(pjsua.calls[i].med_tp); 1058 } 1059 1051 1060 /* Destroy media endpoint. */ 1052 1061
Note: See TracChangeset
for help on using the changeset viewer.