- Timestamp:
- Feb 8, 2006 10:43:39 PM (19 years ago)
- Location:
- pjproject/trunk/pjmedia
- Files:
-
- 16 edited
- 2 moved
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/build/pjmedia.dsp
r155 r159 97 97 # Begin Source File 98 98 99 SOURCE=..\src\pjmedia\endpoint.c 100 # End Source File 101 # Begin Source File 102 99 103 SOURCE=..\src\pjmedia\errno.c 100 104 # End Source File … … 106 110 107 111 SOURCE=..\src\pjmedia\jbuf.c 108 # End Source File109 # Begin Source File110 111 SOURCE=..\src\pjmedia\mediamgr.c112 112 # End Source File 113 113 # Begin Source File … … 143 143 144 144 SOURCE=..\src\pjmedia\session.c 145 # PROP Exclude_From_Build 1146 145 # End Source File 147 146 # Begin Source File … … 163 162 # Begin Source File 164 163 164 SOURCE=..\include\pjmedia\endpoint.h 165 # End Source File 166 # Begin Source File 167 165 168 SOURCE=..\include\pjmedia\errno.h 166 169 # End Source File … … 168 171 169 172 SOURCE=..\include\pjmedia\jbuf.h 170 # End Source File171 # Begin Source File172 173 SOURCE=..\include\pjmedia\mediamgr.h174 173 # End Source File 175 174 # Begin Source File -
pjproject/trunk/pjmedia/include/pjmedia/codec.h
r121 r159 26 26 */ 27 27 28 #include <pjmedia/types.h> 28 29 #include <pj/list.h> 29 30 … … 37 38 */ 38 39 39 /** Top most media type. */ 40 typedef enum pj_media_type 41 { 42 /** No type. */ 43 PJ_MEDIA_TYPE_NONE = 0, 44 45 /** The media is audio */ 46 PJ_MEDIA_TYPE_AUDIO = 1, 47 48 /** The media is video. */ 49 PJ_MEDIA_TYPE_VIDEO = 2, 50 51 /** Unknown media type, in this case the name will be specified in 52 * encoding_name. 53 */ 54 PJ_MEDIA_TYPE_UNKNOWN = 3, 55 56 } pj_media_type; 57 58 59 /** Media direction. */ 60 typedef enum pj_media_dir_t 61 { 62 /** None */ 63 PJ_MEDIA_DIR_NONE = 0, 64 65 /** Encoding (outgoing to network) stream */ 66 PJ_MEDIA_DIR_ENCODING = 1, 67 68 /** Decoding (incoming from network) stream. */ 69 PJ_MEDIA_DIR_DECODING = 2, 70 71 /** Incoming and outgoing stream. */ 72 PJ_MEDIA_DIR_ENCODING_DECODING = 3, 73 74 } pj_media_dir_t; 75 76 77 /** Standard RTP paylist types. */ 78 typedef enum pj_rtp_pt 79 { 80 PJ_RTP_PT_PCMU = 0, /* audio PCMU */ 81 PJ_RTP_PT_GSM = 3, /* audio GSM */ 82 PJ_RTP_PT_G723 = 4, /* audio G723 */ 83 PJ_RTP_PT_DVI4_8K = 5, /* audio DVI4 8KHz */ 84 PJ_RTP_PT_DVI4_16K = 6, /* audio DVI4 16Khz */ 85 PJ_RTP_PT_LPC = 7, /* audio LPC */ 86 PJ_RTP_PT_PCMA = 8, /* audio PCMA */ 87 PJ_RTP_PT_G722 = 9, /* audio G722 */ 88 PJ_RTP_PT_L16_2 = 10, /* audio 16bit linear 44.1KHz stereo */ 89 PJ_RTP_PT_L16_1 = 11, /* audio 16bit linear 44.1KHz mono */ 90 PJ_RTP_PT_QCELP = 12, /* audio QCELP */ 91 PJ_RTP_PT_CN = 13, /* audio Comfort Noise */ 92 PJ_RTP_PT_MPA = 14, /* audio MPEG1 or MPEG2 as elementary streams */ 93 PJ_RTP_PT_G728 = 15, /* audio G728 */ 94 PJ_RTP_PT_DVI4_11K = 16, /* audio DVI4 11.025KHz mono */ 95 PJ_RTP_PT_DVI4_22K = 17, /* audio DVI4 22.050KHz mono */ 96 PJ_RTP_PT_G729 = 18, /* audio G729 */ 97 PJ_RTP_PT_CELB = 25, /* video/comb Cell-B by Sun Microsystems (RFC 2029) */ 98 PJ_RTP_PT_JPEG = 26, /* video JPEG */ 99 PJ_RTP_PT_NV = 28, /* video NV implemented by nv program by Xerox */ 100 PJ_RTP_PT_H261 = 31, /* video H261 */ 101 PJ_RTP_PT_MPV = 32, /* video MPEG1 or MPEG2 elementary streams */ 102 PJ_RTP_PT_MP2T = 33, /* video MPEG2 transport */ 103 PJ_RTP_PT_H263 = 34, /* video H263 */ 104 105 PJ_RTP_PT_DYNAMIC = 96, /* start of dynamic RTP payload */ 106 } pj_rtp_pt; 107 108 109 /** Identification used to search for codec factory that supports specific 110 * codec specification. 111 */ 112 typedef struct pj_codec_id 113 { 114 /** Media type. */ 115 pj_media_type type; 116 117 /** Payload type (can be dynamic). */ 118 unsigned pt; 119 120 /** Encoding name, must be present if the payload type is dynamic. */ 121 pj_str_t encoding_name; 122 123 /** Sampling rate. */ 124 unsigned sample_rate; 125 } pj_codec_id; 126 127 128 /** Detailed codec attributes used both to configure a codec and to query 129 * the capability of codec factories. 130 */ 131 typedef struct pj_codec_attr 132 { 133 pj_uint32_t sample_rate; /* Sampling rate in Hz */ 134 pj_uint32_t avg_bps; /* Average bandwidth in bits per second */ 135 136 pj_uint8_t pcm_bits_per_sample;/* Bits per sample in the PCM side */ 137 pj_uint16_t ptime; /* Packet time in miliseconds */ 138 139 unsigned pt:8; /* Payload type. */ 140 unsigned vad_enabled:1; /* Voice Activity Detector. */ 141 unsigned cng_enabled:1; /* Comfort Noise Generator. */ 142 unsigned lpf_enabled:1; /* Low pass filter */ 143 unsigned hpf_enabled:1; /* High pass filter */ 144 unsigned penh_enabled:1; /* Perceptual Enhancement */ 145 unsigned concl_enabled:1; /* Packet loss concealment */ 146 unsigned reserved_bit:1; 147 148 } pj_codec_attr; 149 150 /** Types of audio frame. */ 151 typedef enum pj_audio_frame_type 152 { 153 /** The frame is a silence audio frame. */ 154 PJ_AUDIO_FRAME_SILENCE, 155 156 /** The frame is a non-silence audio frame. */ 157 PJ_AUDIO_FRAME_AUDIO, 158 159 } pj_audio_frame_type; 160 161 typedef struct pj_codec pj_codec; 162 typedef struct pj_codec_factory pj_codec_factory; 163 164 165 /** This structure describes an audio frame. */ 166 struct pj_audio_frame 167 { 168 /** Type: silence or non-silence. */ 169 pj_audio_frame_type type; 170 171 /** Pointer to buffer. */ 172 void *buf; 173 174 /** Frame size in bytes. */ 175 unsigned size; 176 }; 177 178 /** 179 * Operations that must be supported by the codec. 180 */ 181 typedef struct pj_codec_op 182 { 183 /** Get default attributes. */ 184 pj_status_t (*default_attr) (pj_codec *codec, pj_codec_attr *attr); 185 186 /** Open and initialize codec using the specified attribute. 187 * @return zero on success. 188 */ 189 pj_status_t (*init)( pj_codec *codec, pj_pool_t *pool ); 190 191 /** Close and shutdown codec. 192 */ 193 pj_status_t (*open)( pj_codec *codec, pj_codec_attr *attr ); 194 195 /** Close and shutdown codec. 196 */ 197 pj_status_t (*close)( pj_codec *codec ); 198 199 /** Encode frame. 200 */ 201 pj_status_t (*encode)( pj_codec *codec, const struct pj_audio_frame *input, 202 unsigned output_buf_len, struct pj_audio_frame *output); 203 204 /** Decode frame. 205 */ 206 pj_status_t (*decode)( pj_codec *codec, const struct pj_audio_frame *input, 207 unsigned output_buf_len, struct pj_audio_frame *output); 208 209 } pj_codec_op; 210 211 /** 212 * A codec describes an instance to encode or decode media frames. 213 */ 214 struct pj_codec 40 41 /** 42 * Standard RTP static payload types, as defined by RFC 3551. 43 */ 44 enum pjmedia_rtp_pt 45 { 46 PJMEDIA_RTP_PT_PCMU = 0, /* audio PCMU */ 47 PJMEDIA_RTP_PT_GSM = 3, /* audio GSM */ 48 PJMEDIA_RTP_PT_G723 = 4, /* audio G723 */ 49 PJMEDIA_RTP_PT_DVI4_8K = 5, /* audio DVI4 8KHz */ 50 PJMEDIA_RTP_PT_DVI4_16K = 6, /* audio DVI4 16Khz */ 51 PJMEDIA_RTP_PT_LPC = 7, /* audio LPC */ 52 PJMEDIA_RTP_PT_PCMA = 8, /* audio PCMA */ 53 PJMEDIA_RTP_PT_G722 = 9, /* audio G722 */ 54 PJMEDIA_RTP_PT_L16_2 = 10, /* audio 16bit linear 44.1KHz stereo */ 55 PJMEDIA_RTP_PT_L16_1 = 11, /* audio 16bit linear 44.1KHz mono */ 56 PJMEDIA_RTP_PT_QCELP = 12, /* audio QCELP */ 57 PJMEDIA_RTP_PT_CN = 13, /* audio Comfort Noise */ 58 PJMEDIA_RTP_PT_MPA = 14, /* audio MPEG1/MPEG2 elementary streams */ 59 PJMEDIA_RTP_PT_G728 = 15, /* audio G728 */ 60 PJMEDIA_RTP_PT_DVI4_11K = 16, /* audio DVI4 11.025KHz mono */ 61 PJMEDIA_RTP_PT_DVI4_22K = 17, /* audio DVI4 22.050KHz mono */ 62 PJMEDIA_RTP_PT_G729 = 18, /* audio G729 */ 63 64 PJMEDIA_RTP_PT_CELB = 25, /* video/comb Cell-B by Sun (RFC 2029) */ 65 PJMEDIA_RTP_PT_JPEG = 26, /* video JPEG */ 66 PJMEDIA_RTP_PT_NV = 28, /* video NV by nv program by Xerox */ 67 PJMEDIA_RTP_PT_H261 = 31, /* video H261 */ 68 PJMEDIA_RTP_PT_MPV = 32, /* video MPEG1 or MPEG2 elementary */ 69 PJMEDIA_RTP_PT_MP2T = 33, /* video MPEG2 transport */ 70 PJMEDIA_RTP_PT_H263 = 34, /* video H263 */ 71 72 PJMEDIA_RTP_PT_DYNAMIC = 96, /* start of dynamic RTP payload */ 73 74 }; 75 76 77 /** 78 * Identification used to search for codec factory that supports specific 79 * codec specification. 80 */ 81 struct pjmedia_codec_info 82 { 83 pjmedia_type type; /**< Media type. */ 84 unsigned pt; /**< Payload type (can be dynamic). */ 85 pj_str_t encoding_name; /**< Encoding name. */ 86 unsigned sample_rate; /**< Sampling rate. */ 87 }; 88 89 90 /** 91 * Detailed codec attributes used both to configure a codec and to query 92 * the capability of codec factories. 93 */ 94 struct pjmedia_codec_param 95 { 96 pj_uint32_t sample_rate; /**< Sampling rate in Hz */ 97 pj_uint32_t avg_bps; /**< Average bandwidth in bits/sec */ 98 99 pj_uint8_t pcm_bits_per_sample;/**< Bits/sample in the PCM side */ 100 pj_uint16_t ptime; /**< Packet time in miliseconds */ 101 102 unsigned pt:8; /**< Payload type. */ 103 unsigned vad_enabled:1; /**< Voice Activity Detector. */ 104 unsigned cng_enabled:1; /**< Comfort Noise Generator. */ 105 unsigned lpf_enabled:1; /**< Low pass filter */ 106 unsigned hpf_enabled:1; /**< High pass filter */ 107 unsigned penh_enabled:1; /**< Perceptual Enhancement */ 108 unsigned concl_enabled:1; /**< Packet loss concealment */ 109 unsigned reserved_bit:1; /**< Reserved, must be NULL. */ 110 111 }; 112 113 114 /** 115 * Types of media frame. 116 */ 117 enum pjmedia_frame_type 118 { 119 PJMEDIA_FRAME_TYPE_SILENCE_AUDIO, /**< Silence audio frame. */ 120 PJMEDIA_FRAME_TYPE_AUDIO, /**< Normal audio frame. */ 121 122 }; 123 124 /** 125 * This structure describes a media frame. 126 */ 127 struct pjmedia_frame 128 { 129 pjmedia_frame_type type; /**< Frame type. */ 130 void *buf; /**< Pointer to buffer. */ 131 pj_size_t size; /**< Frame size in bytes. */ 132 }; 133 134 /** 135 * This structure describes codec operations. Each codec MUST implement 136 * all of these functions. 137 */ 138 struct pjmedia_codec_op 139 { 140 /** 141 * Get default attributes for this codec. 142 * 143 * @param codec The codec instance. 144 * @param attr Pointer to receive default codec attributes. 145 * 146 * @return PJ_SUCCESS on success. 147 */ 148 pj_status_t (*default_attr)(pjmedia_codec *codec, 149 pjmedia_codec_param *attr); 150 151 /** 152 * Initialize codec using the specified attribute. 153 * 154 * @param codec The codec instance. 155 * @param pool Pool to use when the codec needs to allocate 156 * some memory. 157 * 158 * @return PJ_SUCCESS on success. 159 */ 160 pj_status_t (*init)(pjmedia_codec *codec, 161 pj_pool_t *pool ); 162 163 /** 164 * Open the codec and initialize with the specified parameter.. 165 * 166 * @param codec The codec instance. 167 * @param param Codec initialization parameter. 168 * 169 * @return PJ_SUCCESS on success. 170 */ 171 pj_status_t (*open)(pjmedia_codec *codec, 172 pjmedia_codec_param *param ); 173 174 /** 175 * Close and shutdown codec, releasing all resources allocated by 176 * this codec, if any. 177 * 178 * @param codec The codec instance. 179 * 180 * @return PJ_SUCCESS on success. 181 */ 182 pj_status_t (*close)(pjmedia_codec *codec); 183 184 185 /** 186 * Instruct the codec to encode the specified input frame. 187 * 188 * @param codec The codec instance. 189 * @param input The input frame. 190 * @param out_size The length of buffer in the output frame. 191 * @param output The output frame. 192 * 193 * @return PJ_SUCCESS on success; 194 */ 195 pj_status_t (*encode)(pjmedia_codec *codec, 196 const struct pjmedia_frame *input, 197 unsigned out_size, 198 struct pjmedia_frame *output); 199 200 /** 201 * Instruct the codec to decode the specified input frame. 202 * 203 * @param codec The codec instance. 204 * @param input The input frame. 205 * @param out_size The length of buffer in the output frame. 206 * @param output The output frame. 207 * 208 * @return PJ_SUCCESS on success; 209 */ 210 pj_status_t (*decode)(pjmedia_codec *codec, 211 const struct pjmedia_frame *input, 212 unsigned out_size, 213 struct pjmedia_frame *output); 214 215 }; 216 217 218 /** 219 * This structure describes a codec instance. 220 */ 221 struct pjmedia_codec 215 222 { 216 223 /** Entries to put this codec instance in codec factory's list. */ 217 PJ_DECL_LIST_MEMBER(struct pj _codec);224 PJ_DECL_LIST_MEMBER(struct pjmedia_codec); 218 225 219 226 /** Codec's private data. */ … … 221 228 222 229 /** Codec factory where this codec was allocated. */ 223 pj _codec_factory *factory;230 pjmedia_codec_factory *factory; 224 231 225 232 /** Operations to codec. */ 226 pj_codec_op *op; 227 }; 228 229 /** 230 * This structure describes operations that must be supported by codec factories. 231 */ 232 typedef struct pj_codec_factory_op 233 { 234 /** Check whether the factory can create codec with the specified ID. 235 * @param factory The codec factory. 236 * @param id The codec ID. 237 * @return zero it matches. 238 */ 239 pj_status_t (*match_id)( pj_codec_factory *factory, const pj_codec_id *id ); 240 241 /** Create default attributes for the specified codec ID. This function can 242 * be called by application to get the capability of the codec. 243 * @param factory The codec factory. 244 * @param id The codec ID. 245 * @param attr The attribute to be initialized. 246 * @return zero if success. 247 */ 248 pj_status_t (*default_attr)( pj_codec_factory *factory, const pj_codec_id *id, 249 pj_codec_attr *attr ); 250 251 /** Enumerate supported codecs. 252 * @param factory The codec factory. 253 * @param count Number of entries in the array. 254 * @param codecs The codec array. 255 * @return the total number of supported codecs, which can be less or 256 * greater than requested. 257 */ 258 unsigned (*enum_codecs) (pj_codec_factory *factory, unsigned count, pj_codec_id codecs[]); 259 260 /** This function is called by codec manager to instantiate one codec 261 * instance. 262 * @param factory The codec factory. 263 * @param id The codec ID. 264 * @return the instance of the codec, or NULL if codec can not be created. 265 */ 266 pj_codec* (*alloc_codec)( pj_codec_factory *factory, const pj_codec_id *id); 267 268 /** This function is called by codec manager to return a particular instance 269 * of codec back to the codec factory. 270 * @param factory The codec factory. 271 * @param codec The codec instance to be returned. 272 */ 273 void (*dealloc_codec)( pj_codec_factory *factory, pj_codec *codec ); 274 275 } pj_codec_factory_op; 233 pjmedia_codec_op *op; 234 }; 235 236 237 /** 238 * This structure describes operations that must be supported by codec 239 * factories. 240 */ 241 struct pjmedia_codec_factory_op 242 { 243 /** 244 * Check whether the factory can create codec with the specified 245 * codec info. 246 * 247 * @param factory The codec factory. 248 * @param info The codec info. 249 * 250 * @return PJ_SUCCESS if this factory is able to create an 251 * instance of codec with the specified info. 252 */ 253 pj_status_t (*test_alloc)(pjmedia_codec_factory *factory, 254 const pjmedia_codec_info *info ); 255 256 /** 257 * Create default attributes for the specified codec ID. This function 258 * can be called by application to get the capability of the codec. 259 * 260 * @param factory The codec factory. 261 * @param info The codec info. 262 * @param attr The attribute to be initialized. 263 * 264 * @return PJ_SUCCESS if success. 265 */ 266 pj_status_t (*default_attr)(pjmedia_codec_factory *factory, 267 const pjmedia_codec_info *info, 268 pjmedia_codec_param *attr ); 269 270 /** 271 * Enumerate supported codecs that can be created using this factory. 272 * 273 * @param factory The codec factory. 274 * @param count On input, specifies the number of elements in 275 * the array. On output, the value will be set to 276 * the number of elements that have been initialized 277 * by this function. 278 * @param info The codec info array, which contents will be 279 * initialized upon return. 280 * 281 * @return PJ_SUCCESS on success. 282 */ 283 pj_status_t (*enum_info)(pjmedia_codec_factory *factory, 284 unsigned *count, 285 pjmedia_codec_info codecs[]); 286 287 /** 288 * Create one instance of the codec with the specified codec info. 289 * 290 * @param factory The codec factory. 291 * @param info The codec info. 292 * @param p_codec Pointer to receive the codec instance. 293 * 294 * @return PJ_SUCCESS on success. 295 */ 296 pj_status_t (*alloc_codec)(pjmedia_codec_factory *factory, 297 const pjmedia_codec_info *info, 298 pjmedia_codec **p_codec); 299 300 /** 301 * This function is called by codec manager to return a particular 302 * instance of codec back to the codec factory. 303 * 304 * @param factory The codec factory. 305 * @param codec The codec instance to be returned. 306 * 307 * @return PJ_SUCCESS on success. 308 */ 309 pj_status_t (*dealloc_codec)(pjmedia_codec_factory *factory, 310 pjmedia_codec *codec ); 311 312 }; 313 276 314 277 315 /** … … 280 318 * instances of codec. 281 319 */ 282 struct pj _codec_factory320 struct pjmedia_codec_factory 283 321 { 284 322 /** Entries to put this structure in the codec manager list. */ 285 PJ_DECL_LIST_MEMBER(struct pj _codec_factory);323 PJ_DECL_LIST_MEMBER(struct pjmedia_codec_factory); 286 324 287 325 /** The factory's private data. */ 288 void *factory_data;326 void *factory_data; 289 327 290 328 /** Operations to the factory. */ 291 pj _codec_factory_op *op;329 pjmedia_codec_factory_op *op; 292 330 293 331 }; … … 296 334 * Declare maximum codecs 297 335 */ 298 #define PJ _CODEC_MGR_MAX_CODECS 32336 #define PJMEDIA_CODEC_MGR_MAX_CODECS 32 299 337 300 338 /** 301 339 * Codec manager maintains codec factory etc. 302 340 */ 303 typedef struct pj_codec_mgr 304 { 305 pj_codec_factory factory_list; 306 unsigned codec_cnt; 307 pj_codec_id codecs[PJ_CODEC_MGR_MAX_CODECS]; 308 } pj_codec_mgr; 309 310 /** 311 * Init codec manager. 341 typedef struct pjmedia_codec_mgr 342 { 343 pjmedia_codec_factory factory_list; 344 unsigned codec_cnt; 345 pjmedia_codec_info codecs[PJMEDIA_CODEC_MGR_MAX_CODECS]; 346 } pjmedia_codec_mgr; 347 348 349 350 /** 351 * Initialize codec manager. 352 * 353 * @param mgr Codec manager instance. 354 * 355 * @return PJ_SUCCESS on success. 356 */ 357 PJ_DECL(pj_status_t) pjmedia_codec_mgr_init(pjmedia_codec_mgr *mgr); 358 359 360 /** 361 * Register codec factory to codec manager. 362 * 363 * @param mgr The codec manager. 364 * @param factory The codec factory to be registered. 365 * 366 * @return PJ_SUCCESS on success. 312 367 */ 313 368 PJ_DECL(pj_status_t) 314 pj_codec_mgr_init (pj_codec_mgr *mgr); 315 316 /** 317 * Register codec to codec manager. 369 pjmedia_codec_mgr_register_factory( pjmedia_codec_mgr *mgr, 370 pjmedia_codec_factory *factory); 371 372 /** 373 * Unregister codec factory from the codec manager. 374 * 375 * @param mgr The codec manager. 376 * @param factory The codec factory to be unregistered. 377 * 378 * @return PJ_SUCCESS on success. 318 379 */ 319 380 PJ_DECL(pj_status_t) 320 pj_codec_mgr_register_factory (pj_codec_mgr *mgr, pj_codec_factory *factory); 321 322 /** 323 * Unregister codec. 324 */ 325 PJ_DECL(void) 326 pj_codec_mgr_unregister_factory (pj_codec_mgr *mgr, pj_codec_factory *factory); 327 328 /** 329 * Enumerate codecs. 330 */ 331 PJ_DECL(unsigned) 332 pj_codec_mgr_enum_codecs (pj_codec_mgr *mgr, unsigned count, const pj_codec_id *codecs[]); 333 334 /** 335 * Open codec. 336 */ 337 PJ_DECL(pj_codec*) 338 pj_codec_mgr_alloc_codec (pj_codec_mgr *mgr, const struct pj_codec_id *id); 339 340 /** 341 * Close codec. 342 */ 343 PJ_DECL(void) 344 pj_codec_mgr_dealloc_codec (pj_codec_mgr *mgr, pj_codec *codec); 381 pjmedia_codec_mgr_unregister_factory( pjmedia_codec_mgr *mgr, 382 pjmedia_codec_factory *factory); 383 384 /** 385 * Enumerate all supported codec. 386 * 387 * @param mgr The codec manager. 388 * @param count On input, specifies the number of elements in 389 * the array. On output, the value will be set to 390 * the number of elements that have been initialized 391 * by this function. 392 * @param info The codec info array, which contents will be 393 * initialized upon return. 394 * 395 * @return PJ_SUCCESS on success. 396 */ 397 PJ_DECL(pj_status_t) pjmedia_codec_mgr_enum_codecs( pjmedia_codec_mgr *mgr, 398 unsigned *count, 399 pjmedia_codec_info info[]); 400 401 /** 402 * Request the codec manager to allocate one instance of codec with the 403 * specified codec info. The codec will enumerate all codec factories 404 * until it finds factory that is able to create the specified codec. 405 * 406 * @param mgr The codec manager. 407 * @param info The information about the codec to be created. 408 * @param p_codec Pointer to receive the codec instance. 409 * 410 * @return PJ_SUCCESS on success. 411 */ 412 PJ_DECL(pj_status_t) pjmedia_codec_mgr_alloc_codec(pjmedia_codec_mgr *mgr, 413 const pjmedia_codec_info *info, 414 pjmedia_codec **p_codec); 415 416 /** 417 * Deallocate the specified codec instance. The codec manager will return 418 * the instance of the codec back to its factory. 419 * 420 * @param mgr The codec manager. 421 * @param codec The codec instance. 422 * 423 * @return PJ_SUCESS on success. 424 */ 425 PJ_DECL(pj_status_t) pjmedia_codec_mgr_dealloc_codec(pjmedia_codec_mgr *mgr, 426 pjmedia_codec *codec); 345 427 346 428 /** -
pjproject/trunk/pjmedia/include/pjmedia/endpoint.h
r158 r159 26 26 */ 27 27 /** 28 * @defgroup PJMED_ MGR Media Manager28 * @defgroup PJMED_ENDPT Media Endpoint 29 29 * @ingroup PJMEDIA 30 30 * @{ 31 31 * 32 * The media manageracts as placeholder for endpoint capabilities. Each33 * media managerwill have a codec manager to manage list of codecs installed32 * The media endpoint acts as placeholder for endpoint capabilities. Each 33 * media endpoint will have a codec manager to manage list of codecs installed 34 34 * in the endpoint and a sound device factory. 35 35 * 36 * A reference to media managerinstance is required when application wants36 * A reference to media endpoint instance is required when application wants 37 37 * to create a media session (#pj_media_session_create or 38 38 * #pj_media_session_create_from_sdp). … … 46 46 47 47 48 /** Opague declaration of media manager. */49 typedef struct pj_med_mgr_t pj_med_mgr_t;50 48 51 49 /** 52 * Create an instance of media manager.50 * Create an instance of media endpoint. 53 51 * 54 * @param pf Pool factory. 55 * @param conn_addr Connection address to be used by this media manager. 52 * @param pf Pool factory, which will be used by the media endpoint 53 * throughout its lifetime. 54 * @param p_endpt Pointer to receive the endpoint instance. 56 55 * 57 * @return A new instance of media manager, or NULL if failed.56 * @return PJ_SUCCESS on success. 58 57 */ 59 PJ_DECL(pj_med_mgr_t*) pj_med_mgr_create (pj_pool_factory *pf); 58 PJ_DECL(pj_status_t) pjmedia_endpt_create( pj_pool_factory *pf, 59 pjmedia_endpt **p_endpt); 60 60 61 61 /** 62 * Destroy media managerinstance.62 * Destroy media endpoint instance. 63 63 * 64 * @param mgr Media managerinstance.64 * @param endpt Media endpoint instance. 65 65 * 66 * @return zeroon success.66 * @return PJ_SUCCESS on success. 67 67 */ 68 PJ_DECL(pj_status_t) pj_med_mgr_destroy (pj_med_mgr_t *mgr); 68 PJ_DECL(pj_status_t) pjmedia_endpt_destroy(pjmedia_endpt *endpt); 69 69 70 70 71 /** 71 * Get pool factory of the media manager as specified when the media 72 * manager was created. 72 * Request the media endpoint to create pool. 73 73 * 74 * @param mgr The media manager instance. 74 * @param endpt The media endpoint instance. 75 * @param name Name to be assigned to the pool. 76 * @param initial Initial pool size, in bytes. 77 * @param increment Increment size, in bytes. 75 78 * 76 * @return Pool factory instance of the media manager.79 * @return Memory pool. 77 80 */ 78 PJ_DECL(pj_pool_factory*) pj_med_mgr_get_pool_factory (pj_med_mgr_t *mgr); 81 PJ_DECL(pj_pool_t*) pjmedia_endpt_create_pool( pjmedia_endpt *endpt, 82 const char *name, 83 pj_size_t initial, 84 pj_size_t increment); 79 85 80 86 /** 81 * Get the codec manager instance .87 * Get the codec manager instance of the media endpoint. 82 88 * 83 * @param mgr The media managerinstance.89 * @param endpt The media endpoint instance. 84 90 * 85 * @return The instance of codec manager. 91 * @return The instance of codec manager belonging to 92 * this media endpoint. 86 93 */ 87 PJ_DECL(pj_codec_mgr*) pj_med_mgr_get_codec_mgr (pj_med_mgr_t *mgr); 94 PJ_DECL(pjmedia_codec_mgr*) pjmedia_endpt_get_codec_mgr(pjmedia_endpt *mgr); 95 96 97 /** 98 * Create a SDP session description that describes the endpoint 99 * capability. 100 * 101 * @param endpt The media endpoint. 102 * @param pool Pool to use to create the SDP descriptor. 103 * @param stream_cnt Number of elements in the sock_info array. This 104 * also denotes the maximum number of streams (i.e. 105 * the "m=" lines) that will be created in the SDP. 106 * @param sock_info Array of socket transport information. One 107 * transport is needed for each media stream, and 108 * each transport consists of an RTP and RTCP socket 109 * pair. 110 * @param p_sdp Pointer to receive SDP session descriptor. 111 * 112 * @return PJ_SUCCESS on success. 113 */ 114 PJ_DECL(pj_status_t) pjmedia_endpt_create_sdp( pjmedia_endpt *endpt, 115 pj_pool_t *pool, 116 unsigned stream_cnt, 117 const pjmedia_sock_info sock_info[], 118 pjmedia_sdp_session **p_sdp ); 88 119 89 120 -
pjproject/trunk/pjmedia/include/pjmedia/errno.h
r140 r159 260 260 261 261 262 /************************************************************ 263 * CODEC 264 ***********************************************************/ 265 /** 266 * @hideinitializer 267 * Unsupported codec. 268 */ 269 #define PJMEDIA_CODEC_EUNSUP (PJMEDIA_ERRNO_START+80) /* 220080 */ 270 271 272 /************************************************************ 273 * MEDIA 274 ***********************************************************/ 275 /** 276 * @hideinitializer 277 * Invalid remote IP address (in SDP). 278 */ 279 #define PJMEDIA_EINVALIDIP (PJMEDIA_ERRNO_START+100) /* 220100 */ 280 /** 281 * @hideinitializer 282 * Asymetric codec is not supported. 283 */ 284 #define PJMEDIA_EASYMCODEC (PJMEDIA_ERRNO_START+101) /* 220101 */ 285 /** 286 * @hideinitializer 287 * Invalid payload type. 288 */ 289 #define PJMEDIA_EINVALIDPT (PJMEDIA_ERRNO_START+102) /* 220102 */ 290 /** 291 * @hideinitializer 292 * Missing rtpmap. 293 */ 294 #define PJMEDIA_EMISSINGRTPMAP (PJMEDIA_ERRNO_START+103) /* 220103 */ 295 296 297 262 298 PJ_END_DECL 263 299 -
pjproject/trunk/pjmedia/include/pjmedia/rtp.h
r121 r159 80 80 enum pj_rtp_error_t 81 81 { 82 PJ _RTP_ERR_RTP_PACKING, /**< Invalid RTP packet. */83 PJ _RTP_ERR_INVALID_VERSION, /**< Invalid RTP version. */84 PJ _RTP_ERR_INVALID_SSRC, /**< Invalid SSRC. */85 PJ _RTP_ERR_INVALID_PT, /**< Invalid payload type. */86 PJ _RTP_ERR_INVALID_PACKET, /**< Invalid packet. */87 PJ _RTP_ERR_SESSION_RESTARTED, /**< Session has just been restarted. */88 PJ _RTP_ERR_SESSION_PROBATION, /**< Session in probation. */89 PJ _RTP_ERR_BAD_SEQUENCE, /**< Bad RTP sequence number. */82 PJMEDIA_RTP_ERR_RTP_PACKING, /**< Invalid RTP packet. */ 83 PJMEDIA_RTP_ERR_INVALID_VERSION, /**< Invalid RTP version. */ 84 PJMEDIA_RTP_ERR_INVALID_SSRC, /**< Invalid SSRC. */ 85 PJMEDIA_RTP_ERR_INVALID_PT, /**< Invalid payload type. */ 86 PJMEDIA_RTP_ERR_INVALID_PACKET, /**< Invalid packet. */ 87 PJMEDIA_RTP_ERR_SESSION_RESTARTED, /**< Session has just been restarted. */ 88 PJMEDIA_RTP_ERR_SESSION_PROBATION, /**< Session in probation. */ 89 PJMEDIA_RTP_ERR_BAD_SEQUENCE, /**< Bad RTP sequence number. */ 90 90 }; 91 91 -
pjproject/trunk/pjmedia/include/pjmedia/session.h
r121 r159 26 26 */ 27 27 28 #include <pj/types.h> 29 #include <pjmedia/mediamgr.h> 28 #include <pjmedia/endpoint.h> 30 29 #include <pjmedia/stream.h> 31 30 #include <pjmedia/sdp.h> … … 39 38 */ 40 39 41 /** Opaque declaration of media session. */42 typedef struct pj_media_session_t pj_media_session_t;43 44 /** Media socket info. */45 typedef struct pj_media_sock_info46 {47 pj_sock_t rtp_sock, rtcp_sock;48 pj_sockaddr_in rtp_addr_name;49 } pj_media_sock_info;50 51 /** Stream info. */52 typedef struct pj_media_stream_info53 {54 pj_str_t type;55 pj_media_dir_t dir;56 pj_str_t transport;57 pj_media_sock_info sock_info;58 pj_str_t rem_addr;59 unsigned short rem_port;60 unsigned fmt_cnt;61 pj_codec_id fmt[PJSDP_MAX_FMT];62 63 } pj_media_stream_info;64 65 /** Flag for modifying stream. */66 enum67 {68 PJ_MEDIA_STREAM_MODIFY_DIR = 1,69 };70 40 71 41 /** 72 * Create new session offering. 42 * Create new session offering based on the local and remote SDP. 43 * The session initially will be inactive. 44 * 45 * @param endpt The PJMEDIA endpoint instance. 46 * @param stream_cnt Maximum number of streams to be created. This 47 * also denotes the number of elements in the 48 * socket information. 49 * @param skinfo Array of socket informations. The argument stream_cnt 50 * specifies the number of elements in this array. One 51 * element is needed for each media stream to be 52 * created in the session. 53 * @param local_sdp The SDP describing local capability. 54 * @param rem_sdp The SDP describing remote capability. 55 * @param p_session Pointer to receive the media session. 56 * 57 * @return PJ_SUCCESS if media session can be created 58 * successfully. 73 59 */ 74 PJ_DECL(pj_media_session_t*) 75 pj_media_session_create ( pj_med_mgr_t *mgr, const pj_media_sock_info *skinfo ); 60 PJ_DECL(pj_status_t) pjmedia_session_create( pjmedia_endpt *endpt, 61 unsigned stream_cnt, 62 const pjmedia_sock_info skinfo[], 63 const pjmedia_sdp_session *local_sdp, 64 const pjmedia_sdp_session *rem_sdp, 65 pjmedia_session **p_session ); 66 76 67 77 68 /** 78 * Create new session based on peer's offering. 69 * Activate all streams in media session for the specified direction. 70 * 71 * @param session The media session. 72 * @param dir The direction to activate. 73 * 74 * @return PJ_SUCCESS if success. 79 75 */ 80 PJ_DECL(pj_ media_session_t*)81 pj_media_session_create_from_sdp ( pj_med_mgr_t *mgr, const pjsdp_session_desc *sdp, 82 const pj_media_sock_info *skinfo); 76 PJ_DECL(pj_status_t) pjmedia_session_resume(pjmedia_session *session, 77 pjmedia_dir dir); 78 83 79 84 80 /** 85 * Duplicate session. The new session is inactive. 81 * Suspend receipt and transmission of all streams in media session 82 * for the specified direction. 83 * 84 * @param session The media session. 85 * @param dir The media direction to suspend. 86 * 87 * @return PJ_SUCCESS if success. 86 88 */ 87 PJ_DECL(pj_ media_session_t*)88 pj_media_session_clone (const pj_media_session_t *session);89 PJ_DECL(pj_status_t) pjmedia_session_pause(pjmedia_session *session, 90 pjmedia_dir dir); 89 91 90 92 /** 91 * Create SDP description from the session. 93 * Suspend receipt and transmission of individual stream in media session 94 * for the specified direction. 95 * 96 * @param session The media session. 97 * @param index The stream index. 98 * @param dir The media direction to pause. 99 * 100 * @return PJ_SUCCESS on success. 92 101 */ 93 PJ_DECL(pj sdp_session_desc*)94 pj_media_session_create_sdp ( const pj_media_session_t *session, pj_pool_t *pool,95 pj_bool_t only_first_fmt);102 PJ_DECL(pj_status_t) pjmedia_session_pause_stream( pjmedia_session *session, 103 unsigned index, 104 pjmedia_dir dir); 96 105 97 106 /** 98 * Update session with SDP answer from peer. The session must NOT active. 107 * Activate individual stream in media session for the specified direction. 108 * 109 * @param session The media session. 110 * @param index The stream index. 111 * @param dir The media direction to activate. 112 * 113 * @return PJ_SUCCESS on success. 99 114 */ 100 PJ_DECL(pj_status_t) 101 pj_media_session_update ( pj_media_session_t *session, 102 const pjsdp_session_desc *sdp);115 PJ_DECL(pj_status_t) pjmedia_session_resume_stream(pjmedia_session *session, 116 unsigned index, 117 pjmedia_dir dir); 103 118 104 119 /** 105 120 * Enumerate media streams in the session. 106 * @return the actual number of streams. 121 * 122 * @param session The media session. 123 * @param count On input, specifies the number of elements in 124 * the array. On output, the number will be filled 125 * with number of streams in the session. 126 * @param strm_info Array of stream info. 127 * 128 * @return PJ_SUCCESS on success. 107 129 */ 108 PJ_DECL(unsigned) 109 pj_media_session_enum_streams (const pj_media_session_t *session, 110 unsigned count, const pj_media_stream_info *info[]); 130 PJ_DECL(pj_status_t) pjmedia_session_enum_streams(const pjmedia_session *session, 131 unsigned *count, 132 pjmedia_stream_info strm_info[]); 133 111 134 112 135 /** 113 * Get stream statistics. 136 * Get session statistics. The stream statistic shows various 137 * indicators such as packet count, packet lost, jitter, delay, etc. 138 * 139 * @param session The media session. 140 * @param count On input, specifies the number of elements in 141 * the array. On output, the number will be filled 142 * with number of streams in the session. 143 * @param stat Array of stream statistics. 144 * 145 * @return PJ_SUCCESS on success. 114 146 */ 115 PJ_DECL(pj_status_t) 116 pj_media_session_get_stat (const pj_media_session_t *session, unsigned index, 117 pj_media_stream_stat *tx_stat, 118 pj_media_stream_stat *rx_stat); 147 PJ_DECL(pj_status_t) pjmedia_session_get_stat(const pjmedia_session *session, 148 unsigned *count, 149 pjmedia_stream_stat stat[]); 119 150 120 151 /** 121 * Modify stream, only when stream is inactive. 152 * Get individual stream statistics. The stream statistic shows various 153 * indicators such as packet count, packet lost, jitter, delay, etc. 154 * 155 * @param s The media session. 156 * @param index The stream index. 157 * @param stat Stream statistics. 158 * 159 * @return PJ_SUCCESS on success. 122 160 */ 123 PJ_DECL(pj_status_t) 124 pj_media_session_modify_stream (pj_media_session_t *session, unsigned index, 125 unsigned modify_flag, const pj_media_stream_info *info); 126 127 /** 128 * Activate all streams in media session. 129 */ 130 PJ_DECL(pj_status_t) 131 pj_media_session_activate (pj_media_session_t *session); 132 133 /** 134 * Activate individual stream in media session. 135 */ 136 PJ_DECL(pj_status_t) 137 pj_media_session_activate_stream (pj_media_session_t *session, unsigned index); 161 PJ_DECL(pj_status_t) pjmedia_session_get_stream_stat(const pjmedia_session *s, 162 unsigned index, 163 pjmedia_stream_stat *stat); 138 164 139 165 /** 140 166 * Destroy media session. 167 * 168 * @param session The media session. 169 * 170 * @return PJ_SUCCESS if success. 141 171 */ 142 PJ_DECL(pj_status_t) 143 pj_media_session_destroy (pj_media_session_t *session); 172 PJ_DECL(pj_status_t) pjmedia_session_destroy(pjmedia_session *session); 173 144 174 145 175 -
pjproject/trunk/pjmedia/include/pjmedia/stream.h
r121 r159 28 28 #include <pjmedia/sound.h> 29 29 #include <pjmedia/codec.h> 30 #include <pjmedia/ mediamgr.h>30 #include <pjmedia/endpoint.h> 31 31 #include <pj/sock.h> 32 32 … … 40 40 */ 41 41 42 typedef struct pj_media_stream_t pj_media_stream_t; 42 /** 43 * Opaque declaration for media channel. 44 * Media channel is unidirectional flow of media from sender to 45 * receiver. 46 */ 47 typedef struct pjmedia_channel pjmedia_channel; 43 48 44 /** Parameter for creating channel. */ 45 typedef struct pj_media_stream_create_param 49 /** 50 * This structure describes media stream information. Each media stream 51 * corresponds to one "m=" line in SDP session descriptor, and it has 52 * its own RTP/RTCP socket pair. 53 */ 54 struct pjmedia_stream_info 46 55 { 47 /** Codec ID, must NOT be NULL. */ 48 pj_codec_id *codec_id; 56 pjmedia_type type; /**< Media type (audio, video) */ 57 pjmedia_dir dir; /**< Media direction. */ 58 pjmedia_sock_info sock_info; /**< Media transport (RTP/RTCP sockets) */ 59 pj_sockaddr_in rem_addr; /**< Remote RTP address */ 60 pjmedia_codec_info fmt; /**< Codec format info. */ 61 pj_uint32_t ssrc; /**< RTP SSRC. */ 62 int jb_min; /**< Jitter buffer min delay. */ 63 int jb_max; /**< Jitter buffer max delay. */ 64 int jb_maxcnt; /**< Jitter buffer max delay. */ 65 }; 49 66 50 /** Media manager, must NOT be NULL. */51 pj_med_mgr_t *mediamgr;52 67 53 /** Direction: IN_OUT, or IN only, or OUT only. */ 54 pj_media_dir_t dir; 68 /** 69 * Individual channel statistic. 70 */ 71 struct pjmedia_channel_stat 72 { 73 pj_uint32_t pkt; /**< Total number of packets. */ 74 pj_uint32_t bytes; /**< Total number of bytes, including RTP hdr. */ 75 pj_uint32_t lost; /**< Total number of packet lost */ 76 }; 55 77 56 /** RTP socket. */ 57 pj_sock_t rtp_sock; 78 /** 79 * Stream statistic. 80 */ 81 struct pjmedia_stream_stat 82 { 83 pjmedia_channel_stat enc; /**< Encoder statistics. */ 84 pjmedia_channel_stat dec; /**< Decoder statistics. */ 85 }; 58 86 59 /** RTCP socket. */60 pj_sock_t rtcp_sock;61 87 62 /** Address of remote */ 63 pj_sockaddr_in *remote_addr; 88 /** 89 * Create a media stream based on the specified stream parameter. 90 * All channels in the stream initially will be inactive. 91 * 92 * @param endpt Media endpoint. 93 * @param pool Pool to allocate memory for the stream. A large 94 * number of memory may be needed because jitter 95 * buffer needs to preallocate some storage. 96 * @param info Stream information. 97 * @param p_stream Pointer to receive the media stream. 98 * 99 * @return PJ_SUCCESS on success. 100 */ 101 PJ_DECL(pj_status_t) pjmedia_stream_create(pjmedia_endpt *endpt, 102 pj_pool_t *pool, 103 const pjmedia_stream_info *info, 104 pjmedia_stream **p_stream); 64 105 65 /** RTP SSRC */ 66 pj_uint32_t ssrc; 106 /** 107 * Destroy the media stream. 108 * 109 * @param stream The media stream. 110 * 111 * @return PJ_SUCCESS on success. 112 */ 113 PJ_DECL(pj_status_t) pjmedia_stream_destroy(pjmedia_stream *stream); 67 114 68 /** Jitter buffer parameters. */ 69 int jb_min, jb_max, jb_maxcnt; 115 /** 116 * Start the media stream. This will start the appropriate channels 117 * in the media stream, depending on the media direction that was set 118 * when the stream was created. 119 * 120 * @param stream The media stream. 121 * 122 * @return PJ_SUCCESS on success. 123 */ 124 PJ_DECL(pj_status_t) pjmedia_stream_start(pjmedia_stream *stream); 70 125 71 } pj_media_stream_create_param;72 126 73 typedef struct pj_media_stream_stat 74 { 75 pj_uint32_t pkt_tx, pkt_rx; /* packets transmitted/received */ 76 pj_uint32_t oct_tx, oct_rx; /* octets transmitted/received */ 77 pj_uint32_t jitter; /* receive jitter in ms */ 78 pj_uint32_t pkt_lost; /* total packet lost count */ 79 } pj_media_stream_stat; 127 /** 128 * Get the stream statistics. 129 * 130 * @param stream The media stream. 131 * @param stat Media stream statistics. 132 * 133 * @return PJ_SUCCESS on success. 134 */ 135 PJ_DECL(pj_status_t) pjmedia_stream_get_stat( const pjmedia_stream *stream, 136 pjmedia_stream_stat *stat); 80 137 81 PJ_DECL(pj_status_t) pj_media_stream_create (pj_pool_t *pool, 82 pj_media_stream_t **enc_stream, 83 pj_media_stream_t **dec_stream, 84 pj_media_stream_create_param *param); 85 PJ_DECL(pj_status_t) pj_media_stream_start (pj_media_stream_t *stream); 86 PJ_DECL(pj_status_t) pj_media_stream_get_stat (const pj_media_stream_t *stream, 87 pj_media_stream_stat *stat); 88 PJ_DECL(pj_status_t) pj_media_stream_pause (pj_media_stream_t *stream); 89 PJ_DECL(pj_status_t) pj_media_stream_resume (pj_media_stream_t *stream); 90 PJ_DECL(pj_status_t) pj_media_stream_destroy (pj_media_stream_t *stream); 138 /** 139 * Pause the individual channel in the stream. 140 * 141 * @param channel The media channel. 142 * @param dir Which direction to pause. 143 * 144 * @return PJ_SUCCESS on success. 145 */ 146 PJ_DECL(pj_status_t) pjmedia_stream_pause( pjmedia_stream *stream, 147 pjmedia_dir dir); 148 149 /** 150 * Resume the individual channel in the stream. 151 * 152 * @param channel The media channel. 153 * @param dir Which direction to resume. 154 * 155 * @return PJ_SUCCESS on success; 156 */ 157 PJ_DECL(pj_status_t) pjmedia_stream_resume(pjmedia_stream *stream, 158 pjmedia_dir dir); 159 91 160 92 161 /** -
pjproject/trunk/pjmedia/include/pjmedia/types.h
r129 r159 21 21 22 22 #include <pj/types.h> 23 23 #include <pj/sock.h> 24 25 26 /** 27 * Top most media type. 28 */ 29 enum pjmedia_type 30 { 31 /** No type. */ 32 PJMEDIA_TYPE_NONE = 0, 33 34 /** The media is audio */ 35 PJMEDIA_TYPE_AUDIO = 1, 36 37 /** The media is video. */ 38 PJMEDIA_TYPE_VIDEO = 2, 39 40 /** Unknown media type, in this case the name will be specified in 41 * encoding_name. 42 */ 43 PJMEDIA_TYPE_UNKNOWN = 3, 44 45 }; 46 47 48 /** 49 * Media direction. 50 */ 51 enum pjmedia_dir 52 { 53 /** None */ 54 PJMEDIA_DIR_NONE = 0, 55 56 /** Encoding (outgoing to network) stream */ 57 PJMEDIA_DIR_ENCODING = 1, 58 59 /** Decoding (incoming from network) stream. */ 60 PJMEDIA_DIR_DECODING = 2, 61 62 /** Incoming and outgoing stream. */ 63 PJMEDIA_DIR_ENCODING_DECODING = 3, 64 65 }; 66 67 68 /** 69 * Top level media type. 70 */ 71 typedef enum pjmedia_type pjmedia_type; 72 73 /** 74 * Media direction. 75 */ 76 typedef enum pjmedia_dir pjmedia_dir; 77 78 /** 79 * Codec info. 80 */ 81 typedef struct pjmedia_codec_info pjmedia_codec_info; 82 83 /** 84 * Codec initialization parameter. 85 */ 86 typedef struct pjmedia_codec_param pjmedia_codec_param; 87 88 /** 89 * Types of media frames. 90 */ 91 typedef enum pjmedia_frame_type pjmedia_frame_type; 92 93 /** 94 * This structure describes a media frame. 95 */ 96 typedef struct pjmedia_frame pjmedia_frame; 97 98 /** 99 * Codec instance. 100 */ 101 typedef struct pjmedia_codec pjmedia_codec; 102 103 /** 104 * Codec factory. 105 */ 106 typedef struct pjmedia_codec_factory pjmedia_codec_factory; 107 108 /** 109 * Codec operation. 110 */ 111 typedef struct pjmedia_codec_op pjmedia_codec_op; 112 113 /** 114 * Codec factory operation. 115 */ 116 typedef struct pjmedia_codec_factory_op pjmedia_codec_factory_op; 117 118 /** 119 * Codec manager. 120 */ 121 typedef struct pjmedia_codec_mgr pjmedia_codec_mgr; 122 123 /** 124 * Opague declaration of media endpoint. 125 */ 126 typedef struct pjmedia_endpt pjmedia_endpt; 127 128 129 /** 130 * Media socket info. 131 */ 132 typedef struct pjmedia_sock_info 133 { 134 135 pj_sock_t rtp_sock; 136 pj_sock_t rtcp_sock; 137 pj_sockaddr_in rtp_addr_name; 138 139 } pjmedia_sock_info; 140 141 142 /** 143 * Typedef for media stream information. 144 */ 145 typedef struct pjmedia_stream_info pjmedia_stream_info; 146 147 /** 148 * Typedef for media stream statistic. 149 */ 150 typedef struct pjmedia_stream_stat pjmedia_stream_stat; 151 152 /** 153 * Typedef for media stream. 154 */ 155 typedef struct pjmedia_stream pjmedia_stream; 156 157 /** 158 * Individual channel statistic. 159 */ 160 typedef struct pjmedia_channel_stat pjmedia_channel_stat; 161 162 /** 163 * Opaque declaration of media session. 164 */ 165 typedef struct pjmedia_session pjmedia_session; 24 166 25 167 /** -
pjproject/trunk/pjmedia/src/pjmedia/codec.c
r121 r159 18 18 */ 19 19 #include <pjmedia/codec.h> 20 #include <pjmedia/errno.h> 20 21 #include <pj/pool.h> 21 22 #include <pj/string.h> … … 25 26 #define THIS_FILE "codec.c" 26 27 27 static void enum_all_codecs (pj_codec_mgr *cm) 28 /* 29 * Reinitialize array of supported codecs. 30 */ 31 static void enum_all_codecs (pjmedia_codec_mgr *mgr) 28 32 { 29 pj _codec_factory *cf;33 pjmedia_codec_factory *factory; 30 34 31 cf = cm->factory_list.next; 32 cm->codec_cnt = 0; 33 while (cf != &cm->factory_list) { 34 pj_codec_id temp[PJ_CODEC_MGR_MAX_CODECS]; 35 int i, cnt; 35 mgr->codec_cnt = 0; 36 36 37 cnt = cf->op->enum_codecs (cf, PJ_CODEC_MGR_MAX_CODECS, temp); 38 if (cnt > PJ_CODEC_MGR_MAX_CODECS) { 39 pj_assert(0); 40 PJ_LOG(4, (THIS_FILE, "Too many codecs reported by factory")); 41 cnt = PJ_CODEC_MGR_MAX_CODECS; 42 } 37 factory = mgr->factory_list.next; 38 while (factory != &mgr->factory_list) { 39 unsigned count; 40 pj_status_t status; 43 41 44 for (i=0; i<cnt && cm->codec_cnt < PJ_CODEC_MGR_MAX_CODECS; ++i) { 45 cm->codecs[cm->codec_cnt++] = temp[i]; 46 } 42 count = PJ_ARRAY_SIZE(mgr->codecs) - mgr->codec_cnt; 43 status = factory->op->enum_info(factory, &count, 44 mgr->codecs+mgr->codec_cnt); 45 if (status == PJ_SUCCESS) 46 mgr->codec_cnt += count; 47 47 48 cf = cf->next;48 factory = factory->next; 49 49 } 50 50 } 51 51 52 PJ_DEF(pj_status_t) pj_codec_mgr_init (pj_codec_mgr *mgr) 52 /* 53 * Initialize codec manager. 54 */ 55 PJ_DEF(pj_status_t) pjmedia_codec_mgr_init (pjmedia_codec_mgr *mgr) 53 56 { 57 PJ_ASSERT_RETURN(mgr, PJ_EINVAL); 58 54 59 pj_list_init (&mgr->factory_list); 55 60 mgr->codec_cnt = 0; 56 return 0; 61 62 return PJ_SUCCESS; 57 63 } 58 64 59 PJ_DEF(pj_status_t) pj_codec_mgr_register_factory (pj_codec_mgr *mgr, 60 pj_codec_factory *factory) 65 /* 66 * Register a codec factory. 67 */ 68 PJ_DEF(pj_status_t) 69 pjmedia_codec_mgr_register_factory( pjmedia_codec_mgr *mgr, 70 pjmedia_codec_factory *factory) 61 71 { 62 pj_list_insert_before (&mgr->factory_list, factory); 72 PJ_ASSERT_RETURN(mgr && factory, PJ_EINVAL); 73 74 pj_list_push_back(&mgr->factory_list, factory); 63 75 enum_all_codecs (mgr); 64 return 0; 76 77 return PJ_SUCCESS; 65 78 } 66 79 67 PJ_DEF(void) pj_codec_mgr_unregister_factory (pj_codec_mgr *mgr, pj_codec_factory *factory) 80 /* 81 * Unregister a codec factory. 82 */ 83 PJ_DEF(pj_status_t) 84 pjmedia_codec_mgr_unregister_factory(pjmedia_codec_mgr *mgr, 85 pjmedia_codec_factory *factory) 68 86 { 69 PJ_UNUSED_ARG(mgr); 87 88 PJ_ASSERT_RETURN(mgr && factory, PJ_EINVAL); 89 90 /* Factory must be registered. */ 91 PJ_ASSERT_RETURN(pj_list_find_node(&mgr->factory_list, factory)==factory, 92 PJ_ENOTFOUND); 93 94 70 95 pj_list_erase(factory); 71 96 enum_all_codecs (mgr); 97 98 return PJ_SUCCESS; 72 99 } 73 100 74 PJ_DEF(unsigned) 75 pj_codec_mgr_enum_codecs (pj_codec_mgr *mgr, unsigned count, const pj_codec_id *codecs[]) 101 /* 102 * Enum all codecs. 103 */ 104 PJ_DEF(pj_status_t) 105 pjmedia_codec_mgr_enum_codecs(pjmedia_codec_mgr *mgr, 106 unsigned *count, 107 pjmedia_codec_info codecs[]) 76 108 { 77 unsigned i;109 PJ_ASSERT_RETURN(mgr && count && codecs, PJ_EINVAL); 78 110 79 if (count > mgr->codec_cnt) 80 count = mgr->codec_cnt; 111 if (*count > mgr->codec_cnt) 112 *count = mgr->codec_cnt; 113 114 pj_memcpy(codecs, mgr->codecs, *count * sizeof(pjmedia_codec_info)); 81 115 82 for (i=0; i<count; ++i) 83 codecs[i] = &mgr->codecs[i]; 84 85 return mgr->codec_cnt; 116 return PJ_SUCCESS; 86 117 } 87 118 88 PJ_DEF(pj_codec*) pj_codec_mgr_alloc_codec (pj_codec_mgr *mgr, const struct pj_codec_id *id) 119 /* 120 * Allocate one codec. 121 */ 122 PJ_DEF(pj_status_t) pjmedia_codec_mgr_alloc_codec(pjmedia_codec_mgr *mgr, 123 const pjmedia_codec_info *info, 124 pjmedia_codec **p_codec) 89 125 { 90 pj_codec_factory *factory = mgr->factory_list.next; 126 pjmedia_codec_factory *factory; 127 pj_status_t status; 128 129 PJ_ASSERT_RETURN(mgr && info && p_codec, PJ_EINVAL); 130 131 *p_codec = NULL; 132 133 factory = mgr->factory_list.next; 91 134 while (factory != &mgr->factory_list) { 92 if ( (*factory->op->match_id)(factory, id) == 0 ) { 93 pj_codec *codec = (*factory->op->alloc_codec)(factory, id); 94 if (codec != NULL) 95 return codec; 135 136 if ( (*factory->op->test_alloc)(factory, info) == PJ_SUCCESS ) { 137 138 status = (*factory->op->alloc_codec)(factory, info, p_codec); 139 if (status == PJ_SUCCESS) 140 return PJ_SUCCESS; 141 96 142 } 143 97 144 factory = factory->next; 98 145 } 99 return NULL; 146 147 148 return PJMEDIA_CODEC_EUNSUP; 100 149 } 101 150 102 PJ_DEF(void) pj_codec_mgr_dealloc_codec (pj_codec_mgr *mgr, pj_codec *codec) 151 /* 152 * Dealloc codec. 153 */ 154 PJ_DEF(pj_status_t) pjmedia_codec_mgr_dealloc_codec(pjmedia_codec_mgr *mgr, 155 pjmedia_codec *codec) 103 156 { 104 PJ_UNUSED_ARG(mgr); 105 (*codec->factory->op->dealloc_codec)(codec->factory, codec); 157 PJ_ASSERT_RETURN(mgr && codec, PJ_EINVAL); 158 159 return (*codec->factory->op->dealloc_codec)(codec->factory, codec); 106 160 } 107 161 -
pjproject/trunk/pjmedia/src/pjmedia/endpoint.c
r158 r159 17 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 18 */ 19 #include <pjmedia/mediamgr.h> 19 #include <pjmedia/endpoint.h> 20 #include <pjmedia/errno.h> 21 #include <pjmedia/sdp.h> 20 22 #include <pj/sock.h> 21 23 #include <pj/pool.h> 22 24 #include <pj/string.h> 23 24 PJ_DECL(pj_status_t) g711_init_factory (pj_codec_factory *factory, pj_pool_t *pool); 25 PJ_DECL(pj_status_t) g711_deinit_factory (pj_codec_factory *factory); 26 27 /** Concrete declaration of media manager. */ 28 struct pj_med_mgr_t 25 #include <pj/assert.h> 26 #include <pj/os.h> 27 28 29 #define THIS_FILE "endpoint.c" 30 31 static const pj_str_t STR_AUDIO = { "audio", 5}; 32 static const pj_str_t STR_VIDEO = { "video", 5}; 33 static const pj_str_t STR_IN = { "IN", 2 }; 34 static const pj_str_t STR_IP4 = { "IP4", 3}; 35 static const pj_str_t STR_RTP_AVP = { "RTP/AVP", 7 }; 36 static const pj_str_t STR_SDP_NAME = { "pjmedia", 7 }; 37 static const pj_str_t STR_SENDRECV = { "sendrecv", 8 }; 38 39 40 PJ_DECL(pj_status_t) g711_init_factory (pjmedia_codec_factory *factory, pj_pool_t *pool); 41 PJ_DECL(pj_status_t) g711_deinit_factory (pjmedia_codec_factory *factory); 42 43 44 /** Concrete declaration of media endpoint. */ 45 struct pjmedia_endpt 29 46 { 30 47 /** Pool. */ … … 35 52 36 53 /** Codec manager. */ 37 pj _codec_mgr codec_mgr;54 pjmedia_codec_mgr codec_mgr; 38 55 }; 39 56 40 57 /** 41 * Initialize and get the instance of media manager. 42 */ 43 PJ_DEF(pj_med_mgr_t*) pj_med_mgr_create ( pj_pool_factory *pf) 58 * Initialize and get the instance of media endpoint. 59 */ 60 PJ_DEF(pj_status_t) pjmedia_endpt_create(pj_pool_factory *pf, 61 pjmedia_endpt **p_endpt) 44 62 { 45 63 pj_pool_t *pool; 46 pj _med_mgr_t *mm;47 pj _codec_factory *cf;64 pjmedia_endpt *endpt; 65 pjmedia_codec_factory *factory; 48 66 pj_status_t status; 49 67 50 pool = pj_pool_create(pf, "mediamgr", 512, 512, NULL); 68 PJ_ASSERT_RETURN(pf && p_endpt, PJ_EINVAL); 69 70 pool = pj_pool_create(pf, "med-ept", 512, 512, NULL); 51 71 if (!pool) 52 return NULL;53 54 mm = pj_pool_calloc(pool, 1, sizeof(struct pj_med_mgr_t));55 mm->pool = pool;56 mm->pf = pf;72 return PJ_ENOMEM; 73 74 endpt = pj_pool_zalloc(pool, sizeof(struct pjmedia_endpt)); 75 endpt->pool = pool; 76 endpt->pf = pf; 57 77 58 78 /* Sound */ … … 60 80 61 81 /* Init codec manager. */ 62 status = pj _codec_mgr_init(&mm->codec_mgr);63 if (status != 0) {82 status = pjmedia_codec_mgr_init(&endpt->codec_mgr); 83 if (status != PJ_SUCCESS) { 64 84 pj_snd_deinit(); 65 85 goto on_error; … … 67 87 68 88 /* Init and register G.711 codec. */ 69 cf = pj_pool_alloc (mm->pool, sizeof(pj_codec_factory));70 71 status = g711_init_factory ( cf, mm->pool);72 if (status != 0) {89 factory = pj_pool_alloc (endpt->pool, sizeof(pjmedia_codec_factory)); 90 91 status = g711_init_factory (factory, endpt->pool); 92 if (status != PJ_SUCCESS) { 73 93 pj_snd_deinit(); 74 return NULL; 75 } 76 77 status = pj_codec_mgr_register_factory (&mm->codec_mgr, cf); 78 if (status != 0) 79 return NULL; 80 81 return mm; 94 goto on_error; 95 } 96 97 status = pjmedia_codec_mgr_register_factory (&endpt->codec_mgr, factory); 98 if (status != PJ_SUCCESS) { 99 pj_snd_deinit(); 100 goto on_error; 101 } 102 103 *p_endpt = endpt; 104 return PJ_SUCCESS; 82 105 83 106 on_error: 84 107 pj_pool_release(pool); 85 return NULL;108 return status; 86 109 } 87 110 … … 89 112 * Get the codec manager instance. 90 113 */ 91 PJ_DEF(pj_codec_mgr*) pj_med_mgr_get_codec_mgr (pj_med_mgr_t *mgr) 92 { 93 return &mgr->codec_mgr; 94 } 95 96 /** 97 * Deinitialize media manager. 98 */ 99 PJ_DEF(pj_status_t) pj_med_mgr_destroy (pj_med_mgr_t *mgr) 100 { 114 PJ_DEF(pjmedia_codec_mgr*) pjmedia_endpt_get_codec_mgr(pjmedia_endpt *endpt) 115 { 116 return &endpt->codec_mgr; 117 } 118 119 /** 120 * Deinitialize media endpoint. 121 */ 122 PJ_DEF(pj_status_t) pjmedia_endpt_destroy (pjmedia_endpt *endpt) 123 { 124 PJ_ASSERT_RETURN(endpt, PJ_EINVAL); 125 126 endpt->pf = NULL; 127 101 128 pj_snd_deinit(); 102 pj_pool_release (mgr->pool); 103 return 0; 104 } 105 106 /** 107 * Get pool factory. 108 */ 109 PJ_DEF(pj_pool_factory*) pj_med_mgr_get_pool_factory (pj_med_mgr_t *mgr) 110 { 111 return mgr->pf; 112 } 129 pj_pool_release (endpt->pool); 130 131 return PJ_SUCCESS; 132 } 133 134 /** 135 * Create pool. 136 */ 137 PJ_DEF(pj_pool_t*) pjmedia_endpt_create_pool( pjmedia_endpt *endpt, 138 const char *name, 139 pj_size_t initial, 140 pj_size_t increment) 141 { 142 pj_assert(endpt != NULL); 143 144 return pj_pool_create(endpt->pf, name, initial, increment, NULL); 145 } 146 147 /** 148 * Create a SDP session description that describes the endpoint 149 * capability. 150 */ 151 PJ_DEF(pj_status_t) pjmedia_endpt_create_sdp( pjmedia_endpt *endpt, 152 pj_pool_t *pool, 153 unsigned stream_cnt, 154 const pjmedia_sock_info sock_info[], 155 pjmedia_sdp_session **p_sdp ) 156 { 157 pj_time_val tv; 158 unsigned i; 159 pjmedia_sdp_session *sdp; 160 pjmedia_sdp_media *m; 161 pjmedia_sdp_attr *attr; 162 163 PJ_ASSERT_RETURN(endpt && pool && p_sdp && stream_cnt, PJ_EINVAL); 164 165 166 /* Create and initialize basic SDP session */ 167 sdp = pj_pool_zalloc (pool, sizeof(pjmedia_sdp_session)); 168 169 pj_gettimeofday(&tv); 170 sdp->origin.user = pj_str("-"); 171 sdp->origin.version = sdp->origin.id = tv.sec + 2208988800UL; 172 sdp->origin.net_type = STR_IN; 173 sdp->origin.addr_type = STR_IP4; 174 sdp->origin.addr = *pj_gethostname(); 175 sdp->name = STR_SDP_NAME; 176 177 /* Since we only support one media stream at present, put the 178 * SDP connection line in the session level. 179 */ 180 sdp->conn = pj_pool_zalloc (pool, sizeof(pjmedia_sdp_conn)); 181 sdp->conn->net_type = STR_IN; 182 sdp->conn->addr_type = STR_IP4; 183 pj_strdup2(pool, &sdp->conn->addr, 184 pj_inet_ntoa(sock_info[0].rtp_addr_name.sin_addr)); 185 186 187 /* SDP time and attributes. */ 188 sdp->time.start = sdp->time.stop = 0; 189 sdp->attr_count = 0; 190 191 /* Create media stream 0: */ 192 193 sdp->media_count = 1; 194 m = pj_pool_zalloc (pool, sizeof(pjmedia_sdp_media)); 195 sdp->media[0] = m; 196 197 /* Standard media info: */ 198 pj_strdup(pool, &m->desc.media, &STR_AUDIO); 199 m->desc.port = pj_ntohs(sock_info[0].rtp_addr_name.sin_port); 200 m->desc.port_count = 1; 201 pj_strdup (pool, &m->desc.transport, &STR_RTP_AVP); 202 203 /* Add format and rtpmap for each codec. */ 204 m->desc.fmt_count = 0; 205 m->attr_count = 0; 206 207 for (i=0; i<endpt->codec_mgr.codec_cnt; ++i) { 208 209 pjmedia_codec_info *codec_info = &endpt->codec_mgr.codecs[i]; 210 pjmedia_sdp_rtpmap rtpmap; 211 pjmedia_sdp_attr *attr; 212 pj_str_t *fmt = &m->desc.fmt[m->desc.fmt_count++]; 213 214 fmt->ptr = pj_pool_alloc(pool, 8); 215 fmt->slen = pj_utoa(codec_info->pt, fmt->ptr); 216 217 rtpmap.pt = *fmt; 218 rtpmap.clock_rate = codec_info->sample_rate; 219 rtpmap.enc_name = codec_info->encoding_name; 220 rtpmap.param.slen = 0; 221 222 pjmedia_sdp_rtpmap_to_attr(pool, &rtpmap, &attr); 223 m->attr[m->attr_count++] = attr; 224 225 } 226 227 /* Add sendrect attribute. */ 228 attr = pj_pool_zalloc(pool, sizeof(pjmedia_sdp_attr)); 229 attr->name = STR_SENDRECV; 230 m->attr[m->attr_count++] = attr; 231 232 233 /* Done */ 234 *p_sdp = sdp; 235 236 return PJ_SUCCESS; 237 238 } 239 -
pjproject/trunk/pjmedia/src/pjmedia/errno.c
r140 r159 77 77 { PJMEDIA_SDP_ENAMENOTEQUAL, "SDP name/subject line not equal" }, 78 78 { PJMEDIA_SDP_ETIMENOTEQUAL, "SDP time line not equal" }, 79 80 /* Codec errors. */ 81 { PJMEDIA_CODEC_EUNSUP, "Unsupported media codec" }, 82 83 /* Media errors. */ 84 { PJMEDIA_EINVALIDIP, "Invalid remote media (IP) address" }, 85 { PJMEDIA_EASYMCODEC, "Asymetric media codec is not supported" }, 86 { PJMEDIA_EINVALIDPT, "Invalid media payload type" }, 87 { PJMEDIA_EMISSINGRTPMAP, "Missing rtpmap in media description" }, 79 88 }; 80 89 -
pjproject/trunk/pjmedia/src/pjmedia/g711.c
r121 r159 21 21 */ 22 22 #include <pjmedia/codec.h> 23 #include <pjmedia/errno.h> 23 24 #include <pj/pool.h> 24 25 #include <pj/string.h> … … 30 31 31 32 /* These are the only public functions exported to applications */ 32 PJ_DECL(pj_status_t) g711_init_factory (pj _codec_factory *factory, pj_pool_t *pool);33 PJ_DECL(pj_status_t) g711_deinit_factory (pj _codec_factory *factory);33 PJ_DECL(pj_status_t) g711_init_factory (pjmedia_codec_factory *factory, pj_pool_t *pool); 34 PJ_DECL(pj_status_t) g711_deinit_factory (pjmedia_codec_factory *factory); 34 35 35 36 /* Algorithm prototypes. */ … … 40 41 41 42 /* Prototypes for G711 factory */ 42 static pj_status_t g711_match_id( pj_codec_factory *factory, const pj_codec_id*id );43 static pj_status_t g711_default_attr( pj_codec_factory *factory, const pj_codec_id *id, pj_codec_attr*attr );44 static unsigned g711_enum_codecs (pj_codec_factory *factory, unsigned count, pj_codec_idcodecs[]);45 static pj_ codec* g711_alloc_codec( pj_codec_factory *factory, const pj_codec_id *id);46 static void g711_dealloc_codec( pj_codec_factory *factory, pj_codec *codec );43 static pj_status_t g711_match_id( pjmedia_codec_factory *factory, const pjmedia_codec_info *id ); 44 static pj_status_t g711_default_attr( pjmedia_codec_factory *factory, const pjmedia_codec_info *id, pjmedia_codec_param *attr ); 45 static pj_status_t g711_enum_codecs (pjmedia_codec_factory *factory, unsigned *count, pjmedia_codec_info codecs[]); 46 static pj_status_t g711_alloc_codec( pjmedia_codec_factory *factory, const pjmedia_codec_info *id, pjmedia_codec **p_codec); 47 static pj_status_t g711_dealloc_codec( pjmedia_codec_factory *factory, pjmedia_codec *codec ); 47 48 48 49 /* Prototypes for G711 implementation. */ 49 static pj_status_t g711_codec_default_attr (pj _codec *codec, pj_codec_attr*attr);50 static pj_status_t g711_init( pj _codec *codec, pj_pool_t *pool );51 static pj_status_t g711_open( pj _codec *codec, pj_codec_attr*attr );52 static pj_status_t g711_close( pj _codec *codec );53 static pj_status_t g711_encode( pj _codec *codec, const struct pj_audio_frame *input,54 unsigned output_buf_len, struct pj _audio_frame *output);55 static pj_status_t g711_decode( pj _codec *codec, const struct pj_audio_frame *input,56 unsigned output_buf_len, struct pj _audio_frame *output);50 static pj_status_t g711_codec_default_attr (pjmedia_codec *codec, pjmedia_codec_param *attr); 51 static pj_status_t g711_init( pjmedia_codec *codec, pj_pool_t *pool ); 52 static pj_status_t g711_open( pjmedia_codec *codec, pjmedia_codec_param *attr ); 53 static pj_status_t g711_close( pjmedia_codec *codec ); 54 static pj_status_t g711_encode( pjmedia_codec *codec, const struct pjmedia_frame *input, 55 unsigned output_buf_len, struct pjmedia_frame *output); 56 static pj_status_t g711_decode( pjmedia_codec *codec, const struct pjmedia_frame *input, 57 unsigned output_buf_len, struct pjmedia_frame *output); 57 58 58 59 /* Definition for G711 codec operations. */ 59 static pj _codec_op g711_op =60 static pjmedia_codec_op g711_op = 60 61 { 61 62 &g711_codec_default_attr , … … 68 69 69 70 /* Definition for G711 codec factory operations. */ 70 static pj _codec_factory_op g711_factory_op =71 static pjmedia_codec_factory_op g711_factory_op = 71 72 { 72 73 &g711_match_id, … … 81 82 { 82 83 pj_pool_t *pool; 83 pj _codec codec_list;84 pjmedia_codec codec_list; 84 85 }; 85 86 … … 91 92 92 93 93 PJ_DEF(pj_status_t) g711_init_factory (pj _codec_factory *factory, pj_pool_t *pool)94 PJ_DEF(pj_status_t) g711_init_factory (pjmedia_codec_factory *factory, pj_pool_t *pool) 94 95 { 95 96 struct g711_factory_private *priv; 96 //enum { CODEC_MEM_SIZE = sizeof(pj _codec) + sizeof(struct g711_private) + 4 };97 //enum { CODEC_MEM_SIZE = sizeof(pjmedia_codec) + sizeof(struct g711_private) + 4 }; 97 98 98 99 /* Create pool. */ … … 118 119 } 119 120 120 PJ_DEF(pj_status_t) g711_deinit_factory (pj _codec_factory *factory)121 PJ_DEF(pj_status_t) g711_deinit_factory (pjmedia_codec_factory *factory) 121 122 { 122 123 struct g711_factory_private *priv = factory->factory_data; … … 128 129 } 129 130 130 static pj_status_t g711_match_id( pj _codec_factory *factory, const pj_codec_id*id )131 static pj_status_t g711_match_id( pjmedia_codec_factory *factory, const pjmedia_codec_info *id ) 131 132 { 132 133 PJ_UNUSED_ARG(factory); 133 134 134 135 /* It's sufficient to check payload type only. */ 135 return (id->pt==PJ _RTP_PT_PCMU || id->pt==PJ_RTP_PT_PCMA) ? 0 : -1;136 } 137 138 static pj_status_t g711_default_attr (pj _codec_factory *factory,139 const pj _codec_id*id,140 pj _codec_attr*attr )136 return (id->pt==PJMEDIA_RTP_PT_PCMU || id->pt==PJMEDIA_RTP_PT_PCMA) ? 0 : -1; 137 } 138 139 static pj_status_t g711_default_attr (pjmedia_codec_factory *factory, 140 const pjmedia_codec_info *id, 141 pjmedia_codec_param *attr ) 141 142 { 142 143 PJ_UNUSED_ARG(factory); 143 144 144 memset(attr, 0, sizeof(pj _codec_attr));145 memset(attr, 0, sizeof(pjmedia_codec_param)); 145 146 attr->sample_rate = 8000; 146 147 attr->avg_bps = G711_BPS; … … 154 155 } 155 156 156 static unsigned g711_enum_codecs (pj_codec_factory *factory, 157 unsigned count, pj_codec_id codecs[]) 157 static pj_status_t g711_enum_codecs(pjmedia_codec_factory *factory, 158 unsigned *count, 159 pjmedia_codec_info codecs[]) 158 160 { 159 161 PJ_UNUSED_ARG(factory); 160 162 161 if ( count > 0) {162 codecs[0].type = PJ _MEDIA_TYPE_AUDIO;163 codecs[0].pt = PJ _RTP_PT_PCMU;163 if (*count > 0) { 164 codecs[0].type = PJMEDIA_TYPE_AUDIO; 165 codecs[0].pt = PJMEDIA_RTP_PT_PCMU; 164 166 codecs[0].encoding_name = pj_str("PCMU"); 165 167 codecs[0].sample_rate = 8000; 166 168 } 167 if ( count > 1) {168 codecs[1].type = PJ _MEDIA_TYPE_AUDIO;169 codecs[1].pt = PJ _RTP_PT_PCMA;169 if (*count > 1) { 170 codecs[1].type = PJMEDIA_TYPE_AUDIO; 171 codecs[1].pt = PJMEDIA_RTP_PT_PCMA; 170 172 codecs[1].encoding_name = pj_str("PCMA"); 171 173 codecs[1].sample_rate = 8000; 172 174 } 173 175 174 return 2; 175 } 176 177 static pj_codec *g711_alloc_codec( pj_codec_factory *factory, const pj_codec_id *id) 176 if (*count > 0) *count=1; 177 if (*count > 1) *count=2; 178 179 return PJ_SUCCESS; 180 } 181 182 static pj_status_t g711_alloc_codec( pjmedia_codec_factory *factory, 183 const pjmedia_codec_info *id, 184 pjmedia_codec **p_codec) 178 185 { 179 186 struct g711_factory_private *priv = factory->factory_data; 180 pj _codec *codec = NULL;187 pjmedia_codec *codec = NULL; 181 188 182 189 /* Allocate new codec if no more is available */ … … 184 191 struct g711_private *codec_priv; 185 192 186 codec = pj_pool_alloc(priv->pool, sizeof(pj _codec));193 codec = pj_pool_alloc(priv->pool, sizeof(pjmedia_codec)); 187 194 codec_priv = pj_pool_alloc(priv->pool, sizeof(struct g711_private)); 188 195 if (!codec || !codec_priv) 189 return NULL;196 return PJ_ENOMEM; 190 197 191 198 codec_priv->pt = id->pt; … … 202 209 codec->next = codec->prev = NULL; 203 210 204 return codec; 205 } 206 207 static void g711_dealloc_codec( pj_codec_factory *factory, pj_codec *codec ) 211 *p_codec = codec; 212 return PJ_SUCCESS; 213 } 214 215 static pj_status_t g711_dealloc_codec( pjmedia_codec_factory *factory, pjmedia_codec *codec ) 208 216 { 209 217 struct g711_factory_private *priv = factory->factory_data; … … 212 220 pj_assert (codec->next==NULL && codec->prev==NULL); 213 221 if (codec->next!=NULL || codec->prev!=NULL) { 214 return ;222 return PJ_EINVALIDOP; 215 223 } 216 224 217 225 /* Insert at the back of the list */ 218 226 pj_list_insert_before(&priv->codec_list, codec); 219 } 220 221 static pj_status_t g711_codec_default_attr (pj_codec *codec, pj_codec_attr *attr) 227 228 return PJ_SUCCESS; 229 } 230 231 static pj_status_t g711_codec_default_attr (pjmedia_codec *codec, pjmedia_codec_param *attr) 222 232 { 223 233 struct g711_private *priv = codec->codec_data; 224 pj _codec_idid;234 pjmedia_codec_info id; 225 235 226 236 id.pt = priv->pt; … … 228 238 } 229 239 230 static pj_status_t g711_init( pj _codec *codec, pj_pool_t *pool )240 static pj_status_t g711_init( pjmedia_codec *codec, pj_pool_t *pool ) 231 241 { 232 242 /* There's nothing to do here really */ … … 237 247 } 238 248 239 static pj_status_t g711_open( pj _codec *codec, pj_codec_attr*attr )249 static pj_status_t g711_open( pjmedia_codec *codec, pjmedia_codec_param *attr ) 240 250 { 241 251 struct g711_private *priv = codec->codec_data; … … 244 254 } 245 255 246 static pj_status_t g711_close( pj _codec *codec )256 static pj_status_t g711_close( pjmedia_codec *codec ) 247 257 { 248 258 PJ_UNUSED_ARG(codec); … … 251 261 } 252 262 253 static pj_status_t g711_encode( pj _codec *codec, const struct pj_audio_frame *input,254 unsigned output_buf_len, struct pj _audio_frame *output)263 static pj_status_t g711_encode( pjmedia_codec *codec, const struct pjmedia_frame *input, 264 unsigned output_buf_len, struct pjmedia_frame *output) 255 265 { 256 266 pj_int16_t *samples = (pj_int16_t*) input->buf; … … 262 272 263 273 /* Encode */ 264 if (priv->pt == PJ _RTP_PT_PCMA) {274 if (priv->pt == PJMEDIA_RTP_PT_PCMA) { 265 275 unsigned i; 266 276 pj_uint8_t *dst = output->buf; … … 269 279 *dst = linear2alaw(samples[i]); 270 280 } 271 } else if (priv->pt == PJ _RTP_PT_PCMU) {281 } else if (priv->pt == PJMEDIA_RTP_PT_PCMU) { 272 282 unsigned i; 273 283 pj_uint8_t *dst = output->buf; … … 281 291 } 282 292 283 output->type = PJ _AUDIO_FRAME_AUDIO;293 output->type = PJMEDIA_FRAME_TYPE_AUDIO; 284 294 output->size = input->size / 2; 285 295 … … 287 297 } 288 298 289 static pj_status_t g711_decode( pj _codec *codec, const struct pj_audio_frame *input,290 unsigned output_buf_len, struct pj _audio_frame *output)299 static pj_status_t g711_decode( pjmedia_codec *codec, const struct pjmedia_frame *input, 300 unsigned output_buf_len, struct pjmedia_frame *output) 291 301 { 292 302 struct g711_private *priv = codec->codec_data; … … 297 307 298 308 /* Decode */ 299 if (priv->pt == PJ _RTP_PT_PCMA) {309 if (priv->pt == PJMEDIA_RTP_PT_PCMA) { 300 310 unsigned i; 301 311 pj_uint8_t *src = input->buf; … … 305 315 *dst++ = (pj_uint16_t) alaw2linear(*src++); 306 316 } 307 } else if (priv->pt == PJ _RTP_PT_PCMU) {317 } else if (priv->pt == PJMEDIA_RTP_PT_PCMU) { 308 318 unsigned i; 309 319 pj_uint8_t *src = input->buf; … … 318 328 } 319 329 320 output->type = PJ _AUDIO_FRAME_AUDIO;330 output->type = PJMEDIA_FRAME_TYPE_AUDIO; 321 331 output->size = input->size * 2; 322 332 -
pjproject/trunk/pjmedia/src/pjmedia/rtcp.c
r121 r159 93 93 /* Update sequence numbers (received, lost, etc). */ 94 94 status = pj_rtp_seq_update(&s->seq_ctrl, seq); 95 if (status == PJ _RTP_ERR_SESSION_RESTARTED) {95 if (status == PJMEDIA_RTP_ERR_SESSION_RESTARTED) { 96 96 rtcp_init_seq(s, seq); 97 97 status = 0; -
pjproject/trunk/pjmedia/src/pjmedia/rtp.c
r121 r159 44 44 if (sizeof(struct pj_rtp_hdr) != 12) { 45 45 pj_assert(!"Wrong RTP header packing!"); 46 return PJ _RTP_ERR_RTP_PACKING;46 return PJMEDIA_RTP_ERR_RTP_PACKING; 47 47 } 48 48 … … 129 129 if ((*hdr)->v != RTP_VERSION) { 130 130 PJ_LOG(4, (THIS_FILE, " invalid RTP version!")); 131 return PJ _RTP_ERR_INVALID_VERSION;131 return PJMEDIA_RTP_ERR_INVALID_VERSION; 132 132 } 133 133 … … 143 143 /* Check that offset is less than packet size */ 144 144 if (offset >= pkt_len) 145 return PJ _RTP_ERR_INVALID_PACKET;145 return PJMEDIA_RTP_ERR_INVALID_PACKET; 146 146 147 147 /* Find and set payload. */ … … 163 163 PJ_LOG(4, (THIS_FILE, "pj_rtp_session_update: ses=%p, invalid ssrc 0x%p (!=0x%p)", 164 164 ses, pj_ntohl(hdr->ssrc), ses->peer_ssrc)); 165 return PJ _RTP_ERR_INVALID_SSRC;165 return PJMEDIA_RTP_ERR_INVALID_SSRC; 166 166 } 167 167 */ … … 171 171 PJ_LOG(4, (THIS_FILE, "pj_rtp_session_update: ses=%p, invalid payload type %d (!=%d)", 172 172 ses, hdr->pt, ses->out_pt)); 173 return PJ _RTP_ERR_INVALID_PT;173 return PJMEDIA_RTP_ERR_INVALID_PT; 174 174 } 175 175 … … 180 180 /* Check sequence number to see if remote session has been restarted. */ 181 181 status = pj_rtp_seq_update( &ses->seq_ctrl, pj_ntohs(hdr->seq)); 182 if (status == PJ _RTP_ERR_SESSION_RESTARTED) {182 if (status == PJMEDIA_RTP_ERR_SESSION_RESTARTED) { 183 183 pj_rtp_seq_restart( &ses->seq_ctrl, pj_ntohs(hdr->seq)); 184 184 ++ses->received; 185 } else if (status == 0 || status == PJ _RTP_ERR_SESSION_PROBATION) {185 } else if (status == 0 || status == PJMEDIA_RTP_ERR_SESSION_PROBATION) { 186 186 ++ses->received; 187 187 } … … 224 224 sctrl->max_seq = seq; 225 225 if (sctrl->probation == 0) { 226 return PJ _RTP_ERR_SESSION_RESTARTED;226 return PJMEDIA_RTP_ERR_SESSION_RESTARTED; 227 227 } 228 228 } else { … … 230 230 sctrl->max_seq = seq; 231 231 } 232 return PJ _RTP_ERR_SESSION_PROBATION;232 return PJMEDIA_RTP_ERR_SESSION_PROBATION; 233 233 234 234 } else if (udelta < MAX_DROPOUT) { … … 248 248 * (i.e., pretend this was the first packet). 249 249 */ 250 return PJ _RTP_ERR_SESSION_RESTARTED;250 return PJMEDIA_RTP_ERR_SESSION_RESTARTED; 251 251 } 252 252 else { 253 253 sctrl->bad_seq = (seq + 1) & (RTP_SEQ_MOD-1); 254 return PJ _RTP_ERR_BAD_SEQUENCE;254 return PJMEDIA_RTP_ERR_BAD_SEQUENCE; 255 255 } 256 256 } else { -
pjproject/trunk/pjmedia/src/pjmedia/session.c
r121 r159 18 18 */ 19 19 #include <pjmedia/session.h> 20 #include <pjmedia/errno.h> 20 21 #include <pj/log.h> 21 22 #include <pj/os.h> … … 23 24 #include <pj/string.h> 24 25 #include <pj/assert.h> 25 26 27 typedef struct pj_media_stream_desc 28 { 29 pj_media_stream_info info; 30 pj_media_stream_t *enc_stream, *dec_stream; 31 } pj_media_stream_desc; 32 33 struct pj_media_session_t 26 #include <pj/ctype.h> 27 28 29 struct pjmedia_session 34 30 { 35 31 pj_pool_t *pool; 36 pj _med_mgr_t *mediamgr;32 pjmedia_endpt *endpt; 37 33 unsigned stream_cnt; 38 pj_media_stream_desc *stream_desc[PJSDP_MAX_MEDIA]; 34 pjmedia_stream_info stream_info[PJSDP_MAX_MEDIA]; 35 pjmedia_stream *stream[PJSDP_MAX_MEDIA]; 39 36 }; 40 37 41 38 #define THIS_FILE "session.c" 42 39 43 #define PJ _MEDIA_SESSION_SIZE (48*1024)44 #define PJ _MEDIA_SESSION_INC 102440 #define PJMEDIA_SESSION_SIZE (48*1024) 41 #define PJMEDIA_SESSION_INC 1024 45 42 46 43 static const pj_str_t ID_AUDIO = { "audio", 5}; … … 50 47 static const pj_str_t ID_RTP_AVP = { "RTP/AVP", 7 }; 51 48 static const pj_str_t ID_SDP_NAME = { "pjmedia", 7 }; 52 53 static void session_init (pj_media_session_t *ses) 54 { 55 pj_memset (ses, 0, sizeof(pj_media_session_t)); 56 } 57 58 59 /** 60 * Create new session offering. 61 */ 62 PJ_DEF(pj_media_session_t*) 63 pj_media_session_create (pj_med_mgr_t *mgr, const pj_media_sock_info *sock_info) 64 { 65 pj_pool_factory *pf; 49 static const pj_str_t ID_RTPMAP = { "rtpmap", 6 }; 50 51 static const pj_str_t STR_INACTIVE = { "inactive", 8 }; 52 static const pj_str_t STR_SENDRECV = { "sendrecv", 8 }; 53 static const pj_str_t STR_SENDONLY = { "sendonly", 8 }; 54 static const pj_str_t STR_RECVONLY = { "recvonly", 8 }; 55 56 57 /* 58 * Create stream info from SDP media line. 59 */ 60 static pj_status_t create_stream_info_from_sdp(pj_pool_t *pool, 61 pjmedia_stream_info *si, 62 const pjmedia_sdp_conn *local_conn, 63 const pjmedia_sdp_conn *rem_conn, 64 const pjmedia_sdp_media *local_m, 65 const pjmedia_sdp_media *rem_m) 66 { 67 const pjmedia_sdp_attr *attr; 68 pjmedia_sdp_rtpmap *rtpmap; 69 pj_status_t status; 70 71 72 /* Validate arguments: */ 73 74 PJ_ASSERT_RETURN(pool && si && local_conn && rem_conn && 75 local_m && rem_m, PJ_EINVAL); 76 77 /* Reset: */ 78 79 pj_memset(si, 0, sizeof(*si)); 80 81 /* Media type: */ 82 83 if (pj_stricmp(&local_m->desc.media, &ID_AUDIO) == 0) { 84 85 si->type = PJMEDIA_TYPE_AUDIO; 86 87 } else if (pj_stricmp(&local_m->desc.media, &ID_VIDEO) == 0) { 88 89 si->type = PJMEDIA_TYPE_VIDEO; 90 91 } else { 92 93 si->type = PJMEDIA_TYPE_UNKNOWN; 94 95 } 96 97 /* Media direction: */ 98 99 if (local_m->desc.port == 0 || 100 pj_inet_addr(&local_conn->addr).s_addr==0 || 101 pj_inet_addr(&rem_conn->addr).s_addr==0 || 102 pjmedia_sdp_media_find_attr(local_m, &STR_INACTIVE, NULL)!=NULL) 103 { 104 /* Inactive stream. */ 105 106 si->dir = PJMEDIA_DIR_NONE; 107 108 } else if (pjmedia_sdp_media_find_attr(local_m, &STR_SENDONLY, NULL)!=NULL) { 109 110 /* Send only stream. */ 111 112 si->dir = PJMEDIA_DIR_ENCODING; 113 114 } else if (pjmedia_sdp_media_find_attr(local_m, &STR_RECVONLY, NULL)!=NULL) { 115 116 /* Recv only stream. */ 117 118 si->dir = PJMEDIA_DIR_DECODING; 119 120 } else { 121 122 /* Send and receive stream. */ 123 124 si->dir = PJMEDIA_DIR_ENCODING_DECODING; 125 126 } 127 128 129 /* Set remote address: */ 130 131 si->rem_addr.sin_family = PJ_AF_INET; 132 si->rem_addr.sin_port = pj_htons(rem_m->desc.port); 133 if (pj_inet_aton(&rem_conn->addr, &si->rem_addr.sin_addr) == 0) { 134 135 /* Invalid IP address. */ 136 return PJMEDIA_EINVALIDIP; 137 } 138 139 /* For this version of PJMEDIA, send and receive media must use 140 * the same codec. 141 */ 142 if (pj_strcmp(&local_m->desc.fmt[0], &rem_m->desc.fmt[0]) != 0) 143 return PJMEDIA_EASYMCODEC; 144 145 146 /* And codec must be numeric! */ 147 if (!pj_isdigit(*local_m->desc.fmt[0].ptr)) 148 return PJMEDIA_EINVALIDPT; 149 150 /* Find rtpmap for the first codec. 151 * For this version of PJMEDIA, we do not support static payload 152 * type without rtpmap. 153 */ 154 attr = pjmedia_sdp_media_find_attr(local_m, &ID_RTPMAP, NULL); 155 if (attr == NULL) 156 return PJMEDIA_EMISSINGRTPMAP; 157 158 status = pjmedia_sdp_attr_to_rtpmap(pool, attr, &rtpmap); 159 if (status != PJ_SUCCESS) 160 return status; 161 162 /* Build codec format info: */ 163 164 si->fmt.type = si->type; 165 si->fmt.pt = pj_strtoul(&local_m->desc.fmt[0]); 166 pj_strdup(pool, &si->fmt.encoding_name, &rtpmap->enc_name); 167 si->fmt.sample_rate = rtpmap->clock_rate; 168 169 /* Leave SSRC to zero. */ 170 171 /* Leave jitter buffer parameter. */ 172 173 return PJ_SUCCESS; 174 } 175 176 177 /** 178 * Create new session. 179 */ 180 PJ_DEF(pj_status_t) pjmedia_session_create( pjmedia_endpt *endpt, 181 unsigned stream_cnt, 182 const pjmedia_sock_info skinfo[], 183 const pjmedia_sdp_session *local_sdp, 184 const pjmedia_sdp_session *rem_sdp, 185 pjmedia_session **p_session ) 186 { 66 187 pj_pool_t *pool; 67 pj_media_session_t *session; 68 pj_media_stream_desc *sd; 69 unsigned i, codec_cnt; 70 pj_codec_mgr *cm; 71 const pj_codec_id *codecs[PJSDP_MAX_FMT]; 72 73 pf = pj_med_mgr_get_pool_factory(mgr); 74 75 pool = pj_pool_create( pf, "session", PJ_MEDIA_SESSION_SIZE, PJ_MEDIA_SESSION_INC, NULL); 76 if (!pool) 77 return NULL; 78 79 session = pj_pool_alloc(pool, sizeof(pj_media_session_t)); 80 if (!session) 81 return NULL; 82 83 session_init (session); 84 188 pjmedia_session *session; 189 int i; /* Must be signed */ 190 pj_status_t status; 191 192 /* Verify arguments. */ 193 PJ_ASSERT_RETURN(endpt && stream_cnt && skinfo && 194 local_sdp && rem_sdp && p_session, PJ_EINVAL); 195 196 /* Create pool for the session. */ 197 pool = pjmedia_endpt_create_pool( endpt, "session", 198 PJMEDIA_SESSION_SIZE, 199 PJMEDIA_SESSION_INC); 200 PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM); 201 202 session = pj_pool_zalloc(pool, sizeof(pjmedia_session)); 85 203 session->pool = pool; 86 session->mediamgr = mgr; 87 88 /* Create first stream */ 89 sd = pj_pool_calloc (pool, 1, sizeof(pj_media_stream_desc)); 90 if (!sd) 91 return NULL; 92 93 sd->info.type = ID_AUDIO; 94 sd->info.dir = PJ_MEDIA_DIR_ENCODING_DECODING; 95 sd->info.transport = ID_RTP_AVP; 96 pj_memcpy(&sd->info.sock_info, sock_info, sizeof(*sock_info)); 97 98 /* Enum audio codecs. */ 99 sd->info.fmt_cnt = 0; 100 cm = pj_med_mgr_get_codec_mgr (mgr); 101 codec_cnt = pj_codec_mgr_enum_codecs(cm, PJSDP_MAX_FMT, codecs); 102 if (codec_cnt > PJSDP_MAX_FMT) codec_cnt = PJSDP_MAX_FMT; 103 for (i=0; i<codec_cnt; ++i) { 104 if (codecs[i]->type != PJ_MEDIA_TYPE_AUDIO) 105 continue; 106 107 sd->info.fmt[sd->info.fmt_cnt].pt = codecs[i]->pt; 108 sd->info.fmt[sd->info.fmt_cnt].sample_rate = codecs[i]->sample_rate; 109 pj_strdup (pool, &sd->info.fmt[sd->info.fmt_cnt].encoding_name, &codecs[i]->encoding_name); 110 ++sd->info.fmt_cnt; 111 } 112 113 session->stream_desc[session->stream_cnt++] = sd; 114 115 return session; 116 } 117 118 static int sdp_check (const pjsdp_session_desc *sdp) 119 { 120 int has_conn = 0; 204 session->endpt = endpt; 205 session->stream_cnt = stream_cnt; 206 207 /* Stream count is the lower number of stream_cnt or SDP m= lines count */ 208 if (stream_cnt < local_sdp->media_count) 209 stream_cnt = local_sdp->media_count; 210 211 /* 212 * Create streams: 213 */ 214 for (i=0; i<(int)stream_cnt; ++i) { 215 216 pjmedia_stream_info *si = &session->stream_info[i]; 217 const pjmedia_sdp_media *local_m = local_sdp->media[i]; 218 const pjmedia_sdp_media *rem_m = rem_sdp->media[i]; 219 pjmedia_sdp_conn *local_conn, *rem_conn; 220 221 /* Build stream info based on media line in local SDP */ 222 local_conn = local_m->conn ? local_m->conn : local_sdp->conn; 223 rem_conn = rem_m->conn ? rem_m->conn : rem_sdp->conn; 224 225 status = create_stream_info_from_sdp(session->pool, si, 226 local_conn, rem_conn, 227 local_m, rem_m); 228 if (status != PJ_SUCCESS) 229 return status; 230 231 /* Assign sockinfo */ 232 si->sock_info = skinfo[i]; 233 } 234 235 /* 236 * Now create the stream! 237 */ 238 for (i=0; i<(int)stream_cnt; ++i) { 239 240 status = pjmedia_stream_create(endpt, session->pool, 241 &session->stream_info[i], 242 &session->stream[i]); 243 if (status != PJ_SUCCESS) { 244 245 for ( --i; i>=0; ++i) { 246 pjmedia_stream_destroy(session->stream[i]); 247 } 248 249 pj_pool_release(session->pool); 250 return status; 251 } 252 } 253 254 255 /* Done. */ 256 257 *p_session = session; 258 return PJ_SUCCESS; 259 } 260 261 262 /** 263 * Destroy media session. 264 */ 265 PJ_DEF(pj_status_t) pjmedia_session_destroy (pjmedia_session *session) 266 { 121 267 unsigned i; 122 268 123 if (sdp->conn) 124 has_conn = 1; 125 126 if (sdp->media_count == 0) { 127 PJ_LOG(4,(THIS_FILE, "SDP check failed: no media stream definition")); 128 return -1; 129 } 130 131 for (i=0; i<sdp->media_count; ++i) { 132 pjsdp_media_desc *m = sdp->media[i]; 133 134 if (!m) { 135 pj_assert(0); 136 return -1; 137 } 138 139 if (m->desc.fmt_count == 0) { 140 PJ_LOG(4,(THIS_FILE, "SDP check failed: no format listed in media stream")); 141 return -1; 142 } 143 144 if (!has_conn && m->conn == NULL) { 145 PJ_LOG(4,(THIS_FILE, "SDP check failed: no connection information for media")); 146 return -1; 147 } 148 } 149 150 return 0; 151 } 152 153 /* 154 * Create local stream definition that matches SDP received from peer. 155 */ 156 static pj_media_stream_desc* 157 create_stream_from_sdp (pj_pool_t *pool, pj_med_mgr_t *mgr, const pjsdp_conn_info *conn, 158 const pjsdp_media_desc *m, const pj_media_sock_info *sock_info) 159 { 160 pj_media_stream_desc *sd; 161 162 sd = pj_pool_calloc (pool, 1, sizeof(pj_media_stream_desc)); 163 if (!sd) { 164 PJ_LOG(2,(THIS_FILE, "No memory to allocate stream descriptor")); 165 return NULL; 166 } 167 168 if (pj_stricmp(&conn->net_type, &ID_IN)==0 && 169 pj_stricmp(&conn->addr_type, &ID_IP4)==0 && 170 pj_stricmp(&m->desc.media, &ID_AUDIO)==0 && 171 pj_stricmp(&m->desc.transport, &ID_RTP_AVP) == 0) 172 { 173 /* 174 * Got audio stream. 175 */ 176 unsigned i, codec_cnt; 177 pj_codec_mgr *cm; 178 const pj_codec_id *codecs[PJSDP_MAX_FMT]; 179 180 sd->info.type = ID_AUDIO; 181 sd->info.transport = ID_RTP_AVP; 182 pj_memcpy(&sd->info.sock_info, sock_info, sizeof(*sock_info)); 183 sd->info.rem_port = m->desc.port; 184 pj_strdup (pool, &sd->info.rem_addr, &conn->addr); 185 186 /* Enum audio codecs. */ 187 sd->info.fmt_cnt = 0; 188 cm = pj_med_mgr_get_codec_mgr (mgr); 189 codec_cnt = pj_codec_mgr_enum_codecs (cm, PJSDP_MAX_FMT, codecs); 190 if (codec_cnt > PJSDP_MAX_FMT) codec_cnt = PJSDP_MAX_FMT; 191 192 /* Find just one codec which we can support. */ 193 for (i=0; i<m->desc.fmt_count && sd->info.fmt_cnt == 0; ++i) { 194 unsigned j, fmt_i; 195 196 /* For static payload, just match payload type. */ 197 /* Else match clock rate and encoding name. */ 198 fmt_i = pj_strtoul(&m->desc.fmt[i]); 199 if (fmt_i < PJ_RTP_PT_DYNAMIC) { 200 for (j=0; j<codec_cnt; ++j) { 201 if (codecs[j]->pt == fmt_i) { 202 sd->info.fmt_cnt = 1; 203 sd->info.fmt[0].type = PJ_MEDIA_TYPE_AUDIO; 204 sd->info.fmt[0].pt = codecs[j]->pt; 205 sd->info.fmt[0].sample_rate = codecs[j]->sample_rate; 206 pj_strdup (pool, &sd->info.fmt[0].encoding_name, &codecs[j]->encoding_name); 207 break; 208 } 209 } 210 } else { 211 212 /* Find the rtpmap for the payload type. */ 213 const pjsdp_rtpmap_attr *rtpmap = pjsdp_media_desc_find_rtpmap (m, fmt_i); 214 215 /* Don't accept the media if no rtpmap for dynamic PT. */ 216 if (rtpmap == NULL) { 217 PJ_LOG(4,(THIS_FILE, "SDP: No rtpmap found for payload id %d", m->desc.fmt[i])); 218 continue; 219 } 220 221 /* Check whether we can take this codec. */ 222 for (j=0; j<codec_cnt; ++j) { 223 if (rtpmap->clock_rate == codecs[j]->sample_rate && 224 pj_stricmp(&rtpmap->encoding_name, &codecs[j]->encoding_name) == 0) 225 { 226 sd->info.fmt_cnt = 1; 227 sd->info.fmt[0].type = PJ_MEDIA_TYPE_AUDIO; 228 sd->info.fmt[0].pt = codecs[j]->pt; 229 sd->info.fmt[0].sample_rate = codecs[j]->sample_rate; 230 sd->info.fmt[0].encoding_name = codecs[j]->encoding_name; 231 break; 232 } 233 } 234 } 235 } 236 237 /* Match codec and direction. */ 238 if (sd->info.fmt_cnt == 0 || m->desc.port == 0 || 239 pjsdp_media_desc_has_attr(m, PJSDP_ATTR_INACTIVE)) 240 { 241 sd->info.dir = PJ_MEDIA_DIR_NONE; 242 } 243 else if (pjsdp_media_desc_has_attr(m, PJSDP_ATTR_RECV_ONLY)) { 244 sd->info.dir = PJ_MEDIA_DIR_ENCODING; 245 } 246 else if (pjsdp_media_desc_has_attr(m, PJSDP_ATTR_SEND_ONLY)) { 247 sd->info.dir = PJ_MEDIA_DIR_DECODING; 248 } 249 else { 250 sd->info.dir = PJ_MEDIA_DIR_ENCODING_DECODING; 251 } 252 253 } else { 254 /* Unsupported media stream. */ 255 unsigned fmt_num; 256 const pjsdp_rtpmap_attr *rtpmap = NULL; 257 258 pj_strdup(pool, &sd->info.type, &m->desc.media); 259 pj_strdup(pool, &sd->info.transport, &m->desc.transport); 260 pj_memset(&sd->info.sock_info, 0, sizeof(*sock_info)); 261 pj_strdup (pool, &sd->info.rem_addr, &conn->addr); 262 sd->info.rem_port = m->desc.port; 263 264 /* Just put one format and rtpmap, so that we don't have to make 265 * special exception when we convert this stream to SDP. 266 */ 267 268 /* Find the rtpmap for the payload type. */ 269 fmt_num = pj_strtoul(&m->desc.fmt[0]); 270 rtpmap = pjsdp_media_desc_find_rtpmap (m, fmt_num); 271 272 sd->info.fmt_cnt = 1; 273 if (pj_stricmp(&m->desc.media, &ID_VIDEO)==0) { 274 sd->info.fmt[0].type = PJ_MEDIA_TYPE_VIDEO; 275 sd->info.fmt[0].pt = fmt_num; 276 if (rtpmap) { 277 pj_strdup (pool, &sd->info.fmt[0].encoding_name, 278 &rtpmap->encoding_name); 279 sd->info.fmt[0].sample_rate = rtpmap->clock_rate; 280 } 281 } else { 282 sd->info.fmt[0].type = PJ_MEDIA_TYPE_UNKNOWN; 283 pj_strdup(pool, &sd->info.fmt[0].encoding_name, &m->desc.fmt[0]); 284 } 269 PJ_ASSERT_RETURN(session, PJ_EINVAL); 270 271 for (i=0; i<session->stream_cnt; ++i) { 285 272 286 sd->info.dir = PJ_MEDIA_DIR_NONE; 287 } 288 289 return sd; 290 } 291 292 /** 293 * Create new session based on peer's offering. 294 */ 295 PJ_DEF(pj_media_session_t*) 296 pj_media_session_create_from_sdp (pj_med_mgr_t *mgr, const pjsdp_session_desc *sdp, 297 const pj_media_sock_info *sock_info) 298 { 299 pj_pool_factory *pf; 300 pj_pool_t *pool; 301 pj_media_session_t *session; 273 pjmedia_stream_destroy(session->stream[i]); 274 275 } 276 277 pj_pool_release (session->pool); 278 279 return PJ_SUCCESS; 280 } 281 282 283 /** 284 * Activate all stream in media session. 285 * 286 */ 287 PJ_DEF(pj_status_t) pjmedia_session_resume(pjmedia_session *session, 288 pjmedia_dir dir) 289 { 302 290 unsigned i; 303 291 304 if (sdp_check(sdp) != 0) 305 return NULL; 306 307 pf = pj_med_mgr_get_pool_factory(mgr); 308 pool = pj_pool_create( pf, "session", PJ_MEDIA_SESSION_SIZE, PJ_MEDIA_SESSION_INC, NULL); 309 if (!pool) 310 return NULL; 311 312 session = pj_pool_alloc(pool, sizeof(pj_media_session_t)); 313 if (!session) { 314 PJ_LOG(3,(THIS_FILE, "No memory to create media session descriptor")); 315 pj_pool_release (pool); 316 return NULL; 317 } 318 319 session_init (session); 320 321 session->pool = pool; 322 session->mediamgr = mgr; 323 324 /* Enumerate each media stream and create our peer. */ 325 for (i=0; i<sdp->media_count; ++i) { 326 const pjsdp_conn_info *conn; 327 const pjsdp_media_desc *m; 328 pj_media_stream_desc *sd; 329 330 m = sdp->media[i]; 331 conn = m->conn ? m->conn : sdp->conn; 332 333 /* 334 * Bug: 335 * the sock_info below is used by more than one 'm' lines 336 */ 337 PJ_TODO(SUPPORT_MORE_THAN_ONE_SDP_M_LINES) 338 339 sd = create_stream_from_sdp (pool, mgr, conn, m, sock_info); 340 pj_assert (sd); 341 342 session->stream_desc[session->stream_cnt++] = sd; 343 } 344 345 return session; 346 } 347 348 /** 349 * Duplicate session. The new session is inactive. 350 */ 351 PJ_DEF(pj_media_session_t*) 352 pj_media_session_clone (const pj_media_session_t *rhs) 353 { 354 pj_pool_factory *pf; 355 pj_pool_t *pool; 356 pj_media_session_t *session; 292 PJ_ASSERT_RETURN(session, PJ_EINVAL); 293 294 for (i=0; i<session->stream_cnt; ++i) { 295 pjmedia_session_resume_stream(session, i, dir); 296 } 297 298 return PJ_SUCCESS; 299 } 300 301 302 /** 303 * Suspend receipt and transmission of all stream in media session. 304 * 305 */ 306 PJ_DEF(pj_status_t) pjmedia_session_pause(pjmedia_session *session, 307 pjmedia_dir dir) 308 { 357 309 unsigned i; 358 310 359 pf = pj_med_mgr_get_pool_factory(rhs->mediamgr); 360 pool = pj_pool_create( pf, "session", PJ_MEDIA_SESSION_SIZE, PJ_MEDIA_SESSION_INC, NULL); 361 if (!pool) { 362 return NULL; 363 } 364 365 session = pj_pool_alloc (pool, sizeof(*session)); 366 if (!session) { 367 PJ_LOG(3,(THIS_FILE, "No memory to create media session descriptor")); 368 pj_pool_release (pool); 369 return NULL; 370 } 371 372 session->pool = pool; 373 session->mediamgr = rhs->mediamgr; 374 session->stream_cnt = rhs->stream_cnt; 375 376 for (i=0; i<rhs->stream_cnt; ++i) { 377 pj_media_stream_desc *sd1 = pj_pool_alloc (session->pool, sizeof(pj_media_stream_desc)); 378 const pj_media_stream_desc *sd2 = rhs->stream_desc[i]; 379 380 if (!sd1) { 381 PJ_LOG(3,(THIS_FILE, "No memory to create media stream descriptor")); 382 pj_pool_release (pool); 383 return NULL; 384 } 385 386 session->stream_desc[i] = sd1; 387 sd1->enc_stream = sd1->dec_stream = NULL; 388 pj_strdup (pool, &sd1->info.type, &sd2->info.type); 389 sd1->info.dir = sd2->info.dir; 390 pj_strdup (pool, &sd1->info.transport, &sd2->info.transport); 391 pj_memcpy(&sd1->info.sock_info, &sd2->info.sock_info, sizeof(pj_media_sock_info)); 392 pj_strdup (pool, &sd1->info.rem_addr, &sd2->info.rem_addr); 393 sd1->info.rem_port = sd2->info.rem_port; 394 sd1->info.fmt_cnt = sd2->info.fmt_cnt; 395 pj_memcpy (sd1->info.fmt, sd2->info.fmt, sizeof(sd2->info.fmt)); 396 } 397 398 return session; 399 } 400 401 /** 402 * Create SDP description from the session. 403 */ 404 PJ_DEF(pjsdp_session_desc*) 405 pj_media_session_create_sdp (const pj_media_session_t *session, pj_pool_t *pool, 406 pj_bool_t only_first_fmt) 407 { 408 pjsdp_session_desc *sdp; 409 pj_time_val tv; 311 PJ_ASSERT_RETURN(session, PJ_EINVAL); 312 313 for (i=0; i<session->stream_cnt; ++i) { 314 pjmedia_session_pause_stream(session, i, dir); 315 } 316 317 return PJ_SUCCESS; 318 } 319 320 321 /** 322 * Suspend receipt and transmission of individual stream in media session. 323 */ 324 PJ_DEF(pj_status_t) pjmedia_session_pause_stream( pjmedia_session *session, 325 unsigned index, 326 pjmedia_dir dir) 327 { 328 PJ_ASSERT_RETURN(session && index < session->stream_cnt, PJ_EINVAL); 329 330 return pjmedia_stream_pause(session->stream[index], dir); 331 } 332 333 334 /** 335 * Activate individual stream in media session. 336 * 337 */ 338 PJ_DEF(pj_status_t) pjmedia_session_resume_stream( pjmedia_session *session, 339 unsigned index, 340 pjmedia_dir dir) 341 { 342 PJ_ASSERT_RETURN(session && index < session->stream_cnt, PJ_EINVAL); 343 344 return pjmedia_stream_resume(session->stream[index], dir); 345 } 346 347 /** 348 * Enumerate media stream in the session. 349 */ 350 PJ_DEF(pj_status_t) pjmedia_session_enum_streams(const pjmedia_session *session, 351 unsigned *count, 352 pjmedia_stream_info info[]) 353 { 410 354 unsigned i; 411 pj_media_sock_info *c_addr = NULL; 412 413 if (session->stream_cnt == 0) { 414 pj_assert(0); 415 return NULL; 416 } 417 418 sdp = pj_pool_calloc (pool, 1, sizeof(pjsdp_session_desc)); 419 if (!sdp) { 420 PJ_LOG(3,(THIS_FILE, "No memory to allocate SDP session descriptor")); 421 return NULL; 422 } 423 424 pj_gettimeofday(&tv); 425 426 sdp->origin.user = pj_str("-"); 427 sdp->origin.version = sdp->origin.id = tv.sec + 2208988800UL; 428 sdp->origin.net_type = ID_IN; 429 sdp->origin.addr_type = ID_IP4; 430 sdp->origin.addr = *pj_gethostname(); 431 432 sdp->name = ID_SDP_NAME; 433 434 /* If all media addresses are the same, then put the connection 435 * info in the session level, otherwise put it in media stream 436 * level. 437 */ 438 for (i=0; i<session->stream_cnt; ++i) { 439 if (c_addr == NULL) { 440 c_addr = &session->stream_desc[i]->info.sock_info; 441 } else if (c_addr->rtp_addr_name.sin_addr.s_addr != session->stream_desc[i]->info.sock_info.rtp_addr_name.sin_addr.s_addr) 442 { 443 c_addr = NULL; 444 break; 445 } 446 } 447 448 if (c_addr) { 449 /* All addresses are the same, put connection info in session level. */ 450 sdp->conn = pj_pool_alloc (pool, sizeof(pjsdp_conn_info)); 451 if (!sdp->conn) { 452 PJ_LOG(2,(THIS_FILE, "No memory to allocate SDP connection info")); 453 return NULL; 454 } 455 456 sdp->conn->net_type = ID_IN; 457 sdp->conn->addr_type = ID_IP4; 458 pj_strdup2 (pool, &sdp->conn->addr, pj_inet_ntoa(c_addr->rtp_addr_name.sin_addr)); 459 } 460 461 sdp->time.start = sdp->time.stop = 0; 462 sdp->attr_count = 0; 463 464 /* Create each media. */ 465 sdp->media_count = 0; 466 for (i=0; i<session->stream_cnt; ++i) { 467 const pj_media_stream_desc *sd = session->stream_desc[i]; 468 pjsdp_media_desc *m; 469 unsigned j; 470 unsigned fmt_cnt; 471 pjsdp_attr *attr; 472 473 m = pj_pool_calloc (pool, 1, sizeof(pjsdp_media_desc)); 474 if (!m) { 475 PJ_LOG(3,(THIS_FILE, "No memory to allocate SDP media stream descriptor")); 476 return NULL; 477 } 478 479 sdp->media[sdp->media_count++] = m; 480 481 pj_strdup (pool, &m->desc.media, &sd->info.type); 482 m->desc.port = pj_ntohs(sd->info.sock_info.rtp_addr_name.sin_port); 483 m->desc.port_count = 1; 484 pj_strdup (pool, &m->desc.transport, &sd->info.transport); 485 486 /* Add format and rtpmap for each codec. */ 487 m->desc.fmt_count = 0; 488 m->attr_count = 0; 489 fmt_cnt = sd->info.fmt_cnt; 490 if (fmt_cnt > 0 && only_first_fmt) 491 fmt_cnt = 1; 492 for (j=0; j<fmt_cnt; ++j) { 493 pjsdp_rtpmap_attr *rtpmap; 494 pj_str_t *fmt = &m->desc.fmt[m->desc.fmt_count++]; 495 496 if (sd->info.fmt[j].type==PJ_MEDIA_TYPE_UNKNOWN) { 497 pj_strdup(pool, fmt, &sd->info.fmt[j].encoding_name); 498 } else { 499 fmt->ptr = pj_pool_alloc(pool, 8); 500 fmt->slen = pj_utoa(sd->info.fmt[j].pt, fmt->ptr); 501 502 rtpmap = pj_pool_calloc(pool, 1, sizeof(pjsdp_rtpmap_attr)); 503 if (rtpmap) { 504 m->attr[m->attr_count++] = (pjsdp_attr*)rtpmap; 505 rtpmap->type = PJSDP_ATTR_RTPMAP; 506 rtpmap->payload_type = sd->info.fmt[j].pt; 507 rtpmap->clock_rate = sd->info.fmt[j].sample_rate; 508 pj_strdup (pool, &rtpmap->encoding_name, &sd->info.fmt[j].encoding_name); 509 } else { 510 PJ_LOG(3,(THIS_FILE, "No memory to allocate SDP rtpmap descriptor")); 511 } 512 } 513 } 514 515 /* If we don't have connection info in session level, create one. */ 516 if (sdp->conn == NULL) { 517 m->conn = pj_pool_alloc (pool, sizeof(pjsdp_conn_info)); 518 if (m->conn) { 519 m->conn->net_type = ID_IN; 520 m->conn->addr_type = ID_IP4; 521 pj_strdup2 (pool, &m->conn->addr, pj_inet_ntoa(sd->info.sock_info.rtp_addr_name.sin_addr)); 522 } else { 523 PJ_LOG(3,(THIS_FILE, "No memory to allocate SDP media connection info")); 524 return NULL; 525 } 526 } 527 528 /* Add additional attribute to the media stream. */ 529 attr = pj_pool_alloc(pool, sizeof(pjsdp_attr)); 530 if (!attr) { 531 PJ_LOG(3,(THIS_FILE, "No memory to allocate SDP attribute")); 532 return NULL; 533 } 534 m->attr[m->attr_count++] = attr; 535 536 switch (sd->info.dir) { 537 case PJ_MEDIA_DIR_NONE: 538 attr->type = PJSDP_ATTR_INACTIVE; 539 break; 540 case PJ_MEDIA_DIR_ENCODING: 541 attr->type = PJSDP_ATTR_SEND_ONLY; 542 break; 543 case PJ_MEDIA_DIR_DECODING: 544 attr->type = PJSDP_ATTR_RECV_ONLY; 545 break; 546 case PJ_MEDIA_DIR_ENCODING_DECODING: 547 attr->type = PJSDP_ATTR_SEND_RECV; 548 break; 549 } 550 } 551 552 return sdp; 553 } 554 555 /** 556 * Update session with SDP answer from peer. 557 */ 558 PJ_DEF(pj_status_t) 559 pj_media_session_update (pj_media_session_t *session, 560 const pjsdp_session_desc *sdp) 561 { 562 unsigned i; 563 unsigned count; 564 565 /* Check SDP */ 566 if (sdp_check (sdp) != 0) { 567 return -1; 568 } 569 570 /* If the media stream count doesn't match, only update one. */ 571 if (session->stream_cnt != sdp->media_count) { 572 PJ_LOG(3,(THIS_FILE, "pj_media_session_update : " 573 "SDP media count mismatch! (rmt=%d, lcl=%d)", 574 sdp->media_count, session->stream_cnt)); 575 count = (session->stream_cnt < sdp->media_count) ? 576 session->stream_cnt : sdp->media_count; 577 } else { 578 count = session->stream_cnt; 579 } 580 581 for (i=0; i<count; ++i) { 582 pj_media_stream_desc *sd = session->stream_desc[i]; 583 const pjsdp_media_desc *m = sdp->media[i]; 584 const pjsdp_conn_info *conn; 585 unsigned j; 586 587 /* Check that the session is not active. */ 588 pj_assert (sd->enc_stream == NULL && sd->dec_stream == NULL); 589 590 conn = m->conn ? m->conn : sdp->conn; 591 pj_assert(conn); 592 593 /* Update remote address. */ 594 sd->info.rem_port = m->desc.port; 595 pj_strdup (session->pool, &sd->info.rem_addr, &conn->addr); 596 597 /* Select one active codec according to what peer wants. */ 598 for (j=0; j<sd->info.fmt_cnt; ++j) { 599 unsigned fmt_0 = pj_strtoul(&m->desc.fmt[0]); 600 if (sd->info.fmt[j].pt == fmt_0) { 601 pj_codec_id temp; 602 603 /* Put active format to the front. */ 604 if (j == 0) 605 break; 606 607 pj_memcpy(&temp, &sd->info.fmt[0], sizeof(temp)); 608 pj_memcpy(&sd->info.fmt[0], &sd->info.fmt[j], sizeof(temp)); 609 pj_memcpy(&sd->info.fmt[j], &temp, sizeof(temp)); 610 break; 611 } 612 } 613 614 if (j == sd->info.fmt_cnt) { 615 /* Peer has answered SDP with new codec, which doesn't exist 616 * in the offer! 617 * Mute this media. 618 */ 619 PJ_LOG(3,(THIS_FILE, "Peer has answered SDP with new codec!")); 620 sd->info.dir = PJ_MEDIA_DIR_NONE; 621 continue; 622 } 623 624 /* Check direction. */ 625 if (m->desc.port == 0 || pjsdp_media_desc_has_attr(m, PJSDP_ATTR_INACTIVE)) { 626 sd->info.dir = PJ_MEDIA_DIR_NONE; 627 } 628 else if (pjsdp_media_desc_has_attr(m, PJSDP_ATTR_RECV_ONLY)) { 629 sd->info.dir = PJ_MEDIA_DIR_ENCODING; 630 } 631 else if (pjsdp_media_desc_has_attr(m, PJSDP_ATTR_SEND_ONLY)) { 632 sd->info.dir = PJ_MEDIA_DIR_DECODING; 633 } 634 else { 635 sd->info.dir = PJ_MEDIA_DIR_ENCODING_DECODING; 636 } 637 } 638 639 return 0; 640 } 641 642 /** 643 * Enumerate media streams in the session. 644 */ 645 PJ_DEF(unsigned) 646 pj_media_session_enum_streams (const pj_media_session_t *session, 647 unsigned count, const pj_media_stream_info *info[]) 648 { 649 unsigned i; 650 651 if (count > session->stream_cnt) 652 count = session->stream_cnt; 653 654 for (i=0; i<count; ++i) { 655 info[i] = &session->stream_desc[i]->info; 656 } 657 658 return session->stream_cnt; 355 356 PJ_ASSERT_RETURN(session && count && *count && info, PJ_EINVAL); 357 358 if (*count > session->stream_cnt) 359 *count = session->stream_cnt; 360 361 for (i=0; i<*count; ++i) { 362 pj_memcpy(&info[i], &session->stream[i], sizeof(pjmedia_stream_info)); 363 } 364 365 return PJ_SUCCESS; 659 366 } 660 367 … … 662 369 * Get statistics 663 370 */ 664 PJ_DEF(pj_status_t) 665 pj_media_session_get_stat (const pj_media_session_t *session, unsigned index, 666 pj_media_stream_stat *tx_stat, 667 pj_media_stream_stat *rx_stat) 668 { 669 pj_media_stream_desc *sd; 670 int stat_cnt = 0; 671 672 if (index >= session->stream_cnt) { 673 pj_assert(0); 674 return -1; 675 } 676 677 sd = session->stream_desc[index]; 678 679 if (sd->enc_stream && tx_stat) { 680 pj_media_stream_get_stat (sd->enc_stream, tx_stat); 681 ++stat_cnt; 682 } else if (tx_stat) { 683 pj_memset (tx_stat, 0, sizeof(*tx_stat)); 684 } 685 686 if (sd->dec_stream && rx_stat) { 687 pj_media_stream_get_stat (sd->dec_stream, rx_stat); 688 ++stat_cnt; 689 } else if (rx_stat) { 690 pj_memset (rx_stat, 0, sizeof(*rx_stat)); 691 } 692 693 return stat_cnt ? 0 : -1; 694 } 695 696 /** 697 * Modify stream, only when stream is inactive. 698 */ 699 PJ_DEF(pj_status_t) 700 pj_media_session_modify_stream (pj_media_session_t *session, unsigned index, 701 unsigned modify_flag, const pj_media_stream_info *info) 702 { 703 pj_media_stream_desc *sd; 704 705 if (index >= session->stream_cnt) { 706 pj_assert(0); 707 return -1; 708 } 709 710 sd = session->stream_desc[index]; 711 712 if (sd->enc_stream || sd->dec_stream) { 713 pj_assert(0); 714 return -1; 715 } 716 717 if (modify_flag & PJ_MEDIA_STREAM_MODIFY_DIR) { 718 sd->info.dir = info->dir; 719 } 720 721 return 0; 722 } 723 724 /** 725 * Activate media session. 726 */ 727 PJ_DEF(pj_status_t) 728 pj_media_session_activate (pj_media_session_t *session) 729 { 730 unsigned i; 731 pj_status_t status = 0; 732 733 for (i=0; i<session->stream_cnt; ++i) { 734 pj_status_t rc; 735 rc = pj_media_session_activate_stream (session, i); 736 if (status == 0) 737 status = rc; 738 } 739 return status; 740 } 741 742 /** 743 * Activate individual stream in media session. 744 */ 745 PJ_DEF(pj_status_t) 746 pj_media_session_activate_stream (pj_media_session_t *session, unsigned index) 747 { 748 pj_media_stream_desc *sd; 749 pj_media_stream_create_param scp; 750 pj_status_t status; 751 pj_time_val tv; 752 753 if (index < 0 || index >= session->stream_cnt) { 754 pj_assert(0); 755 return -1; 756 } 757 758 sd = session->stream_desc[index]; 759 760 if (sd->enc_stream || sd->dec_stream) { 761 /* Stream already active. */ 762 pj_assert(0); 763 return 0; 764 } 765 766 pj_gettimeofday(&tv); 767 768 /* Initialize parameter to create stream. */ 769 pj_memset (&scp, 0, sizeof(scp)); 770 scp.codec_id = &sd->info.fmt[0]; 771 scp.mediamgr = session->mediamgr; 772 scp.dir = sd->info.dir; 773 scp.rtp_sock = sd->info.sock_info.rtp_sock; 774 scp.rtcp_sock = sd->info.sock_info.rtcp_sock; 775 scp.remote_addr = pj_pool_calloc (session->pool, 1, sizeof(pj_sockaddr_in)); 776 pj_sockaddr_in_init(scp.remote_addr, &sd->info.rem_addr, sd->info.rem_port); 777 scp.ssrc = tv.sec; 778 scp.jb_min = 1; 779 scp.jb_max = 15; 780 scp.jb_maxcnt = 16; 781 782 /* Build the stream! */ 783 status = pj_media_stream_create (session->pool, &sd->enc_stream, &sd->dec_stream, &scp); 784 785 if (status==0 && sd->enc_stream) { 786 status = pj_media_stream_start (sd->enc_stream); 787 if (status != 0) 788 goto on_error; 789 } 790 if (status==0 && sd->dec_stream) { 791 status = pj_media_stream_start (sd->dec_stream); 792 if (status != 0) 793 goto on_error; 794 } 795 return status; 796 797 on_error: 798 if (sd->enc_stream) { 799 pj_media_stream_destroy (sd->enc_stream); 800 sd->enc_stream = NULL; 801 } 802 if (sd->dec_stream) { 803 pj_media_stream_destroy (sd->dec_stream); 804 sd->dec_stream = NULL; 805 } 806 return status; 807 } 808 809 /** 810 * Destroy media session. 811 */ 812 PJ_DEF(pj_status_t) 813 pj_media_session_destroy (pj_media_session_t *session) 814 { 815 unsigned i; 816 817 if (!session) 818 return -1; 819 820 for (i=0; i<session->stream_cnt; ++i) { 821 pj_media_stream_desc *sd = session->stream_desc[i]; 822 823 if (sd->enc_stream) { 824 pj_media_stream_destroy (sd->enc_stream); 825 sd->enc_stream = NULL; 826 } 827 if (sd->dec_stream) { 828 pj_media_stream_destroy (sd->dec_stream); 829 sd->dec_stream = NULL; 830 } 831 } 832 pj_pool_release (session->pool); 833 return 0; 834 } 835 371 PJ_DEF(pj_status_t) pjmedia_session_get_stat(const pjmedia_session *session, 372 unsigned *count, 373 pjmedia_stream_stat stat[]) 374 { 375 PJ_ASSERT_RETURN(session && count && *count && stat, PJ_EINVAL); 376 377 *count = 0; 378 pj_memset(stat, 0, *count * sizeof(pjmedia_stream_stat)); 379 return PJ_EINVALIDOP; 380 } 381 382 383 /** 384 * Get individual stream statistic. 385 */ 386 PJ_DEF(pj_status_t) pjmedia_session_get_stream_stat( const pjmedia_session *s, 387 unsigned index, 388 pjmedia_stream_stat *stat) 389 { 390 PJ_ASSERT_RETURN(s && index < s->stream_cnt && stat, PJ_EINVAL); 391 pj_memset(stat, 0, sizeof(pjmedia_stream_stat)); 392 return PJ_EINVALIDOP; 393 } 394 395 -
pjproject/trunk/pjmedia/src/pjmedia/stream.c
r121 r159 32 32 33 33 34 #define THISFILE "stream.c" 35 #define ERRLEVEL 1 36 37 #define PJ_MAX_FRAME_DURATION_MS 200 38 #define PJ_MAX_BUFFER_SIZE_MS 2000 39 #define PJ_MAX_MTU 1500 34 #define THIS_FILE "stream.c" 35 #define ERRLEVEL 1 36 #define TRACE_(expr) PJ_LOG(3,expr) 37 38 #define PJMEDIA_MAX_FRAME_DURATION_MS 200 39 #define PJMEDIA_MAX_BUFFER_SIZE_MS 2000 40 #define PJMEDIA_MAX_MTU 1500 40 41 41 42 struct jb_frame … … 49 50 #define pj_fifobuf_free(fifo, buf) free(buf) 50 51 51 enum stream_state 52 { 53 STREAM_STOPPED, 54 STREAM_STARTED, 52 53 /** 54 * Media channel. 55 */ 56 struct pjmedia_channel 57 { 58 pjmedia_stream *stream; /**< Parent stream. */ 59 pjmedia_dir dir; /**< Channel direction. */ 60 unsigned pt; /**< Payload type. */ 61 pj_bool_t paused; /**< Paused?. */ 62 pj_snd_stream_info snd_info; /**< Sound stream param. */ 63 pj_snd_stream *snd_stream; /**< Sound stream. */ 64 unsigned in_pkt_size; /**< Size of input buffer. */ 65 void *in_pkt; /**< Input buffer. */ 66 unsigned out_pkt_size; /**< Size of output buffer. */ 67 void *out_pkt; /**< Output buffer. */ 68 unsigned pcm_buf_size; /**< Size of PCM buffer. */ 69 void *pcm_buf; /**< PCM buffer. */ 70 pj_rtp_session rtp; /**< RTP session. */ 55 71 }; 56 72 57 struct pj_media_stream_t 58 { 59 pj_media_dir_t dir; 60 int pt; 61 int state; 62 pj_media_stream_stat stat; 63 pj_media_stream_t *peer; 64 pj_snd_stream_info snd_info; 65 pj_snd_stream *snd_stream; 66 pj_mutex_t *mutex; 67 unsigned in_pkt_size; 68 void *in_pkt; 69 unsigned out_pkt_size; 70 void *out_pkt; 71 unsigned pcm_buf_size; 72 void *pcm_buf; 73 //pj_fifobuf_t fifobuf; 74 pj_codec_mgr *codec_mgr; 75 pj_codec *codec; 76 pj_rtp_session rtp; 77 pj_rtcp_session *rtcp; 78 pj_jitter_buffer *jb; 79 pj_sock_t rtp_sock; 80 pj_sock_t rtcp_sock; 81 pj_sockaddr_in dst_addr; 82 pj_thread_t *transport_thread; 83 int thread_quit_flag; 73 74 /** 75 * This structure describes media stream. 76 * A media stream is bidirectional media transmission between two endpoints. 77 * It consists of two channels, i.e. encoding and decoding channels. 78 * A media stream corresponds to a single "m=" line in a SDP session 79 * description. 80 */ 81 struct pjmedia_stream 82 { 83 pjmedia_channel *enc; /**< Encoding channel. */ 84 pjmedia_channel *dec; /**< Decoding channel. */ 85 86 pjmedia_dir dir; /**< Stream direction. */ 87 pjmedia_stream_stat stat; /**< Stream statistics. */ 88 89 pjmedia_codec_mgr *codec_mgr; /**< Codec manager instance. */ 90 pjmedia_codec *codec; /**< Codec instance being used. */ 91 92 pj_mutex_t *jb_mutex; 93 pj_jitter_buffer jb; /**< Jitter buffer. */ 94 95 pj_sock_t rtp_sock; /**< RTP socket. */ 96 pj_sock_t rtcp_sock; /**< RTCP socket. */ 97 pj_sockaddr_in dst_addr; /**< Destination RTP address. */ 98 99 pj_rtcp_session rtcp; /**< RTCP for incoming RTP. */ 100 101 pj_bool_t quit_flag; /**< To signal thread exit. */ 102 pj_thread_t *thread; /**< Jitter buffer's thread. */ 84 103 }; 85 104 86 105 106 107 /* 108 * play_callback() 109 * 110 * This callback is called by sound device's player thread when it 111 * needs to feed the player with some frames. 112 */ 87 113 static pj_status_t play_callback(/* in */ void *user_data, 88 114 /* in */ pj_uint32_t timestamp, … … 90 116 /*inout*/ unsigned size) 91 117 { 92 pj_media_stream_t *channel = user_data; 118 pjmedia_channel *channel = user_data; 119 pjmedia_stream *stream = channel->stream; 93 120 struct jb_frame *jb_frame; 94 121 void *p; 95 122 pj_uint32_t extseq; 96 123 pj_status_t status; 97 struct pj _audio_frame frame_in, frame_out;124 struct pjmedia_frame frame_in, frame_out; 98 125 99 126 PJ_UNUSED_ARG(timestamp); 100 127 101 /* Lock mutex */ 102 pj_mutex_lock (channel->mutex); 103 104 if (!channel->codec) { 105 pj_mutex_unlock (channel->mutex); 128 /* Do nothing if we're quitting. */ 129 if (stream->quit_flag) 106 130 return -1; 107 } 131 132 /* Lock jitter buffer mutex */ 133 pj_mutex_lock( stream->jb_mutex ); 108 134 109 135 /* Get frame from jitter buffer. */ 110 status = pj_jb_get (channel->jb, &extseq, &p); 136 status = pj_jb_get(&stream->jb, &extseq, &p); 137 138 /* Unlock jitter buffer mutex. */ 139 pj_mutex_unlock( stream->jb_mutex ); 140 111 141 jb_frame = p; 112 if (status != 0|| jb_frame == NULL) {142 if (status != PJ_SUCCESS || jb_frame == NULL) { 113 143 pj_memset(frame, 0, size); 114 pj_mutex_unlock(channel->mutex);115 144 return 0; 116 145 } … … 119 148 frame_in.buf = jb_frame->buf; 120 149 frame_in.size = jb_frame->size; 121 frame_in.type = PJ _AUDIO_FRAME_AUDIO; /* ignored */150 frame_in.type = PJMEDIA_FRAME_TYPE_AUDIO; /* ignored */ 122 151 frame_out.buf = channel->pcm_buf; 123 status = channel->codec->op->decode (channel->codec, &frame_in,124 152 status = stream->codec->op->decode( stream->codec, &frame_in, 153 channel->pcm_buf_size, &frame_out); 125 154 if (status != 0) { 126 PJ_LOG(3, (THISFILE, "decode() has return error status %d", 127 status)); 155 TRACE_((THIS_FILE, "decode() has return error status %d", status)); 128 156 129 157 pj_memset(frame, 0, size); 130 158 pj_fifobuf_free (&channel->fifobuf, jb_frame); 131 pj_mutex_unlock(channel->mutex);132 159 return 0; 133 160 } … … 135 162 /* Put in sound buffer. */ 136 163 if (frame_out.size > size) { 137 PJ_LOG(3, (THISFILE, "Sound playout buffer truncated %d bytes",138 164 TRACE_((THIS_FILE, "Sound playout buffer truncated %d bytes", 165 frame_out.size - size)); 139 166 frame_out.size = size; 140 167 } 141 168 142 169 pj_memcpy(frame, frame_out.buf, size); 143 144 170 pj_fifobuf_free (&channel->fifobuf, jb_frame); 145 pj_mutex_unlock(channel->mutex); 171 146 172 return 0; 147 173 } 148 174 175 176 /** 177 * rec_callback() 178 * 179 * This callback is called when the mic device has gathered 180 * enough audio samples. We will encode the audio samples and 181 * send it to remote. 182 */ 149 183 static pj_status_t rec_callback( /* in */ void *user_data, 150 184 /* in */ pj_uint32_t timestamp, … … 152 186 /* in */ unsigned size) 153 187 { 154 pj_media_stream_t *channel = user_data; 188 pjmedia_channel *channel = user_data; 189 pjmedia_stream *stream = channel->stream; 155 190 pj_status_t status = 0; 156 struct pj _audio_frame frame_in, frame_out;191 struct pjmedia_frame frame_in, frame_out; 157 192 int ts_len; 158 193 void *rtphdr; 159 194 int rtphdrlen; 160 195 pj_ssize_t sent; 161 #if 0 162 static FILE *fhnd = NULL; 163 #endif 196 164 197 165 198 PJ_UNUSED_ARG(timestamp); 166 199 167 /* Start locking channel mutex */ 168 pj_mutex_lock (channel->mutex); 169 170 if (!channel->codec) { 171 status = -1; 172 goto on_return; 173 } 200 /* Check if stream is quitting. */ 201 if (stream->quit_flag) 202 return -1; 174 203 175 204 /* Encode. */ 176 frame_in.type = PJ _MEDIA_TYPE_AUDIO;205 frame_in.type = PJMEDIA_TYPE_AUDIO; 177 206 frame_in.buf = (void*)frame; 178 207 frame_in.size = size; 179 208 frame_out.buf = ((char*)channel->out_pkt) + sizeof(pj_rtp_hdr); 180 status = channel->codec->op->encode (channel->codec, &frame_in,181 182 209 status = stream->codec->op->encode( stream->codec, &frame_in, 210 channel->out_pkt_size - sizeof(pj_rtp_hdr), 211 &frame_out); 183 212 if (status != 0) { 184 PJ_LOG(3,(THISFILE, "Codec encode() has returned error status %d",185 186 goto on_return;213 TRACE_((THIS_FILE, "Codec encode() has returned error status %d", 214 status)); 215 return status; 187 216 } 188 217 189 218 /* Encapsulate. */ 190 219 ts_len = size / (channel->snd_info.bits_per_sample / 8); 191 status = pj_rtp_encode_rtp (&channel->rtp, channel->pt, 0, 220 status = pj_rtp_encode_rtp( &channel->rtp, 221 channel->pt, 0, 192 222 frame_out.size, ts_len, 193 223 (const void**)&rtphdr, &rtphdrlen); 194 224 if (status != 0) { 195 PJ_LOG(3,(THISFILE, "RTP encode_rtp() has returned error status %d",196 197 goto on_return;225 TRACE_((THIS_FILE, "RTP encode_rtp() has returned error status %d", 226 status)); 227 return status; 198 228 } 199 229 … … 201 231 /* We don't support RTP with extended header yet. */ 202 232 PJ_TODO(SUPPORT_SENDING_RTP_WITH_EXTENDED_HEADER); 203 PJ_LOG(3,(THISFILE, "Unsupported extended RTP header for transmission"));204 goto on_return;233 TRACE_((THIS_FILE, "Unsupported extended RTP header for transmission")); 234 return 0; 205 235 } 206 236 … … 209 239 /* Send. */ 210 240 sent = frame_out.size+sizeof(pj_rtp_hdr); 211 status = pj_sock_sendto (channel->rtp_sock, channel->out_pkt, &sent, 0,212 &channel->dst_addr, sizeof(channel->dst_addr));213 if (status != PJ_SUCCESS) 214 goto on_return;241 status = pj_sock_sendto(stream->rtp_sock, channel->out_pkt, &sent, 0, 242 &stream->dst_addr, sizeof(stream->dst_addr)); 243 if (status != PJ_SUCCESS) 244 return status; 215 245 216 246 /* Update stat */ 217 channel->stat.pkt_tx++; 218 channel->stat.oct_tx += frame_out.size+sizeof(pj_rtp_hdr); 219 220 #if 0 221 if (fhnd == NULL) { 222 fhnd = fopen("RTP.DAT", "wb"); 223 if (fhnd) { 224 fwrite (channel->out_pkt, frame_out.size+sizeof(pj_rtp_hdr), 1, fhnd); 225 fclose(fhnd); 226 } 227 } 228 #endif 229 230 on_return: 231 pj_mutex_unlock (channel->mutex); 232 return status; 233 } 234 235 236 static int PJ_THREAD_FUNC stream_decoder_transport_thread (void*arg) 237 { 238 pj_media_stream_t *channel = arg; 239 240 while (!channel->thread_quit_flag) { 247 stream->stat.enc.pkt++; 248 stream->stat.enc.bytes += frame_out.size+sizeof(pj_rtp_hdr); 249 250 return 0; 251 } 252 253 254 /* 255 * This thread will poll the socket for incoming packets, and put 256 * the packets to jitter buffer. 257 */ 258 static int PJ_THREAD_FUNC jitter_buffer_thread (void*arg) 259 { 260 pjmedia_stream *stream = arg; 261 pjmedia_channel *channel = stream->dec; 262 263 while (!stream->quit_flag) { 241 264 pj_ssize_t len, size; 242 265 const pj_rtp_hdr *hdr; … … 251 274 252 275 PJ_FD_ZERO (&fds); 253 PJ_FD_SET ( channel->rtp_sock, &fds);276 PJ_FD_SET (stream->rtp_sock, &fds); 254 277 timeout.sec = 0; 255 timeout.msec = 1 00;278 timeout.msec = 1; 256 279 257 280 /* Wait with timeout. */ 258 status = pj_sock_select( channel->rtp_sock, &fds, NULL, NULL, &timeout);281 status = pj_sock_select(stream->rtp_sock, &fds, NULL, NULL, &timeout); 259 282 if (status != 1) 260 283 continue; … … 262 285 /* Get packet from socket. */ 263 286 len = channel->in_pkt_size; 264 status = pj_sock_recv (channel->rtp_sock, channel->in_pkt, &len, 0);287 status = pj_sock_recv(stream->rtp_sock, channel->in_pkt, &len, 0); 265 288 if (len < 1 || status != PJ_SUCCESS) { 266 289 if (pj_get_netos_error() == PJ_STATUS_FROM_OS(OSERR_ECONNRESET)) { 267 /* On Win2K SP2 (or above) and WinXP, recv() will get WSAECONNRESET 268 when the sending side receives ICMP port unreachable. 290 /* On Win2K SP2 (or above) and WinXP, recv() will get 291 * WSAECONNRESET when the sending side receives ICMP port 292 * unreachable. 269 293 */ 270 294 continue; 271 295 } 272 //pj_perror(THISFILE, "Error receiving packet from socket (len=%d)", len);273 296 pj_thread_sleep(1); 274 297 continue; 275 298 } 276 299 277 if (channel-> state != STREAM_STARTED)300 if (channel->paused) 278 301 continue; 279 302 280 if (channel->thread_quit_flag)281 break;282 283 /* Start locking the channel. */284 pj_mutex_lock (channel->mutex);285 286 303 /* Update RTP and RTCP session. */ 287 status = pj_rtp_decode_rtp (&channel->rtp, channel->in_pkt, len, &hdr, &payload, &payloadlen); 288 if (status != 0) { 289 pj_mutex_unlock (channel->mutex); 290 PJ_LOG(4,(THISFILE, "RTP decode_rtp() has returned error status %d", status)); 304 status = pj_rtp_decode_rtp(&channel->rtp, channel->in_pkt, len, 305 &hdr, &payload, &payloadlen); 306 if (status != PJ_SUCCESS) { 307 TRACE_((THIS_FILE, "RTP decode_rtp() has returned error status %d", 308 status)); 291 309 continue; 292 310 } 293 status = pj_rtp_session_update (&channel->rtp, hdr); 294 if (status != 0 && status != PJ_RTP_ERR_SESSION_PROBATION && status != PJ_RTP_ERR_SESSION_RESTARTED) { 295 pj_mutex_unlock (channel->mutex); 296 PJ_LOG(4,(THISFILE, "RTP session_update() has returned error status %d", status)); 311 312 status = pj_rtp_session_update(&channel->rtp, hdr); 313 if (status != 0 && 314 status != PJMEDIA_RTP_ERR_SESSION_PROBATION && 315 status != PJMEDIA_RTP_ERR_SESSION_RESTARTED) 316 { 317 TRACE_((THIS_FILE, 318 "RTP session_update() has returned error status %d", 319 status)); 297 320 continue; 298 321 } 299 pj_rtcp_rx_rtp (channel->rtcp, pj_ntohs(hdr->seq), pj_ntohl(hdr->ts));322 pj_rtcp_rx_rtp(&stream->rtcp, pj_ntohs(hdr->seq), pj_ntohl(hdr->ts)); 300 323 301 324 /* Update stat */ 302 channel->stat.pkt_rx++;303 channel->stat.oct_rx+= len;325 stream->stat.dec.pkt++; 326 stream->stat.dec.bytes += len; 304 327 305 328 /* Copy to FIFO buffer. */ … … 307 330 jb_frame = pj_fifobuf_alloc (&channel->fifobuf, size); 308 331 if (jb_frame == NULL) { 309 pj_mutex_unlock (channel->mutex);310 PJ_LOG(4,(THISFILE, "Unable to allocate %d bytes FIFO buffer",size));332 TRACE_((THIS_FILE, "Unable to allocate %d bytes FIFO buffer", 333 size)); 311 334 continue; 312 335 } … … 318 341 319 342 /* Put to jitter buffer. */ 320 status = pj_jb_put (channel->jb, pj_ntohs(hdr->seq), jb_frame); 343 pj_mutex_lock( stream->jb_mutex ); 344 status = pj_jb_put(&stream->jb, pj_ntohs(hdr->seq), jb_frame); 345 pj_mutex_unlock( stream->jb_mutex ); 346 321 347 if (status != 0) { 322 348 pj_fifobuf_unalloc (&channel->fifobuf, jb_frame); 323 pj_mutex_unlock (channel->mutex); 324 PJ_LOG(4,(THISFILE, "Jitter buffer put() has returned error status %d", status)); 349 350 TRACE_((THIS_FILE, 351 "Jitter buffer put() has returned error status %d", 352 status)); 325 353 continue; 326 354 } 327 328 pj_mutex_unlock (channel->mutex);329 355 } 330 356 … … 332 358 } 333 359 334 static void init_snd_param_from_codec_attr (pj_snd_stream_info *param, 335 const pj_codec_attr *attr) 336 { 337 param->bits_per_sample = attr->pcm_bits_per_sample; 338 param->bytes_per_frame = 2; 339 param->frames_per_packet = attr->sample_rate * attr->ptime / 1000; 340 param->samples_per_frame = 1; 341 param->samples_per_sec = attr->sample_rate; 342 } 343 344 static pj_media_stream_t *create_channel ( pj_pool_t *pool, 345 pj_media_dir_t dir, 346 pj_media_stream_t *peer, 347 pj_codec_id *codec_id, 348 pj_media_stream_create_param *param) 349 { 350 pj_media_stream_t *channel; 351 pj_codec_attr codec_attr; 352 void *ptr; 353 unsigned size; 360 361 /* 362 * Create sound stream parameter from codec attributes. 363 */ 364 static void init_snd_param( pj_snd_stream_info *snd_param, 365 const pjmedia_codec_param *codec_param) 366 { 367 pj_memset(snd_param, 0, sizeof(*snd_param)); 368 369 snd_param->bits_per_sample = codec_param->pcm_bits_per_sample; 370 snd_param->bytes_per_frame = 2; 371 snd_param->frames_per_packet = codec_param->sample_rate * 372 codec_param->ptime / 373 1000; 374 snd_param->samples_per_frame = 1; 375 snd_param->samples_per_sec = codec_param->sample_rate; 376 } 377 378 379 /* 380 * Create media channel. 381 */ 382 static pj_status_t create_channel( pj_pool_t *pool, 383 pjmedia_stream *stream, 384 pjmedia_dir dir, 385 const pjmedia_stream_info *param, 386 const pjmedia_codec_param *codec_param, 387 pjmedia_channel **p_channel) 388 { 389 pjmedia_channel *channel; 354 390 pj_status_t status; 355 391 356 392 /* Allocate memory for channel descriptor */ 357 size = sizeof(pj_media_stream_t); 358 channel = pj_pool_calloc(pool, 1, size); 359 if (!channel) { 360 PJ_LOG(1,(THISFILE, "Unable to allocate %u bytes channel descriptor", 361 size)); 362 return NULL; 363 } 364 393 394 channel = pj_pool_zalloc(pool, sizeof(pjmedia_channel)); 395 PJ_ASSERT_RETURN(channel != NULL, PJ_ENOMEM); 396 397 /* Init channel info. */ 398 399 channel->stream = stream; 365 400 channel->dir = dir; 366 channel->pt = codec_id->pt; 367 channel->peer = peer; 368 channel->codec_mgr = pj_med_mgr_get_codec_mgr (param->mediamgr); 369 channel->rtp_sock = param->rtp_sock; 370 channel->rtcp_sock = param->rtcp_sock; 371 channel->dst_addr = *param->remote_addr; 372 channel->state = STREAM_STOPPED; 373 374 /* Create mutex for the channel. */ 375 status = pj_mutex_create_simple(pool, NULL, &channel->mutex); 376 if (status != PJ_SUCCESS) 377 goto err_cleanup; 378 379 /* Create and initialize codec, only if peer is not present. 380 We only use one codec instance for both encoder and decoder. 381 */ 382 if (peer && peer->codec) { 383 channel->codec = peer->codec; 384 status = channel->codec->factory->op->default_attr(channel->codec->factory, codec_id, 385 &codec_attr); 386 if (status != 0) { 387 goto err_cleanup; 388 } 389 390 } else { 391 channel->codec = pj_codec_mgr_alloc_codec(channel->codec_mgr, codec_id); 392 if (channel->codec == NULL) { 393 goto err_cleanup; 394 } 395 396 status = channel->codec->factory->op->default_attr(channel->codec->factory, codec_id, 397 &codec_attr); 398 if (status != 0) { 399 goto err_cleanup; 400 } 401 402 codec_attr.pt = codec_id->pt; 403 status = channel->codec->op->open(channel->codec, &codec_attr); 404 if (status != 0) { 405 goto err_cleanup; 406 } 407 } 401 channel->paused = 1; 402 channel->pt = param->fmt.pt; 408 403 409 404 /* Allocate buffer for incoming packet. */ 410 channel->in_pkt_size = PJ_MAX_MTU; 411 channel->in_pkt = pj_pool_alloc(pool, channel->in_pkt_size); 412 if (!channel->in_pkt) { 413 PJ_LOG(1, (THISFILE, "Unable to allocate %u bytes incoming packet buffer", 414 channel->in_pkt_size)); 415 goto err_cleanup; 416 } 417 405 406 channel->in_pkt_size = PJMEDIA_MAX_MTU; 407 channel->in_pkt = pj_pool_alloc( pool, channel->in_pkt_size ); 408 PJ_ASSERT_RETURN(channel->in_pkt != NULL, PJ_ENOMEM); 409 410 418 411 /* Allocate buffer for outgoing packet. */ 412 419 413 channel->out_pkt_size = sizeof(pj_rtp_hdr) + 420 codec_attr.avg_bps / 8 * PJ_MAX_FRAME_DURATION_MS / 1000; 421 if (channel->out_pkt_size > PJ_MAX_MTU) 422 channel->out_pkt_size = PJ_MAX_MTU; 414 codec_param->avg_bps/8 * 415 PJMEDIA_MAX_FRAME_DURATION_MS / 416 1000; 417 418 if (channel->out_pkt_size > PJMEDIA_MAX_MTU) 419 channel->out_pkt_size = PJMEDIA_MAX_MTU; 420 423 421 channel->out_pkt = pj_pool_alloc(pool, channel->out_pkt_size); 424 if (!channel->out_pkt) { 425 PJ_LOG(1, (THISFILE, "Unable to allocate %u bytes encoding buffer", 426 channel->out_pkt_size)); 427 goto err_cleanup; 428 } 429 430 /* Allocate buffer for decoding to PCM */ 431 channel->pcm_buf_size = codec_attr.sample_rate * 432 codec_attr.pcm_bits_per_sample / 8 * 433 PJ_MAX_FRAME_DURATION_MS / 1000; 422 PJ_ASSERT_RETURN(channel->out_pkt != NULL, PJ_ENOMEM); 423 424 425 /* Allocate buffer for decoding to PCM: */ 426 427 channel->pcm_buf_size = codec_param->sample_rate * 428 codec_param->pcm_bits_per_sample / 8 * 429 PJMEDIA_MAX_FRAME_DURATION_MS / 1000; 434 430 channel->pcm_buf = pj_pool_alloc (pool, channel->pcm_buf_size); 435 if (!channel->pcm_buf) { 436 PJ_LOG(1, (THISFILE, "Unable to allocate %u bytes PCM buffer", 437 channel->pcm_buf_size)); 438 goto err_cleanup; 439 } 440 441 /* Allocate buffer for frames put in jitter buffer. */ 442 size = codec_attr.avg_bps / 8 * PJ_MAX_BUFFER_SIZE_MS / 1000; 443 ptr = pj_pool_alloc(pool, size); 444 if (!ptr) { 445 PJ_LOG(1, (THISFILE, "Unable to allocate %u bytes jitter buffer", 446 channel->pcm_buf_size)); 447 goto err_cleanup; 448 } 449 //pj_fifobuf_init (&channel->fifobuf, ptr, size); 431 PJ_ASSERT_RETURN(channel->pcm_buf != NULL, PJ_ENOMEM); 432 433 434 /* Create RTP and RTCP sessions: */ 435 436 status = pj_rtp_session_init(&channel->rtp, param->fmt.pt, 437 param->ssrc); 438 if (status != PJ_SUCCESS) 439 return status; 450 440 451 441 /* Create and initialize sound device */ 452 init_snd_param_from_codec_attr (&channel->snd_info, &codec_attr); 453 454 if (dir == PJ_MEDIA_DIR_ENCODING) 442 443 init_snd_param(&channel->snd_info, codec_param); 444 445 if (dir == PJMEDIA_DIR_ENCODING) 455 446 channel->snd_stream = pj_snd_open_recorder(-1, &channel->snd_info, 456 447 &rec_callback, channel); … … 460 451 461 452 if (!channel->snd_stream) 462 goto err_cleanup; 463 464 /* Create RTP and RTCP sessions. */ 465 if (pj_rtp_session_init(&channel->rtp, codec_id->pt, param->ssrc) != 0) { 466 PJ_LOG(1, (THISFILE, "RTP session initialization error")); 467 goto err_cleanup; 468 } 469 470 /* For decoder, create RTCP session, jitter buffer, and transport thread. */ 471 if (dir == PJ_MEDIA_DIR_DECODING) { 472 channel->rtcp = pj_pool_calloc(pool, 1, sizeof(pj_rtcp_session)); 473 if (!channel->rtcp) { 474 PJ_LOG(1, (THISFILE, "Unable to allocate RTCP session")); 475 goto err_cleanup; 476 } 477 478 pj_rtcp_init(channel->rtcp, param->ssrc); 479 480 channel->jb = pj_pool_calloc(pool, 1, sizeof(pj_jitter_buffer)); 481 if (!channel->jb) { 482 PJ_LOG(1, (THISFILE, "Unable to allocate jitter buffer descriptor")); 483 goto err_cleanup; 484 } 485 if (pj_jb_init(channel->jb, pool, param->jb_min, param->jb_max, param->jb_maxcnt)) { 486 PJ_LOG(1, (THISFILE, "Unable to allocate jitter buffer")); 487 goto err_cleanup; 488 } 489 490 status = pj_thread_create(pool, "decode", 491 &stream_decoder_transport_thread, channel, 492 0, 0, &channel->transport_thread); 493 if (status != PJ_SUCCESS) { 494 //pj_perror(THISFILE, "Unable to create transport thread"); 495 goto err_cleanup; 496 } 497 } 453 return -1; 454 498 455 499 456 /* Done. */ 500 return channel; 457 *p_channel = channel; 458 return PJ_SUCCESS; 459 } 460 461 462 /* 463 * Create media stream. 464 */ 465 PJ_DEF(pj_status_t) pjmedia_stream_create( pjmedia_endpt *endpt, 466 pj_pool_t *pool, 467 const pjmedia_stream_info *info, 468 pjmedia_stream **p_stream) 469 470 { 471 pjmedia_stream *stream; 472 pjmedia_codec_param codec_param; 473 pj_status_t status; 474 475 PJ_ASSERT_RETURN(pool && info && p_stream, PJ_EINVAL); 476 477 478 /* Allocate the media stream: */ 479 480 stream = pj_pool_zalloc(pool, sizeof(pjmedia_stream)); 481 PJ_ASSERT_RETURN(stream != NULL, PJ_ENOMEM); 482 483 484 /* Init stream: */ 485 486 stream->dir = info->dir; 487 stream->codec_mgr = pjmedia_endpt_get_codec_mgr(endpt); 488 489 /* Create mutex to protect jitter buffer: */ 490 491 status = pj_mutex_create_simple(pool, NULL, &stream->jb_mutex); 492 if (status != PJ_SUCCESS) 493 goto err_cleanup; 494 495 496 /* Create and initialize codec: */ 497 498 status = pjmedia_codec_mgr_alloc_codec( stream->codec_mgr, 499 &info->fmt, &stream->codec); 500 if (status != PJ_SUCCESS) 501 goto err_cleanup; 502 503 504 /* Get default codec param: */ 505 506 status = stream->codec->op->default_attr(stream->codec, &codec_param); 507 if (status != PJ_SUCCESS) 508 goto err_cleanup; 509 510 511 /* Open the codec: */ 512 513 status = stream->codec->op->open(stream->codec, &codec_param); 514 if (status != PJ_SUCCESS) 515 goto err_cleanup; 516 517 518 /* Init RTCP session: */ 519 520 pj_rtcp_init(&stream->rtcp, info->ssrc); 521 522 523 /* Init jitter buffer: */ 524 525 status = pj_jb_init(&stream->jb, pool, 526 info->jb_min, info->jb_max, info->jb_maxcnt); 527 if (status != PJ_SUCCESS) 528 goto err_cleanup; 529 530 531 /* Create jitter buffer thread: */ 532 533 status = pj_thread_create(pool, "decode", 534 &jitter_buffer_thread, stream, 535 0, 0, &stream->thread); 536 if (status != PJ_SUCCESS) 537 goto err_cleanup; 538 539 540 /* Create decoder channel: */ 541 542 status = create_channel( pool, stream, PJMEDIA_DIR_DECODING, info, 543 &codec_param, &stream->dec); 544 if (status != PJ_SUCCESS) 545 goto err_cleanup; 546 547 548 /* Create encoder channel: */ 549 550 status = create_channel( pool, stream, PJMEDIA_DIR_ENCODING, info, 551 &codec_param, &stream->enc); 552 if (status != PJ_SUCCESS) 553 goto err_cleanup; 554 555 556 /* Success! */ 557 *p_stream = stream; 558 return PJ_SUCCESS; 559 501 560 502 561 err_cleanup: 503 pj_media_stream_destroy(channel); 504 return NULL; 505 } 506 507 508 PJ_DEF(pj_status_t) pj_media_stream_create (pj_pool_t *pool, 509 pj_media_stream_t **enc_stream, 510 pj_media_stream_t **dec_stream, 511 pj_media_stream_create_param *param) 512 { 513 *dec_stream = *enc_stream = NULL; 514 515 if (param->dir & PJ_MEDIA_DIR_DECODING) { 516 *dec_stream = 517 create_channel(pool, PJ_MEDIA_DIR_DECODING, NULL, param->codec_id, param); 518 if (!*dec_stream) 519 return -1; 520 } 521 522 if (param->dir & PJ_MEDIA_DIR_ENCODING) { 523 *enc_stream = 524 create_channel(pool, PJ_MEDIA_DIR_ENCODING, *dec_stream, param->codec_id, param); 525 if (!*enc_stream) { 526 if (*dec_stream) { 527 pj_media_stream_destroy(*dec_stream); 528 *dec_stream = NULL; 529 } 530 return -1; 531 } 532 533 if (*dec_stream) { 534 (*dec_stream)->peer = *enc_stream; 535 } 536 } 537 538 return 0; 539 } 540 541 PJ_DEF(pj_status_t) pj_media_stream_start (pj_media_stream_t *channel) 542 { 543 pj_status_t status; 544 545 status = pj_snd_stream_start(channel->snd_stream); 546 547 if (status == 0) 548 channel->state = STREAM_STARTED; 562 pjmedia_stream_destroy(stream); 549 563 return status; 550 564 } 551 565 552 PJ_DEF(pj_status_t) pj_media_stream_get_stat (const pj_media_stream_t *stream, 553 pj_media_stream_stat *stat) 554 { 555 if (stream->dir == PJ_MEDIA_DIR_ENCODING) { 556 pj_memcpy (stat, &stream->stat, sizeof(*stat)); 557 } else { 558 pj_rtcp_pkt *rtcp_pkt; 559 int len; 560 561 pj_memset (stat, 0, sizeof(*stat)); 562 pj_assert (stream->rtcp != 0); 563 pj_rtcp_build_rtcp (stream->rtcp, &rtcp_pkt, &len); 564 565 stat->pkt_rx = stream->stat.pkt_rx; 566 stat->oct_rx = stream->stat.oct_rx; 567 568 PJ_TODO(SUPPORT_JITTER_CALCULATION_FOR_NON_8KHZ_SAMPLE_RATE) 569 stat->jitter = pj_ntohl(rtcp_pkt->rr.jitter) / 8; 570 stat->pkt_lost = (rtcp_pkt->rr.total_lost_2 << 16) + 571 (rtcp_pkt->rr.total_lost_1 << 8) + 572 rtcp_pkt->rr.total_lost_0; 573 } 574 return 0; 575 } 576 577 PJ_DEF(pj_status_t) pj_media_stream_pause (pj_media_stream_t *channel) 578 { 579 PJ_UNUSED_ARG(channel); 580 return -1; 581 } 582 583 PJ_DEF(pj_status_t) pj_media_stream_resume (pj_media_stream_t *channel) 584 { 585 PJ_UNUSED_ARG(channel); 586 return -1; 587 } 588 589 PJ_DEF(pj_status_t) pj_media_stream_destroy (pj_media_stream_t *channel) 590 { 591 channel->thread_quit_flag = 1; 592 593 pj_mutex_lock (channel->mutex); 594 if (channel->peer) 595 pj_mutex_lock (channel->peer->mutex); 596 597 if (channel->jb) { 598 /* No need to deinitialize jitter buffer. */ 599 } 600 if (channel->transport_thread) { 601 pj_thread_join(channel->transport_thread); 602 pj_thread_destroy(channel->transport_thread); 603 channel->transport_thread = NULL; 604 } 605 if (channel->snd_stream != NULL) { 606 pj_mutex_unlock (channel->mutex); 607 pj_snd_stream_stop(channel->snd_stream); 608 pj_mutex_lock (channel->mutex); 609 pj_snd_stream_close(channel->snd_stream); 610 channel->snd_stream = NULL; 611 } 612 if (channel->codec) { 613 channel->codec->op->close(channel->codec); 614 pj_codec_mgr_dealloc_codec(channel->codec_mgr, channel->codec); 615 channel->codec = NULL; 616 } 617 if (channel->peer) { 618 pj_media_stream_t *peer = channel->peer; 619 peer->peer = NULL; 620 peer->codec = NULL; 621 peer->thread_quit_flag = 1; 622 if (peer->transport_thread) { 623 pj_mutex_unlock (peer->mutex); 624 pj_thread_join(peer->transport_thread); 625 pj_mutex_lock (peer->mutex); 626 pj_thread_destroy(peer->transport_thread); 627 peer->transport_thread = NULL; 628 } 629 if (peer->snd_stream) { 630 pj_mutex_unlock (peer->mutex); 631 pj_snd_stream_stop(peer->snd_stream); 632 pj_mutex_lock (peer->mutex); 633 pj_snd_stream_close(peer->snd_stream); 634 peer->snd_stream = NULL; 635 } 636 } 637 638 channel->state = STREAM_STOPPED; 639 640 if (channel->peer) 641 pj_mutex_unlock (channel->peer->mutex); 642 pj_mutex_unlock(channel->mutex); 643 pj_mutex_destroy(channel->mutex); 644 645 return 0; 646 } 647 566 567 /* 568 * Destroy stream. 569 */ 570 PJ_DEF(pj_status_t) pjmedia_stream_destroy( pjmedia_stream *stream ) 571 { 572 573 PJ_ASSERT_RETURN(stream != NULL, PJ_EINVAL); 574 575 /* Signal threads to quit. */ 576 577 stream->quit_flag = 1; 578 579 580 /* Close encoding sound stream. */ 581 582 if (stream->enc && stream->enc->snd_stream) { 583 584 pj_snd_stream_stop(stream->enc->snd_stream); 585 pj_snd_stream_close(stream->enc->snd_stream); 586 stream->enc->snd_stream = NULL; 587 588 } 589 590 /* Close decoding sound stream. */ 591 592 if (stream->dec && stream->dec->snd_stream) { 593 594 pj_snd_stream_stop(stream->dec->snd_stream); 595 pj_snd_stream_close(stream->dec->snd_stream); 596 stream->dec->snd_stream = NULL; 597 598 } 599 600 /* Wait for jitter buffer thread to quit: */ 601 602 if (stream->thread) { 603 pj_thread_join(stream->thread); 604 pj_thread_destroy(stream->thread); 605 stream->thread = NULL; 606 } 607 608 /* Free codec. */ 609 610 if (stream->codec) { 611 stream->codec->op->close(stream->codec); 612 pjmedia_codec_mgr_dealloc_codec(stream->codec_mgr, stream->codec); 613 stream->codec = NULL; 614 } 615 616 /* Free mutex */ 617 618 if (stream->jb_mutex) { 619 pj_mutex_destroy(stream->jb_mutex); 620 stream->jb_mutex = NULL; 621 } 622 623 return PJ_SUCCESS; 624 } 625 626 627 628 /* 629 * Start stream. 630 */ 631 PJ_DEF(pj_status_t) pjmedia_stream_start(pjmedia_stream *stream) 632 { 633 634 PJ_ASSERT_RETURN(stream && stream->enc && stream->dec, PJ_EINVALIDOP); 635 636 if (stream->enc && (stream->dir & PJMEDIA_DIR_ENCODING)) { 637 stream->enc->paused = 0; 638 pj_snd_stream_start(stream->enc->snd_stream); 639 } 640 641 if (stream->dec && (stream->dir & PJMEDIA_DIR_DECODING)) { 642 stream->dec->paused = 0; 643 pj_snd_stream_start(stream->dec->snd_stream); 644 } 645 646 return PJ_SUCCESS; 647 } 648 649 650 /* 651 * Get stream statistics. 652 */ 653 PJ_DEF(pj_status_t) pjmedia_stream_get_stat( const pjmedia_stream *stream, 654 pjmedia_stream_stat *stat) 655 { 656 PJ_ASSERT_RETURN(stream && stat, PJ_EINVAL); 657 658 pj_memcpy(stat, &stream->stat, sizeof(pjmedia_stream_stat)); 659 660 return PJ_SUCCESS; 661 } 662 663 664 /* 665 * Pause stream. 666 */ 667 PJ_DEF(pj_status_t) pjmedia_stream_pause( pjmedia_stream *stream, 668 pjmedia_dir dir) 669 { 670 PJ_ASSERT_RETURN(stream, PJ_EINVAL); 671 672 if ((dir & PJMEDIA_DIR_ENCODING) && stream->enc) 673 stream->enc->paused = 1; 674 675 if ((dir & PJMEDIA_DIR_DECODING) && stream->dec) 676 stream->dec->paused = 1; 677 678 return PJ_SUCCESS; 679 } 680 681 682 /* 683 * Resume stream 684 */ 685 PJ_DEF(pj_status_t) pjmedia_stream_resume( pjmedia_stream *stream, 686 pjmedia_dir dir) 687 { 688 PJ_ASSERT_RETURN(stream, PJ_EINVAL); 689 690 if ((dir & PJMEDIA_DIR_ENCODING) && stream->enc) 691 stream->enc->paused = 1; 692 693 if ((dir & PJMEDIA_DIR_DECODING) && stream->dec) 694 stream->dec->paused = 1; 695 696 return PJ_SUCCESS; 697 } 698 -
pjproject/trunk/pjmedia/src/test/audio_tool.c
r65 r159 27 27 static FILE *fhnd; 28 28 static pj_med_mgr_t *mm; 29 static pj _codec *codec;30 static pj _codec_attrcattr;29 static pjmedia_codec *codec; 30 static pjmedia_codec_param cattr; 31 31 32 32 … … 61 61 { 62 62 char pkt[160]; 63 struct pj _audio_frame in, out;63 struct pjmedia_frame in, out; 64 64 int frmsz = cattr.avg_bps / 8 * cattr.ptime / 1000; 65 65 … … 68 68 return -1; 69 69 } else { 70 in.type = PJ _AUDIO_FRAME_AUDIO;70 in.type = PJMEDIA_FRAME_TYPE_AUDIO; 71 71 in.buf = pkt; 72 72 in.size = frmsz; … … 86 86 { 87 87 char pkt[160]; 88 struct pj _audio_frame in, out;88 struct pjmedia_frame in, out; 89 89 //int frmsz = cattr.avg_bps / 8 * cattr.ptime / 1000; 90 90 … … 93 93 #endif 94 94 95 in.type = PJ _AUDIO_FRAME_AUDIO;95 in.type = PJMEDIA_FRAME_TYPE_AUDIO; 96 96 in.buf = (void*)frame; 97 97 in.size = size; … … 108 108 static pj_status_t init() 109 109 { 110 pj _codec_mgr *cm;111 pj _codec_idid;110 pjmedia_codec_mgr *cm; 111 pjmedia_codec_info id; 112 112 int i; 113 113 … … 130 130 cm = pj_med_mgr_get_codec_mgr (mm); 131 131 132 id.type = PJ _MEDIA_TYPE_AUDIO;132 id.type = PJMEDIA_TYPE_AUDIO; 133 133 id.pt = 0; 134 134 id.encoding_name = pj_str("PCMU"); 135 135 id.sample_rate = 8000; 136 136 137 codec = pj _codec_mgr_alloc_codec (cm, &id);137 codec = pjmedia_codec_mgr_alloc_codec (cm, &id); 138 138 codec->op->default_attr(codec, &cattr); 139 139 codec->op->open(codec, &cattr); … … 143 143 static pj_status_t deinit() 144 144 { 145 pj _codec_mgr *cm;145 pjmedia_codec_mgr *cm; 146 146 cm = pj_med_mgr_get_codec_mgr (mm); 147 147 codec->op->close(codec); 148 pj _codec_mgr_dealloc_codec (cm, codec);148 pjmedia_codec_mgr_dealloc_codec (cm, codec); 149 149 pj_med_mgr_destroy (mm); 150 150 pj_caching_pool_destroy(&caching_pool); … … 301 301 302 302 switch (info[i]->dir) { 303 case PJ _MEDIA_DIR_NONE:303 case PJMEDIA_DIR_NONE: 304 304 dir = "- NONE -"; break; 305 case PJ _MEDIA_DIR_ENCODING:305 case PJMEDIA_DIR_ENCODING: 306 306 dir = "SENDONLY"; break; 307 case PJ _MEDIA_DIR_DECODING:307 case PJMEDIA_DIR_DECODING: 308 308 dir = "RECVONLY"; break; 309 case PJ _MEDIA_DIR_ENCODING_DECODING:309 case PJMEDIA_DIR_ENCODING_DECODING: 310 310 dir = "SENDRECV"; break; 311 311 default: … … 346 346 char pcm[320]; 347 347 char frame[160]; 348 struct pj _audio_frame in, out;348 struct pjmedia_frame in, out; 349 349 350 350 fhnd_pcm = fopen(src, "rb"); … … 357 357 while (fread(pcm, 320, 1, fhnd_pcm) == 1) { 358 358 359 in.type = PJ _AUDIO_FRAME_AUDIO;359 in.type = PJMEDIA_FRAME_TYPE_AUDIO; 360 360 in.buf = pcm; 361 361 in.size = 320; -
pjproject/trunk/pjmedia/src/test/session_test.c
r65 r159 45 45 46 46 // Set caller's media to send-only. 47 sd_info.dir = PJ _MEDIA_DIR_ENCODING;48 pj_media_session_modify_stream (s1, 0, PJ _MEDIA_STREAM_MODIFY_DIR, &sd_info);47 sd_info.dir = PJMEDIA_DIR_ENCODING; 48 pj_media_session_modify_stream (s1, 0, PJMEDIA_STREAM_MODIFY_DIR, &sd_info); 49 49 50 50 // Create caller SDP.
Note: See TracChangeset
for help on using the changeset viewer.