Changeset 205 for pjproject/trunk
- Timestamp:
- Feb 21, 2006 12:11:18 AM (19 years ago)
- Location:
- pjproject/trunk
- Files:
-
- 4 added
- 18 edited
- 2 moved
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/build/pjmedia.dsp
r203 r205 66 66 # PROP Target_Dir "" 67 67 # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c 68 # ADD CPP /nologo /MTd /W4 /Gm /GX /ZI /Od /I "../include" /I "../../pjlib/include" /I "../../pjlib-util/include" /I "../src/pjmedia/portaudio" /D "_DEBUG" /D "PA_NO_ASIO" /D " WIN32" /D "_MBCS" /D "_LIB" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /FD /GZ /c68 # ADD CPP /nologo /MTd /W4 /Gm /GX /ZI /Od /I "../include" /I "../../pjlib/include" /I "../../pjlib-util/include" /I "../src/pjmedia/portaudio" /D "_DEBUG" /D "PA_NO_ASIO" /D "PA_NO_WIN_DS" /D "WIN32" /D "_MBCS" /D "_LIB" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /FD /GZ /c 69 69 # SUBTRACT CPP /YX 70 70 # ADD BASE RSC /l 0x409 /d "_DEBUG" … … 88 88 # Begin Source File 89 89 90 SOURCE=..\src\pjmedia\audio_conf.c91 # End Source File92 # Begin Source File93 94 90 SOURCE=..\src\pjmedia\codec.c 91 # End Source File 92 # Begin Source File 93 94 SOURCE=..\src\pjmedia\conference.c 95 95 # End Source File 96 96 # Begin Source File … … 126 126 # Begin Source File 127 127 128 SOURCE=..\src\pjmedia\port.c 129 # End Source File 130 # Begin Source File 131 128 132 SOURCE=..\src\pjmedia\rtcp.c 129 133 # End Source File … … 131 135 132 136 SOURCE=..\src\pjmedia\rtp.c 137 # End Source File 138 # Begin Source File 139 140 SOURCE=..\src\pjmedia\rtp_port.c 133 141 # End Source File 134 142 # Begin Source File … … 162 170 # Begin Source File 163 171 164 SOURCE=..\include\pjmedia\audio_conf.h165 # End Source File166 # Begin Source File167 168 172 SOURCE=..\include\pjmedia\codec.h 169 173 # End Source File 170 174 # Begin Source File 171 175 176 SOURCE=..\include\pjmedia\conference.h 177 # End Source File 178 # Begin Source File 179 172 180 SOURCE=..\include\pjmedia\config.h 173 181 # End Source File … … 194 202 # Begin Source File 195 203 204 SOURCE=..\include\pjmedia\port.h 205 # End Source File 206 # Begin Source File 207 196 208 SOURCE=..\include\pjmedia\rtcp.h 197 209 # End Source File … … 199 211 200 212 SOURCE=..\include\pjmedia\rtp.h 213 # End Source File 214 # Begin Source File 215 216 SOURCE=..\include\pjmedia\rtp_port.h 201 217 # End Source File 202 218 # Begin Source File -
pjproject/trunk/pjmedia/include/pjmedia.h
r188 r205 26 26 27 27 #include <pjmedia/types.h> 28 #include <pjmedia/codec.h> 29 #include <pjmedia/conference.h> 30 #include <pjmedia/endpoint.h> 28 31 #include <pjmedia/errno.h> 29 #include <pjmedia/codec.h>30 32 #include <pjmedia/jbuf.h> 31 #include <pjmedia/ endpoint.h>33 #include <pjmedia/port.h> 32 34 #include <pjmedia/rtcp.h> 33 35 #include <pjmedia/rtp.h> 36 #include <pjmedia/sdp.h> 37 #include <pjmedia/sdp_neg.h> 34 38 #include <pjmedia/session.h> 35 39 #include <pjmedia/sound.h> 36 #include <pjmedia/sdp.h>37 #include <pjmedia/sdp_neg.h>38 40 39 41 #endif /* __PJMEDIA_H__ */ -
pjproject/trunk/pjmedia/include/pjmedia/codec.h
r189 r205 120 120 121 121 122 /**123 * Types of media frame.124 */125 enum pjmedia_frame_type126 {127 PJMEDIA_FRAME_TYPE_SILENCE_AUDIO, /**< Silence audio frame. */128 PJMEDIA_FRAME_TYPE_AUDIO, /**< Normal audio frame. */129 130 };131 132 /**133 * This structure describes a media frame.134 */135 struct pjmedia_frame136 {137 pjmedia_frame_type type; /**< Frame type. */138 void *buf; /**< Pointer to buffer. */139 pj_size_t size; /**< Frame size in bytes. */140 };141 142 122 /** 143 123 * This structure describes codec operations. Each codec MUST implement -
pjproject/trunk/pjmedia/include/pjmedia/conference.h
r203 r205 22 22 23 23 /** 24 * @file conf .h24 * @file conference.h 25 25 * @brief Conference bridge. 26 26 */ 27 #include <pjmedia/types.h> 27 #include <pjmedia/port.h> 28 29 30 PJ_BEGIN_DECL 31 28 32 29 33 /** … … 32 36 typedef struct pjmedia_conf pjmedia_conf; 33 37 38 /** 39 * Conference port info. 40 */ 41 typedef struct pjmedia_conf_port_info 42 { 43 pj_str_t name; 44 pjmedia_port_op tx_setting; 45 pjmedia_port_op rx_setting; 46 pj_bool_t *listener; 47 } pjmedia_conf_port_info; 48 34 49 35 50 /** … … 37 52 */ 38 53 PJ_DECL(pj_status_t) pjmedia_conf_create( pj_pool_t *pool, 39 unsigned max_ports, 54 unsigned max_slots, 55 unsigned sampling_rate, 56 unsigned samples_per_frame, 57 unsigned bits_per_sample, 40 58 pjmedia_conf **p_conf ); 41 59 42 60 43 61 /** 44 * Add stream port to the conference bridge. 62 * Destroy conference bridge. 63 */ 64 PJ_DECL(pj_status_t) pjmedia_conf_destroy( pjmedia_conf *conf ); 65 66 67 /** 68 * Add stream port to the conference bridge. By default, the new conference 69 * port will have both TX and RX enabled, but it is not connected to any 70 * other ports. 71 * 72 * Application SHOULD call #pjmedia_conf_connect_port() to enable audio 73 * transmission and receipt to/from this port. 74 * 75 * @param conf The conference bridge. 76 * @param pool Pool to allocate buffers for this port. 77 * @param strm_port Stream port interface. 78 * @param name Port name. 79 * @param p_slot Pointer to receive the slot index of the port in 80 * the conference bridge. 81 * 82 * @return PJ_SUCCESS on success. 45 83 */ 46 84 PJ_DECL(pj_status_t) pjmedia_conf_add_port( pjmedia_conf *conf, 47 85 pj_pool_t *pool, 48 pjmedia_stream_port *strm_port, 49 const pj_str_t *port_name, 50 unsigned *p_port ); 86 pjmedia_port *strm_port, 87 const pj_str_t *name, 88 unsigned *p_slot ); 89 51 90 52 91 53 92 /** 54 * Mute or unmute port. 93 * Change TX and RX settings for the port. 94 * 95 * @param conf The conference bridge. 96 * @param slot Port number/slot in the conference bridge. 97 * @param tx Settings for the transmission TO this port. 98 * @param rx Settings for the receipt FROM this port. 99 * 100 * @return PJ_SUCCESS on success. 55 101 */ 56 PJ_DECL(pj_status_t) pjmedia_conf_set_mute( pjmedia_conf *conf, 57 unsigned port, 58 pj_bool_t mute ); 102 PJ_DECL(pj_status_t) pjmedia_conf_configure_port( pjmedia_conf *conf, 103 unsigned slot, 104 pjmedia_port_op tx, 105 pjmedia_port_op rx); 59 106 60 107 61 108 /** 62 * Set the specified port to be member of conference bridge. 109 * Enable unidirectional audio from the specified source slot to the 110 * specified sink slot. 111 * 112 * @param conf The conference bridge. 113 * @param src_slot Source slot. 114 * @param sink_slot Sink slot. 115 * 116 * @return PJ_SUCCES on success. 63 117 */ 64 PJ_DECL(pj_status_t) pjmedia_conf_ set_membership( pjmedia_conf *conf,65 unsigned port,66 pj_bool_t enabled);118 PJ_DECL(pj_status_t) pjmedia_conf_connect_port( pjmedia_conf *conf, 119 unsigned src_slot, 120 unsigned sink_slot ); 67 121 68 122 69 123 /** 70 * Remove the specified port. 124 * Disconnect unidirectional audio from the specified source to the specified 125 * sink slot. 126 * 127 * @param conf The conference bridge. 128 * @param src_slot Source slot. 129 * @param sink_slot Sink slot. 130 * 131 * @reutrn PJ_SUCCESS on success. 132 */ 133 PJ_DECL(pj_status_t) pjmedia_conf_disconnect_port( pjmedia_conf *conf, 134 unsigned src_slot, 135 unsigned sink_slot ); 136 137 138 /** 139 * Remove the specified port from the conference bridge. 140 * 141 * @param conf The conference bridge. 142 * @param slot The port index to be removed. 143 * 144 * @return PJ_SUCCESS on success. 71 145 */ 72 146 PJ_DECL(pj_status_t) pjmedia_conf_remove_port( pjmedia_conf *conf, 73 unsigned port );147 unsigned slot ); 74 148 149 150 151 /** 152 * Get port info. 153 */ 154 PJ_DECL(pj_status_t) pjmedia_conf_get_port_info( pjmedia_conf *conf, 155 unsigned slot, 156 pjmedia_conf_port_info *info); 157 158 159 PJ_END_DECL 75 160 76 161 -
pjproject/trunk/pjmedia/include/pjmedia/errno.h
r188 r205 345 345 */ 346 346 #define PJMEDIA_RTP_EBADSEQ (PJMEDIA_ERRNO_START+132) /* 220132 */ 347 /** 348 * @hideinitializer 349 * RTP media port destination is not configured 350 */ 351 #define PJMEDIA_RTP_EBADDEST (PJMEDIA_ERRNO_START+133) /* 220133 */ 352 /** 353 * @hideinitializer 354 * RTP is not configured. 355 */ 356 #define PJMEDIA_RTP_ENOCONFIG (PJMEDIA_ERRNO_START+134) /* 220134 */ 347 357 348 358 … … 352 362 353 363 364 /************************************************************ 365 * PORT ERRORS 366 ***********************************************************/ 367 /** 368 * @hideinitializer 369 * Generic incompatible port error. 370 */ 371 #define PJMEDIA_ENOTCOMPATIBLE (PJMEDIA_ERRNO_START+160) /* 220160 */ 372 /** 373 * @hideinitializer 374 * Incompatible clock rate 375 */ 376 #define PJMEDIA_ENCCLOCKRATE (PJMEDIA_ERRNO_START+161) /* 220161 */ 377 /** 378 * @hideinitializer 379 * Incompatible samples per frame 380 */ 381 #define PJMEDIA_ENCSAMPLESPFRAME (PJMEDIA_ERRNO_START+162) /* 220162 */ 382 /** 383 * @hideinitializer 384 * Incompatible media type 385 */ 386 #define PJMEDIA_ENCTYPE (PJMEDIA_ERRNO_START+163) /* 220163 */ 387 /** 388 * @hideinitializer 389 * Incompatible bits per sample 390 */ 391 #define PJMEDIA_ENCBITS (PJMEDIA_ERRNO_START+164) /* 220164 */ 392 /** 393 * @hideinitializer 394 * Incompatible bytes per frame 395 */ 396 #define PJMEDIA_ENCBYTES (PJMEDIA_ERRNO_START+165) /* 220165 */ 397 398 399 354 400 PJ_END_DECL 355 401 -
pjproject/trunk/pjmedia/include/pjmedia/rtp.h
r199 r205 70 70 */ 71 71 72 #ifdef _MSC_VER 73 # pragma warning(disable:4214) // bit field types other than int 74 #endif 72 75 73 76 -
pjproject/trunk/pjmedia/include/pjmedia/session.h
r189 r205 176 176 177 177 /** 178 * Get the port interface for the specified stream. 179 */ 180 PJ_DECL(pj_status_t) pjmedia_session_get_port( pjmedia_session *session, 181 unsigned index, 182 pjmedia_port **p_port); 183 184 185 /** 178 186 * Get session statistics. The stream statistic shows various 179 187 * indicators such as packet count, packet lost, jitter, delay, etc. -
pjproject/trunk/pjmedia/include/pjmedia/stream.h
r203 r205 29 29 #include <pjmedia/codec.h> 30 30 #include <pjmedia/endpoint.h> 31 #include <pjmedia/port.h> 31 32 #include <pj/sock.h> 32 33 … … 98 99 99 100 100 /**101 * Stream ports.102 */103 struct pjmedia_stream_port104 {105 /**106 * Sink port.107 */108 pj_status_t (*put_frame)(const pj_int16_t *frame, pj_size_t frame_cnt);109 110 /**111 * Source port.112 */113 pj_status_t (*get_frame)(pj_int16_t *frame, pj_size_t frame_cnt);114 };115 116 101 117 102 /** … … 141 126 */ 142 127 PJ_DECL(pj_status_t) pjmedia_stream_destroy(pjmedia_stream *stream); 128 129 /** 130 * Get the port interface of the stream. 131 * 132 * @param stream The media stream. 133 * @param p_port Pointer to receive the port interface. 134 * 135 * @return PJ_SUCCESS on success. 136 */ 137 PJ_DECL(pj_status_t) pjmedia_stream_get_port(pjmedia_stream *stream, 138 pjmedia_port **p_port ); 139 143 140 144 141 /** -
pjproject/trunk/pjmedia/include/pjmedia/types.h
r203 r205 152 152 153 153 /** 154 * @see pjmedia_stream_port155 */156 typedef struct pjmedia_stream_port pjmedia_stream_port;157 158 /**159 154 * Typedef for media stream. 160 155 */ -
pjproject/trunk/pjmedia/src/pjmedia-codec/gsm.c
r198 r205 21 21 #include <pjmedia/errno.h> 22 22 #include <pjmedia/endpoint.h> 23 #include <pjmedia/port.h> 23 24 #include <pj/assert.h> 24 25 #include <pj/pool.h> -
pjproject/trunk/pjmedia/src/pjmedia/conference.c
r203 r205 17 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 18 */ 19 #include <pjmedia/ audio_conf.h>19 #include <pjmedia/conference.h> 20 20 #include <pjmedia/vad.h> 21 21 #include <pjmedia/stream.h> 22 22 #include <pjmedia/sound.h> 23 23 #include <pjmedia/errno.h> 24 #include <pjmedia/port.h> 24 25 #include <pj/assert.h> 25 26 #include <pj/log.h> … … 27 28 #include <pj/string.h> 28 29 29 30 31 #define THIS_FILE "audio_conf.c" 30 //#define CONF_DEBUG 31 #ifdef CONF_DEBUG 32 # include <stdio.h> 33 # define TRACE_(x) printf x 34 #else 35 # define TRACE_(x) 36 #endif 37 38 39 #define THIS_FILE "conference.c" 40 #define RX_BUF_COUNT 8 41 42 /* 43 * DON'T GET CONFUSED!! 44 * 45 * TX and RX directions are always viewed from the conference bridge's point 46 * of view, and NOT from the port's point of view. 47 */ 32 48 33 49 34 50 struct conf_port 35 51 { 36 pj_str_t name; 37 pjmedia_stream_port *port; 38 pj_bool_t online; 39 pj_bool_t is_member; 40 pjmedia_vad *vad; 41 pj_int32_t level; 52 pj_str_t name; /**< Port name. */ 53 pjmedia_port *port; /**< get_frame() and put_frame() */ 54 pjmedia_port_op rx_setting; /**< Can we receive from this port */ 55 pjmedia_port_op tx_setting; /**< Can we transmit to this port */ 56 pj_bool_t *listeners; /**< Array of listeners. */ 57 pjmedia_vad *vad; /**< VAD for this port. */ 58 59 /* Tx buffer contains the frame to be "transmitted" to this port 60 * (i.e. for put_frame()). 61 * We use dual buffer since the port may be accessed by two threads, 62 * and we don't want to use mutex for synchronization. 63 */ 64 pj_int16_t *cur_tx_buf; /**< Buffer for put_frame(). */ 65 pj_int16_t *tx_buf1; /**< Buffer 1. */ 66 pj_int16_t *tx_buf2; /**< Buffer 2. */ 67 68 /* Rx buffers is a special buffer for sound device port (port 0). 69 * It's not used by other ports. 70 */ 71 int rx_write, rx_read; 72 pj_int16_t *rx_buf[RX_BUF_COUNT]; /**< Buffer */ 73 74 75 /* Sum buf is a temporary buffer used to calculate the average signal 76 * received by this port from all other ports. 77 */ 78 unsigned sources; /**< Number of sources. */ 79 pj_uint32_t *sum_buf; /**< Total sum of signal. */ 42 80 }; 43 81 82 44 83 /* 45 84 * Conference bridge. … … 47 86 struct pjmedia_conf 48 87 { 49 unsigned max_ports; /**< Maximum ports. */ 50 unsigned port_cnt; /**< Current number of ports. */ 51 pj_snd_stream *snd_rec; /**< Sound recorder stream. */ 52 pj_snd_stream *snd_player; /**< Sound player stream. */ 53 struct conf_port **port; /**< Array of ports. */ 54 pj_int16_t *rec_buf; /**< Sample buffer for rec. */ 55 pj_int16_t *play_buf; /**< Sample buffer for player */ 56 unsigned samples_cnt; /**< Samples per frame. */ 57 pj_size_t buf_size; /**< Buffer size, in bytes. */ 88 unsigned max_ports; /**< Maximum ports. */ 89 unsigned port_cnt; /**< Current number of ports. */ 90 unsigned connect_cnt; /**< Total number of connections */ 91 pj_snd_stream *snd_rec; /**< Sound recorder stream. */ 92 pj_snd_stream *snd_player; /**< Sound player stream. */ 93 struct conf_port **ports; /**< Array of ports. */ 94 pj_uint16_t *uns_buf; /**< Buf for unsigned conversion */ 95 unsigned sampling_rate; /**< Sampling rate. */ 96 unsigned samples_per_frame; /**< Samples per frame. */ 97 unsigned bits_per_sample; /**< Bits per sample. */ 98 pj_snd_stream_info snd_info; 58 99 }; 59 100 … … 69 110 /* in*/ unsigned size); 70 111 112 /* 113 * Create port. 114 */ 115 static pj_status_t create_conf_port( pj_pool_t *pool, 116 pjmedia_conf *conf, 117 const pj_str_t *name, 118 struct conf_port **p_conf_port) 119 { 120 struct conf_port *conf_port; 121 pj_status_t status; 122 123 /* Create port. */ 124 conf_port = pj_pool_zalloc(pool, sizeof(struct conf_port)); 125 PJ_ASSERT_RETURN(conf_port, PJ_ENOMEM); 126 127 /* Set name */ 128 pj_strdup(pool, &conf_port->name, name); 129 130 /* Default has tx and rx enabled. */ 131 conf_port->rx_setting = PJMEDIA_PORT_ENABLE; 132 conf_port->tx_setting = PJMEDIA_PORT_ENABLE; 133 134 /* Create transmit flag array */ 135 conf_port->listeners = pj_pool_zalloc(pool, 136 conf->max_ports*sizeof(pj_bool_t)); 137 PJ_ASSERT_RETURN(conf_port->listeners, PJ_ENOMEM); 138 139 140 /* Create and init vad. */ 141 status = pjmedia_vad_create( pool, &conf_port->vad); 142 if (status != PJ_SUCCESS) 143 return status; 144 145 pjmedia_vad_set_adaptive(conf_port->vad, conf->samples_per_frame); 146 147 148 /* Create TX buffers. */ 149 conf_port->tx_buf1 = pj_pool_zalloc(pool, conf->samples_per_frame * 150 sizeof(conf_port->tx_buf1[0])); 151 PJ_ASSERT_RETURN(conf_port->tx_buf1, PJ_ENOMEM); 152 153 conf_port->tx_buf2 = pj_pool_zalloc(pool, conf->samples_per_frame * 154 sizeof(conf_port->tx_buf2[0])); 155 PJ_ASSERT_RETURN(conf_port->tx_buf2, PJ_ENOMEM); 156 157 /* Set initial TX buffer */ 158 conf_port->cur_tx_buf = conf_port->tx_buf1; 159 160 /* Create temporary buffer to calculate average signal received by 161 * this port. 162 */ 163 conf_port->sum_buf = pj_pool_zalloc(pool, conf->samples_per_frame * 164 sizeof(conf_port->sum_buf[0])); 165 166 167 168 /* Done */ 169 *p_conf_port = conf_port; 170 return PJ_SUCCESS; 171 } 172 173 /* 174 * Create port zero for the sound device. 175 */ 176 static pj_status_t create_sound_port( pj_pool_t *pool, 177 pjmedia_conf *conf ) 178 { 179 struct conf_port *conf_port; 180 pj_str_t name = { "sound-device", 12 }; 181 unsigned i; 182 pj_status_t status; 183 184 185 /* Init default sound device parameters. */ 186 pj_memset(&conf->snd_info, 0, sizeof(conf->snd_info)); 187 conf->snd_info.samples_per_sec = conf->sampling_rate; 188 conf->snd_info.bits_per_sample = conf->bits_per_sample; 189 conf->snd_info.samples_per_frame = conf->samples_per_frame; 190 conf->snd_info.bytes_per_frame = conf->samples_per_frame * 191 conf->bits_per_sample / 8; 192 conf->snd_info.frames_per_packet = 1; 193 194 195 /* Create port */ 196 status = create_conf_port(pool, conf, &name, &conf_port); 197 if (status != PJ_SUCCESS) 198 goto on_error; 199 200 /* Sound device has rx buffers. */ 201 for (i=0; i<RX_BUF_COUNT; ++i) { 202 conf_port->rx_buf[i] = pj_pool_zalloc(pool, conf->samples_per_frame * 203 sizeof(conf_port->rx_buf[0][0])); 204 if (conf_port->rx_buf[i] == NULL) { 205 status = PJ_ENOMEM; 206 goto on_error; 207 } 208 } 209 conf_port->rx_write = 0; 210 conf_port->rx_read = 0; 211 212 213 /* Set to port zero */ 214 conf->ports[0] = conf_port; 215 conf->port_cnt++; 216 217 PJ_LOG(5,(THIS_FILE, "Sound device successfully created for port 0")); 218 return PJ_SUCCESS; 219 220 on_error: 221 return status; 222 223 } 71 224 72 225 /* … … 75 228 PJ_DEF(pj_status_t) pjmedia_conf_create( pj_pool_t *pool, 76 229 unsigned max_ports, 230 unsigned sampling_rate, 231 unsigned samples_per_frame, 232 unsigned bits_per_sample, 77 233 pjmedia_conf **p_conf ) 78 234 { 79 235 pjmedia_conf *conf; 80 pj_snd_stream_info snd_info;81 236 pj_status_t status; 82 237 238 PJ_LOG(5,(THIS_FILE, "Creating conference bridge with %d ports", 239 max_ports)); 240 241 /* Create and init conf structure. */ 83 242 conf = pj_pool_zalloc(pool, sizeof(pjmedia_conf)); 243 PJ_ASSERT_RETURN(conf, PJ_ENOMEM); 244 245 conf->ports = pj_pool_zalloc(pool, max_ports*sizeof(void*)); 246 PJ_ASSERT_RETURN(conf->ports, PJ_ENOMEM); 247 84 248 conf->max_ports = max_ports; 85 conf->port = pj_pool_zalloc(pool, max_ports*sizeof(void*)); 86 87 /* Create default parameters. */ 88 pj_memset(&snd_info, 0, sizeof(snd_info)); 89 snd_info.samples_per_sec = 8000; 90 snd_info.bits_per_sample = 16; 91 snd_info.samples_per_frame = 160; 92 snd_info.bytes_per_frame = 16000; 93 snd_info.frames_per_packet = 1; 94 95 /* Create buffers. */ 96 conf->samples_cnt = snd_info.samples_per_frame; 97 conf->buf_size = snd_info.samples_per_frame * snd_info.bits_per_sample / 8; 98 conf->rec_buf = pj_pool_alloc(pool, conf->buf_size); 99 conf->play_buf = pj_pool_alloc(pool, conf->buf_size ); 100 101 249 conf->sampling_rate = sampling_rate; 250 conf->samples_per_frame = samples_per_frame; 251 conf->bits_per_sample = bits_per_sample; 252 253 254 /* Create port zero for sound device. */ 255 status = create_sound_port(pool, conf); 256 if (status != PJ_SUCCESS) 257 return status; 258 259 /* Create temporary buffer. */ 260 conf->uns_buf = pj_pool_zalloc(pool, samples_per_frame * 261 sizeof(conf->uns_buf[0])); 262 /* Done */ 263 264 *p_conf = conf; 265 266 return PJ_SUCCESS; 267 } 268 269 270 /* 271 * Create sound device 272 */ 273 static pj_status_t create_sound( pjmedia_conf *conf ) 274 { 102 275 /* Open recorder. */ 103 conf->snd_rec = pj_snd_open_recorder(-1 ,& snd_info, &rec_cb, conf);276 conf->snd_rec = pj_snd_open_recorder(-1 ,&conf->snd_info, &rec_cb, conf); 104 277 if (conf->snd_rec == NULL) { 105 status = -1; 106 goto on_error; 278 return -1; 107 279 } 108 280 109 281 /* Open player */ 110 conf->snd_player = pj_snd_open_player(-1, & snd_info, &play_cb, conf);282 conf->snd_player = pj_snd_open_player(-1, &conf->snd_info, &play_cb, conf); 111 283 if (conf->snd_player == NULL) { 112 status = -1;113 goto on_error;114 } 115 116 /* Done */117 118 *p_conf = conf; 119 120 return PJ_SUCCESS;121 122 123 on_error: 284 pj_snd_stream_close(conf->snd_rec); 285 return -1; 286 } 287 288 return PJ_SUCCESS; 289 } 290 291 /* 292 * Destroy sound device 293 */ 294 static pj_status_t destroy_sound( pjmedia_conf *conf ) 295 { 124 296 if (conf->snd_rec) { 125 pj_snd_stream_stop(conf->snd_rec);126 297 pj_snd_stream_close(conf->snd_rec); 127 298 conf->snd_rec = NULL; 128 299 } 129 300 if (conf->snd_player) { 130 pj_snd_stream_stop(conf->snd_player);131 301 pj_snd_stream_close(conf->snd_player); 132 302 conf->snd_player = NULL; 133 303 } 134 return status;304 return PJ_SUCCESS; 135 305 } 136 306 … … 138 308 * Activate sound device. 139 309 */ 140 static pj_status_t activate_conf( pjmedia_conf *conf )310 static pj_status_t resume_sound( pjmedia_conf *conf ) 141 311 { 142 312 char errmsg[PJ_ERR_MSG_SIZE]; 143 313 pj_status_t status; 144 314 315 if (conf->snd_rec == NULL) { 316 status = create_sound(conf); 317 if (status != PJ_SUCCESS) 318 return status; 319 } 320 145 321 /* Start recorder. */ 146 status = pj_snd_stream_start(conf->snd_rec); 147 if (status != PJ_SUCCESS) 148 goto on_error; 322 if (conf->snd_rec) { 323 status = pj_snd_stream_start(conf->snd_rec); 324 if (status != PJ_SUCCESS) 325 goto on_error; 326 } 149 327 150 328 /* Start player. */ 151 status = pj_snd_stream_start(conf->snd_rec); 152 if (status != PJ_SUCCESS) 153 goto on_error; 329 if (conf->snd_player) { 330 status = pj_snd_stream_start(conf->snd_player); 331 if (status != PJ_SUCCESS) 332 goto on_error; 333 } 154 334 155 335 return PJ_SUCCESS; … … 166 346 * Suspend sound device 167 347 */ 168 static void suspend_conf( pjmedia_conf *conf ) 169 { 170 pj_snd_stream_stop(conf->snd_rec); 171 pj_snd_stream_stop(conf->snd_player); 348 static void suspend_sound( pjmedia_conf *conf ) 349 { 350 if (conf->snd_rec) 351 pj_snd_stream_stop(conf->snd_rec); 352 if (conf->snd_player) 353 pj_snd_stream_stop(conf->snd_player); 354 } 355 356 357 /** 358 * Destroy conference bridge. 359 */ 360 PJ_DEF(pj_status_t) pjmedia_conf_destroy( pjmedia_conf *conf ) 361 { 362 PJ_ASSERT_RETURN(conf != NULL, PJ_EINVAL); 363 364 suspend_sound(conf); 365 366 pj_snd_stream_close(conf->snd_rec); 367 conf->snd_rec = NULL; 368 pj_snd_stream_close(conf->snd_player); 369 conf->snd_player = NULL; 370 371 return PJ_SUCCESS; 172 372 } 173 373 … … 178 378 PJ_DEF(pj_status_t) pjmedia_conf_add_port( pjmedia_conf *conf, 179 379 pj_pool_t *pool, 180 pjmedia_ stream_port *strm_port,380 pjmedia_port *strm_port, 181 381 const pj_str_t *port_name, 182 382 unsigned *p_port ) … … 194 394 } 195 395 396 /* Find empty port in the conference bridge. */ 397 for (index=0; index < conf->max_ports; ++index) { 398 if (conf->ports[index] == NULL) 399 break; 400 } 401 402 pj_assert(index != conf->max_ports); 403 196 404 /* Create port structure. */ 197 conf_port = pj_pool_zalloc(pool, sizeof(struct conf_port)); 198 pj_strdup_with_null(pool, &conf_port->name, port_name); 199 conf_port->port = strm_port; 200 conf_port->online = PJ_TRUE; 201 conf_port->level = 0; 202 203 /* Create VAD for this port. */ 204 status = pjmedia_vad_create(pool, &conf_port->vad); 405 status = create_conf_port(pool, conf, port_name, &conf_port); 205 406 if (status != PJ_SUCCESS) 206 407 return status; 207 408 208 /* Set vad settings. */ 209 pjmedia_vad_set_adaptive(conf_port->vad, conf->samples_cnt); 210 211 /* Find empty port in the conference bridge. */ 212 for (index=0; index < conf->max_ports; ++index) { 213 if (conf->port[index] == NULL) 214 break; 215 } 216 217 pj_assert(index != conf->max_ports); 409 /* Set the port */ 410 conf_port->port = strm_port; 218 411 219 412 /* Put the port. */ 220 conf->port [index] = conf_port;413 conf->ports[index] = conf_port; 221 414 conf->port_cnt++; 222 415 223 /* If this is the first port, activate sound device. */ 224 if (conf->port_cnt == 1) { 225 status = activate_conf(conf);; 226 if (status != PJ_SUCCESS) { 227 conf->port[index] = NULL; 228 --conf->port_cnt; 229 return status; 416 /* Done. */ 417 *p_port = index; 418 419 return PJ_SUCCESS; 420 } 421 422 423 /* 424 * Change TX and RX settings for the port. 425 */ 426 PJ_DECL(pj_status_t) pjmedia_conf_configure_port( pjmedia_conf *conf, 427 unsigned slot, 428 pjmedia_port_op tx, 429 pjmedia_port_op rx) 430 { 431 struct conf_port *conf_port; 432 433 /* Check arguments */ 434 PJ_ASSERT_RETURN(conf && slot<conf->max_ports, PJ_EINVAL); 435 436 /* Port must be valid. */ 437 PJ_ASSERT_RETURN(conf->ports[slot] != NULL, PJ_EINVAL); 438 439 conf_port = conf->ports[slot]; 440 441 if (tx != PJMEDIA_PORT_NO_CHANGE) 442 conf_port->tx_setting = tx; 443 444 if (rx != PJMEDIA_PORT_NO_CHANGE) 445 conf_port->rx_setting = rx; 446 447 return PJ_SUCCESS; 448 } 449 450 451 /* 452 * Connect port. 453 */ 454 PJ_DEF(pj_status_t) pjmedia_conf_connect_port( pjmedia_conf *conf, 455 unsigned src_slot, 456 unsigned sink_slot ) 457 { 458 struct conf_port *src_port, *dst_port; 459 460 /* Check arguments */ 461 PJ_ASSERT_RETURN(conf && src_slot<conf->max_ports && 462 sink_slot<conf->max_ports, PJ_EINVAL); 463 464 /* Ports must be valid. */ 465 PJ_ASSERT_RETURN(conf->ports[src_slot] != NULL, PJ_EINVAL); 466 PJ_ASSERT_RETURN(conf->ports[sink_slot] != NULL, PJ_EINVAL); 467 468 src_port = conf->ports[src_slot]; 469 dst_port = conf->ports[sink_slot]; 470 471 if (src_port->listeners[sink_slot] == 0) { 472 src_port->listeners[sink_slot] = 1; 473 ++conf->connect_cnt; 474 475 if (conf->connect_cnt == 1) 476 resume_sound(conf); 477 478 PJ_LOG(5,(THIS_FILE,"Port %.*s transmitting to port %.*s", 479 (int)src_port->name.slen, 480 src_port->name.ptr, 481 (int)dst_port->name.slen, 482 dst_port->name.ptr)); 483 } 484 485 return PJ_SUCCESS; 486 } 487 488 489 /* 490 * Disconnect port 491 */ 492 PJ_DEF(pj_status_t) pjmedia_conf_disconnect_port( pjmedia_conf *conf, 493 unsigned src_slot, 494 unsigned sink_slot ) 495 { 496 struct conf_port *src_port, *dst_port; 497 498 /* Check arguments */ 499 PJ_ASSERT_RETURN(conf && src_slot<conf->max_ports && 500 sink_slot<conf->max_ports, PJ_EINVAL); 501 502 /* Ports must be valid. */ 503 PJ_ASSERT_RETURN(conf->ports[src_slot] != NULL, PJ_EINVAL); 504 PJ_ASSERT_RETURN(conf->ports[sink_slot] != NULL, PJ_EINVAL); 505 506 src_port = conf->ports[src_slot]; 507 dst_port = conf->ports[sink_slot]; 508 509 if (src_port->listeners[sink_slot] != 0) { 510 src_port->listeners[sink_slot] = 0; 511 --conf->connect_cnt; 512 513 PJ_LOG(5,(THIS_FILE,"Port %.*s stop transmitting to port %.*s", 514 (int)src_port->name.slen, 515 src_port->name.ptr, 516 (int)dst_port->name.slen, 517 dst_port->name.ptr)); 518 519 if (conf->connect_cnt == 0) { 520 suspend_sound(conf); 521 destroy_sound(conf); 230 522 } 231 523 } 232 524 233 /* Done. */ 234 return PJ_SUCCESS; 235 } 236 237 238 /* 239 * Mute or unmute port. 240 */ 241 PJ_DEF(pj_status_t) pjmedia_conf_set_mute( pjmedia_conf *conf, 242 unsigned port, 243 pj_bool_t mute ) 244 { 525 return PJ_SUCCESS; 526 } 527 528 529 /* 530 * Remove the specified port. 531 */ 532 PJ_DEF(pj_status_t) pjmedia_conf_remove_port( pjmedia_conf *conf, 533 unsigned port ) 534 { 535 struct conf_port *conf_port; 536 unsigned i; 537 245 538 /* Check arguments */ 246 539 PJ_ASSERT_RETURN(conf && port < conf->max_ports, PJ_EINVAL); 247 540 248 541 /* Port must be valid. */ 249 PJ_ASSERT_RETURN(conf->port[port] != NULL, PJ_EINVAL); 250 251 conf->port[port]->online = !mute; 252 253 return PJ_SUCCESS; 254 } 255 256 257 /* 258 * Set the specified port to be member of conference bridge. 259 */ 260 PJ_DEF(pj_status_t) pjmedia_conf_set_membership( pjmedia_conf *conf, 261 unsigned port, 262 pj_bool_t enabled ) 263 { 264 /* Check arguments */ 265 PJ_ASSERT_RETURN(conf && port < conf->max_ports, PJ_EINVAL); 266 267 /* Port must be valid. */ 268 PJ_ASSERT_RETURN(conf->port[port] != NULL, PJ_EINVAL); 269 270 conf->port[port]->is_member = enabled; 271 272 return PJ_SUCCESS; 273 } 274 275 276 /* 277 * Remove the specified port. 278 */ 279 PJ_DEF(pj_status_t) pjmedia_conf_remove_port( pjmedia_conf *conf, 280 unsigned port ) 281 { 282 /* Check arguments */ 283 PJ_ASSERT_RETURN(conf && port < conf->max_ports, PJ_EINVAL); 284 285 /* Port must be valid. */ 286 PJ_ASSERT_RETURN(conf->port[port] != NULL, PJ_EINVAL); 542 PJ_ASSERT_RETURN(conf->ports[port] != NULL, PJ_EINVAL); 287 543 288 544 /* Suspend the sound devices. 289 545 * Don't want to remove port while port is being accessed by sound 290 * device's threads .546 * device's threads! 291 547 */ 292 suspend_conf(conf); 548 //suspend_sound(conf); 549 550 conf_port = conf->ports[port]; 551 conf_port->tx_setting = PJMEDIA_PORT_DISABLE; 552 conf_port->rx_setting = PJMEDIA_PORT_DISABLE; 553 554 /* Remove this port from transmit array of other ports. */ 555 for (i=0; i<conf->max_ports; ++i) { 556 conf_port = conf->ports[i]; 557 558 if (!conf_port) 559 continue; 560 561 if (conf_port->listeners[port] != 0) { 562 --conf->connect_cnt; 563 conf_port->listeners[port] = 0; 564 } 565 } 566 567 /* Remove all ports listening from this port. */ 568 conf_port = conf->ports[port]; 569 for (i=0; i<conf->max_ports; ++i) { 570 if (conf_port->listeners[i]) 571 --conf->connect_cnt; 572 } 293 573 294 574 /* Remove the port. */ 295 conf->port [port] = NULL;575 conf->ports[port] = NULL; 296 576 --conf->port_cnt; 297 577 298 /* Reactivate sound device if ports are not zero */ 299 if (conf->port_cnt != 0) 300 activate_conf(conf); 301 302 return PJ_SUCCESS; 303 } 304 578 /* Reactivate sound device if there are connections */ 579 if (conf->connect_cnt != 0) { 580 //resume_sound(conf); 581 } else { 582 destroy_sound(conf); 583 } 584 585 pj_thread_sleep(60); 586 return PJ_SUCCESS; 587 } 588 589 /* 590 * Get port info 591 */ 592 PJ_DEF(pj_status_t) pjmedia_conf_get_port_info( pjmedia_conf *conf, 593 unsigned slot, 594 pjmedia_conf_port_info *info) 595 { 596 struct conf_port *conf_port; 597 598 /* Check arguments */ 599 PJ_ASSERT_RETURN(conf && slot<conf->max_ports, PJ_EINVAL); 600 601 /* Port must be valid. */ 602 PJ_ASSERT_RETURN(conf->ports[slot] != NULL, PJ_EINVAL); 603 604 conf_port = conf->ports[slot]; 605 606 info->name = conf_port->name; 607 info->tx_setting = conf_port->tx_setting; 608 info->rx_setting = conf_port->rx_setting; 609 info->listener = conf_port->listeners; 610 611 return PJ_SUCCESS; 612 } 613 614 615 /* Convert signed 16bit pcm sample to unsigned 16bit sample */ 616 static pj_uint16_t pcm2unsigned(pj_int32_t pcm) 617 { 618 return (pj_uint16_t)(pcm + 32767); 619 } 620 621 /* Convert unsigned 16bit sample to signed 16bit pcm sample */ 622 static pj_int16_t unsigned2pcm(pj_uint32_t uns) 623 { 624 return (pj_int16_t)(uns - 32767); 625 } 305 626 306 627 /* … … 314 635 pjmedia_conf *conf = user_data; 315 636 pj_int16_t *output_buf = output; 316 pj_int32_t highest_level = 0;317 int highest_index = -1;318 unsigned sources = 0;319 637 unsigned i, j; 320 638 321 639 PJ_UNUSED_ARG(timestamp); 322 323 /* Clear temporary buffer. */ 324 pj_memset(output_buf, 0, size);325 326 /* Get frames from ports. */640 PJ_UNUSED_ARG(size); 641 642 TRACE_(("p")); 643 644 /* Clear all port's tmp buffers. */ 327 645 for (i=0; i<conf->max_ports; ++i) { 328 struct conf_port *conf_port = conf->port[i]; 646 struct conf_port *conf_port = conf->ports[i]; 647 pj_uint32_t *sum_buf; 648 649 if (!conf_port) 650 continue; 651 652 conf_port->sources = 0; 653 sum_buf = conf_port->sum_buf; 654 655 for (j=0; j<conf->samples_per_frame; ++j) 656 sum_buf[j] = 0; 657 } 658 659 /* Get frames from all ports, and "add" the signal 660 * to sum_buf of all listeners of the port. 661 */ 662 for (i=0; i<conf->max_ports; ++i) { 663 struct conf_port *conf_port = conf->ports[i]; 329 664 pj_int32_t level; 330 665 pj_bool_t silence; 331 666 667 /* Skip empty port. */ 332 668 if (!conf_port) 333 669 continue; 334 670 335 conf_port->port->get_frame(conf->play_buf, conf->samples_cnt); 671 /* Skip if we're not allowed to receive from this port. */ 672 if (conf_port->rx_setting == PJMEDIA_PORT_DISABLE) { 673 TRACE_(("rxdis:%d ", i)); 674 continue; 675 } 676 677 /* Get frame from this port. 678 * If port has rx_buffer, then get the frame from the rx_buffer 679 * instead. 680 */ 681 if (i==0/*conf_port->cur_rx_buf*/) { 682 pj_int16_t *rx_buf; 683 684 if (conf_port->rx_read == conf_port->rx_write) 685 conf_port->rx_read = (conf_port->rx_write+RX_BUF_COUNT-RX_BUF_COUNT/2) % RX_BUF_COUNT; 686 687 rx_buf = conf_port->rx_buf[conf_port->rx_read]; 688 for (j=0; j<conf->samples_per_frame; ++j) { 689 ((pj_int16_t*)output)[j] = rx_buf[j]; 690 } 691 conf_port->rx_read = (conf_port->rx_read+1) % RX_BUF_COUNT; 692 } else { 693 pjmedia_frame frame; 694 695 pj_memset(&frame, 0, sizeof(frame)); 696 frame.buf = output; 697 frame.size = size; 698 pjmedia_port_get_frame(conf_port->port, &frame); 699 } 700 701 /* Skip (after receiving the frame) if this port is muted. */ 702 if (conf_port->rx_setting == PJMEDIA_PORT_MUTE) 703 continue; 704 705 /* Do we have signal? */ 336 706 silence = pjmedia_vad_detect_silence(conf_port->vad, 337 conf->play_buf,338 conf->samples_ cnt,707 output, 708 conf->samples_per_frame, 339 709 &level); 340 if (!silence) { 341 if (level > highest_level) { 342 highest_index = i; 343 highest_level = level; 344 } 345 346 ++sources; 347 348 for (j=0; j<conf->samples_cnt; ++j) { 349 output_buf[j] = (pj_int16_t)(output_buf[j] + conf->play_buf[j]); 710 711 /* Skip if we don't have signal. */ 712 if (silence) { 713 TRACE_(("sil:%d ", i)); 714 continue; 715 } 716 717 /* Convert the buffer to unsigned value */ 718 for (j=0; j<conf->samples_per_frame; ++j) 719 conf->uns_buf[j] = pcm2unsigned(((pj_int16_t*)output)[j]); 720 721 /* Add the signal to all listeners. */ 722 for (j=0; j<conf->max_ports; ++j) { 723 struct conf_port *listener = conf->ports[j]; 724 pj_uint32_t *sum_buf; 725 unsigned k; 726 727 if (conf_port->listeners[j] == 0) 728 continue; 729 730 /* Skip if this listener doesn't want to receive audio */ 731 if (listener->tx_setting != PJMEDIA_PORT_ENABLE) 732 continue; 733 734 //TRACE_(("mix:%d->%d ", i, j)); 735 736 sum_buf = listener->sum_buf; 737 for (k=0; k<conf->samples_per_frame; ++k) 738 sum_buf[k] += conf->uns_buf[k]; 739 740 listener->sources++; 741 } 742 } 743 744 /* For all ports, calculate avg signal. */ 745 for (i=0; i<conf->max_ports; ++i) { 746 struct conf_port *conf_port = conf->ports[i]; 747 pjmedia_frame frame; 748 pj_int16_t *target_buf; 749 750 if (!conf_port) 751 continue; 752 753 754 target_buf = (conf_port->cur_tx_buf==conf_port->tx_buf1? 755 conf_port->tx_buf2 : conf_port->tx_buf1); 756 757 if (!conf_port->sources) { 758 for (j=0; j<conf->samples_per_frame; ++j) 759 target_buf[j] = 0; 760 } else { 761 for (j=0; j<conf->samples_per_frame; ++j) { 762 target_buf[j] = unsigned2pcm(conf_port->sum_buf[j] / conf_port->sources); 350 763 } 351 764 } 352 } 353 354 /* Calculate average signal. */ 355 if (sources) { 356 for (j=0; j<conf->samples_cnt; ++j) { 357 output_buf[j] = (pj_int16_t)(output_buf[j] / sources); 358 } 359 } 360 361 /* Broadcast to conference member. */ 362 for (i=0; i<conf->max_ports; ++i) { 363 struct conf_port *conf_port = conf->port[i]; 364 365 if (!conf_port) 765 766 /* Switch buffer. */ 767 conf_port->cur_tx_buf = target_buf; 768 769 if (conf_port->tx_setting != PJMEDIA_PORT_ENABLE) 366 770 continue; 367 771 368 if (!conf_port->is_member) 369 continue; 370 371 conf_port->port->put_frame(output_buf, conf->samples_cnt); 372 } 373 374 return PJ_SUCCESS; 375 } 772 pj_memset(&frame, 0, sizeof(frame)); 773 frame.type = PJMEDIA_FRAME_TYPE_AUDIO; 774 frame.buf = conf_port->cur_tx_buf; 775 frame.size = conf->samples_per_frame * conf->bits_per_sample / 8; 776 frame.timestamp.u64 = timestamp; 777 778 if (conf_port->port) 779 pjmedia_port_put_frame(conf_port->port, &frame); 780 781 } 782 783 /* Return sound playback frame. */ 784 for (j=0; j<conf->samples_per_frame; ++j) 785 output_buf[j] = conf->ports[0]->cur_tx_buf[j]; 786 787 return PJ_SUCCESS; 788 } 789 376 790 377 791 /* … … 381 795 /* in */ pj_uint32_t timestamp, 382 796 /* in */ const void *input, 383 /* in */unsigned size)797 /* in */ unsigned size) 384 798 { 385 799 pjmedia_conf *conf = user_data; 800 struct conf_port *snd_port = conf->ports[0]; 801 pj_int16_t *target_rx_buf; 386 802 unsigned i; 387 803 388 804 PJ_UNUSED_ARG(timestamp); 389 PJ_UNUSED_ARG(size); 390 391 for (i=0; i<conf->max_ports; ++i) { 392 struct conf_port *conf_port = conf->port[i]; 805 806 TRACE_(("r")); 807 808 if (size != conf->samples_per_frame*2) { 809 TRACE_(("rxerr ")); 810 } 811 812 813 /* Determine which rx_buffer to fill in */ 814 target_rx_buf = snd_port->rx_buf[snd_port->rx_write]; 815 816 /* Copy samples from audio device to target rx_buffer */ 817 for (i=0; i<conf->samples_per_frame; ++i) { 818 target_rx_buf[i] = ((pj_int16_t*)input)[i]; 819 } 820 821 /* Switch buffer */ 822 snd_port->rx_write = (snd_port->rx_write+1)%RX_BUF_COUNT; 823 824 825 /* Time for all ports (except sound port) to transmit frames */ 826 /* 827 for (i=1; i<conf->max_ports; ++i) { 828 struct conf_port *conf_port = conf->ports[i]; 829 pjmedia_frame frame; 393 830 394 831 if (!conf_port) 395 832 continue; 396 833 397 if (!conf_port->online) 398 continue; 399 400 conf_port->port->put_frame(input, conf->samples_cnt); 401 } 834 } 835 */ 402 836 403 837 return PJ_SUCCESS; -
pjproject/trunk/pjmedia/src/pjmedia/g711.c
r203 r205 22 22 #include <pjmedia/codec.h> 23 23 #include <pjmedia/errno.h> 24 #include <pjmedia/port.h> 24 25 #include <pj/pool.h> 25 26 #include <pj/string.h> … … 502 503 * John Wiley & Sons, pps 98-111 and 472-476. 503 504 */ 504 staticunsigned char505 unsigned char 505 506 linear2alaw( 506 507 int pcm_val) /* 2's complement (16-bit range) */ … … 538 539 * 539 540 */ 540 staticint541 int 541 542 alaw2linear( 542 543 unsigned char a_val) … … 636 637 * original code word. This is in keeping with ISDN conventions. 637 638 */ 638 staticint639 int 639 640 ulaw2linear( 640 641 unsigned char u_val) -
pjproject/trunk/pjmedia/src/pjmedia/rtp.c
r199 r205 44 44 /* Check RTP header packing. */ 45 45 if (sizeof(struct pjmedia_rtp_hdr) != 12) { 46 unsigned sz = sizeof(struct pjmedia_rtp_hdr);47 46 pj_assert(!"Wrong RTP header packing!"); 48 47 return PJMEDIA_RTP_EINPACK; -
pjproject/trunk/pjmedia/src/pjmedia/session.c
r188 r205 385 385 } 386 386 387 388 PJ_DEF(pj_status_t) pjmedia_session_get_port( pjmedia_session *session, 389 unsigned index, 390 pjmedia_port **p_port) 391 { 392 return pjmedia_stream_get_port( session->stream[index], p_port); 393 } 394 387 395 /** 388 396 * Get statistics -
pjproject/trunk/pjmedia/src/pjmedia/stream.c
r188 r205 53 53 pj_bool_t paused; /**< Paused?. */ 54 54 pj_snd_stream_info snd_info; /**< Sound stream param. */ 55 pj_snd_stream *snd_stream; /**< Sound stream. */55 //pj_snd_stream *snd_stream; /**< Sound stream. */ 56 56 unsigned in_pkt_size; /**< Size of input buffer. */ 57 57 void *in_pkt; /**< Input buffer. */ … … 73 73 struct pjmedia_stream 74 74 { 75 pjmedia_port port; /**< Port interface. */ 75 76 pjmedia_channel *enc; /**< Encoding channel. */ 76 77 pjmedia_channel *dec; /**< Decoding channel. */ … … 103 104 * needs to feed the player with some frames. 104 105 */ 105 static pj_status_t play_callback(/* in */ void *user_data, 106 /* in */ pj_uint32_t timestamp, 107 /* out */ void *frame, 108 /*inout*/ unsigned size) 109 { 110 pjmedia_channel *channel = user_data; 111 pjmedia_stream *stream = channel->stream; 106 static pj_status_t get_frame( pjmedia_port *port, pjmedia_frame *frame) 107 { 108 pjmedia_stream *stream = port->user_data; 109 pjmedia_channel *channel = stream->dec; 110 112 111 char frame_type; 113 112 pj_status_t status; 114 113 struct pjmedia_frame frame_in, frame_out; 115 114 116 PJ_UNUSED_ARG(timestamp);117 118 115 /* Do nothing if we're quitting. */ 119 if (stream->quit_flag) 120 return -1; 116 if (stream->quit_flag) { 117 frame->type = PJMEDIA_FRAME_TYPE_NONE; 118 return PJ_SUCCESS; 119 } 121 120 122 121 /* Lock jitter buffer mutex */ … … 133 132 frame_type == PJMEDIA_JB_MISSING_FRAME) 134 133 { 135 pj_memset(frame, 0, size);136 return 0;134 frame->type = PJMEDIA_FRAME_TYPE_NONE; 135 return PJ_SUCCESS; 137 136 } 138 137 … … 148 147 TRACE_((THIS_FILE, "decode() has return error status %d", status)); 149 148 150 pj_memset(frame, 0, size);151 return 0;149 frame->type = PJMEDIA_FRAME_TYPE_NONE; 150 return PJ_SUCCESS; 152 151 } 153 152 154 153 /* Put in sound buffer. */ 155 if (frame_out.size > size) {154 if (frame_out.size > frame->size) { 156 155 TRACE_((THIS_FILE, "Sound playout buffer truncated %d bytes", 157 frame_out.size - size)); 158 frame_out.size = size; 159 } 160 161 pj_memcpy(frame, frame_out.buf, size); 162 163 return 0; 156 frame_out.size - frame->size)); 157 frame_out.size = frame->size; 158 } 159 160 frame->type = PJMEDIA_FRAME_TYPE_AUDIO; 161 frame->size = frame_out.size; 162 frame->timestamp.u64 = 0; 163 pj_memcpy(frame->buf, frame_out.buf, frame_out.size); 164 165 return PJ_SUCCESS; 164 166 } 165 167 … … 172 174 * send it to remote. 173 175 */ 174 static pj_status_t rec_callback( /* in */ void *user_data, 175 /* in */ pj_uint32_t timestamp, 176 /* in */ const void *frame, 177 /* in */ unsigned size) 178 { 179 pjmedia_channel *channel = user_data; 180 pjmedia_stream *stream = channel->stream; 176 static pj_status_t put_frame( pjmedia_port *port, 177 const pjmedia_frame *frame ) 178 { 179 pjmedia_stream *stream = port->user_data; 180 pjmedia_channel *channel = stream->enc; 181 181 pj_status_t status = 0; 182 struct pjmedia_frame frame_ in, frame_out;182 struct pjmedia_frame frame_out; 183 183 int ts_len; 184 184 void *rtphdr; … … 187 187 188 188 189 PJ_UNUSED_ARG(timestamp);190 191 189 /* Check if stream is quitting. */ 192 190 if (stream->quit_flag) … … 194 192 195 193 /* Encode. */ 196 frame_in.type = PJMEDIA_TYPE_AUDIO;197 frame_in.buf = (void*)frame;198 frame_in.size = size;199 194 frame_out.buf = ((char*)channel->out_pkt) + sizeof(pjmedia_rtp_hdr); 200 status = stream->codec->op->encode( stream->codec, &frame_in,195 status = stream->codec->op->encode( stream->codec, frame, 201 196 channel->out_pkt_size - sizeof(pjmedia_rtp_hdr), 202 197 &frame_out); … … 208 203 209 204 /* Encapsulate. */ 210 ts_len = size / (channel->snd_info.bits_per_sample / 8);205 ts_len = frame->size / (channel->snd_info.bits_per_sample / 8); 211 206 status = pjmedia_rtp_encode_rtp( &channel->rtp, 212 207 channel->pt, 0, … … 239 234 stream->stat.enc.bytes += frame_out.size+sizeof(pjmedia_rtp_hdr); 240 235 241 return 0;236 return PJ_SUCCESS; 242 237 } 243 238 … … 426 421 init_snd_param(&channel->snd_info, codec_param); 427 422 423 /* 428 424 if (dir == PJMEDIA_DIR_ENCODING) 429 425 channel->snd_stream = pj_snd_open_recorder(-1, &channel->snd_info, … … 435 431 if (!channel->snd_stream) 436 432 return -1; 437 433 */ 438 434 439 435 /* Done. */ … … 463 459 stream = pj_pool_zalloc(pool, sizeof(pjmedia_stream)); 464 460 PJ_ASSERT_RETURN(stream != NULL, PJ_ENOMEM); 461 462 /* Init port. */ 463 stream->port.info.name = pj_str("stream"); 464 stream->port.info.signature = ('S'<<3 | 'T'<<2 | 'R'<<1 | 'M'); 465 stream->port.info.type = PJMEDIA_TYPE_AUDIO; 466 stream->port.info.has_info = 1; 467 stream->port.info.need_info = 0; 468 stream->port.info.pt = info->fmt.pt; 469 pj_strdup(pool, &stream->port.info.encoding_name, &info->fmt.encoding_name); 470 stream->port.info.sample_rate = info->fmt.sample_rate; 471 stream->port.user_data = stream; 472 stream->port.put_frame = &put_frame; 473 stream->port.get_frame = &get_frame; 465 474 466 475 … … 495 504 goto err_cleanup; 496 505 506 /* Set additional info. */ 507 stream->port.info.bits_per_sample = 0; 508 stream->port.info.samples_per_frame = info->fmt.sample_rate*codec_param.ptime/1000; 509 stream->port.info.bytes_per_frame = codec_param.avg_bps/8 * codec_param.ptime/1000; 510 497 511 498 512 /* Open the codec: */ … … 576 590 /* Close encoding sound stream. */ 577 591 592 /* 578 593 if (stream->enc && stream->enc->snd_stream) { 579 594 … … 583 598 584 599 } 600 */ 585 601 586 602 /* Close decoding sound stream. */ 587 603 604 /* 588 605 if (stream->dec && stream->dec->snd_stream) { 589 606 … … 593 610 594 611 } 612 */ 595 613 596 614 /* Wait for jitter buffer thread to quit: */ … … 623 641 624 642 /* 643 * Get the port interface. 644 */ 645 PJ_DEF(pj_status_t) pjmedia_stream_get_port( pjmedia_stream *stream, 646 pjmedia_port **p_port ) 647 { 648 *p_port = &stream->port; 649 return PJ_SUCCESS; 650 } 651 652 653 /* 625 654 * Start stream. 626 655 */ … … 632 661 if (stream->enc && (stream->dir & PJMEDIA_DIR_ENCODING)) { 633 662 stream->enc->paused = 0; 634 pj_snd_stream_start(stream->enc->snd_stream);663 //pj_snd_stream_start(stream->enc->snd_stream); 635 664 } 636 665 637 666 if (stream->dec && (stream->dir & PJMEDIA_DIR_DECODING)) { 638 667 stream->dec->paused = 0; 639 pj_snd_stream_start(stream->dec->snd_stream);668 //pj_snd_stream_start(stream->dec->snd_stream); 640 669 } 641 670 -
pjproject/trunk/pjmedia/src/pjmedia/vad.c
r203 r205 57 57 58 58 59 unsigned char linear2ulaw(int pcm_val); 59 unsigned char linear2ulaw(int pcm_val); 60 60 61 61 62 PJ_DEF(pj_status_t) pjmedia_vad_create( pj_pool_t *pool, … … 88 89 vad->frame_size = frame_size; 89 90 vad->mode = VAD_MODE_ADAPTIVE; 90 vad->min_signal_cnt = 3;91 vad->min_silence_cnt = 20;92 vad->recalc_cnt = 30;91 vad->min_signal_cnt = 10; 92 vad->min_silence_cnt = 64; 93 vad->recalc_cnt = 250; 93 94 vad->cur_threshold = 20; 94 95 … … 228 229 */ 229 230 vad->cur_threshold += (vad->weakest_signal - vad->cur_threshold)/4; 230 PJ_LOG( 5,(THIS_FILE, "Vad cur_threshold increased to %d",231 PJ_LOG(6,(THIS_FILE, "Vad cur_threshold increased to %d", 231 232 vad->cur_threshold)); 232 233 } … … 236 237 */ 237 238 vad->cur_threshold = (vad->cur_threshold+vad->loudest_silence)/2+1; 238 PJ_LOG( 5,(THIS_FILE, "Vad cur_threshold decreased to %d",239 PJ_LOG(6,(THIS_FILE, "Vad cur_threshold decreased to %d", 239 240 vad->cur_threshold)); 240 241 } … … 251 252 252 253 if (updated) { 253 PJ_LOG( 5,(THIS_FILE,254 PJ_LOG(6,(THIS_FILE, 254 255 "Vad cur_threshold updated to %d", 255 256 vad->cur_threshold)); -
pjproject/trunk/pjsip/src/pjsua/main.c
r201 r205 137 137 puts("| [ Select previous dialog | | |"); 138 138 puts("+-----------------------------------------------------------------------------+"); 139 puts("| Conference Command |"); 140 puts("| cl List ports |"); 141 puts("| cc Connect port |"); 142 puts("| cd Disconnect port |"); 143 puts("+-----------------------------------------------------------------------------+"); 139 144 puts("| q QUIT |"); 140 145 puts("+=============================================================================+"); … … 254 259 } 255 260 } 261 262 static void conf_list(void) 263 { 264 pjmedia_conf_port_info info; 265 struct pjsua_inv_data *inv_data; 266 267 printf("Conference ports:\n"); 268 269 inv_data = pjsua.inv_list.next; 270 while (inv_data != &pjsua.inv_list) { 271 272 pjmedia_conf_get_port_info(pjsua.mconf, inv_data->conf_slot, &info); 273 274 printf("Port %2d %.*s\n", inv_data->conf_slot, 275 (int)info.name.slen, info.name.ptr); 276 277 inv_data = inv_data->next; 278 } 279 } 280 256 281 257 282 static void ui_console_main(void) … … 396 421 break; 397 422 423 case 'c': 424 switch (menuin[1]) { 425 case 'l': 426 conf_list(); 427 break; 428 case 'c': 429 case 'd': 430 { 431 char src_port[10], dst_port[10]; 432 pj_status_t status; 433 434 if (!simple_input("Connect src port #:", src_port, sizeof(src_port))) 435 break; 436 if (!simple_input("To dst port #:", dst_port, sizeof(dst_port))) 437 break; 438 439 if (menuin[1]=='c') { 440 status = pjmedia_conf_connect_port(pjsua.mconf, atoi(src_port), atoi(dst_port)); 441 } else { 442 status = pjmedia_conf_disconnect_port(pjsua.mconf, atoi(src_port), atoi(dst_port)); 443 } 444 if (status == PJ_SUCCESS) { 445 puts("Success"); 446 } else { 447 puts("ERROR!!"); 448 } 449 } 450 break; 451 } 452 break; 453 398 454 case 'd': 399 455 pjsua_dump(); -
pjproject/trunk/pjsip/src/pjsua/pjsua.h
r201 r205 50 50 #define PJSUA_MAX_BUDDIES 32 51 51 52 /** 53 * Max simultaneous calls. 54 */ 55 #define PJSUA_MAX_CALLS 8 56 57 52 58 /** 53 59 * Structure to be attached to all dialog. … … 59 65 PJ_DECL_LIST_MEMBER(struct pjsua_inv_data); 60 66 61 pjsip_inv_session *inv; 62 pjmedia_session *session; 63 void *mod_data[PJSIP_MAX_MODULE]; 67 pjsip_inv_session *inv; /**< The invite session. */ 68 pjmedia_session *session; /**< The media session. */ 69 unsigned conf_slot; /**< Slot # in conference bridge. */ 70 unsigned call_slot; /**< RTP media index in med_sock_use[] */ 64 71 }; 65 72 … … 106 113 /* Media: */ 107 114 108 pjmedia_endpt *med_endpt; /**< Media endpoint. */ 109 pj_bool_t null_audio; 110 pjmedia_sock_info med_skinfo; 115 pjmedia_endpt *med_endpt; /**< Media endpoint. */ 116 pjmedia_conf *mconf; /**< Media conference. */ 117 pj_bool_t null_audio; /**< Null audio flag. */ 118 119 120 /* Since we support simultaneous calls, we need to have multiple 121 * RTP sockets. 122 */ 123 pjmedia_sock_info med_sock_info[PJSUA_MAX_CALLS]; 124 pj_bool_t med_sock_use[PJSUA_MAX_CALLS]; 111 125 112 126 /* User info: */ … … 138 152 139 153 140 /* Threading : */154 /* Threading (optional): */ 141 155 142 156 int thread_cnt; /**< Thread count. */ -
pjproject/trunk/pjsip/src/pjsua/pjsua_core.c
r201 r205 136 136 * Initialize sockets and optionally get the public address via STUN. 137 137 */ 138 static pj_status_t init_sockets() 138 static pj_status_t init_sockets(pj_bool_t sip, 139 pjmedia_sock_info *skinfo) 139 140 { 140 141 enum { … … 152 153 pj_sock_t sock[3]; 153 154 pj_sockaddr_in mapped_addr[3]; 154 pj_status_t status ;155 pj_status_t status = PJ_SUCCESS; 155 156 156 157 for (i=0; i<3; ++i) 157 158 sock[i] = PJ_INVALID_SOCKET; 158 159 159 /* Create and bind SIP UDP socket. */ 160 status = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &sock[SIP_SOCK]); 161 if (status != PJ_SUCCESS) { 162 pjsua_perror(THIS_FILE, "socket() error", status); 163 goto on_error; 164 } 160 if (sip) { 161 /* Create and bind SIP UDP socket. */ 162 status = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &sock[SIP_SOCK]); 163 if (status != PJ_SUCCESS) { 164 pjsua_perror(THIS_FILE, "socket() error", status); 165 goto on_error; 166 } 165 167 166 status = pj_sock_bind_in(sock[SIP_SOCK], 0, pjsua.sip_port); 167 if (status != PJ_SUCCESS) { 168 pjsua_perror(THIS_FILE, "bind() error", status); 169 goto on_error; 168 status = pj_sock_bind_in(sock[SIP_SOCK], 0, pjsua.sip_port); 169 if (status != PJ_SUCCESS) { 170 pjsua_perror(THIS_FILE, "bind() error", status); 171 goto on_error; 172 } 170 173 } 171 174 … … 230 233 pj_memcpy(&mapped_addr[i], &addr, sizeof(addr)); 231 234 232 mapped_addr[SIP_SOCK].sin_port = pj_htons((pj_uint16_t)pjsua.sip_port); 235 if (sip) 236 mapped_addr[SIP_SOCK].sin_port = pj_htons((pj_uint16_t)pjsua.sip_port); 237 else 238 mapped_addr[RTP_SOCK].sin_port = pj_htons((pj_uint16_t)rtp_port); 233 239 mapped_addr[RTP_SOCK].sin_port = pj_htons((pj_uint16_t)rtp_port); 234 240 mapped_addr[RTCP_SOCK].sin_port = pj_htons((pj_uint16_t)(rtp_port+1)); … … 257 263 } 258 264 259 pjsua.sip_sock = sock[SIP_SOCK]; 260 pj_memcpy(&pjsua.sip_sock_name, &mapped_addr[SIP_SOCK], sizeof(pj_sockaddr_in)); 261 262 pjsua.med_skinfo.rtp_sock = sock[RTP_SOCK]; 263 pj_memcpy(&pjsua.med_skinfo.rtp_addr_name, 265 if (sip) { 266 pjsua.sip_sock = sock[SIP_SOCK]; 267 pj_memcpy(&pjsua.sip_sock_name, &mapped_addr[SIP_SOCK], sizeof(pj_sockaddr_in)); 268 } 269 270 skinfo->rtp_sock = sock[RTP_SOCK]; 271 pj_memcpy(&skinfo->rtp_addr_name, 264 272 &mapped_addr[RTP_SOCK], sizeof(pj_sockaddr_in)); 265 273 266 pjsua.med_skinfo.rtcp_sock = sock[RTCP_SOCK];267 pj_memcpy(& pjsua.med_skinfo.rtcp_addr_name,274 skinfo->rtcp_sock = sock[RTCP_SOCK]; 275 pj_memcpy(&skinfo->rtcp_addr_name, 268 276 &mapped_addr[RTCP_SOCK], sizeof(pj_sockaddr_in)); 269 277 270 PJ_LOG(4,(THIS_FILE, "SIP UDP socket reachable at %s:%d", 271 pj_inet_ntoa(pjsua.sip_sock_name.sin_addr), 272 pj_ntohs(pjsua.sip_sock_name.sin_port))); 278 if (sip) { 279 PJ_LOG(4,(THIS_FILE, "SIP UDP socket reachable at %s:%d", 280 pj_inet_ntoa(pjsua.sip_sock_name.sin_addr), 281 pj_ntohs(pjsua.sip_sock_name.sin_port))); 282 } 273 283 PJ_LOG(4,(THIS_FILE, "RTP socket reachable at %s:%d", 274 pj_inet_ntoa( pjsua.med_skinfo.rtp_addr_name.sin_addr),275 pj_ntohs( pjsua.med_skinfo.rtp_addr_name.sin_port)));284 pj_inet_ntoa(skinfo->rtp_addr_name.sin_addr), 285 pj_ntohs(skinfo->rtp_addr_name.sin_port))); 276 286 PJ_LOG(4,(THIS_FILE, "RTCP UDP socket reachable at %s:%d", 277 pj_inet_ntoa( pjsua.med_skinfo.rtcp_addr_name.sin_addr),278 pj_ntohs( pjsua.med_skinfo.rtcp_addr_name.sin_port)));287 pj_inet_ntoa(skinfo->rtcp_addr_name.sin_addr), 288 pj_ntohs(skinfo->rtcp_addr_name.sin_port))); 279 289 280 290 return PJ_SUCCESS; … … 282 292 on_error: 283 293 for (i=0; i<3; ++i) { 294 if (sip && i==0) 295 continue; 284 296 if (sock[i] != PJ_INVALID_SOCKET) 285 297 pj_sock_close(sock[i]); … … 485 497 } 486 498 499 /* Init conference bridge. */ 500 501 status = pjmedia_conf_create(pjsua.pool, 8, 8000, 160, 16, &pjsua.mconf); 502 if (status != PJ_SUCCESS) { 503 pj_caching_pool_destroy(&pjsua.cp); 504 pjsua_perror(THIS_FILE, 505 "Media stack initialization has returned error", 506 status); 507 return status; 508 } 509 487 510 /* Init pjmedia-codecs: */ 488 511 … … 511 534 int i; /* Must be signed */ 512 535 pjsip_transport *udp_transport; 513 pj_status_t status ;536 pj_status_t status = PJ_SUCCESS; 514 537 515 538 /* Init sockets (STUN etc): */ 516 517 status = init_sockets();518 519 pjsua_perror(THIS_FILE, "init_sockets() has returned error",520 521 return status;522 523 539 for (i=0; i<PJ_ARRAY_SIZE(pjsua.med_sock_info); ++i) { 540 status = init_sockets(i==0, &pjsua.med_sock_info[i]); 541 if (status != PJ_SUCCESS) { 542 pjsua_perror(THIS_FILE, "init_sockets() has returned error", 543 status); 544 return status; 545 } 546 } 524 547 525 548 /* Add UDP transport: */ -
pjproject/trunk/pjsip/src/pjsua/pjsua_inv.c
r201 r205 42 42 struct pjsua_inv_data *inv_data; 43 43 pjsip_tx_data *tdata; 44 int med_sk_index = 0; 44 45 pj_status_t status; 45 46 … … 48 49 dest_uri = pj_str((char*)cstr_dest_uri); 49 50 51 /* Find free socket. */ 52 for (med_sk_index=0; med_sk_index<PJSUA_MAX_CALLS; ++med_sk_index) { 53 if (!pjsua.med_sock_use[med_sk_index]) 54 break; 55 } 56 57 if (med_sk_index == PJSUA_MAX_CALLS) { 58 PJ_LOG(3,(THIS_FILE, "Error: too many calls!")); 59 return PJ_ETOOMANY; 60 } 61 62 pjsua.med_sock_use[med_sk_index] = 1; 63 50 64 /* Create outgoing dialog: */ 51 65 … … 61 75 62 76 status = pjmedia_endpt_create_sdp( pjsua.med_endpt, dlg->pool, 63 1, &pjsua.med_skinfo, &offer); 77 1, &pjsua.med_sock_info[med_sk_index], 78 &offer); 64 79 if (status != PJ_SUCCESS) { 65 80 pjsua_perror(THIS_FILE, "pjmedia unable to create SDP", status); … … 80 95 inv_data = pj_pool_zalloc( dlg->pool, sizeof(struct pjsua_inv_data)); 81 96 inv_data->inv = inv; 97 inv_data->call_slot = med_sk_index; 82 98 dlg->mod_data[pjsua.mod.id] = inv_data; 83 99 inv->mod_data[pjsua.mod.id] = inv_data; … … 130 146 131 147 PJ_TODO(DESTROY_DIALOG_ON_FAIL); 148 pjsua.med_sock_use[med_sk_index] = 0; 132 149 return status; 133 150 } … … 183 200 struct pjsua_inv_data *inv_data; 184 201 pjmedia_sdp_session *answer; 185 202 int med_sk_index; 203 204 205 /* Find free socket. */ 206 for (med_sk_index=0; med_sk_index<PJSUA_MAX_CALLS; ++med_sk_index) { 207 if (!pjsua.med_sock_use[med_sk_index]) 208 break; 209 } 210 211 if (med_sk_index == PJSUA_MAX_CALLS) { 212 PJ_LOG(3,(THIS_FILE, "Error: too many calls!")); 213 return PJ_TRUE; 214 } 215 216 217 pjsua.med_sock_use[med_sk_index] = 1; 186 218 187 219 /* Get media capability from media endpoint: */ 188 220 189 221 status = pjmedia_endpt_create_sdp( pjsua.med_endpt, rdata->tp_info.pool, 190 1, &pjsua.med_skinfo, &answer ); 222 1, &pjsua.med_sock_info[med_sk_index], 223 &answer ); 191 224 if (status != PJ_SUCCESS) { 192 225 193 226 pjsip_endpt_respond_stateless(pjsua.endpt, rdata, 500, NULL, 194 227 NULL, NULL); 228 pjsua.med_sock_use[med_sk_index] = 0; 195 229 return PJ_TRUE; 196 230 } … … 200 234 status = pjsip_dlg_create_uas( pjsip_ua_instance(), rdata, 201 235 &pjsua.contact_uri, &dlg); 202 if (status != PJ_SUCCESS) 236 if (status != PJ_SUCCESS) { 237 pjsua.med_sock_use[med_sk_index] = 0; 203 238 return PJ_TRUE; 239 } 204 240 205 241 … … 215 251 pjsip_rdata_get_tsx(rdata), 216 252 response); 253 pjsua.med_sock_use[med_sk_index] = 0; 217 254 return PJ_TRUE; 218 255 … … 224 261 inv_data = pj_pool_zalloc(dlg->pool, sizeof(struct pjsua_inv_data)); 225 262 inv_data->inv = inv; 263 inv_data->call_slot = inv_data->call_slot = med_sk_index; 226 264 dlg->mod_data[pjsua.mod.id] = inv_data; 227 265 inv->mod_data[pjsua.mod.id] = inv_data; … … 261 299 262 300 if (inv_data && inv_data->session) { 301 pjmedia_conf_remove_port(pjsua.mconf, inv_data->conf_slot); 263 302 pjmedia_session_destroy(inv_data->session); 303 pjsua.med_sock_use[inv_data->call_slot] = 0; 264 304 inv_data->session = NULL; 265 305 … … 313 353 inv_data = inv->dlg->mod_data[pjsua.mod.id]; 314 354 if (inv_data && inv_data->session) { 355 pjmedia_conf_remove_port(pjsua.mconf, inv_data->conf_slot); 315 356 pjmedia_session_destroy(inv_data->session); 357 pjsua.med_sock_use[inv_data->call_slot] = 0; 316 358 inv_data->session = NULL; 317 359 } … … 336 378 } 337 379 338 339 380 /* Create new media session. 340 381 * The media session is active immediately. … … 342 383 343 384 if (!pjsua.null_audio) { 344 345 status = pjmedia_session_create( pjsua.med_endpt, 1, &pjsua.med_skinfo, 385 pjmedia_port *media_port; 386 pj_str_t port_name; 387 char tmp[PJSIP_MAX_URL_SIZE]; 388 389 status = pjmedia_session_create( pjsua.med_endpt, 1, 390 &pjsua.med_sock_info[inv_data->call_slot], 346 391 local_sdp, remote_sdp, 347 392 &inv_data->session ); … … 352 397 } 353 398 399 pjmedia_session_get_port(inv_data->session, 0, &media_port); 400 401 port_name.ptr = tmp; 402 port_name.slen = pjsip_uri_print(PJSIP_URI_IN_REQ_URI, 403 inv_data->inv->dlg->remote.info->uri, 404 tmp, sizeof(tmp)); 405 if (port_name.slen < 1) { 406 port_name = pj_str("call"); 407 } 408 status = pjmedia_conf_add_port( pjsua.mconf, inv->pool, 409 media_port, 410 &port_name, 411 &inv_data->conf_slot); 412 if (status != PJ_SUCCESS) { 413 pjsua_perror(THIS_FILE, "Unable to create conference slot", 414 status); 415 pjmedia_session_destroy(inv_data->session); 416 inv_data->session = NULL; 417 return; 418 } 419 420 pjmedia_conf_connect_port( pjsua.mconf, 0, inv_data->conf_slot); 421 pjmedia_conf_connect_port( pjsua.mconf, inv_data->conf_slot, 0); 422 354 423 PJ_LOG(3,(THIS_FILE,"Media has been started successfully")); 355 424 }
Note: See TracChangeset
for help on using the changeset viewer.