Index: pjproject/trunk/pjmedia/build/pjmedia.dsp
===================================================================
--- pjproject/trunk/pjmedia/build/pjmedia.dsp	(revision 158)
+++ pjproject/trunk/pjmedia/build/pjmedia.dsp	(revision 159)
@@ -97,4 +97,8 @@
 # Begin Source File
 
+SOURCE=..\src\pjmedia\endpoint.c
+# End Source File
+# Begin Source File
+
 SOURCE=..\src\pjmedia\errno.c
 # End Source File
@@ -106,8 +110,4 @@
 
 SOURCE=..\src\pjmedia\jbuf.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\pjmedia\mediamgr.c
 # End Source File
 # Begin Source File
@@ -143,5 +143,4 @@
 
 SOURCE=..\src\pjmedia\session.c
-# PROP Exclude_From_Build 1
 # End Source File
 # Begin Source File
@@ -163,4 +162,8 @@
 # Begin Source File
 
+SOURCE=..\include\pjmedia\endpoint.h
+# End Source File
+# Begin Source File
+
 SOURCE=..\include\pjmedia\errno.h
 # End Source File
@@ -168,8 +171,4 @@
 
 SOURCE=..\include\pjmedia\jbuf.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\include\pjmedia\mediamgr.h
 # End Source File
 # Begin Source File
Index: pjproject/trunk/pjmedia/include/pjmedia/codec.h
===================================================================
--- pjproject/trunk/pjmedia/include/pjmedia/codec.h	(revision 158)
+++ pjproject/trunk/pjmedia/include/pjmedia/codec.h	(revision 159)
@@ -26,4 +26,5 @@
  */
 
+#include <pjmedia/types.h>
 #include <pj/list.h>
 
@@ -37,183 +38,189 @@
  */
 
-/** Top most media type. */
-typedef enum pj_media_type
-{
-    /** No type. */
-    PJ_MEDIA_TYPE_NONE = 0,
-
-    /** The media is audio */
-    PJ_MEDIA_TYPE_AUDIO = 1,
-
-    /** The media is video. */
-    PJ_MEDIA_TYPE_VIDEO = 2,
-
-    /** Unknown media type, in this case the name will be specified in 
-     *  encoding_name.
-     */
-    PJ_MEDIA_TYPE_UNKNOWN = 3,
-
-} pj_media_type;
-
-
-/** Media direction. */
-typedef enum pj_media_dir_t
-{
-    /** None */
-    PJ_MEDIA_DIR_NONE = 0,
-
-    /** Encoding (outgoing to network) stream */
-    PJ_MEDIA_DIR_ENCODING = 1,
-
-    /** Decoding (incoming from network) stream. */
-    PJ_MEDIA_DIR_DECODING = 2,
-
-    /** Incoming and outgoing stream. */
-    PJ_MEDIA_DIR_ENCODING_DECODING = 3,
-
-} pj_media_dir_t;
-
-
-/** Standard RTP paylist types. */
-typedef enum pj_rtp_pt
-{
-    PJ_RTP_PT_PCMU = 0,		/* audio PCMU */
-    PJ_RTP_PT_GSM  = 3,		/* audio GSM */
-    PJ_RTP_PT_G723 = 4,		/* audio G723 */
-    PJ_RTP_PT_DVI4_8K = 5,	/* audio DVI4 8KHz */
-    PJ_RTP_PT_DVI4_16K = 6,	/* audio DVI4 16Khz */
-    PJ_RTP_PT_LPC = 7,		/* audio LPC */
-    PJ_RTP_PT_PCMA = 8,		/* audio PCMA */
-    PJ_RTP_PT_G722 = 9,		/* audio G722 */
-    PJ_RTP_PT_L16_2 = 10,	/* audio 16bit linear 44.1KHz stereo */
-    PJ_RTP_PT_L16_1 = 11,	/* audio 16bit linear 44.1KHz mono */
-    PJ_RTP_PT_QCELP = 12,	/* audio QCELP */
-    PJ_RTP_PT_CN = 13,		/* audio Comfort Noise */
-    PJ_RTP_PT_MPA = 14,		/* audio MPEG1 or MPEG2 as elementary streams */
-    PJ_RTP_PT_G728 = 15,	/* audio G728 */
-    PJ_RTP_PT_DVI4_11K = 16,	/* audio DVI4 11.025KHz mono */
-    PJ_RTP_PT_DVI4_22K = 17,	/* audio DVI4 22.050KHz mono */
-    PJ_RTP_PT_G729 = 18,	/* audio G729 */
-    PJ_RTP_PT_CELB = 25,	/* video/comb Cell-B by Sun Microsystems (RFC 2029) */
-    PJ_RTP_PT_JPEG = 26,	/* video JPEG */
-    PJ_RTP_PT_NV = 28,		/* video NV implemented by nv program by Xerox */
-    PJ_RTP_PT_H261 = 31,	/* video H261 */
-    PJ_RTP_PT_MPV = 32,		/* video MPEG1 or MPEG2 elementary streams */
-    PJ_RTP_PT_MP2T = 33,	/* video MPEG2 transport */
-    PJ_RTP_PT_H263 = 34,	/* video H263 */
-
-    PJ_RTP_PT_DYNAMIC = 96,	/* start of dynamic RTP payload */
-} pj_rtp_pt;
-
-
-/** Identification used to search for codec factory that supports specific 
- *  codec specification. 
- */
-typedef struct pj_codec_id
-{
-    /** Media type. */
-    pj_media_type   type;
-
-    /** Payload type (can be dynamic). */
-    unsigned	    pt;
-
-    /** Encoding name, must be present if the payload type is dynamic. */
-    pj_str_t	    encoding_name;
-
-    /** Sampling rate. */
-    unsigned	    sample_rate;
-} pj_codec_id;
-
-
-/** Detailed codec attributes used both to configure a codec and to query
- *  the capability of codec factories.
- */
-typedef struct pj_codec_attr
-{
-    pj_uint32_t	sample_rate;	    /* Sampling rate in Hz */
-    pj_uint32_t	avg_bps;	    /* Average bandwidth in bits per second */
-
-    pj_uint8_t	pcm_bits_per_sample;/* Bits per sample in the PCM side */
-    pj_uint16_t	ptime;		    /* Packet time in miliseconds */
-
-    unsigned	pt:8;		    /* Payload type. */
-    unsigned    vad_enabled:1;	    /* Voice Activity Detector. */
-    unsigned    cng_enabled:1;	    /* Comfort Noise Generator. */
-    unsigned    lpf_enabled:1;	    /* Low pass filter */
-    unsigned    hpf_enabled:1;	    /* High pass filter */
-    unsigned    penh_enabled:1;	    /* Perceptual Enhancement */
-    unsigned    concl_enabled:1;    /* Packet loss concealment */
-    unsigned    reserved_bit:1;
-
-} pj_codec_attr;
-
-/** Types of audio frame. */
-typedef enum pj_audio_frame_type
-{
-    /** The frame is a silence audio frame. */
-    PJ_AUDIO_FRAME_SILENCE,
-
-    /** The frame is a non-silence audio frame. */
-    PJ_AUDIO_FRAME_AUDIO,
-
-} pj_audio_frame_type;
-
-typedef struct pj_codec pj_codec;
-typedef struct pj_codec_factory pj_codec_factory;
-
-
-/** This structure describes an audio frame. */
-struct pj_audio_frame
-{
-    /** Type: silence or non-silence. */
-    pj_audio_frame_type type;
-
-    /** Pointer to buffer. */
-    void	*buf;
-
-    /** Frame size in bytes. */
-    unsigned	 size;
-};
-
-/**
- * Operations that must be supported by the codec.
- */
-typedef struct pj_codec_op
-{
-    /** Get default attributes. */
-    pj_status_t (*default_attr) (pj_codec *codec, pj_codec_attr *attr);
-
-    /** Open and initialize codec using the specified attribute.
-     *  @return zero on success.
-     */
-    pj_status_t	(*init)( pj_codec *codec, pj_pool_t *pool );
-
-    /** Close and shutdown codec.
-     */
-    pj_status_t	(*open)( pj_codec *codec, pj_codec_attr *attr );
-
-    /** Close and shutdown codec.
-     */
-    pj_status_t (*close)( pj_codec *codec );
-
-    /** Encode frame.
-     */
-    pj_status_t (*encode)( pj_codec *codec, const struct pj_audio_frame *input,
-			   unsigned output_buf_len, struct pj_audio_frame *output);
-
-    /** Decode frame.
-     */
-    pj_status_t (*decode)( pj_codec *codec, const struct pj_audio_frame *input,
-			   unsigned output_buf_len, struct pj_audio_frame *output);
-
-} pj_codec_op;
-
-/**
- * A codec describes an instance to encode or decode media frames. 
- */
-struct pj_codec
+
+/** 
+ * Standard RTP static payload types, as defined by RFC 3551. 
+ */
+enum pjmedia_rtp_pt
+{
+    PJMEDIA_RTP_PT_PCMU = 0,	    /* audio PCMU			    */
+    PJMEDIA_RTP_PT_GSM  = 3,	    /* audio GSM			    */
+    PJMEDIA_RTP_PT_G723 = 4,	    /* audio G723			    */
+    PJMEDIA_RTP_PT_DVI4_8K = 5,	    /* audio DVI4 8KHz			    */
+    PJMEDIA_RTP_PT_DVI4_16K = 6,    /* audio DVI4 16Khz			    */
+    PJMEDIA_RTP_PT_LPC = 7,	    /* audio LPC			    */
+    PJMEDIA_RTP_PT_PCMA = 8,	    /* audio PCMA			    */
+    PJMEDIA_RTP_PT_G722 = 9,	    /* audio G722			    */
+    PJMEDIA_RTP_PT_L16_2 = 10,	    /* audio 16bit linear 44.1KHz stereo    */
+    PJMEDIA_RTP_PT_L16_1 = 11,	    /* audio 16bit linear 44.1KHz mono	    */
+    PJMEDIA_RTP_PT_QCELP = 12,	    /* audio QCELP			    */
+    PJMEDIA_RTP_PT_CN = 13,	    /* audio Comfort Noise		    */
+    PJMEDIA_RTP_PT_MPA = 14,	    /* audio MPEG1/MPEG2 elementary streams */
+    PJMEDIA_RTP_PT_G728 = 15,	    /* audio G728			    */
+    PJMEDIA_RTP_PT_DVI4_11K = 16,   /* audio DVI4 11.025KHz mono	    */
+    PJMEDIA_RTP_PT_DVI4_22K = 17,   /* audio DVI4 22.050KHz mono	    */
+    PJMEDIA_RTP_PT_G729 = 18,	    /* audio G729			    */
+
+    PJMEDIA_RTP_PT_CELB = 25,	    /* video/comb Cell-B by Sun (RFC 2029)  */
+    PJMEDIA_RTP_PT_JPEG = 26,	    /* video JPEG			    */
+    PJMEDIA_RTP_PT_NV = 28,	    /* video NV  by nv program by Xerox	    */
+    PJMEDIA_RTP_PT_H261 = 31,	    /* video H261			    */
+    PJMEDIA_RTP_PT_MPV = 32,	    /* video MPEG1 or MPEG2 elementary	    */
+    PJMEDIA_RTP_PT_MP2T = 33,	    /* video MPEG2 transport		    */
+    PJMEDIA_RTP_PT_H263 = 34,	    /* video H263			    */
+
+    PJMEDIA_RTP_PT_DYNAMIC = 96,    /* start of dynamic RTP payload	    */
+
+};
+
+
+/** 
+ * Identification used to search for codec factory that supports specific 
+ * codec specification. 
+ */
+struct pjmedia_codec_info
+{
+    pjmedia_type    type;	    /**< Media type.			*/
+    unsigned	    pt;		    /**< Payload type (can be dynamic). */
+    pj_str_t	    encoding_name;  /**< Encoding name.			*/
+    unsigned	    sample_rate;    /**< Sampling rate.			*/
+};
+
+
+/** 
+ * Detailed codec attributes used both to configure a codec and to query
+ * the capability of codec factories.
+ */
+struct pjmedia_codec_param
+{
+    pj_uint32_t	sample_rate;	    /**< Sampling rate in Hz		*/
+    pj_uint32_t	avg_bps;	    /**< Average bandwidth in bits/sec	*/
+
+    pj_uint8_t	pcm_bits_per_sample;/**< Bits/sample in the PCM side	*/
+    pj_uint16_t	ptime;		    /**< Packet time in miliseconds	*/
+
+    unsigned	pt:8;		    /**< Payload type.			*/
+    unsigned    vad_enabled:1;	    /**< Voice Activity Detector.	*/
+    unsigned    cng_enabled:1;	    /**< Comfort Noise Generator.	*/
+    unsigned    lpf_enabled:1;	    /**< Low pass filter		*/
+    unsigned    hpf_enabled:1;	    /**< High pass filter		*/
+    unsigned    penh_enabled:1;	    /**< Perceptual Enhancement		*/
+    unsigned    concl_enabled:1;    /**< Packet loss concealment	*/
+    unsigned    reserved_bit:1;	    /**< Reserved, must be NULL.	*/
+
+};
+
+
+/** 
+ * Types of media frame. 
+ */
+enum pjmedia_frame_type
+{
+    PJMEDIA_FRAME_TYPE_SILENCE_AUDIO,	/**< Silence audio frame.	*/
+    PJMEDIA_FRAME_TYPE_AUDIO,		/**< Normal audio frame.	*/
+
+};
+
+/** 
+ * This structure describes a media frame. 
+ */
+struct pjmedia_frame
+{
+    pjmedia_frame_type	 type;	/**< Frame type.		    */
+    void		*buf;	/**< Pointer to buffer.		    */
+    pj_size_t		 size;	/**< Frame size in bytes.	    */
+};
+
+/**
+ * This structure describes codec operations. Each codec MUST implement
+ * all of these functions.
+ */
+struct pjmedia_codec_op
+{
+    /** 
+     * Get default attributes for this codec. 
+     *
+     * @param codec	The codec instance.
+     * @param attr	Pointer to receive default codec attributes.
+     *
+     * @return		PJ_SUCCESS on success.
+     */
+    pj_status_t (*default_attr)(pjmedia_codec *codec, 
+				pjmedia_codec_param *attr);
+
+    /** 
+     * Initialize codec using the specified attribute.
+     *
+     * @param codec	The codec instance.
+     * @param pool	Pool to use when the codec needs to allocate
+     *			some memory.
+     *
+     * @return		PJ_SUCCESS on success.
+     */
+    pj_status_t	(*init)(pjmedia_codec *codec, 
+			pj_pool_t *pool );
+
+    /** 
+     * Open the codec and initialize with the specified parameter..
+     *
+     * @param codec	The codec instance.
+     * @param param	Codec initialization parameter.
+     *
+     * @return		PJ_SUCCESS on success.
+     */
+    pj_status_t	(*open)(pjmedia_codec *codec, 
+			pjmedia_codec_param *param );
+
+    /** 
+     * Close and shutdown codec, releasing all resources allocated by
+     * this codec, if any.
+     *
+     * @param codec	The codec instance.
+     *
+     * @return		PJ_SUCCESS on success.
+     */
+    pj_status_t (*close)(pjmedia_codec *codec);
+
+
+    /** 
+     * Instruct the codec to encode the specified input frame.
+     *
+     * @param codec	The codec instance.
+     * @param input	The input frame.
+     * @param out_size	The length of buffer in the output frame.
+     * @param output	The output frame.
+     *
+     * @return		PJ_SUCCESS on success;
+     */
+    pj_status_t (*encode)(pjmedia_codec *codec, 
+			  const struct pjmedia_frame *input,
+			  unsigned out_size, 
+			  struct pjmedia_frame *output);
+
+    /** 
+     * Instruct the codec to decode the specified input frame.
+     *
+     * @param codec	The codec instance.
+     * @param input	The input frame.
+     * @param out_size	The length of buffer in the output frame.
+     * @param output	The output frame.
+     *
+     * @return		PJ_SUCCESS on success;
+     */
+    pj_status_t (*decode)(pjmedia_codec *codec, 
+			  const struct pjmedia_frame *input,
+			  unsigned out_size, 
+			  struct pjmedia_frame *output);
+
+};
+
+
+/**
+ * This structure describes a codec instance. 
+ */
+struct pjmedia_codec
 {
     /** Entries to put this codec instance in codec factory's list. */
-    PJ_DECL_LIST_MEMBER(struct pj_codec);
+    PJ_DECL_LIST_MEMBER(struct pjmedia_codec);
 
     /** Codec's private data. */
@@ -221,57 +228,88 @@
 
     /** Codec factory where this codec was allocated. */
-    pj_codec_factory *factory;
+    pjmedia_codec_factory *factory;
 
     /** Operations to codec. */
-    pj_codec_op	*op;
-};
-
-/**
- * This structure describes operations that must be supported by codec factories.
- */
-typedef struct pj_codec_factory_op
-{
-    /** Check whether the factory can create codec with the specified ID.
-     *  @param factory The codec factory.
-     *  @param id  The codec ID.
-     *  @return zero it matches.
-     */
-    pj_status_t	(*match_id)( pj_codec_factory *factory, const pj_codec_id *id );
-
-    /** Create default attributes for the specified codec ID. This function can
-     *  be called by application to get the capability of the codec.
-     *  @param factory The codec factory.
-     *  @param id  The codec ID.
-     *  @param attr The attribute to be initialized.
-     *  @return zero if success.
-     */
-    pj_status_t (*default_attr)( pj_codec_factory *factory, const pj_codec_id *id,
-				 pj_codec_attr *attr );
-
-    /** Enumerate supported codecs.
-     *  @param factory The codec factory.
-     *  @param count Number of entries in the array.
-     *  @param codecs The codec array.
-     *  @return the total number of supported codecs, which can be less or 
-     *          greater than requested.
-     */
-    unsigned (*enum_codecs) (pj_codec_factory *factory, unsigned count, pj_codec_id codecs[]);
-
-    /** This function is called by codec manager to instantiate one codec
-     *  instance.
-     *  @param factory The codec factory.
-     *  @param id  The codec ID.
-     *  @return the instance of the codec, or NULL if codec can not be created.
-     */
-    pj_codec* (*alloc_codec)( pj_codec_factory *factory, const pj_codec_id *id);
-
-    /** This function is called by codec manager to return a particular instance
-     *  of codec back to the codec factory.
-     *  @param factory The codec factory.
-     *  @param codec The codec instance to be returned.
-     */
-    void (*dealloc_codec)( pj_codec_factory *factory, pj_codec *codec );
-
-} pj_codec_factory_op;
+    pjmedia_codec_op	*op;
+};
+
+
+/**
+ * This structure describes operations that must be supported by codec 
+ * factories.
+ */
+struct pjmedia_codec_factory_op
+{
+    /** 
+     * Check whether the factory can create codec with the specified 
+     * codec info.
+     *
+     * @param factory	The codec factory.
+     * @param info	The codec info.
+     *
+     * @return		PJ_SUCCESS if this factory is able to create an
+     *			instance of codec with the specified info.
+     */
+    pj_status_t	(*test_alloc)(pjmedia_codec_factory *factory, 
+			      const pjmedia_codec_info *info );
+
+    /** 
+     * Create default attributes for the specified codec ID. This function
+     * can be called by application to get the capability of the codec.
+     *
+     * @param factory	The codec factory.
+     * @param info	The codec info.
+     * @param attr	The attribute to be initialized.
+     *
+     * @return		PJ_SUCCESS if success.
+     */
+    pj_status_t (*default_attr)(pjmedia_codec_factory *factory, 
+				const pjmedia_codec_info *info,
+				pjmedia_codec_param *attr );
+
+    /** 
+     * Enumerate supported codecs that can be created using this factory.
+     * 
+     *  @param factory	The codec factory.
+     *  @param count	On input, specifies the number of elements in
+     *			the array. On output, the value will be set to
+     *			the number of elements that have been initialized
+     *			by this function.
+     *  @param info	The codec info array, which contents will be 
+     *			initialized upon return.
+     *
+     *  @return		PJ_SUCCESS on success.
+     */
+    pj_status_t (*enum_info)(pjmedia_codec_factory *factory, 
+			     unsigned *count, 
+			     pjmedia_codec_info codecs[]);
+
+    /** 
+     * Create one instance of the codec with the specified codec info.
+     *
+     * @param factory	The codec factory.
+     * @param info	The codec info.
+     * @param p_codec	Pointer to receive the codec instance.
+     *
+     * @return		PJ_SUCCESS on success.
+     */
+    pj_status_t (*alloc_codec)(pjmedia_codec_factory *factory, 
+			       const pjmedia_codec_info *info,
+			       pjmedia_codec **p_codec);
+
+    /** 
+     * This function is called by codec manager to return a particular 
+     * instance of codec back to the codec factory.
+     *
+     * @param factory	The codec factory.
+     * @param codec	The codec instance to be returned.
+     *
+     * @return		PJ_SUCCESS on success.
+     */
+    pj_status_t (*dealloc_codec)(pjmedia_codec_factory *factory, 
+				 pjmedia_codec *codec );
+
+};
+
 
 /**
@@ -280,14 +318,14 @@
  * instances of codec.
  */
-struct pj_codec_factory
+struct pjmedia_codec_factory
 {
     /** Entries to put this structure in the codec manager list. */
-    PJ_DECL_LIST_MEMBER(struct pj_codec_factory);
+    PJ_DECL_LIST_MEMBER(struct pjmedia_codec_factory);
 
     /** The factory's private data. */
-    void		*factory_data;
+    void		     *factory_data;
 
     /** Operations to the factory. */
-    pj_codec_factory_op *op;
+    pjmedia_codec_factory_op *op;
 
 };
@@ -296,51 +334,95 @@
  * Declare maximum codecs
  */
-#define PJ_CODEC_MGR_MAX_CODECS	    32
+#define PJMEDIA_CODEC_MGR_MAX_CODECS	    32
 
 /**
  * Codec manager maintains codec factory etc.
  */
-typedef struct pj_codec_mgr
-{
-    pj_codec_factory factory_list;
-    unsigned	     codec_cnt;
-    pj_codec_id	     codecs[PJ_CODEC_MGR_MAX_CODECS];
-} pj_codec_mgr;
-
-/**
- * Init codec manager.
+typedef struct pjmedia_codec_mgr
+{
+    pjmedia_codec_factory   factory_list;
+    unsigned		    codec_cnt;
+    pjmedia_codec_info	    codecs[PJMEDIA_CODEC_MGR_MAX_CODECS];
+} pjmedia_codec_mgr;
+
+
+
+/**
+ * Initialize codec manager.
+ *
+ * @param mgr	    Codec manager instance.
+ *
+ * @return	    PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_codec_mgr_init(pjmedia_codec_mgr *mgr);
+
+
+/** 
+ * Register codec factory to codec manager. 
+ *
+ * @param mgr	    The codec manager.
+ * @param factory   The codec factory to be registered.
+ *
+ * @return	    PJ_SUCCESS on success.
  */
 PJ_DECL(pj_status_t) 
-pj_codec_mgr_init (pj_codec_mgr *mgr);
-
-/** 
- * Register codec to codec manager. 
+pjmedia_codec_mgr_register_factory( pjmedia_codec_mgr *mgr,
+				    pjmedia_codec_factory *factory);
+
+/**
+ * Unregister codec factory from the codec manager.
+ *
+ * @param mgr	    The codec manager.
+ * @param factory   The codec factory to be unregistered.
+ *
+ * @return	    PJ_SUCCESS on success.
  */
 PJ_DECL(pj_status_t) 
-pj_codec_mgr_register_factory (pj_codec_mgr *mgr, pj_codec_factory *factory);
-
-/**
- * Unregister codec.
- */
-PJ_DECL(void) 
-pj_codec_mgr_unregister_factory (pj_codec_mgr *mgr, pj_codec_factory *factory);
-
-/**
- * Enumerate codecs.
- */
-PJ_DECL(unsigned)
-pj_codec_mgr_enum_codecs (pj_codec_mgr *mgr, unsigned count, const pj_codec_id *codecs[]);
-
-/**
- * Open codec.
- */
-PJ_DECL(pj_codec*) 
-pj_codec_mgr_alloc_codec (pj_codec_mgr *mgr, const struct pj_codec_id *id);
-
-/**
- * Close codec.
- */
-PJ_DECL(void) 
-pj_codec_mgr_dealloc_codec (pj_codec_mgr *mgr, pj_codec *codec);
+pjmedia_codec_mgr_unregister_factory( pjmedia_codec_mgr *mgr, 
+				      pjmedia_codec_factory *factory);
+
+/**
+ * Enumerate all supported codec.
+ *
+ * @param mgr	    The codec manager.
+ * @param count	    On input, specifies the number of elements in
+ *		    the array. On output, the value will be set to
+ *		    the number of elements that have been initialized
+ *		    by this function.
+ * @param info	    The codec info array, which contents will be 
+ *		    initialized upon return.
+ *
+ * @return	    PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_codec_mgr_enum_codecs( pjmedia_codec_mgr *mgr, 
+						    unsigned *count, 
+						    pjmedia_codec_info info[]);
+
+/**
+ * Request the codec manager to allocate one instance of codec with the
+ * specified codec info. The codec will enumerate all codec factories
+ * until it finds factory that is able to create the specified codec.
+ *
+ * @param mgr	    The codec manager.
+ * @param info	    The information about the codec to be created.
+ * @param p_codec   Pointer to receive the codec instance.
+ *
+ * @return	    PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_codec_mgr_alloc_codec(pjmedia_codec_mgr *mgr, 
+						   const pjmedia_codec_info *info,
+						   pjmedia_codec **p_codec);
+
+/**
+ * Deallocate the specified codec instance. The codec manager will return
+ * the instance of the codec back to its factory.
+ *
+ * @param mgr	    The codec manager.
+ * @param codec	    The codec instance.
+ *
+ * @return	    PJ_SUCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_codec_mgr_dealloc_codec(pjmedia_codec_mgr *mgr, 
+						     pjmedia_codec *codec);
 
 /**
Index: pjproject/trunk/pjmedia/include/pjmedia/endpoint.h
===================================================================
--- pjproject/trunk/pjmedia/include/pjmedia/endpoint.h	(revision 159)
+++ pjproject/trunk/pjmedia/include/pjmedia/endpoint.h	(revision 159)
@@ -0,0 +1,131 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#ifndef __PJMEDIA_MEDIAMGR_H__
+#define __PJMEDIA_MEDIAMGR_H__
+
+
+/**
+ * @file mediamgr.h
+ * @brief Media Manager.
+ */
+/**
+ * @defgroup PJMED_ENDPT Media Endpoint
+ * @ingroup PJMEDIA
+ * @{
+ *
+ * The media endpoint acts as placeholder for endpoint capabilities. Each 
+ * media endpoint will have a codec manager to manage list of codecs installed
+ * in the endpoint and a sound device factory.
+ *
+ * A reference to media endpoint instance is required when application wants
+ * to create a media session (#pj_media_session_create or 
+ * #pj_media_session_create_from_sdp).
+ */
+
+#include <pjmedia/sound.h>
+#include <pjmedia/codec.h>
+
+
+PJ_BEGIN_DECL
+
+
+
+/**
+ * Create an instance of media endpoint.
+ *
+ * @param pf		Pool factory, which will be used by the media endpoint
+ *			throughout its lifetime.
+ * @param p_endpt	Pointer to receive the endpoint instance.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_endpt_create( pj_pool_factory *pf,
+					   pjmedia_endpt **p_endpt);
+
+/**
+ * Destroy media endpoint instance.
+ *
+ * @param endpt		Media endpoint instance.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_endpt_destroy(pjmedia_endpt *endpt);
+
+
+/**
+ * Request the media endpoint to create pool.
+ *
+ * @param endpt		The media endpoint instance.
+ * @param name		Name to be assigned to the pool.
+ * @param initial	Initial pool size, in bytes.
+ * @param increment	Increment size, in bytes.
+ *
+ * @return		Memory pool.
+ */
+PJ_DECL(pj_pool_t*) pjmedia_endpt_create_pool( pjmedia_endpt *endpt,
+					       const char *name,
+					       pj_size_t initial,
+					       pj_size_t increment);
+
+/**
+ * Get the codec manager instance of the media endpoint.
+ *
+ * @param endpt		The media endpoint instance.
+ *
+ * @return		The instance of codec manager belonging to
+ *			this media endpoint.
+ */
+PJ_DECL(pjmedia_codec_mgr*) pjmedia_endpt_get_codec_mgr(pjmedia_endpt *mgr);
+
+
+/**
+ * Create a SDP session description that describes the endpoint
+ * capability.
+ *
+ * @param endpt		The media endpoint.
+ * @param pool		Pool to use to create the SDP descriptor.
+ * @param stream_cnt	Number of elements in the sock_info array. This
+ *			also denotes the maximum number of streams (i.e.
+ *			the "m=" lines) that will be created in the SDP.
+ * @param sock_info	Array of socket transport information. One 
+ *			transport is needed for each media stream, and
+ *			each transport consists of an RTP and RTCP socket
+ *			pair.
+ * @param p_sdp		Pointer to receive SDP session descriptor.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_endpt_create_sdp( pjmedia_endpt *endpt,
+					       pj_pool_t *pool,
+					       unsigned stream_cnt,
+					       const pjmedia_sock_info sock_info[],
+					       pjmedia_sdp_session **p_sdp );
+
+
+
+PJ_END_DECL
+
+
+/**
+ * @}
+ */
+
+
+
+#endif	/* __PJMEDIA_MEDIAMGR_H__ */
Index: pjproject/trunk/pjmedia/include/pjmedia/errno.h
===================================================================
--- pjproject/trunk/pjmedia/include/pjmedia/errno.h	(revision 158)
+++ pjproject/trunk/pjmedia/include/pjmedia/errno.h	(revision 159)
@@ -260,4 +260,40 @@
 
 
+/************************************************************
+ * CODEC
+ ***********************************************************/
+/**
+ * @hideinitializer
+ * Unsupported codec.
+ */
+#define PJMEDIA_CODEC_EUNSUP	    (PJMEDIA_ERRNO_START+80)    /* 220080 */
+
+
+/************************************************************
+ * MEDIA
+ ***********************************************************/
+/**
+ * @hideinitializer
+ * Invalid remote IP address (in SDP).
+ */
+#define PJMEDIA_EINVALIDIP	    (PJMEDIA_ERRNO_START+100)    /* 220100 */
+/**
+ * @hideinitializer
+ * Asymetric codec is not supported.
+ */
+#define PJMEDIA_EASYMCODEC	    (PJMEDIA_ERRNO_START+101)    /* 220101 */
+/**
+ * @hideinitializer
+ * Invalid payload type.
+ */
+#define PJMEDIA_EINVALIDPT	    (PJMEDIA_ERRNO_START+102)    /* 220102 */
+/**
+ * @hideinitializer
+ * Missing rtpmap.
+ */
+#define PJMEDIA_EMISSINGRTPMAP	    (PJMEDIA_ERRNO_START+103)    /* 220103 */
+
+
+
 PJ_END_DECL
 
Index: pjproject/trunk/pjmedia/include/pjmedia/mediamgr.h
===================================================================
--- pjproject/trunk/pjmedia/include/pjmedia/mediamgr.h	(revision 158)
+++ 	(revision )
@@ -1,100 +1,0 @@
-/* $Id$ */
-/* 
- * Copyright (C) 2003-2006 Benny Prijono <benny@prijono.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
- */
-#ifndef __PJMEDIA_MEDIAMGR_H__
-#define __PJMEDIA_MEDIAMGR_H__
-
-
-/**
- * @file mediamgr.h
- * @brief Media Manager.
- */
-/**
- * @defgroup PJMED_MGR Media Manager
- * @ingroup PJMEDIA
- * @{
- *
- * The media manager acts as placeholder for endpoint capabilities. Each 
- * media manager will have a codec manager to manage list of codecs installed
- * in the endpoint and a sound device factory.
- *
- * A reference to media manager instance is required when application wants
- * to create a media session (#pj_media_session_create or 
- * #pj_media_session_create_from_sdp).
- */
-
-#include <pjmedia/sound.h>
-#include <pjmedia/codec.h>
-
-
-PJ_BEGIN_DECL
-
-
-/** Opague declaration of media manager. */
-typedef struct pj_med_mgr_t pj_med_mgr_t;
-
-/**
- * Create an instance of media manager.
- *
- * @param pf		Pool factory.
- * @param conn_addr	Connection address to be used by this media manager.
- *
- * @return A new instance of media manager, or NULL if failed.
- */
-PJ_DECL(pj_med_mgr_t*) pj_med_mgr_create (pj_pool_factory *pf);
-
-/**
- * Destroy media manager instance.
- *
- * @param mgr		Media manager instance.
- *
- * @return zero on success.
- */
-PJ_DECL(pj_status_t) pj_med_mgr_destroy (pj_med_mgr_t *mgr);
-
-/**
- * Get pool factory of the media manager as specified when the media
- * manager was created.
- *
- * @param mgr		The media manager instance.
- *
- * @return Pool factory instance of the media manager.
- */
-PJ_DECL(pj_pool_factory*) pj_med_mgr_get_pool_factory (pj_med_mgr_t *mgr);
-
-/**
- * Get the codec manager instance.
- *
- * @param mgr		The media manager instance.
- *
- * @return The instance of codec manager.
- */
-PJ_DECL(pj_codec_mgr*) pj_med_mgr_get_codec_mgr (pj_med_mgr_t *mgr);
-
-
-
-PJ_END_DECL
-
-
-/**
- * @}
- */
-
-
-
-#endif	/* __PJMEDIA_MEDIAMGR_H__ */
Index: pjproject/trunk/pjmedia/include/pjmedia/rtp.h
===================================================================
--- pjproject/trunk/pjmedia/include/pjmedia/rtp.h	(revision 158)
+++ pjproject/trunk/pjmedia/include/pjmedia/rtp.h	(revision 159)
@@ -80,12 +80,12 @@
 enum pj_rtp_error_t
 {
-    PJ_RTP_ERR_RTP_PACKING,	    /**< Invalid RTP packet. */
-    PJ_RTP_ERR_INVALID_VERSION,	    /**< Invalid RTP version. */
-    PJ_RTP_ERR_INVALID_SSRC,	    /**< Invalid SSRC. */
-    PJ_RTP_ERR_INVALID_PT,	    /**< Invalid payload type. */
-    PJ_RTP_ERR_INVALID_PACKET,	    /**< Invalid packet. */
-    PJ_RTP_ERR_SESSION_RESTARTED,   /**< Session has just been restarted. */
-    PJ_RTP_ERR_SESSION_PROBATION,   /**< Session in probation. */
-    PJ_RTP_ERR_BAD_SEQUENCE,	    /**< Bad RTP sequence number. */
+    PJMEDIA_RTP_ERR_RTP_PACKING,	    /**< Invalid RTP packet. */
+    PJMEDIA_RTP_ERR_INVALID_VERSION,	    /**< Invalid RTP version. */
+    PJMEDIA_RTP_ERR_INVALID_SSRC,	    /**< Invalid SSRC. */
+    PJMEDIA_RTP_ERR_INVALID_PT,	    /**< Invalid payload type. */
+    PJMEDIA_RTP_ERR_INVALID_PACKET,	    /**< Invalid packet. */
+    PJMEDIA_RTP_ERR_SESSION_RESTARTED,   /**< Session has just been restarted. */
+    PJMEDIA_RTP_ERR_SESSION_PROBATION,   /**< Session in probation. */
+    PJMEDIA_RTP_ERR_BAD_SEQUENCE,	    /**< Bad RTP sequence number. */
 };
 
Index: pjproject/trunk/pjmedia/include/pjmedia/session.h
===================================================================
--- pjproject/trunk/pjmedia/include/pjmedia/session.h	(revision 158)
+++ pjproject/trunk/pjmedia/include/pjmedia/session.h	(revision 159)
@@ -26,6 +26,5 @@
  */
 
-#include <pj/types.h>
-#include <pjmedia/mediamgr.h>
+#include <pjmedia/endpoint.h>
 #include <pjmedia/stream.h>
 #include <pjmedia/sdp.h>
@@ -39,107 +38,138 @@
  */
 
-/** Opaque declaration of media session. */
-typedef struct pj_media_session_t pj_media_session_t;
-
-/** Media socket info. */
-typedef struct pj_media_sock_info
-{
-    pj_sock_t	    rtp_sock, rtcp_sock;
-    pj_sockaddr_in  rtp_addr_name;
-} pj_media_sock_info;
-
-/** Stream info. */
-typedef struct pj_media_stream_info
-{
-    pj_str_t		type;
-    pj_media_dir_t	dir;
-    pj_str_t		transport;
-    pj_media_sock_info	sock_info;
-    pj_str_t		rem_addr;
-    unsigned short	rem_port;
-    unsigned		fmt_cnt;
-    pj_codec_id		fmt[PJSDP_MAX_FMT];
-
-} pj_media_stream_info;
-
-/** Flag for modifying stream. */
-enum
-{
-    PJ_MEDIA_STREAM_MODIFY_DIR = 1,
-};
 
 /**
- * Create new session offering.
+ * Create new session offering based on the local and remote SDP.
+ * The session initially will be inactive.
+ *
+ * @param endpt		The PJMEDIA endpoint instance.
+ * @param stream_cnt	Maximum number of streams to be created. This
+ *			also denotes the number of elements in the
+ *			socket information.
+ * @param skinfo	Array of socket informations. The argument stream_cnt
+ *			specifies the number of elements in this array. One
+ *			element is needed for each media stream to be
+ *			created in the session.
+ * @param local_sdp	The SDP describing local capability.
+ * @param rem_sdp	The SDP describing remote capability.
+ * @param p_session	Pointer to receive the media session.
+ *
+ * @return		PJ_SUCCESS if media session can be created 
+ *			successfully.
  */
-PJ_DECL(pj_media_session_t*) 
-pj_media_session_create ( pj_med_mgr_t *mgr, const pj_media_sock_info *skinfo );
+PJ_DECL(pj_status_t) pjmedia_session_create( pjmedia_endpt *endpt, 
+					     unsigned stream_cnt,
+					     const pjmedia_sock_info skinfo[],
+					     const pjmedia_sdp_session *local_sdp,
+					     const pjmedia_sdp_session *rem_sdp,
+					     pjmedia_session **p_session );
+
 
 /**
- * Create new session based on peer's offering.
+ * Activate all streams in media session for the specified direction.
+ *
+ * @param session	The media session.
+ * @param dir		The direction to activate.
+ *
+ * @return		PJ_SUCCESS if success.
  */
-PJ_DECL(pj_media_session_t*) 
-pj_media_session_create_from_sdp ( pj_med_mgr_t *mgr, const pjsdp_session_desc *sdp,
-				   const pj_media_sock_info *skinfo);
+PJ_DECL(pj_status_t) pjmedia_session_resume(pjmedia_session *session,
+					    pjmedia_dir dir);
+
 
 /**
- * Duplicate session. The new session is inactive.
+ * Suspend receipt and transmission of all streams in media session
+ * for the specified direction.
+ *
+ * @param session	The media session.
+ * @param dir		The media direction to suspend.
+ *
+ * @return		PJ_SUCCESS if success.
  */
-PJ_DECL(pj_media_session_t*)
-pj_media_session_clone (const pj_media_session_t *session);
+PJ_DECL(pj_status_t) pjmedia_session_pause(pjmedia_session *session,
+					   pjmedia_dir dir);
 
 /**
- * Create SDP description from the session.
+ * Suspend receipt and transmission of individual stream in media session
+ * for the specified direction.
+ *
+ * @param session	The media session.
+ * @param index		The stream index.
+ * @param dir		The media direction to pause.
+ *
+ * @return		PJ_SUCCESS on success.
  */
-PJ_DECL(pjsdp_session_desc*)
-pj_media_session_create_sdp ( const pj_media_session_t *session, pj_pool_t *pool,
-			      pj_bool_t only_first_fmt);
+PJ_DECL(pj_status_t) pjmedia_session_pause_stream( pjmedia_session *session,
+						   unsigned index,
+						   pjmedia_dir dir);
 
 /**
- * Update session with SDP answer from peer. The session must NOT active.
+ * Activate individual stream in media session for the specified direction.
+ *
+ * @param session	The media session.
+ * @param index		The stream index.
+ * @param dir		The media direction to activate.
+ *
+ * @return		PJ_SUCCESS on success.
  */
-PJ_DECL(pj_status_t)
-pj_media_session_update ( pj_media_session_t *session, 
-			  const pjsdp_session_desc *sdp);
+PJ_DECL(pj_status_t) pjmedia_session_resume_stream(pjmedia_session *session,
+						   unsigned index,
+						   pjmedia_dir dir);
 
 /**
  * Enumerate media streams in the session.
- * @return the actual number of streams.
+ *
+ * @param session	The media session.
+ * @param count		On input, specifies the number of elements in
+ *			the array. On output, the number will be filled
+ *			with number of streams in the session.
+ * @param strm_info	Array of stream info.
+ *
+ * @return		PJ_SUCCESS on success.
  */
-PJ_DECL(unsigned)
-pj_media_session_enum_streams (const pj_media_session_t *session, 
-			       unsigned count, const pj_media_stream_info *info[]);
+PJ_DECL(pj_status_t) pjmedia_session_enum_streams(const pjmedia_session *session,
+						  unsigned *count, 
+						  pjmedia_stream_info strm_info[]);
+
 
 /**
- * Get stream statistics.
+ * Get session statistics. The stream statistic shows various
+ * indicators such as packet count, packet lost, jitter, delay, etc.
+ *
+ * @param session	The media session.
+ * @param count		On input, specifies the number of elements in
+ *			the array. On output, the number will be filled
+ *			with number of streams in the session.
+ * @param stat		Array of stream statistics.
+ *
+ * @return		PJ_SUCCESS on success.
  */
-PJ_DECL(pj_status_t)
-pj_media_session_get_stat (const pj_media_session_t *session, unsigned index,
-			   pj_media_stream_stat *tx_stat,
-			   pj_media_stream_stat *rx_stat);
+PJ_DECL(pj_status_t) pjmedia_session_get_stat(const pjmedia_session *session,
+					      unsigned *count,
+					      pjmedia_stream_stat stat[]);
 
 /**
- * Modify stream, only when stream is inactive.
+ * Get individual stream statistics. The stream statistic shows various
+ * indicators such as packet count, packet lost, jitter, delay, etc.
+ *
+ * @param s		The media session.
+ * @param index		The stream index.
+ * @param stat		Stream statistics.
+ *
+ * @return		PJ_SUCCESS on success.
  */
-PJ_DECL(pj_status_t)
-pj_media_session_modify_stream (pj_media_session_t *session, unsigned index,
-				unsigned modify_flag, const pj_media_stream_info *info);
-
-/**
- * Activate all streams in media session.
- */
-PJ_DECL(pj_status_t)
-pj_media_session_activate (pj_media_session_t *session);
-
-/**
- * Activate individual stream in media session.
- */
-PJ_DECL(pj_status_t)
-pj_media_session_activate_stream (pj_media_session_t *session, unsigned index);
+PJ_DECL(pj_status_t) pjmedia_session_get_stream_stat(const pjmedia_session *s,
+						     unsigned index,
+						     pjmedia_stream_stat *stat);
 
 /**
  * Destroy media session.
+ *
+ * @param session	The media session.
+ *
+ * @return		PJ_SUCCESS if success.
  */
-PJ_DECL(pj_status_t)
-pj_media_session_destroy (pj_media_session_t *session);
+PJ_DECL(pj_status_t) pjmedia_session_destroy(pjmedia_session *session);
+
 
 
Index: pjproject/trunk/pjmedia/include/pjmedia/stream.h
===================================================================
--- pjproject/trunk/pjmedia/include/pjmedia/stream.h	(revision 158)
+++ pjproject/trunk/pjmedia/include/pjmedia/stream.h	(revision 159)
@@ -28,5 +28,5 @@
 #include <pjmedia/sound.h>
 #include <pjmedia/codec.h>
-#include <pjmedia/mediamgr.h>
+#include <pjmedia/endpoint.h>
 #include <pj/sock.h>
 
@@ -40,53 +40,122 @@
  */
 
-typedef struct pj_media_stream_t pj_media_stream_t;
+/**
+ * Opaque declaration for media channel.
+ * Media channel is unidirectional flow of media from sender to
+ * receiver.
+ */
+typedef struct pjmedia_channel pjmedia_channel;
 
-/** Parameter for creating channel. */
-typedef struct pj_media_stream_create_param
+/** 
+ * This structure describes media stream information. Each media stream
+ * corresponds to one "m=" line in SDP session descriptor, and it has
+ * its own RTP/RTCP socket pair.
+ */
+struct pjmedia_stream_info
 {
-    /** Codec ID, must NOT be NULL. */
-    pj_codec_id		 *codec_id;
+    pjmedia_type	type;	    /**< Media type (audio, video)	    */
+    pjmedia_dir		dir;	    /**< Media direction.		    */
+    pjmedia_sock_info	sock_info;  /**< Media transport (RTP/RTCP sockets) */
+    pj_sockaddr_in	rem_addr;   /**< Remote RTP address		    */
+    pjmedia_codec_info	fmt;	    /**< Codec format info.		    */
+    pj_uint32_t		ssrc;	    /**< RTP SSRC.			    */
+    int			jb_min;	    /**< Jitter buffer min delay.	    */
+    int			jb_max;	    /**< Jitter buffer max delay.	    */
+    int			jb_maxcnt;  /**< Jitter buffer max delay.	    */
+};
 
-    /** Media manager, must NOT be NULL. */
-    pj_med_mgr_t	 *mediamgr;
 
-    /** Direction: IN_OUT, or IN only, or OUT only. */
-    pj_media_dir_t	  dir;
+/**
+ * Individual channel statistic.
+ */
+struct pjmedia_channel_stat
+{
+    pj_uint32_t pkt;	    /**< Total number of packets.		    */
+    pj_uint32_t bytes;	    /**< Total number of bytes, including RTP hdr.  */
+    pj_uint32_t lost;	    /**< Total number of packet lost		    */
+};
 
-    /** RTP socket. */
-    pj_sock_t		 rtp_sock;
+/**
+ * Stream statistic.
+ */
+struct pjmedia_stream_stat
+{
+    pjmedia_channel_stat    enc;    /**< Encoder statistics.		    */
+    pjmedia_channel_stat    dec;    /**< Decoder statistics.		    */
+};
 
-    /** RTCP socket. */
-    pj_sock_t		 rtcp_sock;
 
-    /** Address of remote */
-    pj_sockaddr_in	 *remote_addr;
+/**
+ * Create a media stream based on the specified stream parameter.
+ * All channels in the stream initially will be inactive.
+ *
+ * @param endpt		Media endpoint.
+ * @param pool		Pool to allocate memory for the stream. A large
+ *			number of memory may be needed because jitter
+ *			buffer needs to preallocate some storage.
+ * @param info		Stream information.
+ * @param p_stream	Pointer to receive the media stream.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_stream_create(pjmedia_endpt *endpt,
+					   pj_pool_t *pool,
+					   const pjmedia_stream_info *info,
+					   pjmedia_stream **p_stream);
 
-    /** RTP SSRC */
-    pj_uint32_t		  ssrc;
+/**
+ * Destroy the media stream.
+ *
+ * @param stream	The media stream.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_stream_destroy(pjmedia_stream *stream);
 
-    /** Jitter buffer parameters. */
-    int			  jb_min, jb_max, jb_maxcnt;
+/**
+ * Start the media stream. This will start the appropriate channels
+ * in the media stream, depending on the media direction that was set
+ * when the stream was created.
+ *
+ * @param stream	The media stream.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_stream_start(pjmedia_stream *stream);
 
-} pj_media_stream_create_param;
 
-typedef struct pj_media_stream_stat
-{
-    pj_uint32_t pkt_tx, pkt_rx;	/* packets transmitted/received */
-    pj_uint32_t oct_tx, oct_rx;	/* octets transmitted/received */
-    pj_uint32_t jitter;		/* receive jitter in ms */
-    pj_uint32_t pkt_lost;	/* total packet lost count */
-} pj_media_stream_stat;
+/**
+ * Get the stream statistics.
+ *
+ * @param stream	The media stream.
+ * @param stat		Media stream statistics.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_stream_get_stat( const pjmedia_stream *stream,
+					      pjmedia_stream_stat *stat);
 
-PJ_DECL(pj_status_t) pj_media_stream_create (pj_pool_t *pool,
-					     pj_media_stream_t **enc_stream,
-					     pj_media_stream_t **dec_stream,
-					     pj_media_stream_create_param *param);
-PJ_DECL(pj_status_t) pj_media_stream_start (pj_media_stream_t *stream);
-PJ_DECL(pj_status_t) pj_media_stream_get_stat (const pj_media_stream_t *stream,
-					       pj_media_stream_stat *stat);
-PJ_DECL(pj_status_t) pj_media_stream_pause (pj_media_stream_t *stream);
-PJ_DECL(pj_status_t) pj_media_stream_resume (pj_media_stream_t *stream);
-PJ_DECL(pj_status_t) pj_media_stream_destroy (pj_media_stream_t *stream);
+/**
+ * Pause the individual channel in the stream.
+ *
+ * @param channel	The media channel.
+ * @param dir		Which direction to pause.
+ *
+ * @return		PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_stream_pause( pjmedia_stream *stream,
+					   pjmedia_dir dir);
+
+/**
+ * Resume the individual channel in the stream.
+ *
+ * @param channel	The media channel.
+ * @param dir		Which direction to resume.
+ *
+ * @return		PJ_SUCCESS on success;
+ */
+PJ_DECL(pj_status_t) pjmedia_stream_resume(pjmedia_stream *stream,
+					   pjmedia_dir dir);
+
 
 /**
Index: pjproject/trunk/pjmedia/include/pjmedia/types.h
===================================================================
--- pjproject/trunk/pjmedia/include/pjmedia/types.h	(revision 158)
+++ pjproject/trunk/pjmedia/include/pjmedia/types.h	(revision 159)
@@ -21,5 +21,147 @@
 
 #include <pj/types.h>
-
+#include <pj/sock.h>
+
+
+/** 
+ * Top most media type. 
+ */
+enum pjmedia_type
+{
+    /** No type. */
+    PJMEDIA_TYPE_NONE = 0,
+
+    /** The media is audio */
+    PJMEDIA_TYPE_AUDIO = 1,
+
+    /** The media is video. */
+    PJMEDIA_TYPE_VIDEO = 2,
+
+    /** Unknown media type, in this case the name will be specified in 
+     *  encoding_name.
+     */
+    PJMEDIA_TYPE_UNKNOWN = 3,
+
+};
+
+
+/** 
+ * Media direction. 
+ */
+enum pjmedia_dir
+{
+    /** None */
+    PJMEDIA_DIR_NONE = 0,
+
+    /** Encoding (outgoing to network) stream */
+    PJMEDIA_DIR_ENCODING = 1,
+
+    /** Decoding (incoming from network) stream. */
+    PJMEDIA_DIR_DECODING = 2,
+
+    /** Incoming and outgoing stream. */
+    PJMEDIA_DIR_ENCODING_DECODING = 3,
+
+};
+
+
+/**
+ * Top level media type.
+ */
+typedef enum pjmedia_type pjmedia_type;
+
+/**
+ * Media direction.
+ */
+typedef enum pjmedia_dir pjmedia_dir;
+
+/**
+ * Codec info.
+ */
+typedef struct pjmedia_codec_info pjmedia_codec_info;
+
+/**
+ * Codec initialization parameter.
+ */
+typedef struct pjmedia_codec_param pjmedia_codec_param;
+
+/** 
+ * Types of media frames. 
+ */
+typedef enum pjmedia_frame_type pjmedia_frame_type;
+
+/** 
+ * This structure describes a media frame. 
+ */
+typedef struct pjmedia_frame pjmedia_frame;
+
+/**
+ * Codec instance.
+ */
+typedef struct pjmedia_codec pjmedia_codec;
+
+/**
+ * Codec factory.
+ */
+typedef struct pjmedia_codec_factory pjmedia_codec_factory;
+
+/**
+ * Codec operation.
+ */
+typedef struct pjmedia_codec_op pjmedia_codec_op;
+
+/**
+ * Codec factory operation.
+ */
+typedef struct pjmedia_codec_factory_op pjmedia_codec_factory_op;
+
+/**
+ * Codec manager.
+ */
+typedef struct pjmedia_codec_mgr pjmedia_codec_mgr;
+
+/** 
+ * Opague declaration of media endpoint. 
+ */
+typedef struct pjmedia_endpt pjmedia_endpt;
+
+
+/** 
+ * Media socket info. 
+ */
+typedef struct pjmedia_sock_info
+{
+
+    pj_sock_t	    rtp_sock;
+    pj_sock_t	    rtcp_sock;
+    pj_sockaddr_in  rtp_addr_name;
+
+} pjmedia_sock_info;
+
+
+/**
+ * Typedef for media stream information.
+ */
+typedef struct pjmedia_stream_info pjmedia_stream_info;
+
+/**
+ * Typedef for media stream statistic.
+ */
+typedef struct pjmedia_stream_stat pjmedia_stream_stat;
+
+/**
+ * Typedef for media stream.
+ */
+typedef struct pjmedia_stream pjmedia_stream;
+
+/**
+ * Individual channel statistic.
+ */
+typedef struct pjmedia_channel_stat pjmedia_channel_stat;
+
+/** 
+ * Opaque declaration of media session. 
+ */
+typedef struct pjmedia_session pjmedia_session;
 
 /**
Index: pjproject/trunk/pjmedia/src/pjmedia/codec.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/codec.c	(revision 158)
+++ pjproject/trunk/pjmedia/src/pjmedia/codec.c	(revision 159)
@@ -18,4 +18,5 @@
  */
 #include <pjmedia/codec.h>
+#include <pjmedia/errno.h>
 #include <pj/pool.h>
 #include <pj/string.h>
@@ -25,83 +26,136 @@
 #define THIS_FILE   "codec.c"
 
-static void enum_all_codecs (pj_codec_mgr *cm)
+/*
+ * Reinitialize array of supported codecs.
+ */
+static void enum_all_codecs (pjmedia_codec_mgr *mgr)
 {
-    pj_codec_factory *cf;
+    pjmedia_codec_factory *factory;
 
-    cf = cm->factory_list.next;
-    cm->codec_cnt = 0;
-    while (cf != &cm->factory_list) {
-	pj_codec_id temp[PJ_CODEC_MGR_MAX_CODECS];
-	int i, cnt;
+    mgr->codec_cnt = 0;
 
-	cnt = cf->op->enum_codecs (cf, PJ_CODEC_MGR_MAX_CODECS, temp);
-	if (cnt > PJ_CODEC_MGR_MAX_CODECS) {
-	    pj_assert(0);
-	    PJ_LOG(4, (THIS_FILE, "Too many codecs reported by factory"));
-	    cnt = PJ_CODEC_MGR_MAX_CODECS;
-	}
+    factory = mgr->factory_list.next;
+    while (factory != &mgr->factory_list) {
+	unsigned count;
+	pj_status_t status;
 
-	for (i=0; i<cnt && cm->codec_cnt < PJ_CODEC_MGR_MAX_CODECS; ++i) {
-	    cm->codecs[cm->codec_cnt++] = temp[i];
-	}
+	count = PJ_ARRAY_SIZE(mgr->codecs) - mgr->codec_cnt;
+	status = factory->op->enum_info(factory, &count, 
+					mgr->codecs+mgr->codec_cnt);
+	if (status == PJ_SUCCESS)
+	    mgr->codec_cnt += count;
 
-	cf = cf->next;
+	factory = factory->next;
     }
 }
 
-PJ_DEF(pj_status_t) pj_codec_mgr_init (pj_codec_mgr *mgr)
+/*
+ * Initialize codec manager.
+ */
+PJ_DEF(pj_status_t) pjmedia_codec_mgr_init (pjmedia_codec_mgr *mgr)
 {
+    PJ_ASSERT_RETURN(mgr, PJ_EINVAL);
+
     pj_list_init (&mgr->factory_list);
     mgr->codec_cnt = 0;
-    return 0;
+
+    return PJ_SUCCESS;
 }
 
-PJ_DEF(pj_status_t) pj_codec_mgr_register_factory (pj_codec_mgr *mgr,
-						   pj_codec_factory *factory)
+/*
+ * Register a codec factory.
+ */
+PJ_DEF(pj_status_t) 
+pjmedia_codec_mgr_register_factory( pjmedia_codec_mgr *mgr,
+				    pjmedia_codec_factory *factory)
 {
-    pj_list_insert_before (&mgr->factory_list, factory);
+    PJ_ASSERT_RETURN(mgr && factory, PJ_EINVAL);
+
+    pj_list_push_back(&mgr->factory_list, factory);
     enum_all_codecs (mgr);
-    return 0;
+
+    return PJ_SUCCESS;
 }
 
-PJ_DEF(void) pj_codec_mgr_unregister_factory (pj_codec_mgr *mgr, pj_codec_factory *factory)
+/*
+ * Unregister a codec factory.
+ */
+PJ_DEF(pj_status_t) 
+pjmedia_codec_mgr_unregister_factory(pjmedia_codec_mgr *mgr, 
+				     pjmedia_codec_factory *factory)
 {
-    PJ_UNUSED_ARG(mgr);
+
+    PJ_ASSERT_RETURN(mgr && factory, PJ_EINVAL);
+
+    /* Factory must be registered. */
+    PJ_ASSERT_RETURN(pj_list_find_node(&mgr->factory_list, factory)==factory,
+		     PJ_ENOTFOUND);
+
+
     pj_list_erase(factory);
     enum_all_codecs (mgr);
+
+    return PJ_SUCCESS;
 }
 
-PJ_DEF(unsigned)
-pj_codec_mgr_enum_codecs (pj_codec_mgr *mgr, unsigned count, const pj_codec_id *codecs[])
+/*
+ * Enum all codecs.
+ */
+PJ_DEF(pj_status_t)
+pjmedia_codec_mgr_enum_codecs(pjmedia_codec_mgr *mgr, 
+			      unsigned *count, 
+			      pjmedia_codec_info codecs[])
 {
-    unsigned i;
+    PJ_ASSERT_RETURN(mgr && count && codecs, PJ_EINVAL);
 
-    if (count > mgr->codec_cnt)
-	count = mgr->codec_cnt;
+    if (*count > mgr->codec_cnt)
+	*count = mgr->codec_cnt;
+    
+    pj_memcpy(codecs, mgr->codecs, *count * sizeof(pjmedia_codec_info));
 
-    for (i=0; i<count; ++i)
-	codecs[i] = &mgr->codecs[i];
-
-    return mgr->codec_cnt;
+    return PJ_SUCCESS;
 }
 
-PJ_DEF(pj_codec*) pj_codec_mgr_alloc_codec (pj_codec_mgr *mgr, const struct pj_codec_id *id)
+/*
+ * Allocate one codec.
+ */
+PJ_DEF(pj_status_t) pjmedia_codec_mgr_alloc_codec(pjmedia_codec_mgr *mgr, 
+						  const pjmedia_codec_info *info,
+						  pjmedia_codec **p_codec)
 {
-    pj_codec_factory *factory = mgr->factory_list.next;
+    pjmedia_codec_factory *factory;
+    pj_status_t status;
+
+    PJ_ASSERT_RETURN(mgr && info && p_codec, PJ_EINVAL);
+
+    *p_codec = NULL;
+
+    factory = mgr->factory_list.next;
     while (factory != &mgr->factory_list) {
-	if ( (*factory->op->match_id)(factory, id) == 0 ) {
-	    pj_codec *codec = (*factory->op->alloc_codec)(factory, id);
-	    if (codec != NULL)
-		return codec;
+
+	if ( (*factory->op->test_alloc)(factory, info) == PJ_SUCCESS ) {
+
+	    status = (*factory->op->alloc_codec)(factory, info, p_codec);
+	    if (status == PJ_SUCCESS)
+		return PJ_SUCCESS;
+
 	}
+
 	factory = factory->next;
     }
-    return NULL;
+
+
+    return PJMEDIA_CODEC_EUNSUP;
 }
 
-PJ_DEF(void) pj_codec_mgr_dealloc_codec (pj_codec_mgr *mgr, pj_codec *codec)
+/*
+ * Dealloc codec.
+ */
+PJ_DEF(pj_status_t) pjmedia_codec_mgr_dealloc_codec(pjmedia_codec_mgr *mgr, 
+						    pjmedia_codec *codec)
 {
-    PJ_UNUSED_ARG(mgr);
-    (*codec->factory->op->dealloc_codec)(codec->factory, codec);
+    PJ_ASSERT_RETURN(mgr && codec, PJ_EINVAL);
+
+    return (*codec->factory->op->dealloc_codec)(codec->factory, codec);
 }
 
Index: pjproject/trunk/pjmedia/src/pjmedia/endpoint.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/endpoint.c	(revision 159)
+++ pjproject/trunk/pjmedia/src/pjmedia/endpoint.c	(revision 159)
@@ -0,0 +1,239 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include <pjmedia/endpoint.h>
+#include <pjmedia/errno.h>
+#include <pjmedia/sdp.h>
+#include <pj/sock.h>
+#include <pj/pool.h>
+#include <pj/string.h>
+#include <pj/assert.h>
+#include <pj/os.h>
+
+
+#define THIS_FILE   "endpoint.c"
+
+static const pj_str_t STR_AUDIO = { "audio", 5};
+static const pj_str_t STR_VIDEO = { "video", 5};
+static const pj_str_t STR_IN = { "IN", 2 };
+static const pj_str_t STR_IP4 = { "IP4", 3};
+static const pj_str_t STR_RTP_AVP = { "RTP/AVP", 7 };
+static const pj_str_t STR_SDP_NAME = { "pjmedia", 7 };
+static const pj_str_t STR_SENDRECV = { "sendrecv", 8 };
+
+
+PJ_DECL(pj_status_t) g711_init_factory (pjmedia_codec_factory *factory, pj_pool_t *pool);
+PJ_DECL(pj_status_t) g711_deinit_factory (pjmedia_codec_factory *factory);
+
+
+/** Concrete declaration of media endpoint. */
+struct pjmedia_endpt
+{
+    /** Pool. */
+    pj_pool_t		 *pool;
+
+    /** Pool factory. */
+    pj_pool_factory	 *pf;
+
+    /** Codec manager. */
+    pjmedia_codec_mgr	  codec_mgr;
+};
+
+/**
+ * Initialize and get the instance of media endpoint.
+ */
+PJ_DEF(pj_status_t) pjmedia_endpt_create(pj_pool_factory *pf,
+					 pjmedia_endpt **p_endpt)
+{
+    pj_pool_t *pool;
+    pjmedia_endpt *endpt;
+    pjmedia_codec_factory *factory;
+    pj_status_t status;
+
+    PJ_ASSERT_RETURN(pf && p_endpt, PJ_EINVAL);
+
+    pool = pj_pool_create(pf, "med-ept", 512, 512, NULL);
+    if (!pool)
+	return PJ_ENOMEM;
+
+    endpt = pj_pool_zalloc(pool, sizeof(struct pjmedia_endpt));
+    endpt->pool = pool;
+    endpt->pf = pf;
+
+    /* Sound */
+    pj_snd_init(pf);
+
+    /* Init codec manager. */
+    status = pjmedia_codec_mgr_init(&endpt->codec_mgr);
+    if (status != PJ_SUCCESS) {
+	pj_snd_deinit();
+	goto on_error;
+    }
+
+    /* Init and register G.711 codec. */
+    factory = pj_pool_alloc (endpt->pool, sizeof(pjmedia_codec_factory));
+
+    status = g711_init_factory (factory, endpt->pool);
+    if (status != PJ_SUCCESS) {
+	pj_snd_deinit();
+	goto on_error;
+    }
+
+    status = pjmedia_codec_mgr_register_factory (&endpt->codec_mgr, factory);
+    if (status != PJ_SUCCESS)  {
+	pj_snd_deinit();
+	goto on_error;
+    }
+
+    *p_endpt = endpt;
+    return PJ_SUCCESS;
+
+on_error:
+    pj_pool_release(pool);
+    return status;
+}
+
+/**
+ * Get the codec manager instance.
+ */
+PJ_DEF(pjmedia_codec_mgr*) pjmedia_endpt_get_codec_mgr(pjmedia_endpt *endpt)
+{
+    return &endpt->codec_mgr;
+}
+
+/**
+ * Deinitialize media endpoint.
+ */
+PJ_DEF(pj_status_t) pjmedia_endpt_destroy (pjmedia_endpt *endpt)
+{
+    PJ_ASSERT_RETURN(endpt, PJ_EINVAL);
+
+    endpt->pf = NULL;
+
+    pj_snd_deinit();
+    pj_pool_release (endpt->pool);
+
+    return PJ_SUCCESS;
+}
+
+/**
+ * Create pool.
+ */
+PJ_DEF(pj_pool_t*) pjmedia_endpt_create_pool( pjmedia_endpt *endpt,
+					      const char *name,
+					      pj_size_t initial,
+					      pj_size_t increment)
+{
+    pj_assert(endpt != NULL);
+
+    return pj_pool_create(endpt->pf, name, initial, increment, NULL);
+}
+
+/**
+ * Create a SDP session description that describes the endpoint
+ * capability.
+ */
+PJ_DEF(pj_status_t) pjmedia_endpt_create_sdp( pjmedia_endpt *endpt,
+					      pj_pool_t *pool,
+					      unsigned stream_cnt,
+					      const pjmedia_sock_info sock_info[],
+					      pjmedia_sdp_session **p_sdp )
+{
+    pj_time_val tv;
+    unsigned i;
+    pjmedia_sdp_session *sdp;
+    pjmedia_sdp_media *m;
+    pjmedia_sdp_attr *attr;
+
+    PJ_ASSERT_RETURN(endpt && pool && p_sdp && stream_cnt, PJ_EINVAL);
+
+
+    /* Create and initialize basic SDP session */
+    sdp = pj_pool_zalloc (pool, sizeof(pjmedia_sdp_session));
+
+    pj_gettimeofday(&tv);
+    sdp->origin.user = pj_str("-");
+    sdp->origin.version = sdp->origin.id = tv.sec + 2208988800UL;
+    sdp->origin.net_type = STR_IN;
+    sdp->origin.addr_type = STR_IP4;
+    sdp->origin.addr = *pj_gethostname();
+    sdp->name = STR_SDP_NAME;
+
+    /* Since we only support one media stream at present, put the
+     * SDP connection line in the session level.
+     */
+    sdp->conn = pj_pool_zalloc (pool, sizeof(pjmedia_sdp_conn));
+    sdp->conn->net_type = STR_IN;
+    sdp->conn->addr_type = STR_IP4;
+    pj_strdup2(pool, &sdp->conn->addr, 
+	       pj_inet_ntoa(sock_info[0].rtp_addr_name.sin_addr));
+
+
+    /* SDP time and attributes. */
+    sdp->time.start = sdp->time.stop = 0;
+    sdp->attr_count = 0;
+
+    /* Create media stream 0: */
+
+    sdp->media_count = 1;
+    m = pj_pool_zalloc (pool, sizeof(pjmedia_sdp_media));
+    sdp->media[0] = m;
+
+    /* Standard media info: */
+    pj_strdup(pool, &m->desc.media, &STR_AUDIO);
+    m->desc.port = pj_ntohs(sock_info[0].rtp_addr_name.sin_port);
+    m->desc.port_count = 1;
+    pj_strdup (pool, &m->desc.transport, &STR_RTP_AVP);
+
+    /* Add format and rtpmap for each codec. */
+    m->desc.fmt_count = 0;
+    m->attr_count = 0;
+
+    for (i=0; i<endpt->codec_mgr.codec_cnt; ++i) {
+
+	pjmedia_codec_info *codec_info = &endpt->codec_mgr.codecs[i];
+	pjmedia_sdp_rtpmap rtpmap;
+	pjmedia_sdp_attr *attr;
+	pj_str_t *fmt = &m->desc.fmt[m->desc.fmt_count++];
+
+	fmt->ptr = pj_pool_alloc(pool, 8);
+	fmt->slen = pj_utoa(codec_info->pt, fmt->ptr);
+
+	rtpmap.pt = *fmt;
+	rtpmap.clock_rate = codec_info->sample_rate;
+	rtpmap.enc_name = codec_info->encoding_name;
+	rtpmap.param.slen = 0;
+
+	pjmedia_sdp_rtpmap_to_attr(pool, &rtpmap, &attr);
+	m->attr[m->attr_count++] = attr;
+
+    }
+
+    /* Add sendrect attribute. */
+    attr = pj_pool_zalloc(pool, sizeof(pjmedia_sdp_attr));
+    attr->name = STR_SENDRECV;
+    m->attr[m->attr_count++] = attr;
+
+
+    /* Done */
+    *p_sdp = sdp;
+
+    return PJ_SUCCESS;
+
+}
+
Index: pjproject/trunk/pjmedia/src/pjmedia/errno.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/errno.c	(revision 158)
+++ pjproject/trunk/pjmedia/src/pjmedia/errno.c	(revision 159)
@@ -77,4 +77,13 @@
     { PJMEDIA_SDP_ENAMENOTEQUAL,    "SDP name/subject line not equal" },
     { PJMEDIA_SDP_ETIMENOTEQUAL,    "SDP time line not equal" },
+
+    /* Codec errors. */
+    { PJMEDIA_CODEC_EUNSUP,	    "Unsupported media codec" },
+
+    /* Media errors. */
+    { PJMEDIA_EINVALIDIP,	    "Invalid remote media (IP) address" },
+    { PJMEDIA_EASYMCODEC,	    "Asymetric media codec is not supported" },
+    { PJMEDIA_EINVALIDPT,	    "Invalid media payload type" },
+    { PJMEDIA_EMISSINGRTPMAP,	    "Missing rtpmap in media description" },
 };
 
Index: pjproject/trunk/pjmedia/src/pjmedia/g711.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/g711.c	(revision 158)
+++ pjproject/trunk/pjmedia/src/pjmedia/g711.c	(revision 159)
@@ -21,4 +21,5 @@
  */
 #include <pjmedia/codec.h>
+#include <pjmedia/errno.h>
 #include <pj/pool.h>
 #include <pj/string.h>
@@ -30,6 +31,6 @@
 
 /* These are the only public functions exported to applications */
-PJ_DECL(pj_status_t) g711_init_factory (pj_codec_factory *factory, pj_pool_t *pool);
-PJ_DECL(pj_status_t) g711_deinit_factory (pj_codec_factory *factory);
+PJ_DECL(pj_status_t) g711_init_factory (pjmedia_codec_factory *factory, pj_pool_t *pool);
+PJ_DECL(pj_status_t) g711_deinit_factory (pjmedia_codec_factory *factory);
 
 /* Algorithm prototypes. */
@@ -40,22 +41,22 @@
 
 /* Prototypes for G711 factory */
-static pj_status_t  g711_match_id( pj_codec_factory *factory, const pj_codec_id *id );
-static pj_status_t  g711_default_attr( pj_codec_factory *factory, const pj_codec_id *id, pj_codec_attr *attr );
-static unsigned	    g711_enum_codecs (pj_codec_factory *factory, unsigned count, pj_codec_id codecs[]);
-static pj_codec*    g711_alloc_codec( pj_codec_factory *factory, const pj_codec_id *id);
-static void	    g711_dealloc_codec( pj_codec_factory *factory, pj_codec *codec );
+static pj_status_t g711_match_id( pjmedia_codec_factory *factory, const pjmedia_codec_info *id );
+static pj_status_t g711_default_attr( pjmedia_codec_factory *factory, const pjmedia_codec_info *id, pjmedia_codec_param *attr );
+static pj_status_t g711_enum_codecs (pjmedia_codec_factory *factory, unsigned *count, pjmedia_codec_info codecs[]);
+static pj_status_t g711_alloc_codec( pjmedia_codec_factory *factory, const pjmedia_codec_info *id, pjmedia_codec **p_codec);
+static pj_status_t g711_dealloc_codec( pjmedia_codec_factory *factory, pjmedia_codec *codec );
 
 /* Prototypes for G711 implementation. */
-static pj_status_t  g711_codec_default_attr (pj_codec *codec, pj_codec_attr *attr);
-static pj_status_t  g711_init( pj_codec *codec, pj_pool_t *pool );
-static pj_status_t  g711_open( pj_codec *codec, pj_codec_attr *attr );
-static pj_status_t  g711_close( pj_codec *codec );
-static pj_status_t  g711_encode( pj_codec *codec, const struct pj_audio_frame *input,
-				 unsigned output_buf_len, struct pj_audio_frame *output);
-static pj_status_t  g711_decode( pj_codec *codec, const struct pj_audio_frame *input,
-				 unsigned output_buf_len, struct pj_audio_frame *output);
+static pj_status_t  g711_codec_default_attr (pjmedia_codec *codec, pjmedia_codec_param *attr);
+static pj_status_t  g711_init( pjmedia_codec *codec, pj_pool_t *pool );
+static pj_status_t  g711_open( pjmedia_codec *codec, pjmedia_codec_param *attr );
+static pj_status_t  g711_close( pjmedia_codec *codec );
+static pj_status_t  g711_encode( pjmedia_codec *codec, const struct pjmedia_frame *input,
+				 unsigned output_buf_len, struct pjmedia_frame *output);
+static pj_status_t  g711_decode( pjmedia_codec *codec, const struct pjmedia_frame *input,
+				 unsigned output_buf_len, struct pjmedia_frame *output);
 
 /* Definition for G711 codec operations. */
-static pj_codec_op g711_op = 
+static pjmedia_codec_op g711_op = 
 {
     &g711_codec_default_attr ,
@@ -68,5 +69,5 @@
 
 /* Definition for G711 codec factory operations. */
-static pj_codec_factory_op g711_factory_op =
+static pjmedia_codec_factory_op g711_factory_op =
 {
     &g711_match_id,
@@ -81,5 +82,5 @@
 {
     pj_pool_t  *pool;
-    pj_codec	codec_list;
+    pjmedia_codec	codec_list;
 };
 
@@ -91,8 +92,8 @@
 
 
-PJ_DEF(pj_status_t) g711_init_factory (pj_codec_factory *factory, pj_pool_t *pool)
+PJ_DEF(pj_status_t) g711_init_factory (pjmedia_codec_factory *factory, pj_pool_t *pool)
 {
     struct g711_factory_private *priv;
-    //enum { CODEC_MEM_SIZE = sizeof(pj_codec) + sizeof(struct g711_private) + 4 };
+    //enum { CODEC_MEM_SIZE = sizeof(pjmedia_codec) + sizeof(struct g711_private) + 4 };
 
     /* Create pool. */
@@ -118,5 +119,5 @@
 }
 
-PJ_DEF(pj_status_t) g711_deinit_factory (pj_codec_factory *factory)
+PJ_DEF(pj_status_t) g711_deinit_factory (pjmedia_codec_factory *factory)
 {
     struct g711_factory_private *priv = factory->factory_data;
@@ -128,19 +129,19 @@
 }
 
-static pj_status_t g711_match_id( pj_codec_factory *factory, const pj_codec_id *id )
+static pj_status_t g711_match_id( pjmedia_codec_factory *factory, const pjmedia_codec_info *id )
 {
     PJ_UNUSED_ARG(factory);
 
     /* It's sufficient to check payload type only. */
-    return (id->pt==PJ_RTP_PT_PCMU || id->pt==PJ_RTP_PT_PCMA) ? 0 : -1;
-}
-
-static pj_status_t g711_default_attr (pj_codec_factory *factory, 
-				      const pj_codec_id *id, 
-				      pj_codec_attr *attr )
+    return (id->pt==PJMEDIA_RTP_PT_PCMU || id->pt==PJMEDIA_RTP_PT_PCMA) ? 0 : -1;
+}
+
+static pj_status_t g711_default_attr (pjmedia_codec_factory *factory, 
+				      const pjmedia_codec_info *id, 
+				      pjmedia_codec_param *attr )
 {
     PJ_UNUSED_ARG(factory);
 
-    memset(attr, 0, sizeof(pj_codec_attr));
+    memset(attr, 0, sizeof(pjmedia_codec_param));
     attr->sample_rate = 8000;
     attr->avg_bps = G711_BPS;
@@ -154,29 +155,35 @@
 }
 
-static unsigned	g711_enum_codecs (pj_codec_factory *factory, 
-				  unsigned count, pj_codec_id codecs[])
+static pj_status_t g711_enum_codecs(pjmedia_codec_factory *factory, 
+				    unsigned *count, 
+				    pjmedia_codec_info codecs[])
 {
     PJ_UNUSED_ARG(factory);
 
-    if (count > 0) {
-	codecs[0].type = PJ_MEDIA_TYPE_AUDIO;
-	codecs[0].pt = PJ_RTP_PT_PCMU;
+    if (*count > 0) {
+	codecs[0].type = PJMEDIA_TYPE_AUDIO;
+	codecs[0].pt = PJMEDIA_RTP_PT_PCMU;
 	codecs[0].encoding_name = pj_str("PCMU");
 	codecs[0].sample_rate = 8000;
     }
-    if (count > 1) {
-	codecs[1].type = PJ_MEDIA_TYPE_AUDIO;
-	codecs[1].pt = PJ_RTP_PT_PCMA;
+    if (*count > 1) {
+	codecs[1].type = PJMEDIA_TYPE_AUDIO;
+	codecs[1].pt = PJMEDIA_RTP_PT_PCMA;
 	codecs[1].encoding_name = pj_str("PCMA");
 	codecs[1].sample_rate = 8000;
     }
 
-    return 2;
-}
-
-static pj_codec *g711_alloc_codec( pj_codec_factory *factory, const pj_codec_id *id)
+    if (*count > 0) *count=1;
+    if (*count > 1) *count=2;
+
+    return PJ_SUCCESS;
+}
+
+static pj_status_t g711_alloc_codec( pjmedia_codec_factory *factory, 
+				     const pjmedia_codec_info *id,
+				     pjmedia_codec **p_codec)
 {
     struct g711_factory_private *priv = factory->factory_data;
-    pj_codec *codec = NULL;
+    pjmedia_codec *codec = NULL;
 
     /* Allocate new codec if no more is available */
@@ -184,8 +191,8 @@
 	struct g711_private *codec_priv;
 
-	codec = pj_pool_alloc(priv->pool, sizeof(pj_codec));
+	codec = pj_pool_alloc(priv->pool, sizeof(pjmedia_codec));
 	codec_priv = pj_pool_alloc(priv->pool, sizeof(struct g711_private));
 	if (!codec || !codec_priv)
-	    return NULL;
+	    return PJ_ENOMEM;
 
 	codec_priv->pt = id->pt;
@@ -202,8 +209,9 @@
     codec->next = codec->prev = NULL;
 
-    return codec;
-}
-
-static void g711_dealloc_codec( pj_codec_factory *factory, pj_codec *codec )
+    *p_codec = codec;
+    return PJ_SUCCESS;
+}
+
+static pj_status_t g711_dealloc_codec( pjmedia_codec_factory *factory, pjmedia_codec *codec )
 {
     struct g711_factory_private *priv = factory->factory_data;
@@ -212,15 +220,17 @@
     pj_assert (codec->next==NULL && codec->prev==NULL);
     if (codec->next!=NULL || codec->prev!=NULL) {
-	return;
+	return PJ_EINVALIDOP;
     }
 
     /* Insert at the back of the list */
     pj_list_insert_before(&priv->codec_list, codec);
-}
-
-static pj_status_t g711_codec_default_attr  (pj_codec *codec, pj_codec_attr *attr)
+
+    return PJ_SUCCESS;
+}
+
+static pj_status_t g711_codec_default_attr  (pjmedia_codec *codec, pjmedia_codec_param *attr)
 {
     struct g711_private *priv = codec->codec_data;
-    pj_codec_id id;
+    pjmedia_codec_info id;
 
     id.pt = priv->pt;
@@ -228,5 +238,5 @@
 }
 
-static pj_status_t g711_init( pj_codec *codec, pj_pool_t *pool )
+static pj_status_t g711_init( pjmedia_codec *codec, pj_pool_t *pool )
 {
     /* There's nothing to do here really */
@@ -237,5 +247,5 @@
 }
 
-static pj_status_t g711_open( pj_codec *codec, pj_codec_attr *attr )
+static pj_status_t g711_open( pjmedia_codec *codec, pjmedia_codec_param *attr )
 {
     struct g711_private *priv = codec->codec_data;
@@ -244,5 +254,5 @@
 }
 
-static pj_status_t g711_close( pj_codec *codec )
+static pj_status_t g711_close( pjmedia_codec *codec )
 {
     PJ_UNUSED_ARG(codec);
@@ -251,6 +261,6 @@
 }
 
-static pj_status_t  g711_encode( pj_codec *codec, const struct pj_audio_frame *input,
-				 unsigned output_buf_len, struct pj_audio_frame *output)
+static pj_status_t  g711_encode( pjmedia_codec *codec, const struct pjmedia_frame *input,
+				 unsigned output_buf_len, struct pjmedia_frame *output)
 {
     pj_int16_t *samples = (pj_int16_t*) input->buf;
@@ -262,5 +272,5 @@
 
     /* Encode */
-    if (priv->pt == PJ_RTP_PT_PCMA) {
+    if (priv->pt == PJMEDIA_RTP_PT_PCMA) {
 	unsigned i;
 	pj_uint8_t *dst = output->buf;
@@ -269,5 +279,5 @@
 	    *dst = linear2alaw(samples[i]);
 	}
-    } else if (priv->pt == PJ_RTP_PT_PCMU) {
+    } else if (priv->pt == PJMEDIA_RTP_PT_PCMU) {
 	unsigned i;
 	pj_uint8_t *dst = output->buf;
@@ -281,5 +291,5 @@
     }
 
-    output->type = PJ_AUDIO_FRAME_AUDIO;
+    output->type = PJMEDIA_FRAME_TYPE_AUDIO;
     output->size = input->size / 2;
 
@@ -287,6 +297,6 @@
 }
 
-static pj_status_t  g711_decode( pj_codec *codec, const struct pj_audio_frame *input,
-				 unsigned output_buf_len, struct pj_audio_frame *output)
+static pj_status_t  g711_decode( pjmedia_codec *codec, const struct pjmedia_frame *input,
+				 unsigned output_buf_len, struct pjmedia_frame *output)
 {
     struct g711_private *priv = codec->codec_data;
@@ -297,5 +307,5 @@
 
     /* Decode */
-    if (priv->pt == PJ_RTP_PT_PCMA) {
+    if (priv->pt == PJMEDIA_RTP_PT_PCMA) {
 	unsigned i;
 	pj_uint8_t *src = input->buf;
@@ -305,5 +315,5 @@
 	    *dst++ = (pj_uint16_t) alaw2linear(*src++);
 	}
-    } else if (priv->pt == PJ_RTP_PT_PCMU) {
+    } else if (priv->pt == PJMEDIA_RTP_PT_PCMU) {
 	unsigned i;
 	pj_uint8_t *src = input->buf;
@@ -318,5 +328,5 @@
     }
 
-    output->type = PJ_AUDIO_FRAME_AUDIO;
+    output->type = PJMEDIA_FRAME_TYPE_AUDIO;
     output->size = input->size * 2;
 
Index: pjproject/trunk/pjmedia/src/pjmedia/mediamgr.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/mediamgr.c	(revision 158)
+++ 	(revision )
@@ -1,112 +1,0 @@
-/* $Id$ */
-/* 
- * Copyright (C) 2003-2006 Benny Prijono <benny@prijono.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
- */
-#include <pjmedia/mediamgr.h>
-#include <pj/sock.h>
-#include <pj/pool.h>
-#include <pj/string.h>
-
-PJ_DECL(pj_status_t) g711_init_factory (pj_codec_factory *factory, pj_pool_t *pool);
-PJ_DECL(pj_status_t) g711_deinit_factory (pj_codec_factory *factory);
-
-/** Concrete declaration of media manager. */
-struct pj_med_mgr_t
-{
-    /** Pool. */
-    pj_pool_t		 *pool;
-
-    /** Pool factory. */
-    pj_pool_factory	 *pf;
-
-    /** Codec manager. */
-    pj_codec_mgr	  codec_mgr;
-};
-
-/**
- * Initialize and get the instance of media manager.
- */
-PJ_DEF(pj_med_mgr_t*) pj_med_mgr_create ( pj_pool_factory *pf)
-{
-    pj_pool_t *pool;
-    pj_med_mgr_t *mm;
-    pj_codec_factory *cf;
-    pj_status_t status;
-
-    pool = pj_pool_create(pf, "mediamgr", 512, 512, NULL);
-    if (!pool)
-	return NULL;
-
-    mm = pj_pool_calloc(pool, 1, sizeof(struct pj_med_mgr_t));
-    mm->pool = pool;
-    mm->pf = pf;
-
-    /* Sound */
-    pj_snd_init(pf);
-
-    /* Init codec manager. */
-    status = pj_codec_mgr_init(&mm->codec_mgr);
-    if (status != 0) {
-	pj_snd_deinit();
-	goto on_error;
-    }
-
-    /* Init and register G.711 codec. */
-    cf = pj_pool_alloc (mm->pool, sizeof(pj_codec_factory));
-
-    status = g711_init_factory (cf, mm->pool);
-    if (status != 0) {
-	pj_snd_deinit();
-	return NULL;
-    }
-
-    status = pj_codec_mgr_register_factory (&mm->codec_mgr, cf);
-    if (status != 0) 
-	return NULL;
-
-    return mm;
-
-on_error:
-    pj_pool_release(pool);
-    return NULL;
-}
-
-/**
- * Get the codec manager instance.
- */
-PJ_DEF(pj_codec_mgr*) pj_med_mgr_get_codec_mgr (pj_med_mgr_t *mgr)
-{
-    return &mgr->codec_mgr;
-}
-
-/**
- * Deinitialize media manager.
- */
-PJ_DEF(pj_status_t) pj_med_mgr_destroy (pj_med_mgr_t *mgr)
-{
-    pj_snd_deinit();
-    pj_pool_release (mgr->pool);
-    return 0;
-}
-
-/**
- * Get pool factory.
- */
-PJ_DEF(pj_pool_factory*) pj_med_mgr_get_pool_factory (pj_med_mgr_t *mgr)
-{
-    return mgr->pf;
-}
Index: pjproject/trunk/pjmedia/src/pjmedia/rtcp.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/rtcp.c	(revision 158)
+++ pjproject/trunk/pjmedia/src/pjmedia/rtcp.c	(revision 159)
@@ -93,5 +93,5 @@
     /* Update sequence numbers (received, lost, etc). */
     status = pj_rtp_seq_update(&s->seq_ctrl, seq);
-    if (status == PJ_RTP_ERR_SESSION_RESTARTED) {
+    if (status == PJMEDIA_RTP_ERR_SESSION_RESTARTED) {
 	rtcp_init_seq(s, seq);
 	status = 0;
Index: pjproject/trunk/pjmedia/src/pjmedia/rtp.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/rtp.c	(revision 158)
+++ pjproject/trunk/pjmedia/src/pjmedia/rtp.c	(revision 159)
@@ -44,5 +44,5 @@
     if (sizeof(struct pj_rtp_hdr) != 12) {
 	pj_assert(!"Wrong RTP header packing!");
-	return PJ_RTP_ERR_RTP_PACKING;
+	return PJMEDIA_RTP_ERR_RTP_PACKING;
     }
 
@@ -129,5 +129,5 @@
     if ((*hdr)->v != RTP_VERSION) {
 	PJ_LOG(4, (THIS_FILE, "  invalid RTP version!"));
-	return PJ_RTP_ERR_INVALID_VERSION;
+	return PJMEDIA_RTP_ERR_INVALID_VERSION;
     }
 
@@ -143,5 +143,5 @@
     /* Check that offset is less than packet size */
     if (offset >= pkt_len)
-	return PJ_RTP_ERR_INVALID_PACKET;
+	return PJMEDIA_RTP_ERR_INVALID_PACKET;
 
     /* Find and set payload. */
@@ -163,5 +163,5 @@
 	PJ_LOG(4, (THIS_FILE, "pj_rtp_session_update: ses=%p, invalid ssrc 0x%p (!=0x%p)",
 		   ses, pj_ntohl(hdr->ssrc), ses->peer_ssrc));
-	return PJ_RTP_ERR_INVALID_SSRC;
+	return PJMEDIA_RTP_ERR_INVALID_SSRC;
     }
     */
@@ -171,5 +171,5 @@
 	PJ_LOG(4, (THIS_FILE, "pj_rtp_session_update: ses=%p, invalid payload type %d (!=%d)",
 		   ses, hdr->pt, ses->out_pt));
-	return PJ_RTP_ERR_INVALID_PT;
+	return PJMEDIA_RTP_ERR_INVALID_PT;
     }
 
@@ -180,8 +180,8 @@
     /* Check sequence number to see if remote session has been restarted. */
     status = pj_rtp_seq_update( &ses->seq_ctrl, pj_ntohs(hdr->seq));
-    if (status == PJ_RTP_ERR_SESSION_RESTARTED) {
+    if (status == PJMEDIA_RTP_ERR_SESSION_RESTARTED) {
 	pj_rtp_seq_restart( &ses->seq_ctrl, pj_ntohs(hdr->seq));
 	++ses->received;
-    } else if (status == 0 || status == PJ_RTP_ERR_SESSION_PROBATION) {
+    } else if (status == 0 || status == PJMEDIA_RTP_ERR_SESSION_PROBATION) {
 	++ses->received;
     }
@@ -224,5 +224,5 @@
             sctrl->max_seq = seq;
             if (sctrl->probation == 0) {
-                return PJ_RTP_ERR_SESSION_RESTARTED;
+                return PJMEDIA_RTP_ERR_SESSION_RESTARTED;
             }
 	} else {
@@ -230,5 +230,5 @@
 	    sctrl->max_seq = seq;
         }
-        return PJ_RTP_ERR_SESSION_PROBATION;
+        return PJMEDIA_RTP_ERR_SESSION_PROBATION;
 
     } else if (udelta < MAX_DROPOUT) {
@@ -248,9 +248,9 @@
 	     * (i.e., pretend this was the first packet).
 	     */
-	    return PJ_RTP_ERR_SESSION_RESTARTED;
+	    return PJMEDIA_RTP_ERR_SESSION_RESTARTED;
 	}
         else {
 	    sctrl->bad_seq = (seq + 1) & (RTP_SEQ_MOD-1);
-            return PJ_RTP_ERR_BAD_SEQUENCE;
+            return PJMEDIA_RTP_ERR_BAD_SEQUENCE;
         }
     } else {
Index: pjproject/trunk/pjmedia/src/pjmedia/session.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/session.c	(revision 158)
+++ pjproject/trunk/pjmedia/src/pjmedia/session.c	(revision 159)
@@ -18,4 +18,5 @@
  */
 #include <pjmedia/session.h>
+#include <pjmedia/errno.h>
 #include <pj/log.h>
 #include <pj/os.h> 
@@ -23,24 +24,20 @@
 #include <pj/string.h>
 #include <pj/assert.h>
-
-
-typedef struct pj_media_stream_desc
-{
-    pj_media_stream_info    info;
-    pj_media_stream_t	   *enc_stream, *dec_stream;
-} pj_media_stream_desc;
-
-struct pj_media_session_t
+#include <pj/ctype.h>
+
+
+struct pjmedia_session
 {
     pj_pool_t		   *pool;
-    pj_med_mgr_t	   *mediamgr;
+    pjmedia_endpt	   *endpt;
     unsigned		    stream_cnt;
-    pj_media_stream_desc   *stream_desc[PJSDP_MAX_MEDIA];
+    pjmedia_stream_info	    stream_info[PJSDP_MAX_MEDIA];
+    pjmedia_stream	   *stream[PJSDP_MAX_MEDIA];
 };
 
 #define THIS_FILE		"session.c"
 
-#define PJ_MEDIA_SESSION_SIZE	(48*1024)
-#define PJ_MEDIA_SESSION_INC	1024
+#define PJMEDIA_SESSION_SIZE	(48*1024)
+#define PJMEDIA_SESSION_INC	1024
 
 static const pj_str_t ID_AUDIO = { "audio", 5};
@@ -50,611 +47,321 @@
 static const pj_str_t ID_RTP_AVP = { "RTP/AVP", 7 };
 static const pj_str_t ID_SDP_NAME = { "pjmedia", 7 };
-
-static void session_init (pj_media_session_t *ses)
-{
-    pj_memset (ses, 0, sizeof(pj_media_session_t));
-}
-
-
-/**
- * Create new session offering.
- */
-PJ_DEF(pj_media_session_t*) 
-pj_media_session_create (pj_med_mgr_t *mgr, const pj_media_sock_info *sock_info)
-{
-    pj_pool_factory *pf;
+static const pj_str_t ID_RTPMAP = { "rtpmap", 6 };
+
+static const pj_str_t STR_INACTIVE = { "inactive", 8 };
+static const pj_str_t STR_SENDRECV = { "sendrecv", 8 };
+static const pj_str_t STR_SENDONLY = { "sendonly", 8 };
+static const pj_str_t STR_RECVONLY = { "recvonly", 8 };
+
+
+/*
+ * Create stream info from SDP media line.
+ */
+static pj_status_t create_stream_info_from_sdp(pj_pool_t *pool,
+					       pjmedia_stream_info *si,
+					       const pjmedia_sdp_conn *local_conn,
+					       const pjmedia_sdp_conn *rem_conn,
+					       const pjmedia_sdp_media *local_m,
+					       const pjmedia_sdp_media *rem_m)
+{
+    const pjmedia_sdp_attr *attr;
+    pjmedia_sdp_rtpmap *rtpmap;
+    pj_status_t status;
+
+
+    /* Validate arguments: */
+
+    PJ_ASSERT_RETURN(pool && si && local_conn && rem_conn &&
+		     local_m && rem_m, PJ_EINVAL);
+
+    /* Reset: */
+
+    pj_memset(si, 0, sizeof(*si));
+
+    /* Media type: */
+
+    if (pj_stricmp(&local_m->desc.media, &ID_AUDIO) == 0) {
+
+	si->type = PJMEDIA_TYPE_AUDIO;
+
+    } else if (pj_stricmp(&local_m->desc.media, &ID_VIDEO) == 0) {
+
+	si->type = PJMEDIA_TYPE_VIDEO;
+
+    } else {
+
+	si->type = PJMEDIA_TYPE_UNKNOWN;
+
+    }
+
+    /* Media direction: */
+
+    if (local_m->desc.port == 0 || 
+	pj_inet_addr(&local_conn->addr).s_addr==0 ||
+	pj_inet_addr(&rem_conn->addr).s_addr==0 ||
+	pjmedia_sdp_media_find_attr(local_m, &STR_INACTIVE, NULL)!=NULL)
+    {
+	/* Inactive stream. */
+
+	si->dir = PJMEDIA_DIR_NONE;
+
+    } else if (pjmedia_sdp_media_find_attr(local_m, &STR_SENDONLY, NULL)!=NULL) {
+
+	/* Send only stream. */
+
+	si->dir = PJMEDIA_DIR_ENCODING;
+
+    } else if (pjmedia_sdp_media_find_attr(local_m, &STR_RECVONLY, NULL)!=NULL) {
+
+	/* Recv only stream. */
+
+	si->dir = PJMEDIA_DIR_DECODING;
+
+    } else {
+
+	/* Send and receive stream. */
+
+	si->dir = PJMEDIA_DIR_ENCODING_DECODING;
+
+    }
+
+
+    /* Set remote address: */
+
+    si->rem_addr.sin_family = PJ_AF_INET;
+    si->rem_addr.sin_port = pj_htons(rem_m->desc.port);
+    if (pj_inet_aton(&rem_conn->addr, &si->rem_addr.sin_addr) == 0) {
+
+	/* Invalid IP address. */
+	return PJMEDIA_EINVALIDIP;
+    }
+
+    /* For this version of PJMEDIA, send and receive media must use
+     * the same codec.
+     */
+    if (pj_strcmp(&local_m->desc.fmt[0], &rem_m->desc.fmt[0]) != 0)
+	return PJMEDIA_EASYMCODEC;
+
+
+    /* And codec must be numeric! */
+    if (!pj_isdigit(*local_m->desc.fmt[0].ptr))
+	return PJMEDIA_EINVALIDPT;
+
+    /* Find rtpmap for the first codec. 
+     * For this version of PJMEDIA, we do not support static payload
+     * type without rtpmap.
+     */
+    attr = pjmedia_sdp_media_find_attr(local_m, &ID_RTPMAP, NULL);
+    if (attr == NULL)
+	return PJMEDIA_EMISSINGRTPMAP;
+
+    status = pjmedia_sdp_attr_to_rtpmap(pool, attr, &rtpmap);
+    if (status != PJ_SUCCESS)
+	return status;
+
+    /* Build codec format info: */
+
+    si->fmt.type = si->type;
+    si->fmt.pt = pj_strtoul(&local_m->desc.fmt[0]);
+    pj_strdup(pool, &si->fmt.encoding_name, &rtpmap->enc_name);
+    si->fmt.sample_rate = rtpmap->clock_rate;
+
+    /* Leave SSRC to zero. */
+
+    /* Leave jitter buffer parameter. */
+    
+    return PJ_SUCCESS;
+}
+
+
+/**
+ * Create new session.
+ */
+PJ_DEF(pj_status_t) pjmedia_session_create( pjmedia_endpt *endpt, 
+					    unsigned stream_cnt,
+					    const pjmedia_sock_info skinfo[],
+					    const pjmedia_sdp_session *local_sdp,
+					    const pjmedia_sdp_session *rem_sdp,
+					    pjmedia_session **p_session )
+{
     pj_pool_t *pool;
-    pj_media_session_t *session;
-    pj_media_stream_desc *sd;
-    unsigned i, codec_cnt;
-    pj_codec_mgr *cm;
-    const pj_codec_id *codecs[PJSDP_MAX_FMT];
-
-    pf = pj_med_mgr_get_pool_factory(mgr);
-
-    pool = pj_pool_create( pf, "session", PJ_MEDIA_SESSION_SIZE, PJ_MEDIA_SESSION_INC, NULL);
-    if (!pool)
-	return NULL;
-
-    session = pj_pool_alloc(pool, sizeof(pj_media_session_t));
-    if (!session)
-	return NULL;
-
-    session_init (session);
-
+    pjmedia_session *session;
+    int i; /* Must be signed */
+    pj_status_t status;
+
+    /* Verify arguments. */
+    PJ_ASSERT_RETURN(endpt && stream_cnt && skinfo &&
+		     local_sdp && rem_sdp && p_session, PJ_EINVAL);
+
+    /* Create pool for the session. */
+    pool = pjmedia_endpt_create_pool( endpt, "session", 
+				      PJMEDIA_SESSION_SIZE, 
+				      PJMEDIA_SESSION_INC);
+    PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM);
+
+    session = pj_pool_zalloc(pool, sizeof(pjmedia_session));
     session->pool = pool;
-    session->mediamgr = mgr;
-
-    /* Create first stream  */
-    sd = pj_pool_calloc (pool, 1, sizeof(pj_media_stream_desc));
-    if (!sd)
-	return NULL;
-
-    sd->info.type = ID_AUDIO;
-    sd->info.dir = PJ_MEDIA_DIR_ENCODING_DECODING;
-    sd->info.transport = ID_RTP_AVP;
-    pj_memcpy(&sd->info.sock_info, sock_info, sizeof(*sock_info));
-
-    /* Enum audio codecs. */
-    sd->info.fmt_cnt = 0;
-    cm = pj_med_mgr_get_codec_mgr (mgr);
-    codec_cnt = pj_codec_mgr_enum_codecs(cm, PJSDP_MAX_FMT, codecs);
-    if (codec_cnt > PJSDP_MAX_FMT) codec_cnt = PJSDP_MAX_FMT;
-    for (i=0; i<codec_cnt; ++i) {
-	if (codecs[i]->type != PJ_MEDIA_TYPE_AUDIO)
-	    continue;
-
-	sd->info.fmt[sd->info.fmt_cnt].pt = codecs[i]->pt;
-	sd->info.fmt[sd->info.fmt_cnt].sample_rate = codecs[i]->sample_rate;
-	pj_strdup (pool, &sd->info.fmt[sd->info.fmt_cnt].encoding_name, &codecs[i]->encoding_name);
-	++sd->info.fmt_cnt;
-    }
-
-    session->stream_desc[session->stream_cnt++] = sd;
-
-    return session;
-}
-
-static int sdp_check (const pjsdp_session_desc *sdp)
-{
-    int has_conn = 0;
+    session->endpt = endpt;
+    session->stream_cnt = stream_cnt;
+    
+    /* Stream count is the lower number of stream_cnt or SDP m= lines count */
+    if (stream_cnt < local_sdp->media_count)
+	stream_cnt = local_sdp->media_count;
+
+    /* 
+     * Create streams: 
+     */
+    for (i=0; i<(int)stream_cnt; ++i) {
+
+	pjmedia_stream_info *si = &session->stream_info[i];
+	const pjmedia_sdp_media *local_m = local_sdp->media[i];
+	const pjmedia_sdp_media *rem_m = rem_sdp->media[i];
+	pjmedia_sdp_conn *local_conn, *rem_conn;
+
+	/* Build stream info based on media line in local SDP */
+	local_conn = local_m->conn ? local_m->conn : local_sdp->conn;
+	rem_conn = rem_m->conn ? rem_m->conn : rem_sdp->conn;
+
+	status = create_stream_info_from_sdp(session->pool, si,
+					     local_conn, rem_conn,
+					     local_m, rem_m);
+	if (status != PJ_SUCCESS)
+	    return status;
+
+	/* Assign sockinfo */
+	si->sock_info = skinfo[i];
+    }
+
+    /*
+     * Now create the stream!
+     */
+    for (i=0; i<(int)stream_cnt; ++i) {
+
+	status = pjmedia_stream_create(endpt, session->pool,
+				       &session->stream_info[i],
+				       &session->stream[i]);
+	if (status != PJ_SUCCESS) {
+
+	    for ( --i; i>=0; ++i) {
+		pjmedia_stream_destroy(session->stream[i]);
+	    }
+
+	    pj_pool_release(session->pool);
+	    return status;
+	}
+    }
+
+
+    /* Done. */
+
+    *p_session = session;
+    return PJ_SUCCESS;
+}
+
+
+/**
+ * Destroy media session.
+ */
+PJ_DEF(pj_status_t) pjmedia_session_destroy (pjmedia_session *session)
+{
     unsigned i;
 
-    if (sdp->conn)
-	has_conn = 1;
-
-    if (sdp->media_count == 0) {
-	PJ_LOG(4,(THIS_FILE, "SDP check failed: no media stream definition"));
-	return -1;
-    }
-
-    for (i=0; i<sdp->media_count; ++i) {
-	pjsdp_media_desc *m = sdp->media[i];
-
-	if (!m) {
-	    pj_assert(0);
-	    return -1;
-	}
-
-	if (m->desc.fmt_count == 0) {
-	    PJ_LOG(4,(THIS_FILE, "SDP check failed: no format listed in media stream"));
-	    return -1;
-	}
-
-	if (!has_conn && m->conn == NULL) {
-	    PJ_LOG(4,(THIS_FILE, "SDP check failed: no connection information for media"));
-	    return -1;
-	}
-    }
-
-    return 0;
-}
-
-/*
- * Create local stream definition that matches SDP received from peer.
- */
-static pj_media_stream_desc* 
-create_stream_from_sdp (pj_pool_t *pool, pj_med_mgr_t *mgr, const pjsdp_conn_info *conn,
-			const pjsdp_media_desc *m, const pj_media_sock_info *sock_info)
-{
-    pj_media_stream_desc *sd;
-
-    sd = pj_pool_calloc (pool, 1, sizeof(pj_media_stream_desc));
-    if (!sd) {
-	PJ_LOG(2,(THIS_FILE, "No memory to allocate stream descriptor"));
-	return NULL;
-    }
-
-    if (pj_stricmp(&conn->net_type, &ID_IN)==0 && 
-	pj_stricmp(&conn->addr_type, &ID_IP4)==0 &&
-	pj_stricmp(&m->desc.media, &ID_AUDIO)==0 &&
-	pj_stricmp(&m->desc.transport, &ID_RTP_AVP) == 0) 
-    {
-	/*
-	 * Got audio stream.
-	 */
-	unsigned i, codec_cnt;
-	pj_codec_mgr *cm;
-	const pj_codec_id *codecs[PJSDP_MAX_FMT];
-
-	sd->info.type = ID_AUDIO;
-	sd->info.transport = ID_RTP_AVP;
-	pj_memcpy(&sd->info.sock_info, sock_info, sizeof(*sock_info));
-	sd->info.rem_port = m->desc.port;
-	pj_strdup (pool, &sd->info.rem_addr, &conn->addr);
-
-	/* Enum audio codecs. */
-	sd->info.fmt_cnt = 0;
-	cm = pj_med_mgr_get_codec_mgr (mgr);
-	codec_cnt = pj_codec_mgr_enum_codecs (cm, PJSDP_MAX_FMT, codecs);
-	if (codec_cnt > PJSDP_MAX_FMT) codec_cnt = PJSDP_MAX_FMT;
-
-	/* Find just one codec which we can support. */
-	for (i=0; i<m->desc.fmt_count && sd->info.fmt_cnt == 0; ++i) {
-	    unsigned j, fmt_i;
-
-	    /* For static payload, just match payload type. */
-	    /* Else match clock rate and encoding name. */
-	    fmt_i = pj_strtoul(&m->desc.fmt[i]);
-	    if (fmt_i < PJ_RTP_PT_DYNAMIC) {
-		for (j=0; j<codec_cnt; ++j) {
-		    if (codecs[j]->pt == fmt_i) {
-			sd->info.fmt_cnt = 1;
-			sd->info.fmt[0].type = PJ_MEDIA_TYPE_AUDIO;
-			sd->info.fmt[0].pt = codecs[j]->pt;
-			sd->info.fmt[0].sample_rate = codecs[j]->sample_rate;
-			pj_strdup (pool, &sd->info.fmt[0].encoding_name, &codecs[j]->encoding_name);
-			break;
-		    }
-		}
-	    } else {
-
-		/* Find the rtpmap for the payload type. */
-		const pjsdp_rtpmap_attr *rtpmap = pjsdp_media_desc_find_rtpmap (m, fmt_i);
-
-		/* Don't accept the media if no rtpmap for dynamic PT. */
-		if (rtpmap == NULL) {
-		    PJ_LOG(4,(THIS_FILE, "SDP: No rtpmap found for payload id %d", m->desc.fmt[i]));
-		    continue;
-		}
-
-		/* Check whether we can take this codec. */
-		for (j=0; j<codec_cnt; ++j) {
-		    if (rtpmap->clock_rate == codecs[j]->sample_rate && 
-			pj_stricmp(&rtpmap->encoding_name, &codecs[j]->encoding_name) == 0)
-		    {
-			sd->info.fmt_cnt = 1;
-			sd->info.fmt[0].type = PJ_MEDIA_TYPE_AUDIO;
-			sd->info.fmt[0].pt = codecs[j]->pt;
-			sd->info.fmt[0].sample_rate = codecs[j]->sample_rate;
-			sd->info.fmt[0].encoding_name = codecs[j]->encoding_name;
-			break;
-		    }
-		}
-	    }
-	}
-
-	/* Match codec and direction. */
-	if (sd->info.fmt_cnt == 0 || m->desc.port == 0 || 
-	    pjsdp_media_desc_has_attr(m, PJSDP_ATTR_INACTIVE)) 
-	{
-	    sd->info.dir = PJ_MEDIA_DIR_NONE;
-	}
-	else if (pjsdp_media_desc_has_attr(m, PJSDP_ATTR_RECV_ONLY)) {
-	    sd->info.dir = PJ_MEDIA_DIR_ENCODING;
-	}
-	else if (pjsdp_media_desc_has_attr(m, PJSDP_ATTR_SEND_ONLY)) {
-	    sd->info.dir = PJ_MEDIA_DIR_DECODING;
-	}
-	else {
-	    sd->info.dir = PJ_MEDIA_DIR_ENCODING_DECODING;
-	}
-
-    } else {
-	/* Unsupported media stream. */
-	unsigned fmt_num;
-	const pjsdp_rtpmap_attr *rtpmap = NULL;
-
-	pj_strdup(pool, &sd->info.type, &m->desc.media);
-	pj_strdup(pool, &sd->info.transport, &m->desc.transport);
-	pj_memset(&sd->info.sock_info, 0, sizeof(*sock_info));
-	pj_strdup (pool, &sd->info.rem_addr, &conn->addr);
-	sd->info.rem_port = m->desc.port;
-
-	/* Just put one format and rtpmap, so that we don't have to make 
-	 * special exception when we convert this stream to SDP.
-	 */
-
-	/* Find the rtpmap for the payload type. */
-	fmt_num = pj_strtoul(&m->desc.fmt[0]);
-	rtpmap = pjsdp_media_desc_find_rtpmap (m, fmt_num);
-
-	sd->info.fmt_cnt = 1;
-	if (pj_stricmp(&m->desc.media, &ID_VIDEO)==0) {
-	    sd->info.fmt[0].type = PJ_MEDIA_TYPE_VIDEO;
-	    sd->info.fmt[0].pt = fmt_num;
-	    if (rtpmap) {
-		pj_strdup (pool, &sd->info.fmt[0].encoding_name, 
-			   &rtpmap->encoding_name);
-		sd->info.fmt[0].sample_rate = rtpmap->clock_rate;
-	    }
-	} else {
-	    sd->info.fmt[0].type = PJ_MEDIA_TYPE_UNKNOWN;
-	    pj_strdup(pool, &sd->info.fmt[0].encoding_name, &m->desc.fmt[0]);
-	}
+    PJ_ASSERT_RETURN(session, PJ_EINVAL);
+
+    for (i=0; i<session->stream_cnt; ++i) {
 	
-	sd->info.dir = PJ_MEDIA_DIR_NONE;
-    }
-
-    return sd;
-}
-
-/**
- * Create new session based on peer's offering.
- */
-PJ_DEF(pj_media_session_t*) 
-pj_media_session_create_from_sdp (pj_med_mgr_t *mgr, const pjsdp_session_desc *sdp,
-				  const pj_media_sock_info *sock_info)
-{
-    pj_pool_factory *pf;
-    pj_pool_t *pool;
-    pj_media_session_t *session;
+	pjmedia_stream_destroy(session->stream[i]);
+
+    }
+
+    pj_pool_release (session->pool);
+
+    return PJ_SUCCESS;
+}
+
+
+/**
+ * Activate all stream in media session.
+ *
+ */
+PJ_DEF(pj_status_t) pjmedia_session_resume(pjmedia_session *session,
+					   pjmedia_dir dir)
+{
     unsigned i;
 
-    if (sdp_check(sdp) != 0)
-	return NULL;
-
-    pf = pj_med_mgr_get_pool_factory(mgr);
-    pool = pj_pool_create( pf, "session", PJ_MEDIA_SESSION_SIZE, PJ_MEDIA_SESSION_INC, NULL);
-    if (!pool)
-	return NULL;
-
-    session = pj_pool_alloc(pool, sizeof(pj_media_session_t));
-    if (!session) {
-	PJ_LOG(3,(THIS_FILE, "No memory to create media session descriptor"));
-	pj_pool_release (pool);
-	return NULL;
-    }
-
-    session_init (session);
-
-    session->pool = pool;
-    session->mediamgr = mgr;
-
-    /* Enumerate each media stream and create our peer. */
-    for (i=0; i<sdp->media_count; ++i) {
-	const pjsdp_conn_info *conn;
-	const pjsdp_media_desc *m;
-	pj_media_stream_desc *sd;
-
-	m = sdp->media[i];
-	conn = m->conn ? m->conn : sdp->conn;
-
-	/*
-	 * Bug:
-	 *  the sock_info below is used by more than one 'm' lines
-	 */
-	PJ_TODO(SUPPORT_MORE_THAN_ONE_SDP_M_LINES)
-
-	sd = create_stream_from_sdp (pool, mgr, conn, m, sock_info);
-	pj_assert (sd);
-
-	session->stream_desc[session->stream_cnt++] = sd;
-    }
-
-    return session;
-}
-
-/**
- * Duplicate session. The new session is inactive.
- */
-PJ_DEF(pj_media_session_t*)
-pj_media_session_clone (const pj_media_session_t *rhs)
-{
-    pj_pool_factory *pf;
-    pj_pool_t *pool;
-    pj_media_session_t *session;
+    PJ_ASSERT_RETURN(session, PJ_EINVAL);
+
+    for (i=0; i<session->stream_cnt; ++i) {
+	pjmedia_session_resume_stream(session, i, dir);
+    }
+
+    return PJ_SUCCESS;
+}
+
+
+/**
+ * Suspend receipt and transmission of all stream in media session.
+ *
+ */
+PJ_DEF(pj_status_t) pjmedia_session_pause(pjmedia_session *session,
+					  pjmedia_dir dir)
+{
     unsigned i;
 
-    pf = pj_med_mgr_get_pool_factory(rhs->mediamgr);
-    pool = pj_pool_create( pf, "session", PJ_MEDIA_SESSION_SIZE, PJ_MEDIA_SESSION_INC, NULL);
-    if (!pool) {
-	return NULL;
-    }
-
-    session = pj_pool_alloc (pool, sizeof(*session));
-    if (!session) {
-	PJ_LOG(3,(THIS_FILE, "No memory to create media session descriptor"));
-	pj_pool_release (pool);
-	return NULL;
-    }
-
-    session->pool = pool;
-    session->mediamgr = rhs->mediamgr;
-    session->stream_cnt = rhs->stream_cnt;
-
-    for (i=0; i<rhs->stream_cnt; ++i) {
-	pj_media_stream_desc *sd1 = pj_pool_alloc (session->pool, sizeof(pj_media_stream_desc));
-	const pj_media_stream_desc *sd2 = rhs->stream_desc[i];
-
-	if (!sd1) {
-	    PJ_LOG(3,(THIS_FILE, "No memory to create media stream descriptor"));
-	    pj_pool_release (pool);
-	    return NULL;
-	}
-
-	session->stream_desc[i] = sd1;
-	sd1->enc_stream = sd1->dec_stream = NULL;
-	pj_strdup (pool, &sd1->info.type, &sd2->info.type);
-	sd1->info.dir = sd2->info.dir;
-	pj_strdup (pool, &sd1->info.transport, &sd2->info.transport);
-	pj_memcpy(&sd1->info.sock_info, &sd2->info.sock_info, sizeof(pj_media_sock_info));
-	pj_strdup (pool, &sd1->info.rem_addr, &sd2->info.rem_addr);
-	sd1->info.rem_port = sd2->info.rem_port;
-	sd1->info.fmt_cnt = sd2->info.fmt_cnt;
-	pj_memcpy (sd1->info.fmt, sd2->info.fmt, sizeof(sd2->info.fmt));
-    }
-
-    return session;
-}
-
-/**
- * Create SDP description from the session.
- */
-PJ_DEF(pjsdp_session_desc*)
-pj_media_session_create_sdp (const pj_media_session_t *session, pj_pool_t *pool,
-			     pj_bool_t only_first_fmt)
-{
-    pjsdp_session_desc *sdp;
-    pj_time_val tv;
+    PJ_ASSERT_RETURN(session, PJ_EINVAL);
+
+    for (i=0; i<session->stream_cnt; ++i) {
+	pjmedia_session_pause_stream(session, i, dir);
+    }
+
+    return PJ_SUCCESS;
+}
+
+
+/**
+ * Suspend receipt and transmission of individual stream in media session.
+ */
+PJ_DEF(pj_status_t) pjmedia_session_pause_stream( pjmedia_session *session,
+						  unsigned index,
+						  pjmedia_dir dir)
+{
+    PJ_ASSERT_RETURN(session && index < session->stream_cnt, PJ_EINVAL);
+
+    return pjmedia_stream_pause(session->stream[index], dir);
+}
+
+
+/**
+ * Activate individual stream in media session.
+ *
+ */
+PJ_DEF(pj_status_t) pjmedia_session_resume_stream( pjmedia_session *session,
+						   unsigned index,
+						   pjmedia_dir dir)
+{
+    PJ_ASSERT_RETURN(session && index < session->stream_cnt, PJ_EINVAL);
+
+    return pjmedia_stream_resume(session->stream[index], dir);
+}
+
+/**
+ * Enumerate media stream in the session.
+ */
+PJ_DEF(pj_status_t) pjmedia_session_enum_streams(const pjmedia_session *session,
+						 unsigned *count, 
+						 pjmedia_stream_info info[])
+{
     unsigned i;
-    pj_media_sock_info *c_addr = NULL;
-
-    if (session->stream_cnt == 0) {
-	pj_assert(0);
-	return NULL;
-    }
-
-    sdp = pj_pool_calloc (pool, 1, sizeof(pjsdp_session_desc));
-    if (!sdp) {
-	PJ_LOG(3,(THIS_FILE, "No memory to allocate SDP session descriptor"));
-	return NULL;
-    }
-
-    pj_gettimeofday(&tv);
-
-    sdp->origin.user = pj_str("-");
-    sdp->origin.version = sdp->origin.id = tv.sec + 2208988800UL;
-    sdp->origin.net_type = ID_IN;
-    sdp->origin.addr_type = ID_IP4;
-    sdp->origin.addr = *pj_gethostname();
-
-    sdp->name = ID_SDP_NAME;
-
-    /* If all media addresses are the same, then put the connection
-     * info in the session level, otherwise put it in media stream
-     * level.
-     */
-    for (i=0; i<session->stream_cnt; ++i) {
-	if (c_addr == NULL) {
-	    c_addr = &session->stream_desc[i]->info.sock_info;
-	} 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)
-	{
-	    c_addr = NULL;
-	    break;
-	}
-    }
-
-    if (c_addr) {
-	/* All addresses are the same, put connection info in session level. */
-	sdp->conn = pj_pool_alloc (pool, sizeof(pjsdp_conn_info));
-	if (!sdp->conn) {
-	    PJ_LOG(2,(THIS_FILE, "No memory to allocate SDP connection info"));
-	    return NULL;
-	}
-
-	sdp->conn->net_type = ID_IN;
-	sdp->conn->addr_type = ID_IP4;
-	pj_strdup2 (pool, &sdp->conn->addr, pj_inet_ntoa(c_addr->rtp_addr_name.sin_addr));
-    }
-
-    sdp->time.start = sdp->time.stop = 0;
-    sdp->attr_count = 0;
-
-    /* Create each media. */
-    sdp->media_count = 0;
-    for (i=0; i<session->stream_cnt; ++i) {
-	const pj_media_stream_desc *sd = session->stream_desc[i];
-	pjsdp_media_desc *m;
-	unsigned j;
-	unsigned fmt_cnt;
-	pjsdp_attr *attr;
-
-	m = pj_pool_calloc (pool, 1, sizeof(pjsdp_media_desc));
-	if (!m) {
-	    PJ_LOG(3,(THIS_FILE, "No memory to allocate SDP media stream descriptor"));
-	    return NULL;
-	}
-
-	sdp->media[sdp->media_count++] = m;
-
-	pj_strdup (pool, &m->desc.media, &sd->info.type);
-	m->desc.port = pj_ntohs(sd->info.sock_info.rtp_addr_name.sin_port);
-	m->desc.port_count = 1;
-	pj_strdup (pool, &m->desc.transport, &sd->info.transport);
-
-	/* Add format and rtpmap for each codec. */
-	m->desc.fmt_count = 0;
-	m->attr_count = 0;
-	fmt_cnt = sd->info.fmt_cnt;
-	if (fmt_cnt > 0 && only_first_fmt)
-	    fmt_cnt = 1;
-	for (j=0; j<fmt_cnt; ++j) {
-	    pjsdp_rtpmap_attr *rtpmap;
-	    pj_str_t *fmt = &m->desc.fmt[m->desc.fmt_count++];
-
-	    if (sd->info.fmt[j].type==PJ_MEDIA_TYPE_UNKNOWN) {
-		pj_strdup(pool, fmt, &sd->info.fmt[j].encoding_name);
-	    } else {
-		fmt->ptr = pj_pool_alloc(pool, 8);
-		fmt->slen = pj_utoa(sd->info.fmt[j].pt, fmt->ptr);
-
-		rtpmap = pj_pool_calloc(pool, 1, sizeof(pjsdp_rtpmap_attr));
-		if (rtpmap) {
-		    m->attr[m->attr_count++] = (pjsdp_attr*)rtpmap;
-		    rtpmap->type = PJSDP_ATTR_RTPMAP;
-		    rtpmap->payload_type = sd->info.fmt[j].pt;
-		    rtpmap->clock_rate = sd->info.fmt[j].sample_rate;
-		    pj_strdup (pool, &rtpmap->encoding_name, &sd->info.fmt[j].encoding_name);
-		} else {
-		    PJ_LOG(3,(THIS_FILE, "No memory to allocate SDP rtpmap descriptor"));
-		}
-	    }
-	}
-
-	/* If we don't have connection info in session level, create one. */
-	if (sdp->conn == NULL) {
-	    m->conn = pj_pool_alloc (pool, sizeof(pjsdp_conn_info));
-	    if (m->conn) {
-		m->conn->net_type = ID_IN;
-		m->conn->addr_type = ID_IP4;
-		pj_strdup2 (pool, &m->conn->addr, pj_inet_ntoa(sd->info.sock_info.rtp_addr_name.sin_addr));
-	    } else {
-		PJ_LOG(3,(THIS_FILE, "No memory to allocate SDP media connection info"));
-		return NULL;
-	    }
-	}
-
-	/* Add additional attribute to the media stream. */
-	attr = pj_pool_alloc(pool, sizeof(pjsdp_attr));
-	if (!attr) {
-	    PJ_LOG(3,(THIS_FILE, "No memory to allocate SDP attribute"));
-	    return NULL;
-	}
-	m->attr[m->attr_count++] = attr;
-
-	switch (sd->info.dir) {
-	case PJ_MEDIA_DIR_NONE:
-	    attr->type = PJSDP_ATTR_INACTIVE;
-	    break;
-	case PJ_MEDIA_DIR_ENCODING:
-	    attr->type = PJSDP_ATTR_SEND_ONLY;
-	    break;
-	case PJ_MEDIA_DIR_DECODING:
-	    attr->type = PJSDP_ATTR_RECV_ONLY;
-	    break;
-	case PJ_MEDIA_DIR_ENCODING_DECODING:
-	    attr->type = PJSDP_ATTR_SEND_RECV;
-	    break;
-	}
-    }
-
-    return sdp;
-}
-
-/**
- * Update session with SDP answer from peer.
- */
-PJ_DEF(pj_status_t)
-pj_media_session_update (pj_media_session_t *session, 
-			 const pjsdp_session_desc *sdp)
-{
-    unsigned i;
-    unsigned count;
-
-    /* Check SDP */
-    if (sdp_check (sdp) != 0) {
-	return -1;
-    }
-
-    /* If the media stream count doesn't match, only update one. */
-    if (session->stream_cnt != sdp->media_count) {
-	PJ_LOG(3,(THIS_FILE, "pj_media_session_update : "
-		 "SDP media count mismatch! (rmt=%d, lcl=%d)",
-		 sdp->media_count, session->stream_cnt));
-	count = (session->stream_cnt < sdp->media_count) ?
-	    session->stream_cnt : sdp->media_count;
-    } else {
-	count = session->stream_cnt;
-    }
-
-    for (i=0; i<count; ++i) {
-	pj_media_stream_desc *sd = session->stream_desc[i];
-	const pjsdp_media_desc *m = sdp->media[i];
-	const pjsdp_conn_info *conn;
-	unsigned j;
-
-	/* Check that the session is not active. */
-	pj_assert (sd->enc_stream == NULL && sd->dec_stream == NULL);
-
-	conn = m->conn ? m->conn : sdp->conn;
-	pj_assert(conn);
-
-	/* Update remote address. */
-	sd->info.rem_port = m->desc.port;
-	pj_strdup (session->pool, &sd->info.rem_addr, &conn->addr);
-
-	/* Select one active codec according to what peer wants. */
-	for (j=0; j<sd->info.fmt_cnt; ++j) {
-	    unsigned fmt_0 = pj_strtoul(&m->desc.fmt[0]);
-	    if (sd->info.fmt[j].pt == fmt_0) {
-		pj_codec_id temp;
-
-		/* Put active format to the front. */
-		if (j == 0)
-		    break;
-
-		pj_memcpy(&temp, &sd->info.fmt[0], sizeof(temp));
-		pj_memcpy(&sd->info.fmt[0], &sd->info.fmt[j], sizeof(temp));
-		pj_memcpy(&sd->info.fmt[j], &temp, sizeof(temp));
-		break;
-	    }
-	}
-
-	if (j == sd->info.fmt_cnt) {
-	    /* Peer has answered SDP with new codec, which doesn't exist
-	     * in the offer!
-	     * Mute this media.
-	     */
-	    PJ_LOG(3,(THIS_FILE, "Peer has answered SDP with new codec!"));
-	    sd->info.dir = PJ_MEDIA_DIR_NONE;
-	    continue;
-	}
-
-	/* Check direction. */
-	if (m->desc.port == 0 || pjsdp_media_desc_has_attr(m, PJSDP_ATTR_INACTIVE)) {
-	    sd->info.dir = PJ_MEDIA_DIR_NONE;
-	}
-	else if (pjsdp_media_desc_has_attr(m, PJSDP_ATTR_RECV_ONLY)) {
-	    sd->info.dir = PJ_MEDIA_DIR_ENCODING;
-	}
-	else if (pjsdp_media_desc_has_attr(m, PJSDP_ATTR_SEND_ONLY)) {
-	    sd->info.dir = PJ_MEDIA_DIR_DECODING;
-	}
-	else {
-	    sd->info.dir = PJ_MEDIA_DIR_ENCODING_DECODING;
-	}
-    }
-
-    return 0;
-}
-
-/**
- * Enumerate media streams in the session.
- */
-PJ_DEF(unsigned)
-pj_media_session_enum_streams (const pj_media_session_t *session, 
-			       unsigned count, const pj_media_stream_info *info[])
-{
-    unsigned i;
-
-    if (count > session->stream_cnt)
-	count = session->stream_cnt;
-
-    for (i=0; i<count; ++i) {
-	info[i] = &session->stream_desc[i]->info;
-    }
-
-    return session->stream_cnt;
+
+    PJ_ASSERT_RETURN(session && count && *count && info, PJ_EINVAL);
+
+    if (*count > session->stream_cnt)
+	*count = session->stream_cnt;
+
+    for (i=0; i<*count; ++i) {
+	pj_memcpy(&info[i], &session->stream[i], sizeof(pjmedia_stream_info));
+    }
+
+    return PJ_SUCCESS;
 }
 
@@ -662,174 +369,27 @@
  * Get statistics
  */
-PJ_DEF(pj_status_t)
-pj_media_session_get_stat (const pj_media_session_t *session, unsigned index,
-			   pj_media_stream_stat *tx_stat,
-			   pj_media_stream_stat *rx_stat)
-{
-    pj_media_stream_desc *sd;
-    int stat_cnt = 0;
-
-    if (index >= session->stream_cnt) {
-	pj_assert(0);
-	return -1;
-    }
-    
-    sd = session->stream_desc[index];
-
-    if (sd->enc_stream && tx_stat) {
-	pj_media_stream_get_stat (sd->enc_stream, tx_stat);
-	++stat_cnt;
-    } else if (tx_stat) {
-	pj_memset (tx_stat, 0, sizeof(*tx_stat));
-    }
-
-    if (sd->dec_stream && rx_stat) {
-	pj_media_stream_get_stat (sd->dec_stream, rx_stat);
-	++stat_cnt;
-    } else if (rx_stat) {
-	pj_memset (rx_stat, 0, sizeof(*rx_stat));
-    }
-
-    return stat_cnt ? 0 : -1;
-}
-
-/**
- * Modify stream, only when stream is inactive.
- */
-PJ_DEF(pj_status_t)
-pj_media_session_modify_stream (pj_media_session_t *session, unsigned index,
-				unsigned modify_flag, const pj_media_stream_info *info)
-{
-    pj_media_stream_desc *sd;
-
-    if (index >= session->stream_cnt) {
-	pj_assert(0);
-	return -1;
-    }
-    
-    sd = session->stream_desc[index];
-
-    if (sd->enc_stream || sd->dec_stream) {
-	pj_assert(0);
-	return -1;
-    }
-
-    if (modify_flag & PJ_MEDIA_STREAM_MODIFY_DIR) {
-	sd->info.dir = info->dir;
-    }
-
-    return 0;
-}
-
-/**
- * Activate media session.
- */
-PJ_DEF(pj_status_t)
-pj_media_session_activate (pj_media_session_t *session)
-{
-    unsigned i;
-    pj_status_t status = 0;
-
-    for (i=0; i<session->stream_cnt; ++i) {
-	pj_status_t rc;
-	rc = pj_media_session_activate_stream (session, i);
-	if (status == 0)
-	    status = rc;
-    }
-    return status;
-}
-
-/**
- * Activate individual stream in media session.
- */
-PJ_DEF(pj_status_t)
-pj_media_session_activate_stream (pj_media_session_t *session, unsigned index)
-{
-    pj_media_stream_desc *sd;
-    pj_media_stream_create_param scp;
-    pj_status_t status;
-    pj_time_val tv;
-
-    if (index < 0 || index >= session->stream_cnt) {
-	pj_assert(0);
-	return -1;
-    }
-
-    sd = session->stream_desc[index];
-
-    if (sd->enc_stream || sd->dec_stream) {
-	/* Stream already active. */
-	pj_assert(0);
-	return 0;
-    }
-
-    pj_gettimeofday(&tv);
-
-    /* Initialize parameter to create stream. */
-    pj_memset (&scp, 0, sizeof(scp));
-    scp.codec_id = &sd->info.fmt[0];
-    scp.mediamgr = session->mediamgr;
-    scp.dir = sd->info.dir;
-    scp.rtp_sock = sd->info.sock_info.rtp_sock;
-    scp.rtcp_sock = sd->info.sock_info.rtcp_sock;
-    scp.remote_addr = pj_pool_calloc (session->pool, 1, sizeof(pj_sockaddr_in));
-    pj_sockaddr_in_init(scp.remote_addr, &sd->info.rem_addr, sd->info.rem_port);
-    scp.ssrc = tv.sec;
-    scp.jb_min = 1;
-    scp.jb_max = 15;
-    scp.jb_maxcnt = 16;
-
-    /* Build the stream! */
-    status = pj_media_stream_create (session->pool, &sd->enc_stream, &sd->dec_stream, &scp);
-
-    if (status==0 && sd->enc_stream) {
-	status = pj_media_stream_start (sd->enc_stream);
-	if (status != 0)
-	    goto on_error;
-    }
-    if (status==0 && sd->dec_stream) {
-	status = pj_media_stream_start (sd->dec_stream);
-	if (status != 0)
-	    goto on_error;
-    }
-    return status;
-
-on_error:
-    if (sd->enc_stream) {
-	pj_media_stream_destroy (sd->enc_stream);
-	sd->enc_stream = NULL;
-    }
-    if (sd->dec_stream) {
-	pj_media_stream_destroy (sd->dec_stream);
-	sd->dec_stream = NULL;
-    }
-    return status;
-}
-
-/**
- * Destroy media session.
- */
-PJ_DEF(pj_status_t)
-pj_media_session_destroy (pj_media_session_t *session)
-{
-    unsigned i;
-
-    if (!session)
-	return -1;
-
-    for (i=0; i<session->stream_cnt; ++i) {
-	pj_media_stream_desc *sd = session->stream_desc[i];
-
-	if (sd->enc_stream) {
-	    pj_media_stream_destroy (sd->enc_stream);
-	    sd->enc_stream = NULL;
-	}
-	if (sd->dec_stream) {
-	    pj_media_stream_destroy (sd->dec_stream);
-	    sd->dec_stream = NULL;
-	}
-    }
-    pj_pool_release (session->pool);
-    return 0;
-}
-
+PJ_DEF(pj_status_t) pjmedia_session_get_stat(const pjmedia_session *session, 
+					     unsigned *count,
+					     pjmedia_stream_stat stat[])
+{
+    PJ_ASSERT_RETURN(session && count && *count && stat, PJ_EINVAL);
+
+    *count = 0;
+    pj_memset(stat, 0, *count * sizeof(pjmedia_stream_stat));
+    return PJ_EINVALIDOP;
+}
+
+
+/**
+ * Get individual stream statistic.
+ */
+PJ_DEF(pj_status_t) pjmedia_session_get_stream_stat( const pjmedia_session *s,
+						     unsigned index,
+						     pjmedia_stream_stat *stat)
+{
+    PJ_ASSERT_RETURN(s && index < s->stream_cnt && stat, PJ_EINVAL);
+    pj_memset(stat, 0, sizeof(pjmedia_stream_stat));
+    return PJ_EINVALIDOP;
+}
+
+
Index: pjproject/trunk/pjmedia/src/pjmedia/stream.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/stream.c	(revision 158)
+++ pjproject/trunk/pjmedia/src/pjmedia/stream.c	(revision 159)
@@ -32,10 +32,11 @@
 
 
-#define THISFILE    "stream.c"
-#define ERRLEVEL    1
-
-#define PJ_MAX_FRAME_DURATION_MS    200
-#define PJ_MAX_BUFFER_SIZE_MS	    2000
-#define PJ_MAX_MTU		    1500
+#define THIS_FILE			"stream.c"
+#define ERRLEVEL			1
+#define TRACE_(expr)			PJ_LOG(3,expr)
+
+#define PJMEDIA_MAX_FRAME_DURATION_MS   200
+#define PJMEDIA_MAX_BUFFER_SIZE_MS	2000
+#define PJMEDIA_MAX_MTU			1500
 
 struct jb_frame
@@ -49,40 +50,65 @@
 #define pj_fifobuf_free(fifo, buf)	free(buf)
 
-enum stream_state
-{
-    STREAM_STOPPED,
-    STREAM_STARTED,
+
+/**
+ * Media channel.
+ */
+struct pjmedia_channel
+{
+    pjmedia_stream	   *stream;	    /**< Parent stream.		    */
+    pjmedia_dir		    dir;	    /**< Channel direction.	    */
+    unsigned		    pt;		    /**< Payload type.		    */
+    pj_bool_t		    paused;	    /**< Paused?.		    */
+    pj_snd_stream_info	    snd_info;	    /**< Sound stream param.	    */
+    pj_snd_stream	   *snd_stream;	    /**< Sound stream.		    */
+    unsigned		    in_pkt_size;    /**< Size of input buffer.	    */
+    void		   *in_pkt;	    /**< Input buffer.		    */
+    unsigned		    out_pkt_size;   /**< Size of output buffer.	    */
+    void		   *out_pkt;	    /**< Output buffer.		    */
+    unsigned		    pcm_buf_size;   /**< Size of PCM buffer.	    */
+    void		   *pcm_buf;	    /**< PCM buffer.		    */
+    pj_rtp_session	    rtp;	    /**< RTP session.		    */
 };
 
-struct pj_media_stream_t
-{
-    pj_media_dir_t	    dir;
-    int			    pt;
-    int			    state;
-    pj_media_stream_stat    stat;
-    pj_media_stream_t	   *peer;
-    pj_snd_stream_info	    snd_info;
-    pj_snd_stream	   *snd_stream;
-    pj_mutex_t		   *mutex;
-    unsigned		    in_pkt_size;
-    void		   *in_pkt;
-    unsigned		    out_pkt_size;
-    void		   *out_pkt;
-    unsigned		    pcm_buf_size;
-    void		   *pcm_buf;
-    //pj_fifobuf_t	    fifobuf;
-    pj_codec_mgr	   *codec_mgr;
-    pj_codec		   *codec;
-    pj_rtp_session	    rtp;
-    pj_rtcp_session	   *rtcp;
-    pj_jitter_buffer	   *jb;
-    pj_sock_t		    rtp_sock;
-    pj_sock_t		    rtcp_sock;
-    pj_sockaddr_in	    dst_addr;
-    pj_thread_t		   *transport_thread;
-    int			    thread_quit_flag;
+
+/**
+ * This structure describes media stream.
+ * A media stream is bidirectional media transmission between two endpoints.
+ * It consists of two channels, i.e. encoding and decoding channels.
+ * A media stream corresponds to a single "m=" line in a SDP session
+ * description.
+ */
+struct pjmedia_stream
+{
+    pjmedia_channel	    *enc;	    /**< Encoding channel.	    */
+    pjmedia_channel	    *dec;	    /**< Decoding channel.	    */
+
+    pjmedia_dir		     dir;	    /**< Stream direction.	    */
+    pjmedia_stream_stat	     stat;	    /**< Stream statistics.	    */
+
+    pjmedia_codec_mgr	    *codec_mgr;	    /**< Codec manager instance.    */
+    pjmedia_codec	    *codec;	    /**< Codec instance being used. */
+
+    pj_mutex_t		    *jb_mutex;
+    pj_jitter_buffer	     jb;	    /**< Jitter buffer.		    */
+
+    pj_sock_t		     rtp_sock;	    /**< RTP socket.		    */
+    pj_sock_t		     rtcp_sock;	    /**< RTCP socket.		    */
+    pj_sockaddr_in	     dst_addr;	    /**< Destination RTP address.   */
+
+    pj_rtcp_session	     rtcp;	    /**< RTCP for incoming RTP.	    */
+
+    pj_bool_t		     quit_flag;	    /**< To signal thread exit.	    */
+    pj_thread_t		    *thread;	    /**< Jitter buffer's thread.    */
 };
 
 
+
+/*
+ * play_callback()
+ *
+ * This callback is called by sound device's player thread when it
+ * needs to feed the player with some frames.
+ */
 static pj_status_t play_callback(/* in */   void *user_data,
 				 /* in */   pj_uint32_t timestamp,
@@ -90,27 +116,30 @@
 				 /*inout*/  unsigned size)
 {
-    pj_media_stream_t *channel = user_data;
+    pjmedia_channel *channel = user_data;
+    pjmedia_stream *stream = channel->stream;
     struct jb_frame *jb_frame;
     void *p;
     pj_uint32_t extseq;
     pj_status_t status;
-    struct pj_audio_frame frame_in, frame_out;
+    struct pjmedia_frame frame_in, frame_out;
 
     PJ_UNUSED_ARG(timestamp);
 
-    /* Lock mutex */
-    pj_mutex_lock (channel->mutex);
-
-    if (!channel->codec) {
-	pj_mutex_unlock (channel->mutex);
+    /* Do nothing if we're quitting. */
+    if (stream->quit_flag)
 	return -1;
-    }
+
+    /* Lock jitter buffer mutex */
+    pj_mutex_lock( stream->jb_mutex );
 
     /* Get frame from jitter buffer. */
-    status = pj_jb_get (channel->jb, &extseq, &p);
+    status = pj_jb_get(&stream->jb, &extseq, &p);
+
+    /* Unlock jitter buffer mutex. */
+    pj_mutex_unlock( stream->jb_mutex );
+
     jb_frame = p;
-    if (status != 0 || jb_frame == NULL) {
+    if (status != PJ_SUCCESS || jb_frame == NULL) {
 	pj_memset(frame, 0, size);
-	pj_mutex_unlock(channel->mutex);
 	return 0;
     }
@@ -119,15 +148,13 @@
     frame_in.buf = jb_frame->buf;
     frame_in.size = jb_frame->size;
-    frame_in.type = PJ_AUDIO_FRAME_AUDIO;  /* ignored */
+    frame_in.type = PJMEDIA_FRAME_TYPE_AUDIO;  /* ignored */
     frame_out.buf = channel->pcm_buf;
-    status = channel->codec->op->decode (channel->codec, &frame_in,
-					 channel->pcm_buf_size, &frame_out);
+    status = stream->codec->op->decode( stream->codec, &frame_in,
+					channel->pcm_buf_size, &frame_out);
     if (status != 0) {
-	PJ_LOG(3, (THISFILE, "decode() has return error status %d", 
-			  status));
+	TRACE_((THIS_FILE, "decode() has return error status %d", status));
 
 	pj_memset(frame, 0, size);
 	pj_fifobuf_free (&channel->fifobuf, jb_frame);
-	pj_mutex_unlock(channel->mutex);
 	return 0;
     }
@@ -135,16 +162,23 @@
     /* Put in sound buffer. */
     if (frame_out.size > size) {
-	PJ_LOG(3, (THISFILE, "Sound playout buffer truncated %d bytes", 
-			  frame_out.size - size));
+	TRACE_((THIS_FILE, "Sound playout buffer truncated %d bytes", 
+		frame_out.size - size));
 	frame_out.size = size;
     }
 
     pj_memcpy(frame, frame_out.buf, size);
-
     pj_fifobuf_free (&channel->fifobuf, jb_frame);
-    pj_mutex_unlock(channel->mutex);
+
     return 0;
 }
 
+
+/**
+ * rec_callback()
+ *
+ * This callback is called when the mic device has gathered
+ * enough audio samples. We will encode the audio samples and
+ * send it to remote.
+ */
 static pj_status_t rec_callback( /* in */ void *user_data,
 			         /* in */ pj_uint32_t timestamp,
@@ -152,48 +186,44 @@
 			         /* in */ unsigned size)
 {
-    pj_media_stream_t *channel = user_data;
+    pjmedia_channel *channel = user_data;
+    pjmedia_stream *stream = channel->stream;
     pj_status_t status = 0;
-    struct pj_audio_frame frame_in, frame_out;
+    struct pjmedia_frame frame_in, frame_out;
     int ts_len;
     void *rtphdr;
     int rtphdrlen;
     pj_ssize_t sent;
-#if 0
-    static FILE *fhnd = NULL;
-#endif
+
 
     PJ_UNUSED_ARG(timestamp);
 
-    /* Start locking channel mutex */
-    pj_mutex_lock (channel->mutex);
-
-    if (!channel->codec) {
-	status = -1;
-	goto on_return;
-    }
+    /* Check if stream is quitting. */
+    if (stream->quit_flag)
+	return -1;
 
     /* Encode. */
-    frame_in.type = PJ_MEDIA_TYPE_AUDIO;
+    frame_in.type = PJMEDIA_TYPE_AUDIO;
     frame_in.buf = (void*)frame;
     frame_in.size = size;
     frame_out.buf = ((char*)channel->out_pkt) + sizeof(pj_rtp_hdr);
-    status = channel->codec->op->encode (channel->codec, &frame_in, 
-					 channel->out_pkt_size - sizeof(pj_rtp_hdr), 
-					 &frame_out);
+    status = stream->codec->op->encode( stream->codec, &frame_in, 
+					channel->out_pkt_size - sizeof(pj_rtp_hdr), 
+					&frame_out);
     if (status != 0) {
-	PJ_LOG(3,(THISFILE, "Codec encode() has returned error status %d", 
-			     status));
-	goto on_return;
+	TRACE_((THIS_FILE, "Codec encode() has returned error status %d", 
+		status));
+	return status;
     }
 
     /* Encapsulate. */
     ts_len = size / (channel->snd_info.bits_per_sample / 8);
-    status = pj_rtp_encode_rtp (&channel->rtp, channel->pt, 0, 
+    status = pj_rtp_encode_rtp( &channel->rtp, 
+				channel->pt, 0, 
 				frame_out.size, ts_len, 
 				(const void**)&rtphdr, &rtphdrlen);
     if (status != 0) {
-	PJ_LOG(3,(THISFILE, "RTP encode_rtp() has returned error status %d", 
-			    status));
-	goto on_return;
+	TRACE_((THIS_FILE, "RTP encode_rtp() has returned error status %d", 
+			   status));
+	return status;
     }
 
@@ -201,6 +231,6 @@
 	/* We don't support RTP with extended header yet. */
 	PJ_TODO(SUPPORT_SENDING_RTP_WITH_EXTENDED_HEADER);
-	PJ_LOG(3,(THISFILE, "Unsupported extended RTP header for transmission"));
-	goto on_return;
+	TRACE_((THIS_FILE, "Unsupported extended RTP header for transmission"));
+	return 0;
     }
 
@@ -209,34 +239,27 @@
     /* Send. */
     sent = frame_out.size+sizeof(pj_rtp_hdr);
-    status = pj_sock_sendto (channel->rtp_sock, channel->out_pkt, &sent, 0, 
-			   &channel->dst_addr, sizeof(channel->dst_addr));
-    if (status != PJ_SUCCESS)
-	goto on_return;
+    status = pj_sock_sendto(stream->rtp_sock, channel->out_pkt, &sent, 0, 
+			    &stream->dst_addr, sizeof(stream->dst_addr));
+    if (status != PJ_SUCCESS)
+	return status;
 
     /* Update stat */
-    channel->stat.pkt_tx++;
-    channel->stat.oct_tx += frame_out.size+sizeof(pj_rtp_hdr);
-
-#if 0
-    if (fhnd == NULL) {
-	fhnd = fopen("RTP.DAT", "wb");
-	if (fhnd) {
-	    fwrite (channel->out_pkt, frame_out.size+sizeof(pj_rtp_hdr), 1, fhnd);
-	    fclose(fhnd);
-	}
-    }
-#endif
-
-on_return:
-    pj_mutex_unlock (channel->mutex);
-    return status;
-}
-
-
-static int PJ_THREAD_FUNC stream_decoder_transport_thread (void*arg)
-{
-    pj_media_stream_t *channel = arg;
-
-    while (!channel->thread_quit_flag) {
+    stream->stat.enc.pkt++;
+    stream->stat.enc.bytes += frame_out.size+sizeof(pj_rtp_hdr);
+
+    return 0;
+}
+
+
+/*
+ * This thread will poll the socket for incoming packets, and put
+ * the packets to jitter buffer.
+ */
+static int PJ_THREAD_FUNC jitter_buffer_thread (void*arg)
+{
+    pjmedia_stream *stream = arg;
+    pjmedia_channel *channel = stream->dec;
+
+    while (!stream->quit_flag) {
 	pj_ssize_t len, size;
 	const pj_rtp_hdr *hdr;
@@ -251,10 +274,10 @@
 
 	PJ_FD_ZERO (&fds);
-	PJ_FD_SET (channel->rtp_sock, &fds);
+	PJ_FD_SET (stream->rtp_sock, &fds);
 	timeout.sec = 0;
-	timeout.msec = 100;
+	timeout.msec = 1;
 
 	/* Wait with timeout. */
-	status = pj_sock_select(channel->rtp_sock, &fds, NULL, NULL, &timeout);
+	status = pj_sock_select(stream->rtp_sock, &fds, NULL, NULL, &timeout);
 	if (status != 1)
 	    continue;
@@ -262,44 +285,44 @@
 	/* Get packet from socket. */
 	len = channel->in_pkt_size;
-	status = pj_sock_recv (channel->rtp_sock, channel->in_pkt, &len, 0);
+	status = pj_sock_recv(stream->rtp_sock, channel->in_pkt, &len, 0);
 	if (len < 1 || status != PJ_SUCCESS) {
 	    if (pj_get_netos_error() == PJ_STATUS_FROM_OS(OSERR_ECONNRESET)) {
-		/* On Win2K SP2 (or above) and WinXP, recv() will get WSAECONNRESET
-		   when the sending side receives ICMP port unreachable.
+		/* On Win2K SP2 (or above) and WinXP, recv() will get 
+		 * WSAECONNRESET when the sending side receives ICMP port 
+		 * unreachable.
 		 */
 		continue;
 	    }
-	    //pj_perror(THISFILE, "Error receiving packet from socket (len=%d)", len);
 	    pj_thread_sleep(1);
 	    continue;
 	}
 
-	if (channel->state != STREAM_STARTED)
+	if (channel->paused)
 	    continue;
 
-	if (channel->thread_quit_flag)
-	    break;
-
-	/* Start locking the channel. */
-	pj_mutex_lock (channel->mutex);
-
 	/* Update RTP and RTCP session. */
-	status = pj_rtp_decode_rtp (&channel->rtp, channel->in_pkt, len, &hdr, &payload, &payloadlen);
-	if (status != 0) {
-	    pj_mutex_unlock (channel->mutex);
-	    PJ_LOG(4,(THISFILE, "RTP decode_rtp() has returned error status %d", status));
+	status = pj_rtp_decode_rtp(&channel->rtp, channel->in_pkt, len, 
+				   &hdr, &payload, &payloadlen);
+	if (status != PJ_SUCCESS) {
+	    TRACE_((THIS_FILE, "RTP decode_rtp() has returned error status %d",
+		    status));
 	    continue;
 	}
-	status = pj_rtp_session_update (&channel->rtp, hdr);
-	if (status != 0 && status != PJ_RTP_ERR_SESSION_PROBATION && status != PJ_RTP_ERR_SESSION_RESTARTED) {
-	    pj_mutex_unlock (channel->mutex);
-	    PJ_LOG(4,(THISFILE, "RTP session_update() has returned error status %d", status));
+
+	status = pj_rtp_session_update(&channel->rtp, hdr);
+	if (status != 0 && 
+	    status != PJMEDIA_RTP_ERR_SESSION_PROBATION && 
+	    status != PJMEDIA_RTP_ERR_SESSION_RESTARTED) 
+	{
+	    TRACE_((THIS_FILE, 
+		    "RTP session_update() has returned error status %d", 
+		    status));
 	    continue;
 	}
-	pj_rtcp_rx_rtp (channel->rtcp, pj_ntohs(hdr->seq), pj_ntohl(hdr->ts));
+	pj_rtcp_rx_rtp(&stream->rtcp, pj_ntohs(hdr->seq), pj_ntohl(hdr->ts));
 
 	/* Update stat */
-	channel->stat.pkt_rx++;
-	channel->stat.oct_rx += len;
+	stream->stat.dec.pkt++;
+	stream->stat.dec.bytes += len;
 
 	/* Copy to FIFO buffer. */
@@ -307,6 +330,6 @@
 	jb_frame = pj_fifobuf_alloc (&channel->fifobuf, size);
 	if (jb_frame == NULL) {
-	    pj_mutex_unlock (channel->mutex);
-	    PJ_LOG(4,(THISFILE, "Unable to allocate %d bytes FIFO buffer", size));
+	    TRACE_((THIS_FILE, "Unable to allocate %d bytes FIFO buffer", 
+		    size));
 	    continue;
 	}
@@ -318,13 +341,16 @@
 
 	/* Put to jitter buffer. */
-	status = pj_jb_put (channel->jb, pj_ntohs(hdr->seq), jb_frame);
+	pj_mutex_lock( stream->jb_mutex );
+	status = pj_jb_put(&stream->jb, pj_ntohs(hdr->seq), jb_frame);
+	pj_mutex_unlock( stream->jb_mutex );
+
 	if (status != 0) {
 	    pj_fifobuf_unalloc (&channel->fifobuf, jb_frame);
-	    pj_mutex_unlock (channel->mutex);
-	    PJ_LOG(4,(THISFILE, "Jitter buffer put() has returned error status %d", status));
+	    
+	    TRACE_((THIS_FILE, 
+		    "Jitter buffer put() has returned error status %d", 
+		    status));
 	    continue;
 	}
-
-	pj_mutex_unlock (channel->mutex);
     }
 
@@ -332,125 +358,90 @@
 }
 
-static void init_snd_param_from_codec_attr (pj_snd_stream_info *param,
-					    const pj_codec_attr *attr)
-{
-    param->bits_per_sample = attr->pcm_bits_per_sample;
-    param->bytes_per_frame = 2;
-    param->frames_per_packet = attr->sample_rate * attr->ptime / 1000;
-    param->samples_per_frame = 1;
-    param->samples_per_sec = attr->sample_rate;
-}
-
-static pj_media_stream_t *create_channel ( pj_pool_t *pool,
-					   pj_media_dir_t dir,
-					   pj_media_stream_t *peer,
-					   pj_codec_id *codec_id,
-					   pj_media_stream_create_param *param)
-{
-    pj_media_stream_t *channel;
-    pj_codec_attr codec_attr;
-    void *ptr;
-    unsigned size;
+
+/*
+ * Create sound stream parameter from codec attributes.
+ */
+static void init_snd_param( pj_snd_stream_info *snd_param,
+			    const pjmedia_codec_param *codec_param)
+{
+    pj_memset(snd_param, 0, sizeof(*snd_param));
+
+    snd_param->bits_per_sample	 = codec_param->pcm_bits_per_sample;
+    snd_param->bytes_per_frame   = 2;
+    snd_param->frames_per_packet = codec_param->sample_rate * 
+				   codec_param->ptime / 
+				   1000;
+    snd_param->samples_per_frame = 1;
+    snd_param->samples_per_sec   = codec_param->sample_rate;
+}
+
+
+/*
+ * Create media channel.
+ */
+static pj_status_t create_channel( pj_pool_t *pool,
+				   pjmedia_stream *stream,
+				   pjmedia_dir dir,
+				   const pjmedia_stream_info *param,
+				   const pjmedia_codec_param *codec_param,
+				   pjmedia_channel **p_channel)
+{
+    pjmedia_channel *channel;
     pj_status_t status;
     
     /* Allocate memory for channel descriptor */
-    size = sizeof(pj_media_stream_t);
-    channel = pj_pool_calloc(pool, 1, size);
-    if (!channel) {
-	PJ_LOG(1,(THISFILE, "Unable to allocate %u bytes channel descriptor", 
-			 size));
-	return NULL;
-    }
-
+
+    channel = pj_pool_zalloc(pool, sizeof(pjmedia_channel));
+    PJ_ASSERT_RETURN(channel != NULL, PJ_ENOMEM);
+
+    /* Init channel info. */
+
+    channel->stream = stream;
     channel->dir = dir;
-    channel->pt = codec_id->pt;
-    channel->peer = peer;
-    channel->codec_mgr = pj_med_mgr_get_codec_mgr (param->mediamgr);
-    channel->rtp_sock = param->rtp_sock;
-    channel->rtcp_sock = param->rtcp_sock;
-    channel->dst_addr = *param->remote_addr;
-    channel->state = STREAM_STOPPED;
-
-    /* Create mutex for the channel. */
-    status = pj_mutex_create_simple(pool, NULL, &channel->mutex);
-    if (status != PJ_SUCCESS)
-	goto err_cleanup;
-
-    /* Create and initialize codec, only if peer is not present.
-       We only use one codec instance for both encoder and decoder.
-     */
-    if (peer && peer->codec) {
-	channel->codec = peer->codec;
-	status = channel->codec->factory->op->default_attr(channel->codec->factory, codec_id, 
-							   &codec_attr);
-	if (status != 0) {
-	    goto err_cleanup;
-	}
-
-    } else {
-	channel->codec = pj_codec_mgr_alloc_codec(channel->codec_mgr, codec_id);
-	if (channel->codec == NULL) {
-	    goto err_cleanup;
-	}
-
-	status = channel->codec->factory->op->default_attr(channel->codec->factory, codec_id, 
-							   &codec_attr);
-	if (status != 0) {
-	    goto err_cleanup;
-	}
-
-	codec_attr.pt = codec_id->pt;
-	status = channel->codec->op->open(channel->codec, &codec_attr);
-	if (status != 0) {
-	    goto err_cleanup;
-	}
-    }
+    channel->paused = 1;
+    channel->pt = param->fmt.pt;
 
     /* Allocate buffer for incoming packet. */
-    channel->in_pkt_size = PJ_MAX_MTU;
-    channel->in_pkt = pj_pool_alloc(pool, channel->in_pkt_size);
-    if (!channel->in_pkt) {
-	PJ_LOG(1, (THISFILE, "Unable to allocate %u bytes incoming packet buffer", 
-			  channel->in_pkt_size));
-	goto err_cleanup;
-    }
-
+
+    channel->in_pkt_size = PJMEDIA_MAX_MTU;
+    channel->in_pkt = pj_pool_alloc( pool, channel->in_pkt_size );
+    PJ_ASSERT_RETURN(channel->in_pkt != NULL, PJ_ENOMEM);
+
+    
     /* Allocate buffer for outgoing packet. */
+
     channel->out_pkt_size = sizeof(pj_rtp_hdr) + 
-			    codec_attr.avg_bps / 8 * PJ_MAX_FRAME_DURATION_MS / 1000;
-    if (channel->out_pkt_size > PJ_MAX_MTU)
-	channel->out_pkt_size = PJ_MAX_MTU;
+			    codec_param->avg_bps/8 * 
+			    PJMEDIA_MAX_FRAME_DURATION_MS / 
+			    1000;
+
+    if (channel->out_pkt_size > PJMEDIA_MAX_MTU)
+	channel->out_pkt_size = PJMEDIA_MAX_MTU;
+
     channel->out_pkt = pj_pool_alloc(pool, channel->out_pkt_size);
-    if (!channel->out_pkt) {
-	PJ_LOG(1, (THISFILE, "Unable to allocate %u bytes encoding buffer", 
-			  channel->out_pkt_size));
-	goto err_cleanup;
-    }
-
-    /* Allocate buffer for decoding to PCM */
-    channel->pcm_buf_size = codec_attr.sample_rate * 
-			    codec_attr.pcm_bits_per_sample / 8 *
-			    PJ_MAX_FRAME_DURATION_MS / 1000;
+    PJ_ASSERT_RETURN(channel->out_pkt != NULL, PJ_ENOMEM);
+
+
+    /* Allocate buffer for decoding to PCM: */
+
+    channel->pcm_buf_size = codec_param->sample_rate * 
+			    codec_param->pcm_bits_per_sample / 8 *
+			    PJMEDIA_MAX_FRAME_DURATION_MS / 1000;
     channel->pcm_buf = pj_pool_alloc (pool, channel->pcm_buf_size);
-    if (!channel->pcm_buf) {
-	PJ_LOG(1, (THISFILE, "Unable to allocate %u bytes PCM buffer", 
-			  channel->pcm_buf_size));
-	goto err_cleanup;
-    }
-
-    /* Allocate buffer for frames put in jitter buffer. */
-    size = codec_attr.avg_bps / 8 * PJ_MAX_BUFFER_SIZE_MS / 1000;
-    ptr = pj_pool_alloc(pool, size);
-    if (!ptr) {
-	PJ_LOG(1, (THISFILE, "Unable to allocate %u bytes jitter buffer", 
-			  channel->pcm_buf_size));
-	goto err_cleanup;
-    }
-    //pj_fifobuf_init (&channel->fifobuf, ptr, size);
+    PJ_ASSERT_RETURN(channel->pcm_buf != NULL, PJ_ENOMEM);
+
+
+    /* Create RTP and RTCP sessions: */
+
+    status = pj_rtp_session_init(&channel->rtp, param->fmt.pt, 
+				 param->ssrc);
+    if (status != PJ_SUCCESS)
+	return status;
 
     /* Create and initialize sound device */
-    init_snd_param_from_codec_attr (&channel->snd_info, &codec_attr);
-
-    if (dir == PJ_MEDIA_DIR_ENCODING)
+
+    init_snd_param(&channel->snd_info, codec_param);
+
+    if (dir == PJMEDIA_DIR_ENCODING)
 	channel->snd_stream = pj_snd_open_recorder(-1, &channel->snd_info, 
 						   &rec_callback, channel);
@@ -460,188 +451,248 @@
 
     if (!channel->snd_stream)
-	goto err_cleanup;
-
-    /* Create RTP and RTCP sessions. */
-    if (pj_rtp_session_init(&channel->rtp, codec_id->pt, param->ssrc) != 0) {
-	PJ_LOG(1, (THISFILE, "RTP session initialization error"));
-	goto err_cleanup;
-    }
-
-    /* For decoder, create RTCP session, jitter buffer, and transport thread. */
-    if (dir == PJ_MEDIA_DIR_DECODING) {
-	channel->rtcp = pj_pool_calloc(pool, 1, sizeof(pj_rtcp_session));
-	if (!channel->rtcp) {
-	    PJ_LOG(1, (THISFILE, "Unable to allocate RTCP session"));
-	    goto err_cleanup;
-	}
-
-	pj_rtcp_init(channel->rtcp, param->ssrc);
-
-	channel->jb = pj_pool_calloc(pool, 1, sizeof(pj_jitter_buffer));
-	if (!channel->jb) {
-	    PJ_LOG(1, (THISFILE, "Unable to allocate jitter buffer descriptor"));
-	    goto err_cleanup;
-	}
-	if (pj_jb_init(channel->jb, pool, param->jb_min, param->jb_max, param->jb_maxcnt)) {
-	    PJ_LOG(1, (THISFILE, "Unable to allocate jitter buffer"));
-	    goto err_cleanup;
-	}
-
-	status = pj_thread_create(pool, "decode", 
-				  &stream_decoder_transport_thread, channel,
-				  0, 0, &channel->transport_thread);
-	if (status != PJ_SUCCESS) {
-	    //pj_perror(THISFILE, "Unable to create transport thread");
-	    goto err_cleanup;
-	}
-    }
+	return -1;
+
 
     /* Done. */
-    return channel;
+    *p_channel = channel;
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * Create media stream.
+ */
+PJ_DEF(pj_status_t) pjmedia_stream_create( pjmedia_endpt *endpt,
+					   pj_pool_t *pool,
+					   const pjmedia_stream_info *info,
+					   pjmedia_stream **p_stream)
+
+{
+    pjmedia_stream *stream;
+    pjmedia_codec_param codec_param;
+    pj_status_t status;
+
+    PJ_ASSERT_RETURN(pool && info && p_stream, PJ_EINVAL);
+
+
+    /* Allocate the media stream: */
+
+    stream = pj_pool_zalloc(pool, sizeof(pjmedia_stream));
+    PJ_ASSERT_RETURN(stream != NULL, PJ_ENOMEM);
+
+
+    /* Init stream: */
+   
+    stream->dir = info->dir;
+    stream->codec_mgr = pjmedia_endpt_get_codec_mgr(endpt);
+
+    /* Create mutex to protect jitter buffer: */
+
+    status = pj_mutex_create_simple(pool, NULL, &stream->jb_mutex);
+    if (status != PJ_SUCCESS)
+	goto err_cleanup;
+
+
+    /* Create and initialize codec: */
+
+    status = pjmedia_codec_mgr_alloc_codec( stream->codec_mgr,
+					    &info->fmt, &stream->codec);
+    if (status != PJ_SUCCESS)
+	goto err_cleanup;
+
+
+    /* Get default codec param: */
+
+    status = stream->codec->op->default_attr(stream->codec, &codec_param);
+    if (status != PJ_SUCCESS)
+	goto err_cleanup;
+
+
+    /* Open the codec: */
+
+    status = stream->codec->op->open(stream->codec, &codec_param);
+    if (status != PJ_SUCCESS)
+	goto err_cleanup;
+
+
+    /* Init RTCP session: */
+
+    pj_rtcp_init(&stream->rtcp, info->ssrc);
+
+
+    /* Init jitter buffer: */
+
+    status = pj_jb_init(&stream->jb, pool, 
+			info->jb_min, info->jb_max, info->jb_maxcnt);
+    if (status != PJ_SUCCESS)
+	goto err_cleanup;
+
+
+    /*  Create jitter buffer thread: */
+
+    status = pj_thread_create(pool, "decode", 
+			      &jitter_buffer_thread, stream,
+			      0, 0, &stream->thread);
+    if (status != PJ_SUCCESS)
+	goto err_cleanup;
+
+
+    /* Create decoder channel: */
+
+    status = create_channel( pool, stream, PJMEDIA_DIR_DECODING, info,
+			     &codec_param, &stream->dec);
+    if (status != PJ_SUCCESS)
+	goto err_cleanup;
+
+
+    /* Create encoder channel: */
+
+    status = create_channel( pool, stream, PJMEDIA_DIR_ENCODING, info,
+			     &codec_param, &stream->enc);
+    if (status != PJ_SUCCESS)
+	goto err_cleanup;
+
+
+    /* Success! */
+    *p_stream = stream;
+    return PJ_SUCCESS;
+
 
 err_cleanup:
-    pj_media_stream_destroy(channel);
-    return NULL;
-}
-
-
-PJ_DEF(pj_status_t) pj_media_stream_create (pj_pool_t *pool,
-					    pj_media_stream_t **enc_stream,
-					    pj_media_stream_t **dec_stream,
-					    pj_media_stream_create_param *param)
-{
-    *dec_stream = *enc_stream = NULL;
-
-    if (param->dir & PJ_MEDIA_DIR_DECODING) {
-	*dec_stream = 
-	    create_channel(pool, PJ_MEDIA_DIR_DECODING, NULL, param->codec_id, param);
-	if (!*dec_stream)
-	    return -1;
-    }
-
-    if (param->dir & PJ_MEDIA_DIR_ENCODING) {
-	*enc_stream = 
-	    create_channel(pool, PJ_MEDIA_DIR_ENCODING, *dec_stream, param->codec_id, param);
-	if (!*enc_stream) {
-	    if (*dec_stream) {
-		pj_media_stream_destroy(*dec_stream);
-		*dec_stream = NULL;
-	    }
-	    return -1;
-	}
-
-	if (*dec_stream) {
-	    (*dec_stream)->peer = *enc_stream;
-	}
-    }
-
-    return 0;
-}
-
-PJ_DEF(pj_status_t) pj_media_stream_start (pj_media_stream_t *channel)
-{
-    pj_status_t status;
-
-    status = pj_snd_stream_start(channel->snd_stream);
-
-    if (status == 0)
-	channel->state = STREAM_STARTED;
+    pjmedia_stream_destroy(stream);
     return status;
 }
 
-PJ_DEF(pj_status_t)  pj_media_stream_get_stat (const pj_media_stream_t *stream,
-					       pj_media_stream_stat *stat)
-{
-    if (stream->dir == PJ_MEDIA_DIR_ENCODING) {
-	pj_memcpy (stat, &stream->stat, sizeof(*stat));
-    } else {
-	pj_rtcp_pkt *rtcp_pkt;
-	int len;
-
-	pj_memset (stat, 0, sizeof(*stat));
-	pj_assert (stream->rtcp != 0);
-	pj_rtcp_build_rtcp (stream->rtcp, &rtcp_pkt, &len);
-
-	stat->pkt_rx = stream->stat.pkt_rx;
-	stat->oct_rx = stream->stat.oct_rx;
-
-	PJ_TODO(SUPPORT_JITTER_CALCULATION_FOR_NON_8KHZ_SAMPLE_RATE)
-	stat->jitter = pj_ntohl(rtcp_pkt->rr.jitter) / 8;
-	stat->pkt_lost = (rtcp_pkt->rr.total_lost_2 << 16) +
-			 (rtcp_pkt->rr.total_lost_1 << 8) +
-			 rtcp_pkt->rr.total_lost_0;
-    }
-    return 0;
-}
-
-PJ_DEF(pj_status_t) pj_media_stream_pause (pj_media_stream_t *channel)
-{
-    PJ_UNUSED_ARG(channel);
-    return -1;
-}
-
-PJ_DEF(pj_status_t) pj_media_stream_resume (pj_media_stream_t *channel)
-{
-    PJ_UNUSED_ARG(channel);
-    return -1;
-}
-
-PJ_DEF(pj_status_t) pj_media_stream_destroy (pj_media_stream_t *channel)
-{
-    channel->thread_quit_flag = 1;
-
-    pj_mutex_lock (channel->mutex);
-    if (channel->peer)
-	pj_mutex_lock (channel->peer->mutex);
-
-    if (channel->jb) {
-	/* No need to deinitialize jitter buffer. */
-    }
-    if (channel->transport_thread) {
-	pj_thread_join(channel->transport_thread);
-	pj_thread_destroy(channel->transport_thread);
-	channel->transport_thread = NULL;
-    }
-    if (channel->snd_stream != NULL) {
-	pj_mutex_unlock (channel->mutex);
-	pj_snd_stream_stop(channel->snd_stream);
-	pj_mutex_lock (channel->mutex);
-	pj_snd_stream_close(channel->snd_stream);
-	channel->snd_stream = NULL;
-    }
-    if (channel->codec) {
-	channel->codec->op->close(channel->codec);
-	pj_codec_mgr_dealloc_codec(channel->codec_mgr, channel->codec);
-	channel->codec = NULL;
-    }
-    if (channel->peer) {
-	pj_media_stream_t *peer = channel->peer;
-	peer->peer = NULL;
-	peer->codec = NULL;
-	peer->thread_quit_flag = 1;
-	if (peer->transport_thread) {
-	    pj_mutex_unlock (peer->mutex);
-	    pj_thread_join(peer->transport_thread);
-	    pj_mutex_lock (peer->mutex);
-	    pj_thread_destroy(peer->transport_thread);
-	    peer->transport_thread = NULL;
-	}
-	if (peer->snd_stream) {
-	    pj_mutex_unlock (peer->mutex);
-	    pj_snd_stream_stop(peer->snd_stream);
-	    pj_mutex_lock (peer->mutex);
-	    pj_snd_stream_close(peer->snd_stream);
-	    peer->snd_stream = NULL;
-	}
-    }
-
-    channel->state = STREAM_STOPPED;
-
-    if (channel->peer)
-	pj_mutex_unlock (channel->peer->mutex);
-    pj_mutex_unlock(channel->mutex);
-    pj_mutex_destroy(channel->mutex);
-
-    return 0;
-}
-
+
+/*
+ * Destroy stream.
+ */
+PJ_DEF(pj_status_t) pjmedia_stream_destroy( pjmedia_stream *stream )
+{
+
+    PJ_ASSERT_RETURN(stream != NULL, PJ_EINVAL);
+
+    /* Signal threads to quit. */
+
+    stream->quit_flag = 1;
+
+
+    /* Close encoding sound stream. */
+    
+    if (stream->enc && stream->enc->snd_stream) {
+
+	pj_snd_stream_stop(stream->enc->snd_stream);
+	pj_snd_stream_close(stream->enc->snd_stream);
+	stream->enc->snd_stream = NULL;
+
+    }
+
+    /* Close decoding sound stream. */
+
+    if (stream->dec && stream->dec->snd_stream) {
+
+	pj_snd_stream_stop(stream->dec->snd_stream);
+	pj_snd_stream_close(stream->dec->snd_stream);
+	stream->dec->snd_stream = NULL;
+
+    }
+
+    /* Wait for jitter buffer thread to quit: */
+
+    if (stream->thread) {
+	pj_thread_join(stream->thread);
+	pj_thread_destroy(stream->thread);
+	stream->thread = NULL;
+    }
+
+    /* Free codec. */
+
+    if (stream->codec) {
+	stream->codec->op->close(stream->codec);
+	pjmedia_codec_mgr_dealloc_codec(stream->codec_mgr, stream->codec);
+	stream->codec = NULL;
+    }
+
+    /* Free mutex */
+    
+    if (stream->jb_mutex) {
+	pj_mutex_destroy(stream->jb_mutex);
+	stream->jb_mutex = NULL;
+    }
+
+    return PJ_SUCCESS;
+}
+
+
+
+/*
+ * Start stream.
+ */
+PJ_DEF(pj_status_t) pjmedia_stream_start(pjmedia_stream *stream)
+{
+
+    PJ_ASSERT_RETURN(stream && stream->enc && stream->dec, PJ_EINVALIDOP);
+
+    if (stream->enc && (stream->dir & PJMEDIA_DIR_ENCODING)) {
+	stream->enc->paused = 0;
+	pj_snd_stream_start(stream->enc->snd_stream);
+    }
+
+    if (stream->dec && (stream->dir & PJMEDIA_DIR_DECODING)) {
+	stream->dec->paused = 0;
+	pj_snd_stream_start(stream->dec->snd_stream);
+    }
+
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * Get stream statistics.
+ */
+PJ_DEF(pj_status_t) pjmedia_stream_get_stat( const pjmedia_stream *stream,
+					     pjmedia_stream_stat *stat)
+{
+    PJ_ASSERT_RETURN(stream && stat, PJ_EINVAL);
+
+    pj_memcpy(stat, &stream->stat, sizeof(pjmedia_stream_stat));
+
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * Pause stream.
+ */
+PJ_DEF(pj_status_t) pjmedia_stream_pause( pjmedia_stream *stream,
+					  pjmedia_dir dir)
+{
+    PJ_ASSERT_RETURN(stream, PJ_EINVAL);
+
+    if ((dir & PJMEDIA_DIR_ENCODING) && stream->enc)
+	stream->enc->paused = 1;
+
+    if ((dir & PJMEDIA_DIR_DECODING) && stream->dec)
+	stream->dec->paused = 1;
+
+    return PJ_SUCCESS;
+}
+
+
+/*
+ * Resume stream
+ */
+PJ_DEF(pj_status_t) pjmedia_stream_resume( pjmedia_stream *stream,
+					   pjmedia_dir dir)
+{
+    PJ_ASSERT_RETURN(stream, PJ_EINVAL);
+
+    if ((dir & PJMEDIA_DIR_ENCODING) && stream->enc)
+	stream->enc->paused = 1;
+
+    if ((dir & PJMEDIA_DIR_DECODING) && stream->dec)
+	stream->dec->paused = 1;
+
+    return PJ_SUCCESS;
+}
+
Index: pjproject/trunk/pjmedia/src/test/audio_tool.c
===================================================================
--- pjproject/trunk/pjmedia/src/test/audio_tool.c	(revision 158)
+++ pjproject/trunk/pjmedia/src/test/audio_tool.c	(revision 159)
@@ -27,6 +27,6 @@
 static FILE *fhnd;
 static pj_med_mgr_t *mm;
-static pj_codec *codec;
-static pj_codec_attr cattr;
+static pjmedia_codec *codec;
+static pjmedia_codec_param cattr;
 
 
@@ -61,5 +61,5 @@
 {
     char pkt[160];
-    struct pj_audio_frame in, out;
+    struct pjmedia_frame in, out;
     int frmsz = cattr.avg_bps / 8 * cattr.ptime / 1000;
 
@@ -68,5 +68,5 @@
 	return -1;
     } else {
-	in.type = PJ_AUDIO_FRAME_AUDIO;
+	in.type = PJMEDIA_FRAME_TYPE_AUDIO;
 	in.buf = pkt;
 	in.size = frmsz;
@@ -86,5 +86,5 @@
 {
     char pkt[160];
-    struct pj_audio_frame in, out;
+    struct pjmedia_frame in, out;
     //int frmsz = cattr.avg_bps / 8 * cattr.ptime / 1000;
 
@@ -93,5 +93,5 @@
 #endif
 
-    in.type = PJ_AUDIO_FRAME_AUDIO;
+    in.type = PJMEDIA_FRAME_TYPE_AUDIO;
     in.buf = (void*)frame;
     in.size = size;
@@ -108,6 +108,6 @@
 static pj_status_t init()
 {
-    pj_codec_mgr *cm;
-    pj_codec_id id;
+    pjmedia_codec_mgr *cm;
+    pjmedia_codec_info id;
     int i;
 
@@ -130,10 +130,10 @@
     cm = pj_med_mgr_get_codec_mgr (mm);
 
-    id.type = PJ_MEDIA_TYPE_AUDIO;
+    id.type = PJMEDIA_TYPE_AUDIO;
     id.pt = 0;
     id.encoding_name = pj_str("PCMU");
     id.sample_rate = 8000;
 
-    codec = pj_codec_mgr_alloc_codec (cm, &id);
+    codec = pjmedia_codec_mgr_alloc_codec (cm, &id);
     codec->op->default_attr(codec, &cattr);
     codec->op->open(codec, &cattr);
@@ -143,8 +143,8 @@
 static pj_status_t deinit()
 {
-    pj_codec_mgr *cm;
+    pjmedia_codec_mgr *cm;
     cm = pj_med_mgr_get_codec_mgr (mm);
     codec->op->close(codec);
-    pj_codec_mgr_dealloc_codec (cm, codec);
+    pjmedia_codec_mgr_dealloc_codec (cm, codec);
     pj_med_mgr_destroy (mm);
     pj_caching_pool_destroy(&caching_pool);
@@ -301,11 +301,11 @@
 
 	switch (info[i]->dir) {
-	case PJ_MEDIA_DIR_NONE:
+	case PJMEDIA_DIR_NONE:
 	    dir = "- NONE -"; break;
-	case PJ_MEDIA_DIR_ENCODING:
+	case PJMEDIA_DIR_ENCODING:
 	    dir = "SENDONLY"; break;
-	case PJ_MEDIA_DIR_DECODING:
+	case PJMEDIA_DIR_DECODING:
 	    dir = "RECVONLY"; break;
-	case PJ_MEDIA_DIR_ENCODING_DECODING:
+	case PJMEDIA_DIR_ENCODING_DECODING:
 	    dir = "SENDRECV"; break;
 	default:
@@ -346,5 +346,5 @@
     char pcm[320];
     char frame[160];
-    struct pj_audio_frame in, out;
+    struct pjmedia_frame in, out;
 
     fhnd_pcm = fopen(src, "rb");
@@ -357,5 +357,5 @@
     while (fread(pcm, 320, 1, fhnd_pcm) == 1) {
 
-	in.type = PJ_AUDIO_FRAME_AUDIO;
+	in.type = PJMEDIA_FRAME_TYPE_AUDIO;
 	in.buf = pcm;
 	in.size = 320;
Index: pjproject/trunk/pjmedia/src/test/session_test.c
===================================================================
--- pjproject/trunk/pjmedia/src/test/session_test.c	(revision 158)
+++ pjproject/trunk/pjmedia/src/test/session_test.c	(revision 159)
@@ -45,6 +45,6 @@
 
     // Set caller's media to send-only.
-    sd_info.dir = PJ_MEDIA_DIR_ENCODING;
-    pj_media_session_modify_stream (s1, 0, PJ_MEDIA_STREAM_MODIFY_DIR, &sd_info);
+    sd_info.dir = PJMEDIA_DIR_ENCODING;
+    pj_media_session_modify_stream (s1, 0, PJMEDIA_STREAM_MODIFY_DIR, &sd_info);
 
     // Create caller SDP.
