Changeset 159


Ignore:
Timestamp:
Feb 8, 2006 10:43:39 PM (18 years ago)
Author:
bennylp
Message:

Finished new pjmedia rewrite

Location:
pjproject/trunk/pjmedia
Files:
16 edited
2 moved

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/build/pjmedia.dsp

    r155 r159  
    9797# Begin Source File 
    9898 
     99SOURCE=..\src\pjmedia\endpoint.c 
     100# End Source File 
     101# Begin Source File 
     102 
    99103SOURCE=..\src\pjmedia\errno.c 
    100104# End Source File 
     
    106110 
    107111SOURCE=..\src\pjmedia\jbuf.c 
    108 # End Source File 
    109 # Begin Source File 
    110  
    111 SOURCE=..\src\pjmedia\mediamgr.c 
    112112# End Source File 
    113113# Begin Source File 
     
    143143 
    144144SOURCE=..\src\pjmedia\session.c 
    145 # PROP Exclude_From_Build 1 
    146145# End Source File 
    147146# Begin Source File 
     
    163162# Begin Source File 
    164163 
     164SOURCE=..\include\pjmedia\endpoint.h 
     165# End Source File 
     166# Begin Source File 
     167 
    165168SOURCE=..\include\pjmedia\errno.h 
    166169# End Source File 
     
    168171 
    169172SOURCE=..\include\pjmedia\jbuf.h 
    170 # End Source File 
    171 # Begin Source File 
    172  
    173 SOURCE=..\include\pjmedia\mediamgr.h 
    174173# End Source File 
    175174# Begin Source File 
  • pjproject/trunk/pjmedia/include/pjmedia/codec.h

    r121 r159  
    2626 */ 
    2727 
     28#include <pjmedia/types.h> 
    2829#include <pj/list.h> 
    2930 
     
    3738 */ 
    3839 
    39 /** Top most media type. */ 
    40 typedef enum pj_media_type 
    41 { 
    42     /** No type. */ 
    43     PJ_MEDIA_TYPE_NONE = 0, 
    44  
    45     /** The media is audio */ 
    46     PJ_MEDIA_TYPE_AUDIO = 1, 
    47  
    48     /** The media is video. */ 
    49     PJ_MEDIA_TYPE_VIDEO = 2, 
    50  
    51     /** Unknown media type, in this case the name will be specified in  
    52      *  encoding_name. 
    53      */ 
    54     PJ_MEDIA_TYPE_UNKNOWN = 3, 
    55  
    56 } pj_media_type; 
    57  
    58  
    59 /** Media direction. */ 
    60 typedef enum pj_media_dir_t 
    61 { 
    62     /** None */ 
    63     PJ_MEDIA_DIR_NONE = 0, 
    64  
    65     /** Encoding (outgoing to network) stream */ 
    66     PJ_MEDIA_DIR_ENCODING = 1, 
    67  
    68     /** Decoding (incoming from network) stream. */ 
    69     PJ_MEDIA_DIR_DECODING = 2, 
    70  
    71     /** Incoming and outgoing stream. */ 
    72     PJ_MEDIA_DIR_ENCODING_DECODING = 3, 
    73  
    74 } pj_media_dir_t; 
    75  
    76  
    77 /** Standard RTP paylist types. */ 
    78 typedef enum pj_rtp_pt 
    79 { 
    80     PJ_RTP_PT_PCMU = 0,         /* audio PCMU */ 
    81     PJ_RTP_PT_GSM  = 3,         /* audio GSM */ 
    82     PJ_RTP_PT_G723 = 4,         /* audio G723 */ 
    83     PJ_RTP_PT_DVI4_8K = 5,      /* audio DVI4 8KHz */ 
    84     PJ_RTP_PT_DVI4_16K = 6,     /* audio DVI4 16Khz */ 
    85     PJ_RTP_PT_LPC = 7,          /* audio LPC */ 
    86     PJ_RTP_PT_PCMA = 8,         /* audio PCMA */ 
    87     PJ_RTP_PT_G722 = 9,         /* audio G722 */ 
    88     PJ_RTP_PT_L16_2 = 10,       /* audio 16bit linear 44.1KHz stereo */ 
    89     PJ_RTP_PT_L16_1 = 11,       /* audio 16bit linear 44.1KHz mono */ 
    90     PJ_RTP_PT_QCELP = 12,       /* audio QCELP */ 
    91     PJ_RTP_PT_CN = 13,          /* audio Comfort Noise */ 
    92     PJ_RTP_PT_MPA = 14,         /* audio MPEG1 or MPEG2 as elementary streams */ 
    93     PJ_RTP_PT_G728 = 15,        /* audio G728 */ 
    94     PJ_RTP_PT_DVI4_11K = 16,    /* audio DVI4 11.025KHz mono */ 
    95     PJ_RTP_PT_DVI4_22K = 17,    /* audio DVI4 22.050KHz mono */ 
    96     PJ_RTP_PT_G729 = 18,        /* audio G729 */ 
    97     PJ_RTP_PT_CELB = 25,        /* video/comb Cell-B by Sun Microsystems (RFC 2029) */ 
    98     PJ_RTP_PT_JPEG = 26,        /* video JPEG */ 
    99     PJ_RTP_PT_NV = 28,          /* video NV implemented by nv program by Xerox */ 
    100     PJ_RTP_PT_H261 = 31,        /* video H261 */ 
    101     PJ_RTP_PT_MPV = 32,         /* video MPEG1 or MPEG2 elementary streams */ 
    102     PJ_RTP_PT_MP2T = 33,        /* video MPEG2 transport */ 
    103     PJ_RTP_PT_H263 = 34,        /* video H263 */ 
    104  
    105     PJ_RTP_PT_DYNAMIC = 96,     /* start of dynamic RTP payload */ 
    106 } pj_rtp_pt; 
    107  
    108  
    109 /** Identification used to search for codec factory that supports specific  
    110  *  codec specification.  
    111  */ 
    112 typedef struct pj_codec_id 
    113 { 
    114     /** Media type. */ 
    115     pj_media_type   type; 
    116  
    117     /** Payload type (can be dynamic). */ 
    118     unsigned        pt; 
    119  
    120     /** Encoding name, must be present if the payload type is dynamic. */ 
    121     pj_str_t        encoding_name; 
    122  
    123     /** Sampling rate. */ 
    124     unsigned        sample_rate; 
    125 } pj_codec_id; 
    126  
    127  
    128 /** Detailed codec attributes used both to configure a codec and to query 
    129  *  the capability of codec factories. 
    130  */ 
    131 typedef struct pj_codec_attr 
    132 { 
    133     pj_uint32_t sample_rate;        /* Sampling rate in Hz */ 
    134     pj_uint32_t avg_bps;            /* Average bandwidth in bits per second */ 
    135  
    136     pj_uint8_t  pcm_bits_per_sample;/* Bits per sample in the PCM side */ 
    137     pj_uint16_t ptime;              /* Packet time in miliseconds */ 
    138  
    139     unsigned    pt:8;               /* Payload type. */ 
    140     unsigned    vad_enabled:1;      /* Voice Activity Detector. */ 
    141     unsigned    cng_enabled:1;      /* Comfort Noise Generator. */ 
    142     unsigned    lpf_enabled:1;      /* Low pass filter */ 
    143     unsigned    hpf_enabled:1;      /* High pass filter */ 
    144     unsigned    penh_enabled:1;     /* Perceptual Enhancement */ 
    145     unsigned    concl_enabled:1;    /* Packet loss concealment */ 
    146     unsigned    reserved_bit:1; 
    147  
    148 } pj_codec_attr; 
    149  
    150 /** Types of audio frame. */ 
    151 typedef enum pj_audio_frame_type 
    152 { 
    153     /** The frame is a silence audio frame. */ 
    154     PJ_AUDIO_FRAME_SILENCE, 
    155  
    156     /** The frame is a non-silence audio frame. */ 
    157     PJ_AUDIO_FRAME_AUDIO, 
    158  
    159 } pj_audio_frame_type; 
    160  
    161 typedef struct pj_codec pj_codec; 
    162 typedef struct pj_codec_factory pj_codec_factory; 
    163  
    164  
    165 /** This structure describes an audio frame. */ 
    166 struct pj_audio_frame 
    167 { 
    168     /** Type: silence or non-silence. */ 
    169     pj_audio_frame_type type; 
    170  
    171     /** Pointer to buffer. */ 
    172     void        *buf; 
    173  
    174     /** Frame size in bytes. */ 
    175     unsigned     size; 
    176 }; 
    177  
    178 /** 
    179  * Operations that must be supported by the codec. 
    180  */ 
    181 typedef struct pj_codec_op 
    182 { 
    183     /** Get default attributes. */ 
    184     pj_status_t (*default_attr) (pj_codec *codec, pj_codec_attr *attr); 
    185  
    186     /** Open and initialize codec using the specified attribute. 
    187      *  @return zero on success. 
    188      */ 
    189     pj_status_t (*init)( pj_codec *codec, pj_pool_t *pool ); 
    190  
    191     /** Close and shutdown codec. 
    192      */ 
    193     pj_status_t (*open)( pj_codec *codec, pj_codec_attr *attr ); 
    194  
    195     /** Close and shutdown codec. 
    196      */ 
    197     pj_status_t (*close)( pj_codec *codec ); 
    198  
    199     /** Encode frame. 
    200      */ 
    201     pj_status_t (*encode)( pj_codec *codec, const struct pj_audio_frame *input, 
    202                            unsigned output_buf_len, struct pj_audio_frame *output); 
    203  
    204     /** Decode frame. 
    205      */ 
    206     pj_status_t (*decode)( pj_codec *codec, const struct pj_audio_frame *input, 
    207                            unsigned output_buf_len, struct pj_audio_frame *output); 
    208  
    209 } pj_codec_op; 
    210  
    211 /** 
    212  * A codec describes an instance to encode or decode media frames.  
    213  */ 
    214 struct pj_codec 
     40 
     41/**  
     42 * Standard RTP static payload types, as defined by RFC 3551.  
     43 */ 
     44enum pjmedia_rtp_pt 
     45{ 
     46    PJMEDIA_RTP_PT_PCMU = 0,        /* audio PCMU                           */ 
     47    PJMEDIA_RTP_PT_GSM  = 3,        /* audio GSM                            */ 
     48    PJMEDIA_RTP_PT_G723 = 4,        /* audio G723                           */ 
     49    PJMEDIA_RTP_PT_DVI4_8K = 5,     /* audio DVI4 8KHz                      */ 
     50    PJMEDIA_RTP_PT_DVI4_16K = 6,    /* audio DVI4 16Khz                     */ 
     51    PJMEDIA_RTP_PT_LPC = 7,         /* audio LPC                            */ 
     52    PJMEDIA_RTP_PT_PCMA = 8,        /* audio PCMA                           */ 
     53    PJMEDIA_RTP_PT_G722 = 9,        /* audio G722                           */ 
     54    PJMEDIA_RTP_PT_L16_2 = 10,      /* audio 16bit linear 44.1KHz stereo    */ 
     55    PJMEDIA_RTP_PT_L16_1 = 11,      /* audio 16bit linear 44.1KHz mono      */ 
     56    PJMEDIA_RTP_PT_QCELP = 12,      /* audio QCELP                          */ 
     57    PJMEDIA_RTP_PT_CN = 13,         /* audio Comfort Noise                  */ 
     58    PJMEDIA_RTP_PT_MPA = 14,        /* audio MPEG1/MPEG2 elementary streams */ 
     59    PJMEDIA_RTP_PT_G728 = 15,       /* audio G728                           */ 
     60    PJMEDIA_RTP_PT_DVI4_11K = 16,   /* audio DVI4 11.025KHz mono            */ 
     61    PJMEDIA_RTP_PT_DVI4_22K = 17,   /* audio DVI4 22.050KHz mono            */ 
     62    PJMEDIA_RTP_PT_G729 = 18,       /* audio G729                           */ 
     63 
     64    PJMEDIA_RTP_PT_CELB = 25,       /* video/comb Cell-B by Sun (RFC 2029)  */ 
     65    PJMEDIA_RTP_PT_JPEG = 26,       /* video JPEG                           */ 
     66    PJMEDIA_RTP_PT_NV = 28,         /* video NV  by nv program by Xerox     */ 
     67    PJMEDIA_RTP_PT_H261 = 31,       /* video H261                           */ 
     68    PJMEDIA_RTP_PT_MPV = 32,        /* video MPEG1 or MPEG2 elementary      */ 
     69    PJMEDIA_RTP_PT_MP2T = 33,       /* video MPEG2 transport                */ 
     70    PJMEDIA_RTP_PT_H263 = 34,       /* video H263                           */ 
     71 
     72    PJMEDIA_RTP_PT_DYNAMIC = 96,    /* start of dynamic RTP payload         */ 
     73 
     74}; 
     75 
     76 
     77/**  
     78 * Identification used to search for codec factory that supports specific  
     79 * codec specification.  
     80 */ 
     81struct pjmedia_codec_info 
     82{ 
     83    pjmedia_type    type;           /**< Media type.                    */ 
     84    unsigned        pt;             /**< Payload type (can be dynamic). */ 
     85    pj_str_t        encoding_name;  /**< Encoding name.                 */ 
     86    unsigned        sample_rate;    /**< Sampling rate.                 */ 
     87}; 
     88 
     89 
     90/**  
     91 * Detailed codec attributes used both to configure a codec and to query 
     92 * the capability of codec factories. 
     93 */ 
     94struct pjmedia_codec_param 
     95{ 
     96    pj_uint32_t sample_rate;        /**< Sampling rate in Hz            */ 
     97    pj_uint32_t avg_bps;            /**< Average bandwidth in bits/sec  */ 
     98 
     99    pj_uint8_t  pcm_bits_per_sample;/**< Bits/sample in the PCM side    */ 
     100    pj_uint16_t ptime;              /**< Packet time in miliseconds     */ 
     101 
     102    unsigned    pt:8;               /**< Payload type.                  */ 
     103    unsigned    vad_enabled:1;      /**< Voice Activity Detector.       */ 
     104    unsigned    cng_enabled:1;      /**< Comfort Noise Generator.       */ 
     105    unsigned    lpf_enabled:1;      /**< Low pass filter                */ 
     106    unsigned    hpf_enabled:1;      /**< High pass filter               */ 
     107    unsigned    penh_enabled:1;     /**< Perceptual Enhancement         */ 
     108    unsigned    concl_enabled:1;    /**< Packet loss concealment        */ 
     109    unsigned    reserved_bit:1;     /**< Reserved, must be NULL.        */ 
     110 
     111}; 
     112 
     113 
     114/**  
     115 * Types of media frame.  
     116 */ 
     117enum pjmedia_frame_type 
     118{ 
     119    PJMEDIA_FRAME_TYPE_SILENCE_AUDIO,   /**< Silence audio frame.       */ 
     120    PJMEDIA_FRAME_TYPE_AUDIO,           /**< Normal audio frame.        */ 
     121 
     122}; 
     123 
     124/**  
     125 * This structure describes a media frame.  
     126 */ 
     127struct pjmedia_frame 
     128{ 
     129    pjmedia_frame_type   type;  /**< Frame type.                    */ 
     130    void                *buf;   /**< Pointer to buffer.             */ 
     131    pj_size_t            size;  /**< Frame size in bytes.           */ 
     132}; 
     133 
     134/** 
     135 * This structure describes codec operations. Each codec MUST implement 
     136 * all of these functions. 
     137 */ 
     138struct pjmedia_codec_op 
     139{ 
     140    /**  
     141     * Get default attributes for this codec.  
     142     * 
     143     * @param codec     The codec instance. 
     144     * @param attr      Pointer to receive default codec attributes. 
     145     * 
     146     * @return          PJ_SUCCESS on success. 
     147     */ 
     148    pj_status_t (*default_attr)(pjmedia_codec *codec,  
     149                                pjmedia_codec_param *attr); 
     150 
     151    /**  
     152     * Initialize codec using the specified attribute. 
     153     * 
     154     * @param codec     The codec instance. 
     155     * @param pool      Pool to use when the codec needs to allocate 
     156     *                  some memory. 
     157     * 
     158     * @return          PJ_SUCCESS on success. 
     159     */ 
     160    pj_status_t (*init)(pjmedia_codec *codec,  
     161                        pj_pool_t *pool ); 
     162 
     163    /**  
     164     * Open the codec and initialize with the specified parameter.. 
     165     * 
     166     * @param codec     The codec instance. 
     167     * @param param     Codec initialization parameter. 
     168     * 
     169     * @return          PJ_SUCCESS on success. 
     170     */ 
     171    pj_status_t (*open)(pjmedia_codec *codec,  
     172                        pjmedia_codec_param *param ); 
     173 
     174    /**  
     175     * Close and shutdown codec, releasing all resources allocated by 
     176     * this codec, if any. 
     177     * 
     178     * @param codec     The codec instance. 
     179     * 
     180     * @return          PJ_SUCCESS on success. 
     181     */ 
     182    pj_status_t (*close)(pjmedia_codec *codec); 
     183 
     184 
     185    /**  
     186     * Instruct the codec to encode the specified input frame. 
     187     * 
     188     * @param codec     The codec instance. 
     189     * @param input     The input frame. 
     190     * @param out_size  The length of buffer in the output frame. 
     191     * @param output    The output frame. 
     192     * 
     193     * @return          PJ_SUCCESS on success; 
     194     */ 
     195    pj_status_t (*encode)(pjmedia_codec *codec,  
     196                          const struct pjmedia_frame *input, 
     197                          unsigned out_size,  
     198                          struct pjmedia_frame *output); 
     199 
     200    /**  
     201     * Instruct the codec to decode the specified input frame. 
     202     * 
     203     * @param codec     The codec instance. 
     204     * @param input     The input frame. 
     205     * @param out_size  The length of buffer in the output frame. 
     206     * @param output    The output frame. 
     207     * 
     208     * @return          PJ_SUCCESS on success; 
     209     */ 
     210    pj_status_t (*decode)(pjmedia_codec *codec,  
     211                          const struct pjmedia_frame *input, 
     212                          unsigned out_size,  
     213                          struct pjmedia_frame *output); 
     214 
     215}; 
     216 
     217 
     218/** 
     219 * This structure describes a codec instance.  
     220 */ 
     221struct pjmedia_codec 
    215222{ 
    216223    /** Entries to put this codec instance in codec factory's list. */ 
    217     PJ_DECL_LIST_MEMBER(struct pj_codec); 
     224    PJ_DECL_LIST_MEMBER(struct pjmedia_codec); 
    218225 
    219226    /** Codec's private data. */ 
     
    221228 
    222229    /** Codec factory where this codec was allocated. */ 
    223     pj_codec_factory *factory; 
     230    pjmedia_codec_factory *factory; 
    224231 
    225232    /** Operations to codec. */ 
    226     pj_codec_op *op; 
    227 }; 
    228  
    229 /** 
    230  * This structure describes operations that must be supported by codec factories. 
    231  */ 
    232 typedef struct pj_codec_factory_op 
    233 { 
    234     /** Check whether the factory can create codec with the specified ID. 
    235      *  @param factory The codec factory. 
    236      *  @param id  The codec ID. 
    237      *  @return zero it matches. 
    238      */ 
    239     pj_status_t (*match_id)( pj_codec_factory *factory, const pj_codec_id *id ); 
    240  
    241     /** Create default attributes for the specified codec ID. This function can 
    242      *  be called by application to get the capability of the codec. 
    243      *  @param factory The codec factory. 
    244      *  @param id  The codec ID. 
    245      *  @param attr The attribute to be initialized. 
    246      *  @return zero if success. 
    247      */ 
    248     pj_status_t (*default_attr)( pj_codec_factory *factory, const pj_codec_id *id, 
    249                                  pj_codec_attr *attr ); 
    250  
    251     /** Enumerate supported codecs. 
    252      *  @param factory The codec factory. 
    253      *  @param count Number of entries in the array. 
    254      *  @param codecs The codec array. 
    255      *  @return the total number of supported codecs, which can be less or  
    256      *          greater than requested. 
    257      */ 
    258     unsigned (*enum_codecs) (pj_codec_factory *factory, unsigned count, pj_codec_id codecs[]); 
    259  
    260     /** This function is called by codec manager to instantiate one codec 
    261      *  instance. 
    262      *  @param factory The codec factory. 
    263      *  @param id  The codec ID. 
    264      *  @return the instance of the codec, or NULL if codec can not be created. 
    265      */ 
    266     pj_codec* (*alloc_codec)( pj_codec_factory *factory, const pj_codec_id *id); 
    267  
    268     /** This function is called by codec manager to return a particular instance 
    269      *  of codec back to the codec factory. 
    270      *  @param factory The codec factory. 
    271      *  @param codec The codec instance to be returned. 
    272      */ 
    273     void (*dealloc_codec)( pj_codec_factory *factory, pj_codec *codec ); 
    274  
    275 } pj_codec_factory_op; 
     233    pjmedia_codec_op    *op; 
     234}; 
     235 
     236 
     237/** 
     238 * This structure describes operations that must be supported by codec  
     239 * factories. 
     240 */ 
     241struct pjmedia_codec_factory_op 
     242{ 
     243    /**  
     244     * Check whether the factory can create codec with the specified  
     245     * codec info. 
     246     * 
     247     * @param factory   The codec factory. 
     248     * @param info      The codec info. 
     249     * 
     250     * @return          PJ_SUCCESS if this factory is able to create an 
     251     *                  instance of codec with the specified info. 
     252     */ 
     253    pj_status_t (*test_alloc)(pjmedia_codec_factory *factory,  
     254                              const pjmedia_codec_info *info ); 
     255 
     256    /**  
     257     * Create default attributes for the specified codec ID. This function 
     258     * can be called by application to get the capability of the codec. 
     259     * 
     260     * @param factory   The codec factory. 
     261     * @param info      The codec info. 
     262     * @param attr      The attribute to be initialized. 
     263     * 
     264     * @return          PJ_SUCCESS if success. 
     265     */ 
     266    pj_status_t (*default_attr)(pjmedia_codec_factory *factory,  
     267                                const pjmedia_codec_info *info, 
     268                                pjmedia_codec_param *attr ); 
     269 
     270    /**  
     271     * Enumerate supported codecs that can be created using this factory. 
     272     *  
     273     *  @param factory  The codec factory. 
     274     *  @param count    On input, specifies the number of elements in 
     275     *                  the array. On output, the value will be set to 
     276     *                  the number of elements that have been initialized 
     277     *                  by this function. 
     278     *  @param info     The codec info array, which contents will be  
     279     *                  initialized upon return. 
     280     * 
     281     *  @return         PJ_SUCCESS on success. 
     282     */ 
     283    pj_status_t (*enum_info)(pjmedia_codec_factory *factory,  
     284                             unsigned *count,  
     285                             pjmedia_codec_info codecs[]); 
     286 
     287    /**  
     288     * Create one instance of the codec with the specified codec info. 
     289     * 
     290     * @param factory   The codec factory. 
     291     * @param info      The codec info. 
     292     * @param p_codec   Pointer to receive the codec instance. 
     293     * 
     294     * @return          PJ_SUCCESS on success. 
     295     */ 
     296    pj_status_t (*alloc_codec)(pjmedia_codec_factory *factory,  
     297                               const pjmedia_codec_info *info, 
     298                               pjmedia_codec **p_codec); 
     299 
     300    /**  
     301     * This function is called by codec manager to return a particular  
     302     * instance of codec back to the codec factory. 
     303     * 
     304     * @param factory   The codec factory. 
     305     * @param codec     The codec instance to be returned. 
     306     * 
     307     * @return          PJ_SUCCESS on success. 
     308     */ 
     309    pj_status_t (*dealloc_codec)(pjmedia_codec_factory *factory,  
     310                                 pjmedia_codec *codec ); 
     311 
     312}; 
     313 
    276314 
    277315/** 
     
    280318 * instances of codec. 
    281319 */ 
    282 struct pj_codec_factory 
     320struct pjmedia_codec_factory 
    283321{ 
    284322    /** Entries to put this structure in the codec manager list. */ 
    285     PJ_DECL_LIST_MEMBER(struct pj_codec_factory); 
     323    PJ_DECL_LIST_MEMBER(struct pjmedia_codec_factory); 
    286324 
    287325    /** The factory's private data. */ 
    288     void                *factory_data; 
     326    void                     *factory_data; 
    289327 
    290328    /** Operations to the factory. */ 
    291     pj_codec_factory_op *op; 
     329    pjmedia_codec_factory_op *op; 
    292330 
    293331}; 
     
    296334 * Declare maximum codecs 
    297335 */ 
    298 #define PJ_CODEC_MGR_MAX_CODECS     32 
     336#define PJMEDIA_CODEC_MGR_MAX_CODECS        32 
    299337 
    300338/** 
    301339 * Codec manager maintains codec factory etc. 
    302340 */ 
    303 typedef struct pj_codec_mgr 
    304 { 
    305     pj_codec_factory factory_list; 
    306     unsigned         codec_cnt; 
    307     pj_codec_id      codecs[PJ_CODEC_MGR_MAX_CODECS]; 
    308 } pj_codec_mgr; 
    309  
    310 /** 
    311  * Init codec manager. 
     341typedef struct pjmedia_codec_mgr 
     342{ 
     343    pjmedia_codec_factory   factory_list; 
     344    unsigned                codec_cnt; 
     345    pjmedia_codec_info      codecs[PJMEDIA_CODEC_MGR_MAX_CODECS]; 
     346} pjmedia_codec_mgr; 
     347 
     348 
     349 
     350/** 
     351 * Initialize codec manager. 
     352 * 
     353 * @param mgr       Codec manager instance. 
     354 * 
     355 * @return          PJ_SUCCESS on success. 
     356 */ 
     357PJ_DECL(pj_status_t) pjmedia_codec_mgr_init(pjmedia_codec_mgr *mgr); 
     358 
     359 
     360/**  
     361 * Register codec factory to codec manager.  
     362 * 
     363 * @param mgr       The codec manager. 
     364 * @param factory   The codec factory to be registered. 
     365 * 
     366 * @return          PJ_SUCCESS on success. 
    312367 */ 
    313368PJ_DECL(pj_status_t)  
    314 pj_codec_mgr_init (pj_codec_mgr *mgr); 
    315  
    316 /**  
    317  * Register codec to codec manager.  
     369pjmedia_codec_mgr_register_factory( pjmedia_codec_mgr *mgr, 
     370                                    pjmedia_codec_factory *factory); 
     371 
     372/** 
     373 * Unregister codec factory from the codec manager. 
     374 * 
     375 * @param mgr       The codec manager. 
     376 * @param factory   The codec factory to be unregistered. 
     377 * 
     378 * @return          PJ_SUCCESS on success. 
    318379 */ 
    319380PJ_DECL(pj_status_t)  
    320 pj_codec_mgr_register_factory (pj_codec_mgr *mgr, pj_codec_factory *factory); 
    321  
    322 /** 
    323  * Unregister codec. 
    324  */ 
    325 PJ_DECL(void)  
    326 pj_codec_mgr_unregister_factory (pj_codec_mgr *mgr, pj_codec_factory *factory); 
    327  
    328 /** 
    329  * Enumerate codecs. 
    330  */ 
    331 PJ_DECL(unsigned) 
    332 pj_codec_mgr_enum_codecs (pj_codec_mgr *mgr, unsigned count, const pj_codec_id *codecs[]); 
    333  
    334 /** 
    335  * Open codec. 
    336  */ 
    337 PJ_DECL(pj_codec*)  
    338 pj_codec_mgr_alloc_codec (pj_codec_mgr *mgr, const struct pj_codec_id *id); 
    339  
    340 /** 
    341  * Close codec. 
    342  */ 
    343 PJ_DECL(void)  
    344 pj_codec_mgr_dealloc_codec (pj_codec_mgr *mgr, pj_codec *codec); 
     381pjmedia_codec_mgr_unregister_factory( pjmedia_codec_mgr *mgr,  
     382                                      pjmedia_codec_factory *factory); 
     383 
     384/** 
     385 * Enumerate all supported codec. 
     386 * 
     387 * @param mgr       The codec manager. 
     388 * @param count     On input, specifies the number of elements in 
     389 *                  the array. On output, the value will be set to 
     390 *                  the number of elements that have been initialized 
     391 *                  by this function. 
     392 * @param info      The codec info array, which contents will be  
     393 *                  initialized upon return. 
     394 * 
     395 * @return          PJ_SUCCESS on success. 
     396 */ 
     397PJ_DECL(pj_status_t) pjmedia_codec_mgr_enum_codecs( pjmedia_codec_mgr *mgr,  
     398                                                    unsigned *count,  
     399                                                    pjmedia_codec_info info[]); 
     400 
     401/** 
     402 * Request the codec manager to allocate one instance of codec with the 
     403 * specified codec info. The codec will enumerate all codec factories 
     404 * until it finds factory that is able to create the specified codec. 
     405 * 
     406 * @param mgr       The codec manager. 
     407 * @param info      The information about the codec to be created. 
     408 * @param p_codec   Pointer to receive the codec instance. 
     409 * 
     410 * @return          PJ_SUCCESS on success. 
     411 */ 
     412PJ_DECL(pj_status_t) pjmedia_codec_mgr_alloc_codec(pjmedia_codec_mgr *mgr,  
     413                                                   const pjmedia_codec_info *info, 
     414                                                   pjmedia_codec **p_codec); 
     415 
     416/** 
     417 * Deallocate the specified codec instance. The codec manager will return 
     418 * the instance of the codec back to its factory. 
     419 * 
     420 * @param mgr       The codec manager. 
     421 * @param codec     The codec instance. 
     422 * 
     423 * @return          PJ_SUCESS on success. 
     424 */ 
     425PJ_DECL(pj_status_t) pjmedia_codec_mgr_dealloc_codec(pjmedia_codec_mgr *mgr,  
     426                                                     pjmedia_codec *codec); 
    345427 
    346428/** 
  • pjproject/trunk/pjmedia/include/pjmedia/endpoint.h

    r158 r159  
    2626 */ 
    2727/** 
    28  * @defgroup PJMED_MGR Media Manager 
     28 * @defgroup PJMED_ENDPT Media Endpoint 
    2929 * @ingroup PJMEDIA 
    3030 * @{ 
    3131 * 
    32  * The media manager acts as placeholder for endpoint capabilities. Each  
    33  * media manager will have a codec manager to manage list of codecs installed 
     32 * The media endpoint acts as placeholder for endpoint capabilities. Each  
     33 * media endpoint will have a codec manager to manage list of codecs installed 
    3434 * in the endpoint and a sound device factory. 
    3535 * 
    36  * A reference to media manager instance is required when application wants 
     36 * A reference to media endpoint instance is required when application wants 
    3737 * to create a media session (#pj_media_session_create or  
    3838 * #pj_media_session_create_from_sdp). 
     
    4646 
    4747 
    48 /** Opague declaration of media manager. */ 
    49 typedef struct pj_med_mgr_t pj_med_mgr_t; 
    5048 
    5149/** 
    52  * Create an instance of media manager. 
     50 * Create an instance of media endpoint. 
    5351 * 
    54  * @param pf            Pool factory. 
    55  * @param conn_addr     Connection address to be used by this media manager. 
     52 * @param pf            Pool factory, which will be used by the media endpoint 
     53 *                      throughout its lifetime. 
     54 * @param p_endpt       Pointer to receive the endpoint instance. 
    5655 * 
    57  * @return A new instance of media manager, or NULL if failed. 
     56 * @return              PJ_SUCCESS on success. 
    5857 */ 
    59 PJ_DECL(pj_med_mgr_t*) pj_med_mgr_create (pj_pool_factory *pf); 
     58PJ_DECL(pj_status_t) pjmedia_endpt_create( pj_pool_factory *pf, 
     59                                           pjmedia_endpt **p_endpt); 
    6060 
    6161/** 
    62  * Destroy media manager instance. 
     62 * Destroy media endpoint instance. 
    6363 * 
    64  * @param mgr           Media manager instance. 
     64 * @param endpt         Media endpoint instance. 
    6565 * 
    66  * @return zero on success. 
     66 * @return              PJ_SUCCESS on success. 
    6767 */ 
    68 PJ_DECL(pj_status_t) pj_med_mgr_destroy (pj_med_mgr_t *mgr); 
     68PJ_DECL(pj_status_t) pjmedia_endpt_destroy(pjmedia_endpt *endpt); 
     69 
    6970 
    7071/** 
    71  * Get pool factory of the media manager as specified when the media 
    72  * manager was created. 
     72 * Request the media endpoint to create pool. 
    7373 * 
    74  * @param mgr           The media manager instance. 
     74 * @param endpt         The media endpoint instance. 
     75 * @param name          Name to be assigned to the pool. 
     76 * @param initial       Initial pool size, in bytes. 
     77 * @param increment     Increment size, in bytes. 
    7578 * 
    76  * @return Pool factory instance of the media manager. 
     79 * @return              Memory pool. 
    7780 */ 
    78 PJ_DECL(pj_pool_factory*) pj_med_mgr_get_pool_factory (pj_med_mgr_t *mgr); 
     81PJ_DECL(pj_pool_t*) pjmedia_endpt_create_pool( pjmedia_endpt *endpt, 
     82                                               const char *name, 
     83                                               pj_size_t initial, 
     84                                               pj_size_t increment); 
    7985 
    8086/** 
    81  * Get the codec manager instance. 
     87 * Get the codec manager instance of the media endpoint. 
    8288 * 
    83  * @param mgr           The media manager instance. 
     89 * @param endpt         The media endpoint instance. 
    8490 * 
    85  * @return The instance of codec manager. 
     91 * @return              The instance of codec manager belonging to 
     92 *                      this media endpoint. 
    8693 */ 
    87 PJ_DECL(pj_codec_mgr*) pj_med_mgr_get_codec_mgr (pj_med_mgr_t *mgr); 
     94PJ_DECL(pjmedia_codec_mgr*) pjmedia_endpt_get_codec_mgr(pjmedia_endpt *mgr); 
     95 
     96 
     97/** 
     98 * Create a SDP session description that describes the endpoint 
     99 * capability. 
     100 * 
     101 * @param endpt         The media endpoint. 
     102 * @param pool          Pool to use to create the SDP descriptor. 
     103 * @param stream_cnt    Number of elements in the sock_info array. This 
     104 *                      also denotes the maximum number of streams (i.e. 
     105 *                      the "m=" lines) that will be created in the SDP. 
     106 * @param sock_info     Array of socket transport information. One  
     107 *                      transport is needed for each media stream, and 
     108 *                      each transport consists of an RTP and RTCP socket 
     109 *                      pair. 
     110 * @param p_sdp         Pointer to receive SDP session descriptor. 
     111 * 
     112 * @return              PJ_SUCCESS on success. 
     113 */ 
     114PJ_DECL(pj_status_t) pjmedia_endpt_create_sdp( pjmedia_endpt *endpt, 
     115                                               pj_pool_t *pool, 
     116                                               unsigned stream_cnt, 
     117                                               const pjmedia_sock_info sock_info[], 
     118                                               pjmedia_sdp_session **p_sdp ); 
    88119 
    89120 
  • pjproject/trunk/pjmedia/include/pjmedia/errno.h

    r140 r159  
    260260 
    261261 
     262/************************************************************ 
     263 * CODEC 
     264 ***********************************************************/ 
     265/** 
     266 * @hideinitializer 
     267 * Unsupported codec. 
     268 */ 
     269#define PJMEDIA_CODEC_EUNSUP        (PJMEDIA_ERRNO_START+80)    /* 220080 */ 
     270 
     271 
     272/************************************************************ 
     273 * MEDIA 
     274 ***********************************************************/ 
     275/** 
     276 * @hideinitializer 
     277 * Invalid remote IP address (in SDP). 
     278 */ 
     279#define PJMEDIA_EINVALIDIP          (PJMEDIA_ERRNO_START+100)    /* 220100 */ 
     280/** 
     281 * @hideinitializer 
     282 * Asymetric codec is not supported. 
     283 */ 
     284#define PJMEDIA_EASYMCODEC          (PJMEDIA_ERRNO_START+101)    /* 220101 */ 
     285/** 
     286 * @hideinitializer 
     287 * Invalid payload type. 
     288 */ 
     289#define PJMEDIA_EINVALIDPT          (PJMEDIA_ERRNO_START+102)    /* 220102 */ 
     290/** 
     291 * @hideinitializer 
     292 * Missing rtpmap. 
     293 */ 
     294#define PJMEDIA_EMISSINGRTPMAP      (PJMEDIA_ERRNO_START+103)    /* 220103 */ 
     295 
     296 
     297 
    262298PJ_END_DECL 
    263299 
  • pjproject/trunk/pjmedia/include/pjmedia/rtp.h

    r121 r159  
    8080enum pj_rtp_error_t 
    8181{ 
    82     PJ_RTP_ERR_RTP_PACKING,         /**< Invalid RTP packet. */ 
    83     PJ_RTP_ERR_INVALID_VERSION,     /**< Invalid RTP version. */ 
    84     PJ_RTP_ERR_INVALID_SSRC,        /**< Invalid SSRC. */ 
    85     PJ_RTP_ERR_INVALID_PT,          /**< Invalid payload type. */ 
    86     PJ_RTP_ERR_INVALID_PACKET,      /**< Invalid packet. */ 
    87     PJ_RTP_ERR_SESSION_RESTARTED,   /**< Session has just been restarted. */ 
    88     PJ_RTP_ERR_SESSION_PROBATION,   /**< Session in probation. */ 
    89     PJ_RTP_ERR_BAD_SEQUENCE,        /**< Bad RTP sequence number. */ 
     82    PJMEDIA_RTP_ERR_RTP_PACKING,            /**< Invalid RTP packet. */ 
     83    PJMEDIA_RTP_ERR_INVALID_VERSION,        /**< Invalid RTP version. */ 
     84    PJMEDIA_RTP_ERR_INVALID_SSRC,           /**< Invalid SSRC. */ 
     85    PJMEDIA_RTP_ERR_INVALID_PT,     /**< Invalid payload type. */ 
     86    PJMEDIA_RTP_ERR_INVALID_PACKET,         /**< Invalid packet. */ 
     87    PJMEDIA_RTP_ERR_SESSION_RESTARTED,   /**< Session has just been restarted. */ 
     88    PJMEDIA_RTP_ERR_SESSION_PROBATION,   /**< Session in probation. */ 
     89    PJMEDIA_RTP_ERR_BAD_SEQUENCE,           /**< Bad RTP sequence number. */ 
    9090}; 
    9191 
  • pjproject/trunk/pjmedia/include/pjmedia/session.h

    r121 r159  
    2626 */ 
    2727 
    28 #include <pj/types.h> 
    29 #include <pjmedia/mediamgr.h> 
     28#include <pjmedia/endpoint.h> 
    3029#include <pjmedia/stream.h> 
    3130#include <pjmedia/sdp.h> 
     
    3938 */ 
    4039 
    41 /** Opaque declaration of media session. */ 
    42 typedef struct pj_media_session_t pj_media_session_t; 
    43  
    44 /** Media socket info. */ 
    45 typedef struct pj_media_sock_info 
    46 { 
    47     pj_sock_t       rtp_sock, rtcp_sock; 
    48     pj_sockaddr_in  rtp_addr_name; 
    49 } pj_media_sock_info; 
    50  
    51 /** Stream info. */ 
    52 typedef struct pj_media_stream_info 
    53 { 
    54     pj_str_t            type; 
    55     pj_media_dir_t      dir; 
    56     pj_str_t            transport; 
    57     pj_media_sock_info  sock_info; 
    58     pj_str_t            rem_addr; 
    59     unsigned short      rem_port; 
    60     unsigned            fmt_cnt; 
    61     pj_codec_id         fmt[PJSDP_MAX_FMT]; 
    62  
    63 } pj_media_stream_info; 
    64  
    65 /** Flag for modifying stream. */ 
    66 enum 
    67 { 
    68     PJ_MEDIA_STREAM_MODIFY_DIR = 1, 
    69 }; 
    7040 
    7141/** 
    72  * Create new session offering. 
     42 * Create new session offering based on the local and remote SDP. 
     43 * The session initially will be inactive. 
     44 * 
     45 * @param endpt         The PJMEDIA endpoint instance. 
     46 * @param stream_cnt    Maximum number of streams to be created. This 
     47 *                      also denotes the number of elements in the 
     48 *                      socket information. 
     49 * @param skinfo        Array of socket informations. The argument stream_cnt 
     50 *                      specifies the number of elements in this array. One 
     51 *                      element is needed for each media stream to be 
     52 *                      created in the session. 
     53 * @param local_sdp     The SDP describing local capability. 
     54 * @param rem_sdp       The SDP describing remote capability. 
     55 * @param p_session     Pointer to receive the media session. 
     56 * 
     57 * @return              PJ_SUCCESS if media session can be created  
     58 *                      successfully. 
    7359 */ 
    74 PJ_DECL(pj_media_session_t*)  
    75 pj_media_session_create ( pj_med_mgr_t *mgr, const pj_media_sock_info *skinfo ); 
     60PJ_DECL(pj_status_t) pjmedia_session_create( pjmedia_endpt *endpt,  
     61                                             unsigned stream_cnt, 
     62                                             const pjmedia_sock_info skinfo[], 
     63                                             const pjmedia_sdp_session *local_sdp, 
     64                                             const pjmedia_sdp_session *rem_sdp, 
     65                                             pjmedia_session **p_session ); 
     66 
    7667 
    7768/** 
    78  * Create new session based on peer's offering. 
     69 * Activate all streams in media session for the specified direction. 
     70 * 
     71 * @param session       The media session. 
     72 * @param dir           The direction to activate. 
     73 * 
     74 * @return              PJ_SUCCESS if success. 
    7975 */ 
    80 PJ_DECL(pj_media_session_t*)  
    81 pj_media_session_create_from_sdp ( pj_med_mgr_t *mgr, const pjsdp_session_desc *sdp, 
    82                                    const pj_media_sock_info *skinfo); 
     76PJ_DECL(pj_status_t) pjmedia_session_resume(pjmedia_session *session, 
     77                                            pjmedia_dir dir); 
     78 
    8379 
    8480/** 
    85  * Duplicate session. The new session is inactive. 
     81 * Suspend receipt and transmission of all streams in media session 
     82 * for the specified direction. 
     83 * 
     84 * @param session       The media session. 
     85 * @param dir           The media direction to suspend. 
     86 * 
     87 * @return              PJ_SUCCESS if success. 
    8688 */ 
    87 PJ_DECL(pj_media_session_t*) 
    88 pj_media_session_clone (const pj_media_session_t *session); 
     89PJ_DECL(pj_status_t) pjmedia_session_pause(pjmedia_session *session, 
     90                                           pjmedia_dir dir); 
    8991 
    9092/** 
    91  * Create SDP description from the session. 
     93 * Suspend receipt and transmission of individual stream in media session 
     94 * for the specified direction. 
     95 * 
     96 * @param session       The media session. 
     97 * @param index         The stream index. 
     98 * @param dir           The media direction to pause. 
     99 * 
     100 * @return              PJ_SUCCESS on success. 
    92101 */ 
    93 PJ_DECL(pjsdp_session_desc*) 
    94 pj_media_session_create_sdp ( const pj_media_session_t *session, pj_pool_t *pool, 
    95                               pj_bool_t only_first_fmt); 
     102PJ_DECL(pj_status_t) pjmedia_session_pause_stream( pjmedia_session *session, 
     103                                                   unsigned index, 
     104                                                   pjmedia_dir dir); 
    96105 
    97106/** 
    98  * Update session with SDP answer from peer. The session must NOT active. 
     107 * Activate individual stream in media session for the specified direction. 
     108 * 
     109 * @param session       The media session. 
     110 * @param index         The stream index. 
     111 * @param dir           The media direction to activate. 
     112 * 
     113 * @return              PJ_SUCCESS on success. 
    99114 */ 
    100 PJ_DECL(pj_status_t) 
    101 pj_media_session_update ( pj_media_session_t *session,  
    102                           const pjsdp_session_desc *sdp); 
     115PJ_DECL(pj_status_t) pjmedia_session_resume_stream(pjmedia_session *session, 
     116                                                   unsigned index, 
     117                                                   pjmedia_dir dir); 
    103118 
    104119/** 
    105120 * Enumerate media streams in the session. 
    106  * @return the actual number of streams. 
     121 * 
     122 * @param session       The media session. 
     123 * @param count         On input, specifies the number of elements in 
     124 *                      the array. On output, the number will be filled 
     125 *                      with number of streams in the session. 
     126 * @param strm_info     Array of stream info. 
     127 * 
     128 * @return              PJ_SUCCESS on success. 
    107129 */ 
    108 PJ_DECL(unsigned) 
    109 pj_media_session_enum_streams (const pj_media_session_t *session,  
    110                                unsigned count, const pj_media_stream_info *info[]); 
     130PJ_DECL(pj_status_t) pjmedia_session_enum_streams(const pjmedia_session *session, 
     131                                                  unsigned *count,  
     132                                                  pjmedia_stream_info strm_info[]); 
     133 
    111134 
    112135/** 
    113  * Get stream statistics. 
     136 * Get session statistics. The stream statistic shows various 
     137 * indicators such as packet count, packet lost, jitter, delay, etc. 
     138 * 
     139 * @param session       The media session. 
     140 * @param count         On input, specifies the number of elements in 
     141 *                      the array. On output, the number will be filled 
     142 *                      with number of streams in the session. 
     143 * @param stat          Array of stream statistics. 
     144 * 
     145 * @return              PJ_SUCCESS on success. 
    114146 */ 
    115 PJ_DECL(pj_status_t) 
    116 pj_media_session_get_stat (const pj_media_session_t *session, unsigned index, 
    117                            pj_media_stream_stat *tx_stat, 
    118                            pj_media_stream_stat *rx_stat); 
     147PJ_DECL(pj_status_t) pjmedia_session_get_stat(const pjmedia_session *session, 
     148                                              unsigned *count, 
     149                                              pjmedia_stream_stat stat[]); 
    119150 
    120151/** 
    121  * Modify stream, only when stream is inactive. 
     152 * Get individual stream statistics. The stream statistic shows various 
     153 * indicators such as packet count, packet lost, jitter, delay, etc. 
     154 * 
     155 * @param s             The media session. 
     156 * @param index         The stream index. 
     157 * @param stat          Stream statistics. 
     158 * 
     159 * @return              PJ_SUCCESS on success. 
    122160 */ 
    123 PJ_DECL(pj_status_t) 
    124 pj_media_session_modify_stream (pj_media_session_t *session, unsigned index, 
    125                                 unsigned modify_flag, const pj_media_stream_info *info); 
    126  
    127 /** 
    128  * Activate all streams in media session. 
    129  */ 
    130 PJ_DECL(pj_status_t) 
    131 pj_media_session_activate (pj_media_session_t *session); 
    132  
    133 /** 
    134  * Activate individual stream in media session. 
    135  */ 
    136 PJ_DECL(pj_status_t) 
    137 pj_media_session_activate_stream (pj_media_session_t *session, unsigned index); 
     161PJ_DECL(pj_status_t) pjmedia_session_get_stream_stat(const pjmedia_session *s, 
     162                                                     unsigned index, 
     163                                                     pjmedia_stream_stat *stat); 
    138164 
    139165/** 
    140166 * Destroy media session. 
     167 * 
     168 * @param session       The media session. 
     169 * 
     170 * @return              PJ_SUCCESS if success. 
    141171 */ 
    142 PJ_DECL(pj_status_t) 
    143 pj_media_session_destroy (pj_media_session_t *session); 
     172PJ_DECL(pj_status_t) pjmedia_session_destroy(pjmedia_session *session); 
     173 
    144174 
    145175 
  • pjproject/trunk/pjmedia/include/pjmedia/stream.h

    r121 r159  
    2828#include <pjmedia/sound.h> 
    2929#include <pjmedia/codec.h> 
    30 #include <pjmedia/mediamgr.h> 
     30#include <pjmedia/endpoint.h> 
    3131#include <pj/sock.h> 
    3232 
     
    4040 */ 
    4141 
    42 typedef struct pj_media_stream_t pj_media_stream_t; 
     42/** 
     43 * Opaque declaration for media channel. 
     44 * Media channel is unidirectional flow of media from sender to 
     45 * receiver. 
     46 */ 
     47typedef struct pjmedia_channel pjmedia_channel; 
    4348 
    44 /** Parameter for creating channel. */ 
    45 typedef struct pj_media_stream_create_param 
     49/**  
     50 * This structure describes media stream information. Each media stream 
     51 * corresponds to one "m=" line in SDP session descriptor, and it has 
     52 * its own RTP/RTCP socket pair. 
     53 */ 
     54struct pjmedia_stream_info 
    4655{ 
    47     /** Codec ID, must NOT be NULL. */ 
    48     pj_codec_id          *codec_id; 
     56    pjmedia_type        type;       /**< Media type (audio, video)          */ 
     57    pjmedia_dir         dir;        /**< Media direction.                   */ 
     58    pjmedia_sock_info   sock_info;  /**< Media transport (RTP/RTCP sockets) */ 
     59    pj_sockaddr_in      rem_addr;   /**< Remote RTP address                 */ 
     60    pjmedia_codec_info  fmt;        /**< Codec format info.                 */ 
     61    pj_uint32_t         ssrc;       /**< RTP SSRC.                          */ 
     62    int                 jb_min;     /**< Jitter buffer min delay.           */ 
     63    int                 jb_max;     /**< Jitter buffer max delay.           */ 
     64    int                 jb_maxcnt;  /**< Jitter buffer max delay.           */ 
     65}; 
    4966 
    50     /** Media manager, must NOT be NULL. */ 
    51     pj_med_mgr_t         *mediamgr; 
    5267 
    53     /** Direction: IN_OUT, or IN only, or OUT only. */ 
    54     pj_media_dir_t        dir; 
     68/** 
     69 * Individual channel statistic. 
     70 */ 
     71struct pjmedia_channel_stat 
     72{ 
     73    pj_uint32_t pkt;        /**< Total number of packets.                   */ 
     74    pj_uint32_t bytes;      /**< Total number of bytes, including RTP hdr.  */ 
     75    pj_uint32_t lost;       /**< Total number of packet lost                */ 
     76}; 
    5577 
    56     /** RTP socket. */ 
    57     pj_sock_t            rtp_sock; 
     78/** 
     79 * Stream statistic. 
     80 */ 
     81struct pjmedia_stream_stat 
     82{ 
     83    pjmedia_channel_stat    enc;    /**< Encoder statistics.                */ 
     84    pjmedia_channel_stat    dec;    /**< Decoder statistics.                */ 
     85}; 
    5886 
    59     /** RTCP socket. */ 
    60     pj_sock_t            rtcp_sock; 
    6187 
    62     /** Address of remote */ 
    63     pj_sockaddr_in       *remote_addr; 
     88/** 
     89 * Create a media stream based on the specified stream parameter. 
     90 * All channels in the stream initially will be inactive. 
     91 * 
     92 * @param endpt         Media endpoint. 
     93 * @param pool          Pool to allocate memory for the stream. A large 
     94 *                      number of memory may be needed because jitter 
     95 *                      buffer needs to preallocate some storage. 
     96 * @param info          Stream information. 
     97 * @param p_stream      Pointer to receive the media stream. 
     98 * 
     99 * @return              PJ_SUCCESS on success. 
     100 */ 
     101PJ_DECL(pj_status_t) pjmedia_stream_create(pjmedia_endpt *endpt, 
     102                                           pj_pool_t *pool, 
     103                                           const pjmedia_stream_info *info, 
     104                                           pjmedia_stream **p_stream); 
    64105 
    65     /** RTP SSRC */ 
    66     pj_uint32_t           ssrc; 
     106/** 
     107 * Destroy the media stream. 
     108 * 
     109 * @param stream        The media stream. 
     110 * 
     111 * @return              PJ_SUCCESS on success. 
     112 */ 
     113PJ_DECL(pj_status_t) pjmedia_stream_destroy(pjmedia_stream *stream); 
    67114 
    68     /** Jitter buffer parameters. */ 
    69     int                   jb_min, jb_max, jb_maxcnt; 
     115/** 
     116 * Start the media stream. This will start the appropriate channels 
     117 * in the media stream, depending on the media direction that was set 
     118 * when the stream was created. 
     119 * 
     120 * @param stream        The media stream. 
     121 * 
     122 * @return              PJ_SUCCESS on success. 
     123 */ 
     124PJ_DECL(pj_status_t) pjmedia_stream_start(pjmedia_stream *stream); 
    70125 
    71 } pj_media_stream_create_param; 
    72126 
    73 typedef struct pj_media_stream_stat 
    74 { 
    75     pj_uint32_t pkt_tx, pkt_rx; /* packets transmitted/received */ 
    76     pj_uint32_t oct_tx, oct_rx; /* octets transmitted/received */ 
    77     pj_uint32_t jitter;         /* receive jitter in ms */ 
    78     pj_uint32_t pkt_lost;       /* total packet lost count */ 
    79 } pj_media_stream_stat; 
     127/** 
     128 * Get the stream statistics. 
     129 * 
     130 * @param stream        The media stream. 
     131 * @param stat          Media stream statistics. 
     132 * 
     133 * @return              PJ_SUCCESS on success. 
     134 */ 
     135PJ_DECL(pj_status_t) pjmedia_stream_get_stat( const pjmedia_stream *stream, 
     136                                              pjmedia_stream_stat *stat); 
    80137 
    81 PJ_DECL(pj_status_t) pj_media_stream_create (pj_pool_t *pool, 
    82                                              pj_media_stream_t **enc_stream, 
    83                                              pj_media_stream_t **dec_stream, 
    84                                              pj_media_stream_create_param *param); 
    85 PJ_DECL(pj_status_t) pj_media_stream_start (pj_media_stream_t *stream); 
    86 PJ_DECL(pj_status_t) pj_media_stream_get_stat (const pj_media_stream_t *stream, 
    87                                                pj_media_stream_stat *stat); 
    88 PJ_DECL(pj_status_t) pj_media_stream_pause (pj_media_stream_t *stream); 
    89 PJ_DECL(pj_status_t) pj_media_stream_resume (pj_media_stream_t *stream); 
    90 PJ_DECL(pj_status_t) pj_media_stream_destroy (pj_media_stream_t *stream); 
     138/** 
     139 * Pause the individual channel in the stream. 
     140 * 
     141 * @param channel       The media channel. 
     142 * @param dir           Which direction to pause. 
     143 * 
     144 * @return              PJ_SUCCESS on success. 
     145 */ 
     146PJ_DECL(pj_status_t) pjmedia_stream_pause( pjmedia_stream *stream, 
     147                                           pjmedia_dir dir); 
     148 
     149/** 
     150 * Resume the individual channel in the stream. 
     151 * 
     152 * @param channel       The media channel. 
     153 * @param dir           Which direction to resume. 
     154 * 
     155 * @return              PJ_SUCCESS on success; 
     156 */ 
     157PJ_DECL(pj_status_t) pjmedia_stream_resume(pjmedia_stream *stream, 
     158                                           pjmedia_dir dir); 
     159 
    91160 
    92161/** 
  • pjproject/trunk/pjmedia/include/pjmedia/types.h

    r129 r159  
    2121 
    2222#include <pj/types.h> 
    23  
     23#include <pj/sock.h> 
     24 
     25 
     26/**  
     27 * Top most media type.  
     28 */ 
     29enum pjmedia_type 
     30{ 
     31    /** No type. */ 
     32    PJMEDIA_TYPE_NONE = 0, 
     33 
     34    /** The media is audio */ 
     35    PJMEDIA_TYPE_AUDIO = 1, 
     36 
     37    /** The media is video. */ 
     38    PJMEDIA_TYPE_VIDEO = 2, 
     39 
     40    /** Unknown media type, in this case the name will be specified in  
     41     *  encoding_name. 
     42     */ 
     43    PJMEDIA_TYPE_UNKNOWN = 3, 
     44 
     45}; 
     46 
     47 
     48/**  
     49 * Media direction.  
     50 */ 
     51enum pjmedia_dir 
     52{ 
     53    /** None */ 
     54    PJMEDIA_DIR_NONE = 0, 
     55 
     56    /** Encoding (outgoing to network) stream */ 
     57    PJMEDIA_DIR_ENCODING = 1, 
     58 
     59    /** Decoding (incoming from network) stream. */ 
     60    PJMEDIA_DIR_DECODING = 2, 
     61 
     62    /** Incoming and outgoing stream. */ 
     63    PJMEDIA_DIR_ENCODING_DECODING = 3, 
     64 
     65}; 
     66 
     67 
     68/** 
     69 * Top level media type. 
     70 */ 
     71typedef enum pjmedia_type pjmedia_type; 
     72 
     73/** 
     74 * Media direction. 
     75 */ 
     76typedef enum pjmedia_dir pjmedia_dir; 
     77 
     78/** 
     79 * Codec info. 
     80 */ 
     81typedef struct pjmedia_codec_info pjmedia_codec_info; 
     82 
     83/** 
     84 * Codec initialization parameter. 
     85 */ 
     86typedef struct pjmedia_codec_param pjmedia_codec_param; 
     87 
     88/**  
     89 * Types of media frames.  
     90 */ 
     91typedef enum pjmedia_frame_type pjmedia_frame_type; 
     92 
     93/**  
     94 * This structure describes a media frame.  
     95 */ 
     96typedef struct pjmedia_frame pjmedia_frame; 
     97 
     98/** 
     99 * Codec instance. 
     100 */ 
     101typedef struct pjmedia_codec pjmedia_codec; 
     102 
     103/** 
     104 * Codec factory. 
     105 */ 
     106typedef struct pjmedia_codec_factory pjmedia_codec_factory; 
     107 
     108/** 
     109 * Codec operation. 
     110 */ 
     111typedef struct pjmedia_codec_op pjmedia_codec_op; 
     112 
     113/** 
     114 * Codec factory operation. 
     115 */ 
     116typedef struct pjmedia_codec_factory_op pjmedia_codec_factory_op; 
     117 
     118/** 
     119 * Codec manager. 
     120 */ 
     121typedef struct pjmedia_codec_mgr pjmedia_codec_mgr; 
     122 
     123/**  
     124 * Opague declaration of media endpoint.  
     125 */ 
     126typedef struct pjmedia_endpt pjmedia_endpt; 
     127 
     128 
     129/**  
     130 * Media socket info.  
     131 */ 
     132typedef struct pjmedia_sock_info 
     133{ 
     134 
     135    pj_sock_t       rtp_sock; 
     136    pj_sock_t       rtcp_sock; 
     137    pj_sockaddr_in  rtp_addr_name; 
     138 
     139} pjmedia_sock_info; 
     140 
     141 
     142/** 
     143 * Typedef for media stream information. 
     144 */ 
     145typedef struct pjmedia_stream_info pjmedia_stream_info; 
     146 
     147/** 
     148 * Typedef for media stream statistic. 
     149 */ 
     150typedef struct pjmedia_stream_stat pjmedia_stream_stat; 
     151 
     152/** 
     153 * Typedef for media stream. 
     154 */ 
     155typedef struct pjmedia_stream pjmedia_stream; 
     156 
     157/** 
     158 * Individual channel statistic. 
     159 */ 
     160typedef struct pjmedia_channel_stat pjmedia_channel_stat; 
     161 
     162/**  
     163 * Opaque declaration of media session.  
     164 */ 
     165typedef struct pjmedia_session pjmedia_session; 
    24166 
    25167/** 
  • pjproject/trunk/pjmedia/src/pjmedia/codec.c

    r121 r159  
    1818 */ 
    1919#include <pjmedia/codec.h> 
     20#include <pjmedia/errno.h> 
    2021#include <pj/pool.h> 
    2122#include <pj/string.h> 
     
    2526#define THIS_FILE   "codec.c" 
    2627 
    27 static void enum_all_codecs (pj_codec_mgr *cm) 
     28/* 
     29 * Reinitialize array of supported codecs. 
     30 */ 
     31static void enum_all_codecs (pjmedia_codec_mgr *mgr) 
    2832{ 
    29     pj_codec_factory *cf; 
     33    pjmedia_codec_factory *factory; 
    3034 
    31     cf = cm->factory_list.next; 
    32     cm->codec_cnt = 0; 
    33     while (cf != &cm->factory_list) { 
    34         pj_codec_id temp[PJ_CODEC_MGR_MAX_CODECS]; 
    35         int i, cnt; 
     35    mgr->codec_cnt = 0; 
    3636 
    37         cnt = cf->op->enum_codecs (cf, PJ_CODEC_MGR_MAX_CODECS, temp); 
    38         if (cnt > PJ_CODEC_MGR_MAX_CODECS) { 
    39             pj_assert(0); 
    40             PJ_LOG(4, (THIS_FILE, "Too many codecs reported by factory")); 
    41             cnt = PJ_CODEC_MGR_MAX_CODECS; 
    42         } 
     37    factory = mgr->factory_list.next; 
     38    while (factory != &mgr->factory_list) { 
     39        unsigned count; 
     40        pj_status_t status; 
    4341 
    44         for (i=0; i<cnt && cm->codec_cnt < PJ_CODEC_MGR_MAX_CODECS; ++i) { 
    45             cm->codecs[cm->codec_cnt++] = temp[i]; 
    46         } 
     42        count = PJ_ARRAY_SIZE(mgr->codecs) - mgr->codec_cnt; 
     43        status = factory->op->enum_info(factory, &count,  
     44                                        mgr->codecs+mgr->codec_cnt); 
     45        if (status == PJ_SUCCESS) 
     46            mgr->codec_cnt += count; 
    4747 
    48         cf = cf->next; 
     48        factory = factory->next; 
    4949    } 
    5050} 
    5151 
    52 PJ_DEF(pj_status_t) pj_codec_mgr_init (pj_codec_mgr *mgr) 
     52/* 
     53 * Initialize codec manager. 
     54 */ 
     55PJ_DEF(pj_status_t) pjmedia_codec_mgr_init (pjmedia_codec_mgr *mgr) 
    5356{ 
     57    PJ_ASSERT_RETURN(mgr, PJ_EINVAL); 
     58 
    5459    pj_list_init (&mgr->factory_list); 
    5560    mgr->codec_cnt = 0; 
    56     return 0; 
     61 
     62    return PJ_SUCCESS; 
    5763} 
    5864 
    59 PJ_DEF(pj_status_t) pj_codec_mgr_register_factory (pj_codec_mgr *mgr, 
    60                                                    pj_codec_factory *factory) 
     65/* 
     66 * Register a codec factory. 
     67 */ 
     68PJ_DEF(pj_status_t)  
     69pjmedia_codec_mgr_register_factory( pjmedia_codec_mgr *mgr, 
     70                                    pjmedia_codec_factory *factory) 
    6171{ 
    62     pj_list_insert_before (&mgr->factory_list, factory); 
     72    PJ_ASSERT_RETURN(mgr && factory, PJ_EINVAL); 
     73 
     74    pj_list_push_back(&mgr->factory_list, factory); 
    6375    enum_all_codecs (mgr); 
    64     return 0; 
     76 
     77    return PJ_SUCCESS; 
    6578} 
    6679 
    67 PJ_DEF(void) pj_codec_mgr_unregister_factory (pj_codec_mgr *mgr, pj_codec_factory *factory) 
     80/* 
     81 * Unregister a codec factory. 
     82 */ 
     83PJ_DEF(pj_status_t)  
     84pjmedia_codec_mgr_unregister_factory(pjmedia_codec_mgr *mgr,  
     85                                     pjmedia_codec_factory *factory) 
    6886{ 
    69     PJ_UNUSED_ARG(mgr); 
     87 
     88    PJ_ASSERT_RETURN(mgr && factory, PJ_EINVAL); 
     89 
     90    /* Factory must be registered. */ 
     91    PJ_ASSERT_RETURN(pj_list_find_node(&mgr->factory_list, factory)==factory, 
     92                     PJ_ENOTFOUND); 
     93 
     94 
    7095    pj_list_erase(factory); 
    7196    enum_all_codecs (mgr); 
     97 
     98    return PJ_SUCCESS; 
    7299} 
    73100 
    74 PJ_DEF(unsigned) 
    75 pj_codec_mgr_enum_codecs (pj_codec_mgr *mgr, unsigned count, const pj_codec_id *codecs[]) 
     101/* 
     102 * Enum all codecs. 
     103 */ 
     104PJ_DEF(pj_status_t) 
     105pjmedia_codec_mgr_enum_codecs(pjmedia_codec_mgr *mgr,  
     106                              unsigned *count,  
     107                              pjmedia_codec_info codecs[]) 
    76108{ 
    77     unsigned i; 
     109    PJ_ASSERT_RETURN(mgr && count && codecs, PJ_EINVAL); 
    78110 
    79     if (count > mgr->codec_cnt) 
    80         count = mgr->codec_cnt; 
     111    if (*count > mgr->codec_cnt) 
     112        *count = mgr->codec_cnt; 
     113     
     114    pj_memcpy(codecs, mgr->codecs, *count * sizeof(pjmedia_codec_info)); 
    81115 
    82     for (i=0; i<count; ++i) 
    83         codecs[i] = &mgr->codecs[i]; 
    84  
    85     return mgr->codec_cnt; 
     116    return PJ_SUCCESS; 
    86117} 
    87118 
    88 PJ_DEF(pj_codec*) pj_codec_mgr_alloc_codec (pj_codec_mgr *mgr, const struct pj_codec_id *id) 
     119/* 
     120 * Allocate one codec. 
     121 */ 
     122PJ_DEF(pj_status_t) pjmedia_codec_mgr_alloc_codec(pjmedia_codec_mgr *mgr,  
     123                                                  const pjmedia_codec_info *info, 
     124                                                  pjmedia_codec **p_codec) 
    89125{ 
    90     pj_codec_factory *factory = mgr->factory_list.next; 
     126    pjmedia_codec_factory *factory; 
     127    pj_status_t status; 
     128 
     129    PJ_ASSERT_RETURN(mgr && info && p_codec, PJ_EINVAL); 
     130 
     131    *p_codec = NULL; 
     132 
     133    factory = mgr->factory_list.next; 
    91134    while (factory != &mgr->factory_list) { 
    92         if ( (*factory->op->match_id)(factory, id) == 0 ) { 
    93             pj_codec *codec = (*factory->op->alloc_codec)(factory, id); 
    94             if (codec != NULL) 
    95                 return codec; 
     135 
     136        if ( (*factory->op->test_alloc)(factory, info) == PJ_SUCCESS ) { 
     137 
     138            status = (*factory->op->alloc_codec)(factory, info, p_codec); 
     139            if (status == PJ_SUCCESS) 
     140                return PJ_SUCCESS; 
     141 
    96142        } 
     143 
    97144        factory = factory->next; 
    98145    } 
    99     return NULL; 
     146 
     147 
     148    return PJMEDIA_CODEC_EUNSUP; 
    100149} 
    101150 
    102 PJ_DEF(void) pj_codec_mgr_dealloc_codec (pj_codec_mgr *mgr, pj_codec *codec) 
     151/* 
     152 * Dealloc codec. 
     153 */ 
     154PJ_DEF(pj_status_t) pjmedia_codec_mgr_dealloc_codec(pjmedia_codec_mgr *mgr,  
     155                                                    pjmedia_codec *codec) 
    103156{ 
    104     PJ_UNUSED_ARG(mgr); 
    105     (*codec->factory->op->dealloc_codec)(codec->factory, codec); 
     157    PJ_ASSERT_RETURN(mgr && codec, PJ_EINVAL); 
     158 
     159    return (*codec->factory->op->dealloc_codec)(codec->factory, codec); 
    106160} 
    107161 
  • pjproject/trunk/pjmedia/src/pjmedia/endpoint.c

    r158 r159  
    1717 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA  
    1818 */ 
    19 #include <pjmedia/mediamgr.h> 
     19#include <pjmedia/endpoint.h> 
     20#include <pjmedia/errno.h> 
     21#include <pjmedia/sdp.h> 
    2022#include <pj/sock.h> 
    2123#include <pj/pool.h> 
    2224#include <pj/string.h> 
    23  
    24 PJ_DECL(pj_status_t) g711_init_factory (pj_codec_factory *factory, pj_pool_t *pool); 
    25 PJ_DECL(pj_status_t) g711_deinit_factory (pj_codec_factory *factory); 
    26  
    27 /** Concrete declaration of media manager. */ 
    28 struct pj_med_mgr_t 
     25#include <pj/assert.h> 
     26#include <pj/os.h> 
     27 
     28 
     29#define THIS_FILE   "endpoint.c" 
     30 
     31static const pj_str_t STR_AUDIO = { "audio", 5}; 
     32static const pj_str_t STR_VIDEO = { "video", 5}; 
     33static const pj_str_t STR_IN = { "IN", 2 }; 
     34static const pj_str_t STR_IP4 = { "IP4", 3}; 
     35static const pj_str_t STR_RTP_AVP = { "RTP/AVP", 7 }; 
     36static const pj_str_t STR_SDP_NAME = { "pjmedia", 7 }; 
     37static const pj_str_t STR_SENDRECV = { "sendrecv", 8 }; 
     38 
     39 
     40PJ_DECL(pj_status_t) g711_init_factory (pjmedia_codec_factory *factory, pj_pool_t *pool); 
     41PJ_DECL(pj_status_t) g711_deinit_factory (pjmedia_codec_factory *factory); 
     42 
     43 
     44/** Concrete declaration of media endpoint. */ 
     45struct pjmedia_endpt 
    2946{ 
    3047    /** Pool. */ 
     
    3552 
    3653    /** Codec manager. */ 
    37     pj_codec_mgr          codec_mgr; 
     54    pjmedia_codec_mgr     codec_mgr; 
    3855}; 
    3956 
    4057/** 
    41  * Initialize and get the instance of media manager. 
    42  */ 
    43 PJ_DEF(pj_med_mgr_t*) pj_med_mgr_create ( pj_pool_factory *pf) 
     58 * Initialize and get the instance of media endpoint. 
     59 */ 
     60PJ_DEF(pj_status_t) pjmedia_endpt_create(pj_pool_factory *pf, 
     61                                         pjmedia_endpt **p_endpt) 
    4462{ 
    4563    pj_pool_t *pool; 
    46     pj_med_mgr_t *mm; 
    47     pj_codec_factory *cf; 
     64    pjmedia_endpt *endpt; 
     65    pjmedia_codec_factory *factory; 
    4866    pj_status_t status; 
    4967 
    50     pool = pj_pool_create(pf, "mediamgr", 512, 512, NULL); 
     68    PJ_ASSERT_RETURN(pf && p_endpt, PJ_EINVAL); 
     69 
     70    pool = pj_pool_create(pf, "med-ept", 512, 512, NULL); 
    5171    if (!pool) 
    52         return NULL; 
    53  
    54     mm = pj_pool_calloc(pool, 1, sizeof(struct pj_med_mgr_t)); 
    55     mm->pool = pool; 
    56     mm->pf = pf; 
     72        return PJ_ENOMEM; 
     73 
     74    endpt = pj_pool_zalloc(pool, sizeof(struct pjmedia_endpt)); 
     75    endpt->pool = pool; 
     76    endpt->pf = pf; 
    5777 
    5878    /* Sound */ 
     
    6080 
    6181    /* Init codec manager. */ 
    62     status = pj_codec_mgr_init(&mm->codec_mgr); 
    63     if (status != 0) { 
     82    status = pjmedia_codec_mgr_init(&endpt->codec_mgr); 
     83    if (status != PJ_SUCCESS) { 
    6484        pj_snd_deinit(); 
    6585        goto on_error; 
     
    6787 
    6888    /* Init and register G.711 codec. */ 
    69     cf = pj_pool_alloc (mm->pool, sizeof(pj_codec_factory)); 
    70  
    71     status = g711_init_factory (cf, mm->pool); 
    72     if (status != 0) { 
     89    factory = pj_pool_alloc (endpt->pool, sizeof(pjmedia_codec_factory)); 
     90 
     91    status = g711_init_factory (factory, endpt->pool); 
     92    if (status != PJ_SUCCESS) { 
    7393        pj_snd_deinit(); 
    74         return NULL; 
    75     } 
    76  
    77     status = pj_codec_mgr_register_factory (&mm->codec_mgr, cf); 
    78     if (status != 0)  
    79         return NULL; 
    80  
    81     return mm; 
     94        goto on_error; 
     95    } 
     96 
     97    status = pjmedia_codec_mgr_register_factory (&endpt->codec_mgr, factory); 
     98    if (status != PJ_SUCCESS)  { 
     99        pj_snd_deinit(); 
     100        goto on_error; 
     101    } 
     102 
     103    *p_endpt = endpt; 
     104    return PJ_SUCCESS; 
    82105 
    83106on_error: 
    84107    pj_pool_release(pool); 
    85     return NULL; 
     108    return status; 
    86109} 
    87110 
     
    89112 * Get the codec manager instance. 
    90113 */ 
    91 PJ_DEF(pj_codec_mgr*) pj_med_mgr_get_codec_mgr (pj_med_mgr_t *mgr) 
    92 { 
    93     return &mgr->codec_mgr; 
    94 } 
    95  
    96 /** 
    97  * Deinitialize media manager. 
    98  */ 
    99 PJ_DEF(pj_status_t) pj_med_mgr_destroy (pj_med_mgr_t *mgr) 
    100 { 
     114PJ_DEF(pjmedia_codec_mgr*) pjmedia_endpt_get_codec_mgr(pjmedia_endpt *endpt) 
     115{ 
     116    return &endpt->codec_mgr; 
     117} 
     118 
     119/** 
     120 * Deinitialize media endpoint. 
     121 */ 
     122PJ_DEF(pj_status_t) pjmedia_endpt_destroy (pjmedia_endpt *endpt) 
     123{ 
     124    PJ_ASSERT_RETURN(endpt, PJ_EINVAL); 
     125 
     126    endpt->pf = NULL; 
     127 
    101128    pj_snd_deinit(); 
    102     pj_pool_release (mgr->pool); 
    103     return 0; 
    104 } 
    105  
    106 /** 
    107  * Get pool factory. 
    108  */ 
    109 PJ_DEF(pj_pool_factory*) pj_med_mgr_get_pool_factory (pj_med_mgr_t *mgr) 
    110 { 
    111     return mgr->pf; 
    112 } 
     129    pj_pool_release (endpt->pool); 
     130 
     131    return PJ_SUCCESS; 
     132} 
     133 
     134/** 
     135 * Create pool. 
     136 */ 
     137PJ_DEF(pj_pool_t*) pjmedia_endpt_create_pool( pjmedia_endpt *endpt, 
     138                                              const char *name, 
     139                                              pj_size_t initial, 
     140                                              pj_size_t increment) 
     141{ 
     142    pj_assert(endpt != NULL); 
     143 
     144    return pj_pool_create(endpt->pf, name, initial, increment, NULL); 
     145} 
     146 
     147/** 
     148 * Create a SDP session description that describes the endpoint 
     149 * capability. 
     150 */ 
     151PJ_DEF(pj_status_t) pjmedia_endpt_create_sdp( pjmedia_endpt *endpt, 
     152                                              pj_pool_t *pool, 
     153                                              unsigned stream_cnt, 
     154                                              const pjmedia_sock_info sock_info[], 
     155                                              pjmedia_sdp_session **p_sdp ) 
     156{ 
     157    pj_time_val tv; 
     158    unsigned i; 
     159    pjmedia_sdp_session *sdp; 
     160    pjmedia_sdp_media *m; 
     161    pjmedia_sdp_attr *attr; 
     162 
     163    PJ_ASSERT_RETURN(endpt && pool && p_sdp && stream_cnt, PJ_EINVAL); 
     164 
     165 
     166    /* Create and initialize basic SDP session */ 
     167    sdp = pj_pool_zalloc (pool, sizeof(pjmedia_sdp_session)); 
     168 
     169    pj_gettimeofday(&tv); 
     170    sdp->origin.user = pj_str("-"); 
     171    sdp->origin.version = sdp->origin.id = tv.sec + 2208988800UL; 
     172    sdp->origin.net_type = STR_IN; 
     173    sdp->origin.addr_type = STR_IP4; 
     174    sdp->origin.addr = *pj_gethostname(); 
     175    sdp->name = STR_SDP_NAME; 
     176 
     177    /* Since we only support one media stream at present, put the 
     178     * SDP connection line in the session level. 
     179     */ 
     180    sdp->conn = pj_pool_zalloc (pool, sizeof(pjmedia_sdp_conn)); 
     181    sdp->conn->net_type = STR_IN; 
     182    sdp->conn->addr_type = STR_IP4; 
     183    pj_strdup2(pool, &sdp->conn->addr,  
     184               pj_inet_ntoa(sock_info[0].rtp_addr_name.sin_addr)); 
     185 
     186 
     187    /* SDP time and attributes. */ 
     188    sdp->time.start = sdp->time.stop = 0; 
     189    sdp->attr_count = 0; 
     190 
     191    /* Create media stream 0: */ 
     192 
     193    sdp->media_count = 1; 
     194    m = pj_pool_zalloc (pool, sizeof(pjmedia_sdp_media)); 
     195    sdp->media[0] = m; 
     196 
     197    /* Standard media info: */ 
     198    pj_strdup(pool, &m->desc.media, &STR_AUDIO); 
     199    m->desc.port = pj_ntohs(sock_info[0].rtp_addr_name.sin_port); 
     200    m->desc.port_count = 1; 
     201    pj_strdup (pool, &m->desc.transport, &STR_RTP_AVP); 
     202 
     203    /* Add format and rtpmap for each codec. */ 
     204    m->desc.fmt_count = 0; 
     205    m->attr_count = 0; 
     206 
     207    for (i=0; i<endpt->codec_mgr.codec_cnt; ++i) { 
     208 
     209        pjmedia_codec_info *codec_info = &endpt->codec_mgr.codecs[i]; 
     210        pjmedia_sdp_rtpmap rtpmap; 
     211        pjmedia_sdp_attr *attr; 
     212        pj_str_t *fmt = &m->desc.fmt[m->desc.fmt_count++]; 
     213 
     214        fmt->ptr = pj_pool_alloc(pool, 8); 
     215        fmt->slen = pj_utoa(codec_info->pt, fmt->ptr); 
     216 
     217        rtpmap.pt = *fmt; 
     218        rtpmap.clock_rate = codec_info->sample_rate; 
     219        rtpmap.enc_name = codec_info->encoding_name; 
     220        rtpmap.param.slen = 0; 
     221 
     222        pjmedia_sdp_rtpmap_to_attr(pool, &rtpmap, &attr); 
     223        m->attr[m->attr_count++] = attr; 
     224 
     225    } 
     226 
     227    /* Add sendrect attribute. */ 
     228    attr = pj_pool_zalloc(pool, sizeof(pjmedia_sdp_attr)); 
     229    attr->name = STR_SENDRECV; 
     230    m->attr[m->attr_count++] = attr; 
     231 
     232 
     233    /* Done */ 
     234    *p_sdp = sdp; 
     235 
     236    return PJ_SUCCESS; 
     237 
     238} 
     239 
  • pjproject/trunk/pjmedia/src/pjmedia/errno.c

    r140 r159  
    7777    { PJMEDIA_SDP_ENAMENOTEQUAL,    "SDP name/subject line not equal" }, 
    7878    { PJMEDIA_SDP_ETIMENOTEQUAL,    "SDP time line not equal" }, 
     79 
     80    /* Codec errors. */ 
     81    { PJMEDIA_CODEC_EUNSUP,         "Unsupported media codec" }, 
     82 
     83    /* Media errors. */ 
     84    { PJMEDIA_EINVALIDIP,           "Invalid remote media (IP) address" }, 
     85    { PJMEDIA_EASYMCODEC,           "Asymetric media codec is not supported" }, 
     86    { PJMEDIA_EINVALIDPT,           "Invalid media payload type" }, 
     87    { PJMEDIA_EMISSINGRTPMAP,       "Missing rtpmap in media description" }, 
    7988}; 
    8089 
  • pjproject/trunk/pjmedia/src/pjmedia/g711.c

    r121 r159  
    2121 */ 
    2222#include <pjmedia/codec.h> 
     23#include <pjmedia/errno.h> 
    2324#include <pj/pool.h> 
    2425#include <pj/string.h> 
     
    3031 
    3132/* These are the only public functions exported to applications */ 
    32 PJ_DECL(pj_status_t) g711_init_factory (pj_codec_factory *factory, pj_pool_t *pool); 
    33 PJ_DECL(pj_status_t) g711_deinit_factory (pj_codec_factory *factory); 
     33PJ_DECL(pj_status_t) g711_init_factory (pjmedia_codec_factory *factory, pj_pool_t *pool); 
     34PJ_DECL(pj_status_t) g711_deinit_factory (pjmedia_codec_factory *factory); 
    3435 
    3536/* Algorithm prototypes. */ 
     
    4041 
    4142/* Prototypes for G711 factory */ 
    42 static pj_status_t  g711_match_id( pj_codec_factory *factory, const pj_codec_id *id ); 
    43 static pj_status_t  g711_default_attr( pj_codec_factory *factory, const pj_codec_id *id, pj_codec_attr *attr ); 
    44 static unsigned     g711_enum_codecs (pj_codec_factory *factory, unsigned count, pj_codec_id codecs[]); 
    45 static pj_codec*    g711_alloc_codec( pj_codec_factory *factory, const pj_codec_id *id); 
    46 static void         g711_dealloc_codec( pj_codec_factory *factory, pj_codec *codec ); 
     43static pj_status_t g711_match_id( pjmedia_codec_factory *factory, const pjmedia_codec_info *id ); 
     44static pj_status_t g711_default_attr( pjmedia_codec_factory *factory, const pjmedia_codec_info *id, pjmedia_codec_param *attr ); 
     45static pj_status_t g711_enum_codecs (pjmedia_codec_factory *factory, unsigned *count, pjmedia_codec_info codecs[]); 
     46static pj_status_t g711_alloc_codec( pjmedia_codec_factory *factory, const pjmedia_codec_info *id, pjmedia_codec **p_codec); 
     47static pj_status_t g711_dealloc_codec( pjmedia_codec_factory *factory, pjmedia_codec *codec ); 
    4748 
    4849/* Prototypes for G711 implementation. */ 
    49 static pj_status_t  g711_codec_default_attr (pj_codec *codec, pj_codec_attr *attr); 
    50 static pj_status_t  g711_init( pj_codec *codec, pj_pool_t *pool ); 
    51 static pj_status_t  g711_open( pj_codec *codec, pj_codec_attr *attr ); 
    52 static pj_status_t  g711_close( pj_codec *codec ); 
    53 static pj_status_t  g711_encode( pj_codec *codec, const struct pj_audio_frame *input, 
    54                                  unsigned output_buf_len, struct pj_audio_frame *output); 
    55 static pj_status_t  g711_decode( pj_codec *codec, const struct pj_audio_frame *input, 
    56                                  unsigned output_buf_len, struct pj_audio_frame *output); 
     50static pj_status_t  g711_codec_default_attr (pjmedia_codec *codec, pjmedia_codec_param *attr); 
     51static pj_status_t  g711_init( pjmedia_codec *codec, pj_pool_t *pool ); 
     52static pj_status_t  g711_open( pjmedia_codec *codec, pjmedia_codec_param *attr ); 
     53static pj_status_t  g711_close( pjmedia_codec *codec ); 
     54static pj_status_t  g711_encode( pjmedia_codec *codec, const struct pjmedia_frame *input, 
     55                                 unsigned output_buf_len, struct pjmedia_frame *output); 
     56static pj_status_t  g711_decode( pjmedia_codec *codec, const struct pjmedia_frame *input, 
     57                                 unsigned output_buf_len, struct pjmedia_frame *output); 
    5758 
    5859/* Definition for G711 codec operations. */ 
    59 static pj_codec_op g711_op =  
     60static pjmedia_codec_op g711_op =  
    6061{ 
    6162    &g711_codec_default_attr , 
     
    6869 
    6970/* Definition for G711 codec factory operations. */ 
    70 static pj_codec_factory_op g711_factory_op = 
     71static pjmedia_codec_factory_op g711_factory_op = 
    7172{ 
    7273    &g711_match_id, 
     
    8182{ 
    8283    pj_pool_t  *pool; 
    83     pj_codec    codec_list; 
     84    pjmedia_codec       codec_list; 
    8485}; 
    8586 
     
    9192 
    9293 
    93 PJ_DEF(pj_status_t) g711_init_factory (pj_codec_factory *factory, pj_pool_t *pool) 
     94PJ_DEF(pj_status_t) g711_init_factory (pjmedia_codec_factory *factory, pj_pool_t *pool) 
    9495{ 
    9596    struct g711_factory_private *priv; 
    96     //enum { CODEC_MEM_SIZE = sizeof(pj_codec) + sizeof(struct g711_private) + 4 }; 
     97    //enum { CODEC_MEM_SIZE = sizeof(pjmedia_codec) + sizeof(struct g711_private) + 4 }; 
    9798 
    9899    /* Create pool. */ 
     
    118119} 
    119120 
    120 PJ_DEF(pj_status_t) g711_deinit_factory (pj_codec_factory *factory) 
     121PJ_DEF(pj_status_t) g711_deinit_factory (pjmedia_codec_factory *factory) 
    121122{ 
    122123    struct g711_factory_private *priv = factory->factory_data; 
     
    128129} 
    129130 
    130 static pj_status_t g711_match_id( pj_codec_factory *factory, const pj_codec_id *id ) 
     131static pj_status_t g711_match_id( pjmedia_codec_factory *factory, const pjmedia_codec_info *id ) 
    131132{ 
    132133    PJ_UNUSED_ARG(factory); 
    133134 
    134135    /* It's sufficient to check payload type only. */ 
    135     return (id->pt==PJ_RTP_PT_PCMU || id->pt==PJ_RTP_PT_PCMA) ? 0 : -1; 
    136 } 
    137  
    138 static pj_status_t g711_default_attr (pj_codec_factory *factory,  
    139                                       const pj_codec_id *id,  
    140                                       pj_codec_attr *attr ) 
     136    return (id->pt==PJMEDIA_RTP_PT_PCMU || id->pt==PJMEDIA_RTP_PT_PCMA) ? 0 : -1; 
     137} 
     138 
     139static pj_status_t g711_default_attr (pjmedia_codec_factory *factory,  
     140                                      const pjmedia_codec_info *id,  
     141                                      pjmedia_codec_param *attr ) 
    141142{ 
    142143    PJ_UNUSED_ARG(factory); 
    143144 
    144     memset(attr, 0, sizeof(pj_codec_attr)); 
     145    memset(attr, 0, sizeof(pjmedia_codec_param)); 
    145146    attr->sample_rate = 8000; 
    146147    attr->avg_bps = G711_BPS; 
     
    154155} 
    155156 
    156 static unsigned g711_enum_codecs (pj_codec_factory *factory,  
    157                                   unsigned count, pj_codec_id codecs[]) 
     157static pj_status_t g711_enum_codecs(pjmedia_codec_factory *factory,  
     158                                    unsigned *count,  
     159                                    pjmedia_codec_info codecs[]) 
    158160{ 
    159161    PJ_UNUSED_ARG(factory); 
    160162 
    161     if (count > 0) { 
    162         codecs[0].type = PJ_MEDIA_TYPE_AUDIO; 
    163         codecs[0].pt = PJ_RTP_PT_PCMU; 
     163    if (*count > 0) { 
     164        codecs[0].type = PJMEDIA_TYPE_AUDIO; 
     165        codecs[0].pt = PJMEDIA_RTP_PT_PCMU; 
    164166        codecs[0].encoding_name = pj_str("PCMU"); 
    165167        codecs[0].sample_rate = 8000; 
    166168    } 
    167     if (count > 1) { 
    168         codecs[1].type = PJ_MEDIA_TYPE_AUDIO; 
    169         codecs[1].pt = PJ_RTP_PT_PCMA; 
     169    if (*count > 1) { 
     170        codecs[1].type = PJMEDIA_TYPE_AUDIO; 
     171        codecs[1].pt = PJMEDIA_RTP_PT_PCMA; 
    170172        codecs[1].encoding_name = pj_str("PCMA"); 
    171173        codecs[1].sample_rate = 8000; 
    172174    } 
    173175 
    174     return 2; 
    175 } 
    176  
    177 static pj_codec *g711_alloc_codec( pj_codec_factory *factory, const pj_codec_id *id) 
     176    if (*count > 0) *count=1; 
     177    if (*count > 1) *count=2; 
     178 
     179    return PJ_SUCCESS; 
     180} 
     181 
     182static pj_status_t g711_alloc_codec( pjmedia_codec_factory *factory,  
     183                                     const pjmedia_codec_info *id, 
     184                                     pjmedia_codec **p_codec) 
    178185{ 
    179186    struct g711_factory_private *priv = factory->factory_data; 
    180     pj_codec *codec = NULL; 
     187    pjmedia_codec *codec = NULL; 
    181188 
    182189    /* Allocate new codec if no more is available */ 
     
    184191        struct g711_private *codec_priv; 
    185192 
    186         codec = pj_pool_alloc(priv->pool, sizeof(pj_codec)); 
     193        codec = pj_pool_alloc(priv->pool, sizeof(pjmedia_codec)); 
    187194        codec_priv = pj_pool_alloc(priv->pool, sizeof(struct g711_private)); 
    188195        if (!codec || !codec_priv) 
    189             return NULL; 
     196            return PJ_ENOMEM; 
    190197 
    191198        codec_priv->pt = id->pt; 
     
    202209    codec->next = codec->prev = NULL; 
    203210 
    204     return codec; 
    205 } 
    206  
    207 static void g711_dealloc_codec( pj_codec_factory *factory, pj_codec *codec ) 
     211    *p_codec = codec; 
     212    return PJ_SUCCESS; 
     213} 
     214 
     215static pj_status_t g711_dealloc_codec( pjmedia_codec_factory *factory, pjmedia_codec *codec ) 
    208216{ 
    209217    struct g711_factory_private *priv = factory->factory_data; 
     
    212220    pj_assert (codec->next==NULL && codec->prev==NULL); 
    213221    if (codec->next!=NULL || codec->prev!=NULL) { 
    214         return; 
     222        return PJ_EINVALIDOP; 
    215223    } 
    216224 
    217225    /* Insert at the back of the list */ 
    218226    pj_list_insert_before(&priv->codec_list, codec); 
    219 } 
    220  
    221 static pj_status_t g711_codec_default_attr  (pj_codec *codec, pj_codec_attr *attr) 
     227 
     228    return PJ_SUCCESS; 
     229} 
     230 
     231static pj_status_t g711_codec_default_attr  (pjmedia_codec *codec, pjmedia_codec_param *attr) 
    222232{ 
    223233    struct g711_private *priv = codec->codec_data; 
    224     pj_codec_id id; 
     234    pjmedia_codec_info id; 
    225235 
    226236    id.pt = priv->pt; 
     
    228238} 
    229239 
    230 static pj_status_t g711_init( pj_codec *codec, pj_pool_t *pool ) 
     240static pj_status_t g711_init( pjmedia_codec *codec, pj_pool_t *pool ) 
    231241{ 
    232242    /* There's nothing to do here really */ 
     
    237247} 
    238248 
    239 static pj_status_t g711_open( pj_codec *codec, pj_codec_attr *attr ) 
     249static pj_status_t g711_open( pjmedia_codec *codec, pjmedia_codec_param *attr ) 
    240250{ 
    241251    struct g711_private *priv = codec->codec_data; 
     
    244254} 
    245255 
    246 static pj_status_t g711_close( pj_codec *codec ) 
     256static pj_status_t g711_close( pjmedia_codec *codec ) 
    247257{ 
    248258    PJ_UNUSED_ARG(codec); 
     
    251261} 
    252262 
    253 static pj_status_t  g711_encode( pj_codec *codec, const struct pj_audio_frame *input, 
    254                                  unsigned output_buf_len, struct pj_audio_frame *output) 
     263static pj_status_t  g711_encode( pjmedia_codec *codec, const struct pjmedia_frame *input, 
     264                                 unsigned output_buf_len, struct pjmedia_frame *output) 
    255265{ 
    256266    pj_int16_t *samples = (pj_int16_t*) input->buf; 
     
    262272 
    263273    /* Encode */ 
    264     if (priv->pt == PJ_RTP_PT_PCMA) { 
     274    if (priv->pt == PJMEDIA_RTP_PT_PCMA) { 
    265275        unsigned i; 
    266276        pj_uint8_t *dst = output->buf; 
     
    269279            *dst = linear2alaw(samples[i]); 
    270280        } 
    271     } else if (priv->pt == PJ_RTP_PT_PCMU) { 
     281    } else if (priv->pt == PJMEDIA_RTP_PT_PCMU) { 
    272282        unsigned i; 
    273283        pj_uint8_t *dst = output->buf; 
     
    281291    } 
    282292 
    283     output->type = PJ_AUDIO_FRAME_AUDIO; 
     293    output->type = PJMEDIA_FRAME_TYPE_AUDIO; 
    284294    output->size = input->size / 2; 
    285295 
     
    287297} 
    288298 
    289 static pj_status_t  g711_decode( pj_codec *codec, const struct pj_audio_frame *input, 
    290                                  unsigned output_buf_len, struct pj_audio_frame *output) 
     299static pj_status_t  g711_decode( pjmedia_codec *codec, const struct pjmedia_frame *input, 
     300                                 unsigned output_buf_len, struct pjmedia_frame *output) 
    291301{ 
    292302    struct g711_private *priv = codec->codec_data; 
     
    297307 
    298308    /* Decode */ 
    299     if (priv->pt == PJ_RTP_PT_PCMA) { 
     309    if (priv->pt == PJMEDIA_RTP_PT_PCMA) { 
    300310        unsigned i; 
    301311        pj_uint8_t *src = input->buf; 
     
    305315            *dst++ = (pj_uint16_t) alaw2linear(*src++); 
    306316        } 
    307     } else if (priv->pt == PJ_RTP_PT_PCMU) { 
     317    } else if (priv->pt == PJMEDIA_RTP_PT_PCMU) { 
    308318        unsigned i; 
    309319        pj_uint8_t *src = input->buf; 
     
    318328    } 
    319329 
    320     output->type = PJ_AUDIO_FRAME_AUDIO; 
     330    output->type = PJMEDIA_FRAME_TYPE_AUDIO; 
    321331    output->size = input->size * 2; 
    322332 
  • pjproject/trunk/pjmedia/src/pjmedia/rtcp.c

    r121 r159  
    9393    /* Update sequence numbers (received, lost, etc). */ 
    9494    status = pj_rtp_seq_update(&s->seq_ctrl, seq); 
    95     if (status == PJ_RTP_ERR_SESSION_RESTARTED) { 
     95    if (status == PJMEDIA_RTP_ERR_SESSION_RESTARTED) { 
    9696        rtcp_init_seq(s, seq); 
    9797        status = 0; 
  • pjproject/trunk/pjmedia/src/pjmedia/rtp.c

    r121 r159  
    4444    if (sizeof(struct pj_rtp_hdr) != 12) { 
    4545        pj_assert(!"Wrong RTP header packing!"); 
    46         return PJ_RTP_ERR_RTP_PACKING; 
     46        return PJMEDIA_RTP_ERR_RTP_PACKING; 
    4747    } 
    4848 
     
    129129    if ((*hdr)->v != RTP_VERSION) { 
    130130        PJ_LOG(4, (THIS_FILE, "  invalid RTP version!")); 
    131         return PJ_RTP_ERR_INVALID_VERSION; 
     131        return PJMEDIA_RTP_ERR_INVALID_VERSION; 
    132132    } 
    133133 
     
    143143    /* Check that offset is less than packet size */ 
    144144    if (offset >= pkt_len) 
    145         return PJ_RTP_ERR_INVALID_PACKET; 
     145        return PJMEDIA_RTP_ERR_INVALID_PACKET; 
    146146 
    147147    /* Find and set payload. */ 
     
    163163        PJ_LOG(4, (THIS_FILE, "pj_rtp_session_update: ses=%p, invalid ssrc 0x%p (!=0x%p)", 
    164164                   ses, pj_ntohl(hdr->ssrc), ses->peer_ssrc)); 
    165         return PJ_RTP_ERR_INVALID_SSRC; 
     165        return PJMEDIA_RTP_ERR_INVALID_SSRC; 
    166166    } 
    167167    */ 
     
    171171        PJ_LOG(4, (THIS_FILE, "pj_rtp_session_update: ses=%p, invalid payload type %d (!=%d)", 
    172172                   ses, hdr->pt, ses->out_pt)); 
    173         return PJ_RTP_ERR_INVALID_PT; 
     173        return PJMEDIA_RTP_ERR_INVALID_PT; 
    174174    } 
    175175 
     
    180180    /* Check sequence number to see if remote session has been restarted. */ 
    181181    status = pj_rtp_seq_update( &ses->seq_ctrl, pj_ntohs(hdr->seq)); 
    182     if (status == PJ_RTP_ERR_SESSION_RESTARTED) { 
     182    if (status == PJMEDIA_RTP_ERR_SESSION_RESTARTED) { 
    183183        pj_rtp_seq_restart( &ses->seq_ctrl, pj_ntohs(hdr->seq)); 
    184184        ++ses->received; 
    185     } else if (status == 0 || status == PJ_RTP_ERR_SESSION_PROBATION) { 
     185    } else if (status == 0 || status == PJMEDIA_RTP_ERR_SESSION_PROBATION) { 
    186186        ++ses->received; 
    187187    } 
     
    224224            sctrl->max_seq = seq; 
    225225            if (sctrl->probation == 0) { 
    226                 return PJ_RTP_ERR_SESSION_RESTARTED; 
     226                return PJMEDIA_RTP_ERR_SESSION_RESTARTED; 
    227227            } 
    228228        } else { 
     
    230230            sctrl->max_seq = seq; 
    231231        } 
    232         return PJ_RTP_ERR_SESSION_PROBATION; 
     232        return PJMEDIA_RTP_ERR_SESSION_PROBATION; 
    233233 
    234234    } else if (udelta < MAX_DROPOUT) { 
     
    248248             * (i.e., pretend this was the first packet). 
    249249             */ 
    250             return PJ_RTP_ERR_SESSION_RESTARTED; 
     250            return PJMEDIA_RTP_ERR_SESSION_RESTARTED; 
    251251        } 
    252252        else { 
    253253            sctrl->bad_seq = (seq + 1) & (RTP_SEQ_MOD-1); 
    254             return PJ_RTP_ERR_BAD_SEQUENCE; 
     254            return PJMEDIA_RTP_ERR_BAD_SEQUENCE; 
    255255        } 
    256256    } else { 
  • pjproject/trunk/pjmedia/src/pjmedia/session.c

    r121 r159  
    1818 */ 
    1919#include <pjmedia/session.h> 
     20#include <pjmedia/errno.h> 
    2021#include <pj/log.h> 
    2122#include <pj/os.h>  
     
    2324#include <pj/string.h> 
    2425#include <pj/assert.h> 
    25  
    26  
    27 typedef struct pj_media_stream_desc 
    28 { 
    29     pj_media_stream_info    info; 
    30     pj_media_stream_t      *enc_stream, *dec_stream; 
    31 } pj_media_stream_desc; 
    32  
    33 struct pj_media_session_t 
     26#include <pj/ctype.h> 
     27 
     28 
     29struct pjmedia_session 
    3430{ 
    3531    pj_pool_t              *pool; 
    36     pj_med_mgr_t           *mediamgr; 
     32    pjmedia_endpt          *endpt; 
    3733    unsigned                stream_cnt; 
    38     pj_media_stream_desc   *stream_desc[PJSDP_MAX_MEDIA]; 
     34    pjmedia_stream_info     stream_info[PJSDP_MAX_MEDIA]; 
     35    pjmedia_stream         *stream[PJSDP_MAX_MEDIA]; 
    3936}; 
    4037 
    4138#define THIS_FILE               "session.c" 
    4239 
    43 #define PJ_MEDIA_SESSION_SIZE   (48*1024) 
    44 #define PJ_MEDIA_SESSION_INC    1024 
     40#define PJMEDIA_SESSION_SIZE    (48*1024) 
     41#define PJMEDIA_SESSION_INC     1024 
    4542 
    4643static const pj_str_t ID_AUDIO = { "audio", 5}; 
     
    5047static const pj_str_t ID_RTP_AVP = { "RTP/AVP", 7 }; 
    5148static const pj_str_t ID_SDP_NAME = { "pjmedia", 7 }; 
    52  
    53 static void session_init (pj_media_session_t *ses) 
    54 { 
    55     pj_memset (ses, 0, sizeof(pj_media_session_t)); 
    56 } 
    57  
    58  
    59 /** 
    60  * Create new session offering. 
    61  */ 
    62 PJ_DEF(pj_media_session_t*)  
    63 pj_media_session_create (pj_med_mgr_t *mgr, const pj_media_sock_info *sock_info) 
    64 { 
    65     pj_pool_factory *pf; 
     49static const pj_str_t ID_RTPMAP = { "rtpmap", 6 }; 
     50 
     51static const pj_str_t STR_INACTIVE = { "inactive", 8 }; 
     52static const pj_str_t STR_SENDRECV = { "sendrecv", 8 }; 
     53static const pj_str_t STR_SENDONLY = { "sendonly", 8 }; 
     54static const pj_str_t STR_RECVONLY = { "recvonly", 8 }; 
     55 
     56 
     57/* 
     58 * Create stream info from SDP media line. 
     59 */ 
     60static pj_status_t create_stream_info_from_sdp(pj_pool_t *pool, 
     61                                               pjmedia_stream_info *si, 
     62                                               const pjmedia_sdp_conn *local_conn, 
     63                                               const pjmedia_sdp_conn *rem_conn, 
     64                                               const pjmedia_sdp_media *local_m, 
     65                                               const pjmedia_sdp_media *rem_m) 
     66{ 
     67    const pjmedia_sdp_attr *attr; 
     68    pjmedia_sdp_rtpmap *rtpmap; 
     69    pj_status_t status; 
     70 
     71 
     72    /* Validate arguments: */ 
     73 
     74    PJ_ASSERT_RETURN(pool && si && local_conn && rem_conn && 
     75                     local_m && rem_m, PJ_EINVAL); 
     76 
     77    /* Reset: */ 
     78 
     79    pj_memset(si, 0, sizeof(*si)); 
     80 
     81    /* Media type: */ 
     82 
     83    if (pj_stricmp(&local_m->desc.media, &ID_AUDIO) == 0) { 
     84 
     85        si->type = PJMEDIA_TYPE_AUDIO; 
     86 
     87    } else if (pj_stricmp(&local_m->desc.media, &ID_VIDEO) == 0) { 
     88 
     89        si->type = PJMEDIA_TYPE_VIDEO; 
     90 
     91    } else { 
     92 
     93        si->type = PJMEDIA_TYPE_UNKNOWN; 
     94 
     95    } 
     96 
     97    /* Media direction: */ 
     98 
     99    if (local_m->desc.port == 0 ||  
     100        pj_inet_addr(&local_conn->addr).s_addr==0 || 
     101        pj_inet_addr(&rem_conn->addr).s_addr==0 || 
     102        pjmedia_sdp_media_find_attr(local_m, &STR_INACTIVE, NULL)!=NULL) 
     103    { 
     104        /* Inactive stream. */ 
     105 
     106        si->dir = PJMEDIA_DIR_NONE; 
     107 
     108    } else if (pjmedia_sdp_media_find_attr(local_m, &STR_SENDONLY, NULL)!=NULL) { 
     109 
     110        /* Send only stream. */ 
     111 
     112        si->dir = PJMEDIA_DIR_ENCODING; 
     113 
     114    } else if (pjmedia_sdp_media_find_attr(local_m, &STR_RECVONLY, NULL)!=NULL) { 
     115 
     116        /* Recv only stream. */ 
     117 
     118        si->dir = PJMEDIA_DIR_DECODING; 
     119 
     120    } else { 
     121 
     122        /* Send and receive stream. */ 
     123 
     124        si->dir = PJMEDIA_DIR_ENCODING_DECODING; 
     125 
     126    } 
     127 
     128 
     129    /* Set remote address: */ 
     130 
     131    si->rem_addr.sin_family = PJ_AF_INET; 
     132    si->rem_addr.sin_port = pj_htons(rem_m->desc.port); 
     133    if (pj_inet_aton(&rem_conn->addr, &si->rem_addr.sin_addr) == 0) { 
     134 
     135        /* Invalid IP address. */ 
     136        return PJMEDIA_EINVALIDIP; 
     137    } 
     138 
     139    /* For this version of PJMEDIA, send and receive media must use 
     140     * the same codec. 
     141     */ 
     142    if (pj_strcmp(&local_m->desc.fmt[0], &rem_m->desc.fmt[0]) != 0) 
     143        return PJMEDIA_EASYMCODEC; 
     144 
     145 
     146    /* And codec must be numeric! */ 
     147    if (!pj_isdigit(*local_m->desc.fmt[0].ptr)) 
     148        return PJMEDIA_EINVALIDPT; 
     149 
     150    /* Find rtpmap for the first codec.  
     151     * For this version of PJMEDIA, we do not support static payload 
     152     * type without rtpmap. 
     153     */ 
     154    attr = pjmedia_sdp_media_find_attr(local_m, &ID_RTPMAP, NULL); 
     155    if (attr == NULL) 
     156        return PJMEDIA_EMISSINGRTPMAP; 
     157 
     158    status = pjmedia_sdp_attr_to_rtpmap(pool, attr, &rtpmap); 
     159    if (status != PJ_SUCCESS) 
     160        return status; 
     161 
     162    /* Build codec format info: */ 
     163 
     164    si->fmt.type = si->type; 
     165    si->fmt.pt = pj_strtoul(&local_m->desc.fmt[0]); 
     166    pj_strdup(pool, &si->fmt.encoding_name, &rtpmap->enc_name); 
     167    si->fmt.sample_rate = rtpmap->clock_rate; 
     168 
     169    /* Leave SSRC to zero. */ 
     170 
     171    /* Leave jitter buffer parameter. */ 
     172     
     173    return PJ_SUCCESS; 
     174} 
     175 
     176 
     177/** 
     178 * Create new session. 
     179 */ 
     180PJ_DEF(pj_status_t) pjmedia_session_create( pjmedia_endpt *endpt,  
     181                                            unsigned stream_cnt, 
     182                                            const pjmedia_sock_info skinfo[], 
     183                                            const pjmedia_sdp_session *local_sdp, 
     184                                            const pjmedia_sdp_session *rem_sdp, 
     185                                            pjmedia_session **p_session ) 
     186{ 
    66187    pj_pool_t *pool; 
    67     pj_media_session_t *session; 
    68     pj_media_stream_desc *sd; 
    69     unsigned i, codec_cnt; 
    70     pj_codec_mgr *cm; 
    71     const pj_codec_id *codecs[PJSDP_MAX_FMT]; 
    72  
    73     pf = pj_med_mgr_get_pool_factory(mgr); 
    74  
    75     pool = pj_pool_create( pf, "session", PJ_MEDIA_SESSION_SIZE, PJ_MEDIA_SESSION_INC, NULL); 
    76     if (!pool) 
    77         return NULL; 
    78  
    79     session = pj_pool_alloc(pool, sizeof(pj_media_session_t)); 
    80     if (!session) 
    81         return NULL; 
    82  
    83     session_init (session); 
    84  
     188    pjmedia_session *session; 
     189    int i; /* Must be signed */ 
     190    pj_status_t status; 
     191 
     192    /* Verify arguments. */ 
     193    PJ_ASSERT_RETURN(endpt && stream_cnt && skinfo && 
     194                     local_sdp && rem_sdp && p_session, PJ_EINVAL); 
     195 
     196    /* Create pool for the session. */ 
     197    pool = pjmedia_endpt_create_pool( endpt, "session",  
     198                                      PJMEDIA_SESSION_SIZE,  
     199                                      PJMEDIA_SESSION_INC); 
     200    PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM); 
     201 
     202    session = pj_pool_zalloc(pool, sizeof(pjmedia_session)); 
    85203    session->pool = pool; 
    86     session->mediamgr = mgr; 
    87  
    88     /* Create first stream  */ 
    89     sd = pj_pool_calloc (pool, 1, sizeof(pj_media_stream_desc)); 
    90     if (!sd) 
    91         return NULL; 
    92  
    93     sd->info.type = ID_AUDIO; 
    94     sd->info.dir = PJ_MEDIA_DIR_ENCODING_DECODING; 
    95     sd->info.transport = ID_RTP_AVP; 
    96     pj_memcpy(&sd->info.sock_info, sock_info, sizeof(*sock_info)); 
    97  
    98     /* Enum audio codecs. */ 
    99     sd->info.fmt_cnt = 0; 
    100     cm = pj_med_mgr_get_codec_mgr (mgr); 
    101     codec_cnt = pj_codec_mgr_enum_codecs(cm, PJSDP_MAX_FMT, codecs); 
    102     if (codec_cnt > PJSDP_MAX_FMT) codec_cnt = PJSDP_MAX_FMT; 
    103     for (i=0; i<codec_cnt; ++i) { 
    104         if (codecs[i]->type != PJ_MEDIA_TYPE_AUDIO) 
    105             continue; 
    106  
    107         sd->info.fmt[sd->info.fmt_cnt].pt = codecs[i]->pt; 
    108         sd->info.fmt[sd->info.fmt_cnt].sample_rate = codecs[i]->sample_rate; 
    109         pj_strdup (pool, &sd->info.fmt[sd->info.fmt_cnt].encoding_name, &codecs[i]->encoding_name); 
    110         ++sd->info.fmt_cnt; 
    111     } 
    112  
    113     session->stream_desc[session->stream_cnt++] = sd; 
    114  
    115     return session; 
    116 } 
    117  
    118 static int sdp_check (const pjsdp_session_desc *sdp) 
    119 { 
    120     int has_conn = 0; 
     204    session->endpt = endpt; 
     205    session->stream_cnt = stream_cnt; 
     206     
     207    /* Stream count is the lower number of stream_cnt or SDP m= lines count */ 
     208    if (stream_cnt < local_sdp->media_count) 
     209        stream_cnt = local_sdp->media_count; 
     210 
     211    /*  
     212     * Create streams:  
     213     */ 
     214    for (i=0; i<(int)stream_cnt; ++i) { 
     215 
     216        pjmedia_stream_info *si = &session->stream_info[i]; 
     217        const pjmedia_sdp_media *local_m = local_sdp->media[i]; 
     218        const pjmedia_sdp_media *rem_m = rem_sdp->media[i]; 
     219        pjmedia_sdp_conn *local_conn, *rem_conn; 
     220 
     221        /* Build stream info based on media line in local SDP */ 
     222        local_conn = local_m->conn ? local_m->conn : local_sdp->conn; 
     223        rem_conn = rem_m->conn ? rem_m->conn : rem_sdp->conn; 
     224 
     225        status = create_stream_info_from_sdp(session->pool, si, 
     226                                             local_conn, rem_conn, 
     227                                             local_m, rem_m); 
     228        if (status != PJ_SUCCESS) 
     229            return status; 
     230 
     231        /* Assign sockinfo */ 
     232        si->sock_info = skinfo[i]; 
     233    } 
     234 
     235    /* 
     236     * Now create the stream! 
     237     */ 
     238    for (i=0; i<(int)stream_cnt; ++i) { 
     239 
     240        status = pjmedia_stream_create(endpt, session->pool, 
     241                                       &session->stream_info[i], 
     242                                       &session->stream[i]); 
     243        if (status != PJ_SUCCESS) { 
     244 
     245            for ( --i; i>=0; ++i) { 
     246                pjmedia_stream_destroy(session->stream[i]); 
     247            } 
     248 
     249            pj_pool_release(session->pool); 
     250            return status; 
     251        } 
     252    } 
     253 
     254 
     255    /* Done. */ 
     256 
     257    *p_session = session; 
     258    return PJ_SUCCESS; 
     259} 
     260 
     261 
     262/** 
     263 * Destroy media session. 
     264 */ 
     265PJ_DEF(pj_status_t) pjmedia_session_destroy (pjmedia_session *session) 
     266{ 
    121267    unsigned i; 
    122268 
    123     if (sdp->conn) 
    124         has_conn = 1; 
    125  
    126     if (sdp->media_count == 0) { 
    127         PJ_LOG(4,(THIS_FILE, "SDP check failed: no media stream definition")); 
    128         return -1; 
    129     } 
    130  
    131     for (i=0; i<sdp->media_count; ++i) { 
    132         pjsdp_media_desc *m = sdp->media[i]; 
    133  
    134         if (!m) { 
    135             pj_assert(0); 
    136             return -1; 
    137         } 
    138  
    139         if (m->desc.fmt_count == 0) { 
    140             PJ_LOG(4,(THIS_FILE, "SDP check failed: no format listed in media stream")); 
    141             return -1; 
    142         } 
    143  
    144         if (!has_conn && m->conn == NULL) { 
    145             PJ_LOG(4,(THIS_FILE, "SDP check failed: no connection information for media")); 
    146             return -1; 
    147         } 
    148     } 
    149  
    150     return 0; 
    151 } 
    152  
    153 /* 
    154  * Create local stream definition that matches SDP received from peer. 
    155  */ 
    156 static pj_media_stream_desc*  
    157 create_stream_from_sdp (pj_pool_t *pool, pj_med_mgr_t *mgr, const pjsdp_conn_info *conn, 
    158                         const pjsdp_media_desc *m, const pj_media_sock_info *sock_info) 
    159 { 
    160     pj_media_stream_desc *sd; 
    161  
    162     sd = pj_pool_calloc (pool, 1, sizeof(pj_media_stream_desc)); 
    163     if (!sd) { 
    164         PJ_LOG(2,(THIS_FILE, "No memory to allocate stream descriptor")); 
    165         return NULL; 
    166     } 
    167  
    168     if (pj_stricmp(&conn->net_type, &ID_IN)==0 &&  
    169         pj_stricmp(&conn->addr_type, &ID_IP4)==0 && 
    170         pj_stricmp(&m->desc.media, &ID_AUDIO)==0 && 
    171         pj_stricmp(&m->desc.transport, &ID_RTP_AVP) == 0)  
    172     { 
    173         /* 
    174          * Got audio stream. 
    175          */ 
    176         unsigned i, codec_cnt; 
    177         pj_codec_mgr *cm; 
    178         const pj_codec_id *codecs[PJSDP_MAX_FMT]; 
    179  
    180         sd->info.type = ID_AUDIO; 
    181         sd->info.transport = ID_RTP_AVP; 
    182         pj_memcpy(&sd->info.sock_info, sock_info, sizeof(*sock_info)); 
    183         sd->info.rem_port = m->desc.port; 
    184         pj_strdup (pool, &sd->info.rem_addr, &conn->addr); 
    185  
    186         /* Enum audio codecs. */ 
    187         sd->info.fmt_cnt = 0; 
    188         cm = pj_med_mgr_get_codec_mgr (mgr); 
    189         codec_cnt = pj_codec_mgr_enum_codecs (cm, PJSDP_MAX_FMT, codecs); 
    190         if (codec_cnt > PJSDP_MAX_FMT) codec_cnt = PJSDP_MAX_FMT; 
    191  
    192         /* Find just one codec which we can support. */ 
    193         for (i=0; i<m->desc.fmt_count && sd->info.fmt_cnt == 0; ++i) { 
    194             unsigned j, fmt_i; 
    195  
    196             /* For static payload, just match payload type. */ 
    197             /* Else match clock rate and encoding name. */ 
    198             fmt_i = pj_strtoul(&m->desc.fmt[i]); 
    199             if (fmt_i < PJ_RTP_PT_DYNAMIC) { 
    200                 for (j=0; j<codec_cnt; ++j) { 
    201                     if (codecs[j]->pt == fmt_i) { 
    202                         sd->info.fmt_cnt = 1; 
    203                         sd->info.fmt[0].type = PJ_MEDIA_TYPE_AUDIO; 
    204                         sd->info.fmt[0].pt = codecs[j]->pt; 
    205                         sd->info.fmt[0].sample_rate = codecs[j]->sample_rate; 
    206                         pj_strdup (pool, &sd->info.fmt[0].encoding_name, &codecs[j]->encoding_name); 
    207                         break; 
    208                     } 
    209                 } 
    210             } else { 
    211  
    212                 /* Find the rtpmap for the payload type. */ 
    213                 const pjsdp_rtpmap_attr *rtpmap = pjsdp_media_desc_find_rtpmap (m, fmt_i); 
    214  
    215                 /* Don't accept the media if no rtpmap for dynamic PT. */ 
    216                 if (rtpmap == NULL) { 
    217                     PJ_LOG(4,(THIS_FILE, "SDP: No rtpmap found for payload id %d", m->desc.fmt[i])); 
    218                     continue; 
    219                 } 
    220  
    221                 /* Check whether we can take this codec. */ 
    222                 for (j=0; j<codec_cnt; ++j) { 
    223                     if (rtpmap->clock_rate == codecs[j]->sample_rate &&  
    224                         pj_stricmp(&rtpmap->encoding_name, &codecs[j]->encoding_name) == 0) 
    225                     { 
    226                         sd->info.fmt_cnt = 1; 
    227                         sd->info.fmt[0].type = PJ_MEDIA_TYPE_AUDIO; 
    228                         sd->info.fmt[0].pt = codecs[j]->pt; 
    229                         sd->info.fmt[0].sample_rate = codecs[j]->sample_rate; 
    230                         sd->info.fmt[0].encoding_name = codecs[j]->encoding_name; 
    231                         break; 
    232                     } 
    233                 } 
    234             } 
    235         } 
    236  
    237         /* Match codec and direction. */ 
    238         if (sd->info.fmt_cnt == 0 || m->desc.port == 0 ||  
    239             pjsdp_media_desc_has_attr(m, PJSDP_ATTR_INACTIVE))  
    240         { 
    241             sd->info.dir = PJ_MEDIA_DIR_NONE; 
    242         } 
    243         else if (pjsdp_media_desc_has_attr(m, PJSDP_ATTR_RECV_ONLY)) { 
    244             sd->info.dir = PJ_MEDIA_DIR_ENCODING; 
    245         } 
    246         else if (pjsdp_media_desc_has_attr(m, PJSDP_ATTR_SEND_ONLY)) { 
    247             sd->info.dir = PJ_MEDIA_DIR_DECODING; 
    248         } 
    249         else { 
    250             sd->info.dir = PJ_MEDIA_DIR_ENCODING_DECODING; 
    251         } 
    252  
    253     } else { 
    254         /* Unsupported media stream. */ 
    255         unsigned fmt_num; 
    256         const pjsdp_rtpmap_attr *rtpmap = NULL; 
    257  
    258         pj_strdup(pool, &sd->info.type, &m->desc.media); 
    259         pj_strdup(pool, &sd->info.transport, &m->desc.transport); 
    260         pj_memset(&sd->info.sock_info, 0, sizeof(*sock_info)); 
    261         pj_strdup (pool, &sd->info.rem_addr, &conn->addr); 
    262         sd->info.rem_port = m->desc.port; 
    263  
    264         /* Just put one format and rtpmap, so that we don't have to make  
    265          * special exception when we convert this stream to SDP. 
    266          */ 
    267  
    268         /* Find the rtpmap for the payload type. */ 
    269         fmt_num = pj_strtoul(&m->desc.fmt[0]); 
    270         rtpmap = pjsdp_media_desc_find_rtpmap (m, fmt_num); 
    271  
    272         sd->info.fmt_cnt = 1; 
    273         if (pj_stricmp(&m->desc.media, &ID_VIDEO)==0) { 
    274             sd->info.fmt[0].type = PJ_MEDIA_TYPE_VIDEO; 
    275             sd->info.fmt[0].pt = fmt_num; 
    276             if (rtpmap) { 
    277                 pj_strdup (pool, &sd->info.fmt[0].encoding_name,  
    278                            &rtpmap->encoding_name); 
    279                 sd->info.fmt[0].sample_rate = rtpmap->clock_rate; 
    280             } 
    281         } else { 
    282             sd->info.fmt[0].type = PJ_MEDIA_TYPE_UNKNOWN; 
    283             pj_strdup(pool, &sd->info.fmt[0].encoding_name, &m->desc.fmt[0]); 
    284         } 
     269    PJ_ASSERT_RETURN(session, PJ_EINVAL); 
     270 
     271    for (i=0; i<session->stream_cnt; ++i) { 
    285272         
    286         sd->info.dir = PJ_MEDIA_DIR_NONE; 
    287     } 
    288  
    289     return sd; 
    290 } 
    291  
    292 /** 
    293  * Create new session based on peer's offering. 
    294  */ 
    295 PJ_DEF(pj_media_session_t*)  
    296 pj_media_session_create_from_sdp (pj_med_mgr_t *mgr, const pjsdp_session_desc *sdp, 
    297                                   const pj_media_sock_info *sock_info) 
    298 { 
    299     pj_pool_factory *pf; 
    300     pj_pool_t *pool; 
    301     pj_media_session_t *session; 
     273        pjmedia_stream_destroy(session->stream[i]); 
     274 
     275    } 
     276 
     277    pj_pool_release (session->pool); 
     278 
     279    return PJ_SUCCESS; 
     280} 
     281 
     282 
     283/** 
     284 * Activate all stream in media session. 
     285 * 
     286 */ 
     287PJ_DEF(pj_status_t) pjmedia_session_resume(pjmedia_session *session, 
     288                                           pjmedia_dir dir) 
     289{ 
    302290    unsigned i; 
    303291 
    304     if (sdp_check(sdp) != 0) 
    305         return NULL; 
    306  
    307     pf = pj_med_mgr_get_pool_factory(mgr); 
    308     pool = pj_pool_create( pf, "session", PJ_MEDIA_SESSION_SIZE, PJ_MEDIA_SESSION_INC, NULL); 
    309     if (!pool) 
    310         return NULL; 
    311  
    312     session = pj_pool_alloc(pool, sizeof(pj_media_session_t)); 
    313     if (!session) { 
    314         PJ_LOG(3,(THIS_FILE, "No memory to create media session descriptor")); 
    315         pj_pool_release (pool); 
    316         return NULL; 
    317     } 
    318  
    319     session_init (session); 
    320  
    321     session->pool = pool; 
    322     session->mediamgr = mgr; 
    323  
    324     /* Enumerate each media stream and create our peer. */ 
    325     for (i=0; i<sdp->media_count; ++i) { 
    326         const pjsdp_conn_info *conn; 
    327         const pjsdp_media_desc *m; 
    328         pj_media_stream_desc *sd; 
    329  
    330         m = sdp->media[i]; 
    331         conn = m->conn ? m->conn : sdp->conn; 
    332  
    333         /* 
    334          * Bug: 
    335          *  the sock_info below is used by more than one 'm' lines 
    336          */ 
    337         PJ_TODO(SUPPORT_MORE_THAN_ONE_SDP_M_LINES) 
    338  
    339         sd = create_stream_from_sdp (pool, mgr, conn, m, sock_info); 
    340         pj_assert (sd); 
    341  
    342         session->stream_desc[session->stream_cnt++] = sd; 
    343     } 
    344  
    345     return session; 
    346 } 
    347  
    348 /** 
    349  * Duplicate session. The new session is inactive. 
    350  */ 
    351 PJ_DEF(pj_media_session_t*) 
    352 pj_media_session_clone (const pj_media_session_t *rhs) 
    353 { 
    354     pj_pool_factory *pf; 
    355     pj_pool_t *pool; 
    356     pj_media_session_t *session; 
     292    PJ_ASSERT_RETURN(session, PJ_EINVAL); 
     293 
     294    for (i=0; i<session->stream_cnt; ++i) { 
     295        pjmedia_session_resume_stream(session, i, dir); 
     296    } 
     297 
     298    return PJ_SUCCESS; 
     299} 
     300 
     301 
     302/** 
     303 * Suspend receipt and transmission of all stream in media session. 
     304 * 
     305 */ 
     306PJ_DEF(pj_status_t) pjmedia_session_pause(pjmedia_session *session, 
     307                                          pjmedia_dir dir) 
     308{ 
    357309    unsigned i; 
    358310 
    359     pf = pj_med_mgr_get_pool_factory(rhs->mediamgr); 
    360     pool = pj_pool_create( pf, "session", PJ_MEDIA_SESSION_SIZE, PJ_MEDIA_SESSION_INC, NULL); 
    361     if (!pool) { 
    362         return NULL; 
    363     } 
    364  
    365     session = pj_pool_alloc (pool, sizeof(*session)); 
    366     if (!session) { 
    367         PJ_LOG(3,(THIS_FILE, "No memory to create media session descriptor")); 
    368         pj_pool_release (pool); 
    369         return NULL; 
    370     } 
    371  
    372     session->pool = pool; 
    373     session->mediamgr = rhs->mediamgr; 
    374     session->stream_cnt = rhs->stream_cnt; 
    375  
    376     for (i=0; i<rhs->stream_cnt; ++i) { 
    377         pj_media_stream_desc *sd1 = pj_pool_alloc (session->pool, sizeof(pj_media_stream_desc)); 
    378         const pj_media_stream_desc *sd2 = rhs->stream_desc[i]; 
    379  
    380         if (!sd1) { 
    381             PJ_LOG(3,(THIS_FILE, "No memory to create media stream descriptor")); 
    382             pj_pool_release (pool); 
    383             return NULL; 
    384         } 
    385  
    386         session->stream_desc[i] = sd1; 
    387         sd1->enc_stream = sd1->dec_stream = NULL; 
    388         pj_strdup (pool, &sd1->info.type, &sd2->info.type); 
    389         sd1->info.dir = sd2->info.dir; 
    390         pj_strdup (pool, &sd1->info.transport, &sd2->info.transport); 
    391         pj_memcpy(&sd1->info.sock_info, &sd2->info.sock_info, sizeof(pj_media_sock_info)); 
    392         pj_strdup (pool, &sd1->info.rem_addr, &sd2->info.rem_addr); 
    393         sd1->info.rem_port = sd2->info.rem_port; 
    394         sd1->info.fmt_cnt = sd2->info.fmt_cnt; 
    395         pj_memcpy (sd1->info.fmt, sd2->info.fmt, sizeof(sd2->info.fmt)); 
    396     } 
    397  
    398     return session; 
    399 } 
    400  
    401 /** 
    402  * Create SDP description from the session. 
    403  */ 
    404 PJ_DEF(pjsdp_session_desc*) 
    405 pj_media_session_create_sdp (const pj_media_session_t *session, pj_pool_t *pool, 
    406                              pj_bool_t only_first_fmt) 
    407 { 
    408     pjsdp_session_desc *sdp; 
    409     pj_time_val tv; 
     311    PJ_ASSERT_RETURN(session, PJ_EINVAL); 
     312 
     313    for (i=0; i<session->stream_cnt; ++i) { 
     314        pjmedia_session_pause_stream(session, i, dir); 
     315    } 
     316 
     317    return PJ_SUCCESS; 
     318} 
     319 
     320 
     321/** 
     322 * Suspend receipt and transmission of individual stream in media session. 
     323 */ 
     324PJ_DEF(pj_status_t) pjmedia_session_pause_stream( pjmedia_session *session, 
     325                                                  unsigned index, 
     326                                                  pjmedia_dir dir) 
     327{ 
     328    PJ_ASSERT_RETURN(session && index < session->stream_cnt, PJ_EINVAL); 
     329 
     330    return pjmedia_stream_pause(session->stream[index], dir); 
     331} 
     332 
     333 
     334/** 
     335 * Activate individual stream in media session. 
     336 * 
     337 */ 
     338PJ_DEF(pj_status_t) pjmedia_session_resume_stream( pjmedia_session *session, 
     339                                                   unsigned index, 
     340                                                   pjmedia_dir dir) 
     341{ 
     342    PJ_ASSERT_RETURN(session && index < session->stream_cnt, PJ_EINVAL); 
     343 
     344    return pjmedia_stream_resume(session->stream[index], dir); 
     345} 
     346 
     347/** 
     348 * Enumerate media stream in the session. 
     349 */ 
     350PJ_DEF(pj_status_t) pjmedia_session_enum_streams(const pjmedia_session *session, 
     351                                                 unsigned *count,  
     352                                                 pjmedia_stream_info info[]) 
     353{ 
    410354    unsigned i; 
    411     pj_media_sock_info *c_addr = NULL; 
    412  
    413     if (session->stream_cnt == 0) { 
    414         pj_assert(0); 
    415         return NULL; 
    416     } 
    417  
    418     sdp = pj_pool_calloc (pool, 1, sizeof(pjsdp_session_desc)); 
    419     if (!sdp) { 
    420         PJ_LOG(3,(THIS_FILE, "No memory to allocate SDP session descriptor")); 
    421         return NULL; 
    422     } 
    423  
    424     pj_gettimeofday(&tv); 
    425  
    426     sdp->origin.user = pj_str("-"); 
    427     sdp->origin.version = sdp->origin.id = tv.sec + 2208988800UL; 
    428     sdp->origin.net_type = ID_IN; 
    429     sdp->origin.addr_type = ID_IP4; 
    430     sdp->origin.addr = *pj_gethostname(); 
    431  
    432     sdp->name = ID_SDP_NAME; 
    433  
    434     /* If all media addresses are the same, then put the connection 
    435      * info in the session level, otherwise put it in media stream 
    436      * level. 
    437      */ 
    438     for (i=0; i<session->stream_cnt; ++i) { 
    439         if (c_addr == NULL) { 
    440             c_addr = &session->stream_desc[i]->info.sock_info; 
    441         } else if (c_addr->rtp_addr_name.sin_addr.s_addr != session->stream_desc[i]->info.sock_info.rtp_addr_name.sin_addr.s_addr) 
    442         { 
    443             c_addr = NULL; 
    444             break; 
    445         } 
    446     } 
    447  
    448     if (c_addr) { 
    449         /* All addresses are the same, put connection info in session level. */ 
    450         sdp->conn = pj_pool_alloc (pool, sizeof(pjsdp_conn_info)); 
    451         if (!sdp->conn) { 
    452             PJ_LOG(2,(THIS_FILE, "No memory to allocate SDP connection info")); 
    453             return NULL; 
    454         } 
    455  
    456         sdp->conn->net_type = ID_IN; 
    457         sdp->conn->addr_type = ID_IP4; 
    458         pj_strdup2 (pool, &sdp->conn->addr, pj_inet_ntoa(c_addr->rtp_addr_name.sin_addr)); 
    459     } 
    460  
    461     sdp->time.start = sdp->time.stop = 0; 
    462     sdp->attr_count = 0; 
    463  
    464     /* Create each media. */ 
    465     sdp->media_count = 0; 
    466     for (i=0; i<session->stream_cnt; ++i) { 
    467         const pj_media_stream_desc *sd = session->stream_desc[i]; 
    468         pjsdp_media_desc *m; 
    469         unsigned j; 
    470         unsigned fmt_cnt; 
    471         pjsdp_attr *attr; 
    472  
    473         m = pj_pool_calloc (pool, 1, sizeof(pjsdp_media_desc)); 
    474         if (!m) { 
    475             PJ_LOG(3,(THIS_FILE, "No memory to allocate SDP media stream descriptor")); 
    476             return NULL; 
    477         } 
    478  
    479         sdp->media[sdp->media_count++] = m; 
    480  
    481         pj_strdup (pool, &m->desc.media, &sd->info.type); 
    482         m->desc.port = pj_ntohs(sd->info.sock_info.rtp_addr_name.sin_port); 
    483         m->desc.port_count = 1; 
    484         pj_strdup (pool, &m->desc.transport, &sd->info.transport); 
    485  
    486         /* Add format and rtpmap for each codec. */ 
    487         m->desc.fmt_count = 0; 
    488         m->attr_count = 0; 
    489         fmt_cnt = sd->info.fmt_cnt; 
    490         if (fmt_cnt > 0 && only_first_fmt) 
    491             fmt_cnt = 1; 
    492         for (j=0; j<fmt_cnt; ++j) { 
    493             pjsdp_rtpmap_attr *rtpmap; 
    494             pj_str_t *fmt = &m->desc.fmt[m->desc.fmt_count++]; 
    495  
    496             if (sd->info.fmt[j].type==PJ_MEDIA_TYPE_UNKNOWN) { 
    497                 pj_strdup(pool, fmt, &sd->info.fmt[j].encoding_name); 
    498             } else { 
    499                 fmt->ptr = pj_pool_alloc(pool, 8); 
    500                 fmt->slen = pj_utoa(sd->info.fmt[j].pt, fmt->ptr); 
    501  
    502                 rtpmap = pj_pool_calloc(pool, 1, sizeof(pjsdp_rtpmap_attr)); 
    503                 if (rtpmap) { 
    504                     m->attr[m->attr_count++] = (pjsdp_attr*)rtpmap; 
    505                     rtpmap->type = PJSDP_ATTR_RTPMAP; 
    506                     rtpmap->payload_type = sd->info.fmt[j].pt; 
    507                     rtpmap->clock_rate = sd->info.fmt[j].sample_rate; 
    508                     pj_strdup (pool, &rtpmap->encoding_name, &sd->info.fmt[j].encoding_name); 
    509                 } else { 
    510                     PJ_LOG(3,(THIS_FILE, "No memory to allocate SDP rtpmap descriptor")); 
    511                 } 
    512             } 
    513         } 
    514  
    515         /* If we don't have connection info in session level, create one. */ 
    516         if (sdp->conn == NULL) { 
    517             m->conn = pj_pool_alloc (pool, sizeof(pjsdp_conn_info)); 
    518             if (m->conn) { 
    519                 m->conn->net_type = ID_IN; 
    520                 m->conn->addr_type = ID_IP4; 
    521                 pj_strdup2 (pool, &m->conn->addr, pj_inet_ntoa(sd->info.sock_info.rtp_addr_name.sin_addr)); 
    522             } else { 
    523                 PJ_LOG(3,(THIS_FILE, "No memory to allocate SDP media connection info")); 
    524                 return NULL; 
    525             } 
    526         } 
    527  
    528         /* Add additional attribute to the media stream. */ 
    529         attr = pj_pool_alloc(pool, sizeof(pjsdp_attr)); 
    530         if (!attr) { 
    531             PJ_LOG(3,(THIS_FILE, "No memory to allocate SDP attribute")); 
    532             return NULL; 
    533         } 
    534         m->attr[m->attr_count++] = attr; 
    535  
    536         switch (sd->info.dir) { 
    537         case PJ_MEDIA_DIR_NONE: 
    538             attr->type = PJSDP_ATTR_INACTIVE; 
    539             break; 
    540         case PJ_MEDIA_DIR_ENCODING: 
    541             attr->type = PJSDP_ATTR_SEND_ONLY; 
    542             break; 
    543         case PJ_MEDIA_DIR_DECODING: 
    544             attr->type = PJSDP_ATTR_RECV_ONLY; 
    545             break; 
    546         case PJ_MEDIA_DIR_ENCODING_DECODING: 
    547             attr->type = PJSDP_ATTR_SEND_RECV; 
    548             break; 
    549         } 
    550     } 
    551  
    552     return sdp; 
    553 } 
    554  
    555 /** 
    556  * Update session with SDP answer from peer. 
    557  */ 
    558 PJ_DEF(pj_status_t) 
    559 pj_media_session_update (pj_media_session_t *session,  
    560                          const pjsdp_session_desc *sdp) 
    561 { 
    562     unsigned i; 
    563     unsigned count; 
    564  
    565     /* Check SDP */ 
    566     if (sdp_check (sdp) != 0) { 
    567         return -1; 
    568     } 
    569  
    570     /* If the media stream count doesn't match, only update one. */ 
    571     if (session->stream_cnt != sdp->media_count) { 
    572         PJ_LOG(3,(THIS_FILE, "pj_media_session_update : " 
    573                  "SDP media count mismatch! (rmt=%d, lcl=%d)", 
    574                  sdp->media_count, session->stream_cnt)); 
    575         count = (session->stream_cnt < sdp->media_count) ? 
    576             session->stream_cnt : sdp->media_count; 
    577     } else { 
    578         count = session->stream_cnt; 
    579     } 
    580  
    581     for (i=0; i<count; ++i) { 
    582         pj_media_stream_desc *sd = session->stream_desc[i]; 
    583         const pjsdp_media_desc *m = sdp->media[i]; 
    584         const pjsdp_conn_info *conn; 
    585         unsigned j; 
    586  
    587         /* Check that the session is not active. */ 
    588         pj_assert (sd->enc_stream == NULL && sd->dec_stream == NULL); 
    589  
    590         conn = m->conn ? m->conn : sdp->conn; 
    591         pj_assert(conn); 
    592  
    593         /* Update remote address. */ 
    594         sd->info.rem_port = m->desc.port; 
    595         pj_strdup (session->pool, &sd->info.rem_addr, &conn->addr); 
    596  
    597         /* Select one active codec according to what peer wants. */ 
    598         for (j=0; j<sd->info.fmt_cnt; ++j) { 
    599             unsigned fmt_0 = pj_strtoul(&m->desc.fmt[0]); 
    600             if (sd->info.fmt[j].pt == fmt_0) { 
    601                 pj_codec_id temp; 
    602  
    603                 /* Put active format to the front. */ 
    604                 if (j == 0) 
    605                     break; 
    606  
    607                 pj_memcpy(&temp, &sd->info.fmt[0], sizeof(temp)); 
    608                 pj_memcpy(&sd->info.fmt[0], &sd->info.fmt[j], sizeof(temp)); 
    609                 pj_memcpy(&sd->info.fmt[j], &temp, sizeof(temp)); 
    610                 break; 
    611             } 
    612         } 
    613  
    614         if (j == sd->info.fmt_cnt) { 
    615             /* Peer has answered SDP with new codec, which doesn't exist 
    616              * in the offer! 
    617              * Mute this media. 
    618              */ 
    619             PJ_LOG(3,(THIS_FILE, "Peer has answered SDP with new codec!")); 
    620             sd->info.dir = PJ_MEDIA_DIR_NONE; 
    621             continue; 
    622         } 
    623  
    624         /* Check direction. */ 
    625         if (m->desc.port == 0 || pjsdp_media_desc_has_attr(m, PJSDP_ATTR_INACTIVE)) { 
    626             sd->info.dir = PJ_MEDIA_DIR_NONE; 
    627         } 
    628         else if (pjsdp_media_desc_has_attr(m, PJSDP_ATTR_RECV_ONLY)) { 
    629             sd->info.dir = PJ_MEDIA_DIR_ENCODING; 
    630         } 
    631         else if (pjsdp_media_desc_has_attr(m, PJSDP_ATTR_SEND_ONLY)) { 
    632             sd->info.dir = PJ_MEDIA_DIR_DECODING; 
    633         } 
    634         else { 
    635             sd->info.dir = PJ_MEDIA_DIR_ENCODING_DECODING; 
    636         } 
    637     } 
    638  
    639     return 0; 
    640 } 
    641  
    642 /** 
    643  * Enumerate media streams in the session. 
    644  */ 
    645 PJ_DEF(unsigned) 
    646 pj_media_session_enum_streams (const pj_media_session_t *session,  
    647                                unsigned count, const pj_media_stream_info *info[]) 
    648 { 
    649     unsigned i; 
    650  
    651     if (count > session->stream_cnt) 
    652         count = session->stream_cnt; 
    653  
    654     for (i=0; i<count; ++i) { 
    655         info[i] = &session->stream_desc[i]->info; 
    656     } 
    657  
    658     return session->stream_cnt; 
     355 
     356    PJ_ASSERT_RETURN(session && count && *count && info, PJ_EINVAL); 
     357 
     358    if (*count > session->stream_cnt) 
     359        *count = session->stream_cnt; 
     360 
     361    for (i=0; i<*count; ++i) { 
     362        pj_memcpy(&info[i], &session->stream[i], sizeof(pjmedia_stream_info)); 
     363    } 
     364 
     365    return PJ_SUCCESS; 
    659366} 
    660367 
     
    662369 * Get statistics 
    663370 */ 
    664 PJ_DEF(pj_status_t) 
    665 pj_media_session_get_stat (const pj_media_session_t *session, unsigned index, 
    666                            pj_media_stream_stat *tx_stat, 
    667                            pj_media_stream_stat *rx_stat) 
    668 { 
    669     pj_media_stream_desc *sd; 
    670     int stat_cnt = 0; 
    671  
    672     if (index >= session->stream_cnt) { 
    673         pj_assert(0); 
    674         return -1; 
    675     } 
    676      
    677     sd = session->stream_desc[index]; 
    678  
    679     if (sd->enc_stream && tx_stat) { 
    680         pj_media_stream_get_stat (sd->enc_stream, tx_stat); 
    681         ++stat_cnt; 
    682     } else if (tx_stat) { 
    683         pj_memset (tx_stat, 0, sizeof(*tx_stat)); 
    684     } 
    685  
    686     if (sd->dec_stream && rx_stat) { 
    687         pj_media_stream_get_stat (sd->dec_stream, rx_stat); 
    688         ++stat_cnt; 
    689     } else if (rx_stat) { 
    690         pj_memset (rx_stat, 0, sizeof(*rx_stat)); 
    691     } 
    692  
    693     return stat_cnt ? 0 : -1; 
    694 } 
    695  
    696 /** 
    697  * Modify stream, only when stream is inactive. 
    698  */ 
    699 PJ_DEF(pj_status_t) 
    700 pj_media_session_modify_stream (pj_media_session_t *session, unsigned index, 
    701                                 unsigned modify_flag, const pj_media_stream_info *info) 
    702 { 
    703     pj_media_stream_desc *sd; 
    704  
    705     if (index >= session->stream_cnt) { 
    706         pj_assert(0); 
    707         return -1; 
    708     } 
    709      
    710     sd = session->stream_desc[index]; 
    711  
    712     if (sd->enc_stream || sd->dec_stream) { 
    713         pj_assert(0); 
    714         return -1; 
    715     } 
    716  
    717     if (modify_flag & PJ_MEDIA_STREAM_MODIFY_DIR) { 
    718         sd->info.dir = info->dir; 
    719     } 
    720  
    721     return 0; 
    722 } 
    723  
    724 /** 
    725  * Activate media session. 
    726  */ 
    727 PJ_DEF(pj_status_t) 
    728 pj_media_session_activate (pj_media_session_t *session) 
    729 { 
    730     unsigned i; 
    731     pj_status_t status = 0; 
    732  
    733     for (i=0; i<session->stream_cnt; ++i) { 
    734         pj_status_t rc; 
    735         rc = pj_media_session_activate_stream (session, i); 
    736         if (status == 0) 
    737             status = rc; 
    738     } 
    739     return status; 
    740 } 
    741  
    742 /** 
    743  * Activate individual stream in media session. 
    744  */ 
    745 PJ_DEF(pj_status_t) 
    746 pj_media_session_activate_stream (pj_media_session_t *session, unsigned index) 
    747 { 
    748     pj_media_stream_desc *sd; 
    749     pj_media_stream_create_param scp; 
    750     pj_status_t status; 
    751     pj_time_val tv; 
    752  
    753     if (index < 0 || index >= session->stream_cnt) { 
    754         pj_assert(0); 
    755         return -1; 
    756     } 
    757  
    758     sd = session->stream_desc[index]; 
    759  
    760     if (sd->enc_stream || sd->dec_stream) { 
    761         /* Stream already active. */ 
    762         pj_assert(0); 
    763         return 0; 
    764     } 
    765  
    766     pj_gettimeofday(&tv); 
    767  
    768     /* Initialize parameter to create stream. */ 
    769     pj_memset (&scp, 0, sizeof(scp)); 
    770     scp.codec_id = &sd->info.fmt[0]; 
    771     scp.mediamgr = session->mediamgr; 
    772     scp.dir = sd->info.dir; 
    773     scp.rtp_sock = sd->info.sock_info.rtp_sock; 
    774     scp.rtcp_sock = sd->info.sock_info.rtcp_sock; 
    775     scp.remote_addr = pj_pool_calloc (session->pool, 1, sizeof(pj_sockaddr_in)); 
    776     pj_sockaddr_in_init(scp.remote_addr, &sd->info.rem_addr, sd->info.rem_port); 
    777     scp.ssrc = tv.sec; 
    778     scp.jb_min = 1; 
    779     scp.jb_max = 15; 
    780     scp.jb_maxcnt = 16; 
    781  
    782     /* Build the stream! */ 
    783     status = pj_media_stream_create (session->pool, &sd->enc_stream, &sd->dec_stream, &scp); 
    784  
    785     if (status==0 && sd->enc_stream) { 
    786         status = pj_media_stream_start (sd->enc_stream); 
    787         if (status != 0) 
    788             goto on_error; 
    789     } 
    790     if (status==0 && sd->dec_stream) { 
    791         status = pj_media_stream_start (sd->dec_stream); 
    792         if (status != 0) 
    793             goto on_error; 
    794     } 
    795     return status; 
    796  
    797 on_error: 
    798     if (sd->enc_stream) { 
    799         pj_media_stream_destroy (sd->enc_stream); 
    800         sd->enc_stream = NULL; 
    801     } 
    802     if (sd->dec_stream) { 
    803         pj_media_stream_destroy (sd->dec_stream); 
    804         sd->dec_stream = NULL; 
    805     } 
    806     return status; 
    807 } 
    808  
    809 /** 
    810  * Destroy media session. 
    811  */ 
    812 PJ_DEF(pj_status_t) 
    813 pj_media_session_destroy (pj_media_session_t *session) 
    814 { 
    815     unsigned i; 
    816  
    817     if (!session) 
    818         return -1; 
    819  
    820     for (i=0; i<session->stream_cnt; ++i) { 
    821         pj_media_stream_desc *sd = session->stream_desc[i]; 
    822  
    823         if (sd->enc_stream) { 
    824             pj_media_stream_destroy (sd->enc_stream); 
    825             sd->enc_stream = NULL; 
    826         } 
    827         if (sd->dec_stream) { 
    828             pj_media_stream_destroy (sd->dec_stream); 
    829             sd->dec_stream = NULL; 
    830         } 
    831     } 
    832     pj_pool_release (session->pool); 
    833     return 0; 
    834 } 
    835  
     371PJ_DEF(pj_status_t) pjmedia_session_get_stat(const pjmedia_session *session,  
     372                                             unsigned *count, 
     373                                             pjmedia_stream_stat stat[]) 
     374{ 
     375    PJ_ASSERT_RETURN(session && count && *count && stat, PJ_EINVAL); 
     376 
     377    *count = 0; 
     378    pj_memset(stat, 0, *count * sizeof(pjmedia_stream_stat)); 
     379    return PJ_EINVALIDOP; 
     380} 
     381 
     382 
     383/** 
     384 * Get individual stream statistic. 
     385 */ 
     386PJ_DEF(pj_status_t) pjmedia_session_get_stream_stat( const pjmedia_session *s, 
     387                                                     unsigned index, 
     388                                                     pjmedia_stream_stat *stat) 
     389{ 
     390    PJ_ASSERT_RETURN(s && index < s->stream_cnt && stat, PJ_EINVAL); 
     391    pj_memset(stat, 0, sizeof(pjmedia_stream_stat)); 
     392    return PJ_EINVALIDOP; 
     393} 
     394 
     395 
  • pjproject/trunk/pjmedia/src/pjmedia/stream.c

    r121 r159  
    3232 
    3333 
    34 #define THISFILE    "stream.c" 
    35 #define ERRLEVEL    1 
    36  
    37 #define PJ_MAX_FRAME_DURATION_MS    200 
    38 #define PJ_MAX_BUFFER_SIZE_MS       2000 
    39 #define PJ_MAX_MTU                  1500 
     34#define THIS_FILE                       "stream.c" 
     35#define ERRLEVEL                        1 
     36#define TRACE_(expr)                    PJ_LOG(3,expr) 
     37 
     38#define PJMEDIA_MAX_FRAME_DURATION_MS   200 
     39#define PJMEDIA_MAX_BUFFER_SIZE_MS      2000 
     40#define PJMEDIA_MAX_MTU                 1500 
    4041 
    4142struct jb_frame 
     
    4950#define pj_fifobuf_free(fifo, buf)      free(buf) 
    5051 
    51 enum stream_state 
    52 { 
    53     STREAM_STOPPED, 
    54     STREAM_STARTED, 
     52 
     53/** 
     54 * Media channel. 
     55 */ 
     56struct pjmedia_channel 
     57{ 
     58    pjmedia_stream         *stream;         /**< Parent stream.             */ 
     59    pjmedia_dir             dir;            /**< Channel direction.         */ 
     60    unsigned                pt;             /**< Payload type.              */ 
     61    pj_bool_t               paused;         /**< Paused?.                   */ 
     62    pj_snd_stream_info      snd_info;       /**< Sound stream param.        */ 
     63    pj_snd_stream          *snd_stream;     /**< Sound stream.              */ 
     64    unsigned                in_pkt_size;    /**< Size of input buffer.      */ 
     65    void                   *in_pkt;         /**< Input buffer.              */ 
     66    unsigned                out_pkt_size;   /**< Size of output buffer.     */ 
     67    void                   *out_pkt;        /**< Output buffer.             */ 
     68    unsigned                pcm_buf_size;   /**< Size of PCM buffer.        */ 
     69    void                   *pcm_buf;        /**< PCM buffer.                */ 
     70    pj_rtp_session          rtp;            /**< RTP session.               */ 
    5571}; 
    5672 
    57 struct pj_media_stream_t 
    58 { 
    59     pj_media_dir_t          dir; 
    60     int                     pt; 
    61     int                     state; 
    62     pj_media_stream_stat    stat; 
    63     pj_media_stream_t      *peer; 
    64     pj_snd_stream_info      snd_info; 
    65     pj_snd_stream          *snd_stream; 
    66     pj_mutex_t             *mutex; 
    67     unsigned                in_pkt_size; 
    68     void                   *in_pkt; 
    69     unsigned                out_pkt_size; 
    70     void                   *out_pkt; 
    71     unsigned                pcm_buf_size; 
    72     void                   *pcm_buf; 
    73     //pj_fifobuf_t          fifobuf; 
    74     pj_codec_mgr           *codec_mgr; 
    75     pj_codec               *codec; 
    76     pj_rtp_session          rtp; 
    77     pj_rtcp_session        *rtcp; 
    78     pj_jitter_buffer       *jb; 
    79     pj_sock_t               rtp_sock; 
    80     pj_sock_t               rtcp_sock; 
    81     pj_sockaddr_in          dst_addr; 
    82     pj_thread_t            *transport_thread; 
    83     int                     thread_quit_flag; 
     73 
     74/** 
     75 * This structure describes media stream. 
     76 * A media stream is bidirectional media transmission between two endpoints. 
     77 * It consists of two channels, i.e. encoding and decoding channels. 
     78 * A media stream corresponds to a single "m=" line in a SDP session 
     79 * description. 
     80 */ 
     81struct pjmedia_stream 
     82{ 
     83    pjmedia_channel         *enc;           /**< Encoding channel.          */ 
     84    pjmedia_channel         *dec;           /**< Decoding channel.          */ 
     85 
     86    pjmedia_dir              dir;           /**< Stream direction.          */ 
     87    pjmedia_stream_stat      stat;          /**< Stream statistics.         */ 
     88 
     89    pjmedia_codec_mgr       *codec_mgr;     /**< Codec manager instance.    */ 
     90    pjmedia_codec           *codec;         /**< Codec instance being used. */ 
     91 
     92    pj_mutex_t              *jb_mutex; 
     93    pj_jitter_buffer         jb;            /**< Jitter buffer.             */ 
     94 
     95    pj_sock_t                rtp_sock;      /**< RTP socket.                */ 
     96    pj_sock_t                rtcp_sock;     /**< RTCP socket.               */ 
     97    pj_sockaddr_in           dst_addr;      /**< Destination RTP address.   */ 
     98 
     99    pj_rtcp_session          rtcp;          /**< RTCP for incoming RTP.     */ 
     100 
     101    pj_bool_t                quit_flag;     /**< To signal thread exit.     */ 
     102    pj_thread_t             *thread;        /**< Jitter buffer's thread.    */ 
    84103}; 
    85104 
    86105 
     106 
     107/* 
     108 * play_callback() 
     109 * 
     110 * This callback is called by sound device's player thread when it 
     111 * needs to feed the player with some frames. 
     112 */ 
    87113static pj_status_t play_callback(/* in */   void *user_data, 
    88114                                 /* in */   pj_uint32_t timestamp, 
     
    90116                                 /*inout*/  unsigned size) 
    91117{ 
    92     pj_media_stream_t *channel = user_data; 
     118    pjmedia_channel *channel = user_data; 
     119    pjmedia_stream *stream = channel->stream; 
    93120    struct jb_frame *jb_frame; 
    94121    void *p; 
    95122    pj_uint32_t extseq; 
    96123    pj_status_t status; 
    97     struct pj_audio_frame frame_in, frame_out; 
     124    struct pjmedia_frame frame_in, frame_out; 
    98125 
    99126    PJ_UNUSED_ARG(timestamp); 
    100127 
    101     /* Lock mutex */ 
    102     pj_mutex_lock (channel->mutex); 
    103  
    104     if (!channel->codec) { 
    105         pj_mutex_unlock (channel->mutex); 
     128    /* Do nothing if we're quitting. */ 
     129    if (stream->quit_flag) 
    106130        return -1; 
    107     } 
     131 
     132    /* Lock jitter buffer mutex */ 
     133    pj_mutex_lock( stream->jb_mutex ); 
    108134 
    109135    /* Get frame from jitter buffer. */ 
    110     status = pj_jb_get (channel->jb, &extseq, &p); 
     136    status = pj_jb_get(&stream->jb, &extseq, &p); 
     137 
     138    /* Unlock jitter buffer mutex. */ 
     139    pj_mutex_unlock( stream->jb_mutex ); 
     140 
    111141    jb_frame = p; 
    112     if (status != 0 || jb_frame == NULL) { 
     142    if (status != PJ_SUCCESS || jb_frame == NULL) { 
    113143        pj_memset(frame, 0, size); 
    114         pj_mutex_unlock(channel->mutex); 
    115144        return 0; 
    116145    } 
     
    119148    frame_in.buf = jb_frame->buf; 
    120149    frame_in.size = jb_frame->size; 
    121     frame_in.type = PJ_AUDIO_FRAME_AUDIO;  /* ignored */ 
     150    frame_in.type = PJMEDIA_FRAME_TYPE_AUDIO;  /* ignored */ 
    122151    frame_out.buf = channel->pcm_buf; 
    123     status = channel->codec->op->decode (channel->codec, &frame_in, 
    124                                          channel->pcm_buf_size, &frame_out); 
     152    status = stream->codec->op->decode( stream->codec, &frame_in, 
     153                                        channel->pcm_buf_size, &frame_out); 
    125154    if (status != 0) { 
    126         PJ_LOG(3, (THISFILE, "decode() has return error status %d",  
    127                           status)); 
     155        TRACE_((THIS_FILE, "decode() has return error status %d", status)); 
    128156 
    129157        pj_memset(frame, 0, size); 
    130158        pj_fifobuf_free (&channel->fifobuf, jb_frame); 
    131         pj_mutex_unlock(channel->mutex); 
    132159        return 0; 
    133160    } 
     
    135162    /* Put in sound buffer. */ 
    136163    if (frame_out.size > size) { 
    137         PJ_LOG(3, (THISFILE, "Sound playout buffer truncated %d bytes",  
    138                           frame_out.size - size)); 
     164        TRACE_((THIS_FILE, "Sound playout buffer truncated %d bytes",  
     165                frame_out.size - size)); 
    139166        frame_out.size = size; 
    140167    } 
    141168 
    142169    pj_memcpy(frame, frame_out.buf, size); 
    143  
    144170    pj_fifobuf_free (&channel->fifobuf, jb_frame); 
    145     pj_mutex_unlock(channel->mutex); 
     171 
    146172    return 0; 
    147173} 
    148174 
     175 
     176/** 
     177 * rec_callback() 
     178 * 
     179 * This callback is called when the mic device has gathered 
     180 * enough audio samples. We will encode the audio samples and 
     181 * send it to remote. 
     182 */ 
    149183static pj_status_t rec_callback( /* in */ void *user_data, 
    150184                                 /* in */ pj_uint32_t timestamp, 
     
    152186                                 /* in */ unsigned size) 
    153187{ 
    154     pj_media_stream_t *channel = user_data; 
     188    pjmedia_channel *channel = user_data; 
     189    pjmedia_stream *stream = channel->stream; 
    155190    pj_status_t status = 0; 
    156     struct pj_audio_frame frame_in, frame_out; 
     191    struct pjmedia_frame frame_in, frame_out; 
    157192    int ts_len; 
    158193    void *rtphdr; 
    159194    int rtphdrlen; 
    160195    pj_ssize_t sent; 
    161 #if 0 
    162     static FILE *fhnd = NULL; 
    163 #endif 
     196 
    164197 
    165198    PJ_UNUSED_ARG(timestamp); 
    166199 
    167     /* Start locking channel mutex */ 
    168     pj_mutex_lock (channel->mutex); 
    169  
    170     if (!channel->codec) { 
    171         status = -1; 
    172         goto on_return; 
    173     } 
     200    /* Check if stream is quitting. */ 
     201    if (stream->quit_flag) 
     202        return -1; 
    174203 
    175204    /* Encode. */ 
    176     frame_in.type = PJ_MEDIA_TYPE_AUDIO; 
     205    frame_in.type = PJMEDIA_TYPE_AUDIO; 
    177206    frame_in.buf = (void*)frame; 
    178207    frame_in.size = size; 
    179208    frame_out.buf = ((char*)channel->out_pkt) + sizeof(pj_rtp_hdr); 
    180     status = channel->codec->op->encode (channel->codec, &frame_in,  
    181                                          channel->out_pkt_size - sizeof(pj_rtp_hdr),  
    182                                          &frame_out); 
     209    status = stream->codec->op->encode( stream->codec, &frame_in,  
     210                                        channel->out_pkt_size - sizeof(pj_rtp_hdr),  
     211                                        &frame_out); 
    183212    if (status != 0) { 
    184         PJ_LOG(3,(THISFILE, "Codec encode() has returned error status %d",  
    185                              status)); 
    186         goto on_return; 
     213        TRACE_((THIS_FILE, "Codec encode() has returned error status %d",  
     214                status)); 
     215        return status; 
    187216    } 
    188217 
    189218    /* Encapsulate. */ 
    190219    ts_len = size / (channel->snd_info.bits_per_sample / 8); 
    191     status = pj_rtp_encode_rtp (&channel->rtp, channel->pt, 0,  
     220    status = pj_rtp_encode_rtp( &channel->rtp,  
     221                                channel->pt, 0,  
    192222                                frame_out.size, ts_len,  
    193223                                (const void**)&rtphdr, &rtphdrlen); 
    194224    if (status != 0) { 
    195         PJ_LOG(3,(THISFILE, "RTP encode_rtp() has returned error status %d",  
    196                             status)); 
    197         goto on_return; 
     225        TRACE_((THIS_FILE, "RTP encode_rtp() has returned error status %d",  
     226                           status)); 
     227        return status; 
    198228    } 
    199229 
     
    201231        /* We don't support RTP with extended header yet. */ 
    202232        PJ_TODO(SUPPORT_SENDING_RTP_WITH_EXTENDED_HEADER); 
    203         PJ_LOG(3,(THISFILE, "Unsupported extended RTP header for transmission")); 
    204         goto on_return; 
     233        TRACE_((THIS_FILE, "Unsupported extended RTP header for transmission")); 
     234        return 0; 
    205235    } 
    206236 
     
    209239    /* Send. */ 
    210240    sent = frame_out.size+sizeof(pj_rtp_hdr); 
    211     status = pj_sock_sendto (channel->rtp_sock, channel->out_pkt, &sent, 0,  
    212                            &channel->dst_addr, sizeof(channel->dst_addr)); 
    213     if (status != PJ_SUCCESS) 
    214         goto on_return; 
     241    status = pj_sock_sendto(stream->rtp_sock, channel->out_pkt, &sent, 0,  
     242                            &stream->dst_addr, sizeof(stream->dst_addr)); 
     243    if (status != PJ_SUCCESS) 
     244        return status; 
    215245 
    216246    /* Update stat */ 
    217     channel->stat.pkt_tx++; 
    218     channel->stat.oct_tx += frame_out.size+sizeof(pj_rtp_hdr); 
    219  
    220 #if 0 
    221     if (fhnd == NULL) { 
    222         fhnd = fopen("RTP.DAT", "wb"); 
    223         if (fhnd) { 
    224             fwrite (channel->out_pkt, frame_out.size+sizeof(pj_rtp_hdr), 1, fhnd); 
    225             fclose(fhnd); 
    226         } 
    227     } 
    228 #endif 
    229  
    230 on_return: 
    231     pj_mutex_unlock (channel->mutex); 
    232     return status; 
    233 } 
    234  
    235  
    236 static int PJ_THREAD_FUNC stream_decoder_transport_thread (void*arg) 
    237 { 
    238     pj_media_stream_t *channel = arg; 
    239  
    240     while (!channel->thread_quit_flag) { 
     247    stream->stat.enc.pkt++; 
     248    stream->stat.enc.bytes += frame_out.size+sizeof(pj_rtp_hdr); 
     249 
     250    return 0; 
     251} 
     252 
     253 
     254/* 
     255 * This thread will poll the socket for incoming packets, and put 
     256 * the packets to jitter buffer. 
     257 */ 
     258static int PJ_THREAD_FUNC jitter_buffer_thread (void*arg) 
     259{ 
     260    pjmedia_stream *stream = arg; 
     261    pjmedia_channel *channel = stream->dec; 
     262 
     263    while (!stream->quit_flag) { 
    241264        pj_ssize_t len, size; 
    242265        const pj_rtp_hdr *hdr; 
     
    251274 
    252275        PJ_FD_ZERO (&fds); 
    253         PJ_FD_SET (channel->rtp_sock, &fds); 
     276        PJ_FD_SET (stream->rtp_sock, &fds); 
    254277        timeout.sec = 0; 
    255         timeout.msec = 100; 
     278        timeout.msec = 1; 
    256279 
    257280        /* Wait with timeout. */ 
    258         status = pj_sock_select(channel->rtp_sock, &fds, NULL, NULL, &timeout); 
     281        status = pj_sock_select(stream->rtp_sock, &fds, NULL, NULL, &timeout); 
    259282        if (status != 1) 
    260283            continue; 
     
    262285        /* Get packet from socket. */ 
    263286        len = channel->in_pkt_size; 
    264         status = pj_sock_recv (channel->rtp_sock, channel->in_pkt, &len, 0); 
     287        status = pj_sock_recv(stream->rtp_sock, channel->in_pkt, &len, 0); 
    265288        if (len < 1 || status != PJ_SUCCESS) { 
    266289            if (pj_get_netos_error() == PJ_STATUS_FROM_OS(OSERR_ECONNRESET)) { 
    267                 /* On Win2K SP2 (or above) and WinXP, recv() will get WSAECONNRESET 
    268                    when the sending side receives ICMP port unreachable. 
     290                /* On Win2K SP2 (or above) and WinXP, recv() will get  
     291                 * WSAECONNRESET when the sending side receives ICMP port  
     292                 * unreachable. 
    269293                 */ 
    270294                continue; 
    271295            } 
    272             //pj_perror(THISFILE, "Error receiving packet from socket (len=%d)", len); 
    273296            pj_thread_sleep(1); 
    274297            continue; 
    275298        } 
    276299 
    277         if (channel->state != STREAM_STARTED) 
     300        if (channel->paused) 
    278301            continue; 
    279302 
    280         if (channel->thread_quit_flag) 
    281             break; 
    282  
    283         /* Start locking the channel. */ 
    284         pj_mutex_lock (channel->mutex); 
    285  
    286303        /* Update RTP and RTCP session. */ 
    287         status = pj_rtp_decode_rtp (&channel->rtp, channel->in_pkt, len, &hdr, &payload, &payloadlen); 
    288         if (status != 0) { 
    289             pj_mutex_unlock (channel->mutex); 
    290             PJ_LOG(4,(THISFILE, "RTP decode_rtp() has returned error status %d", status)); 
     304        status = pj_rtp_decode_rtp(&channel->rtp, channel->in_pkt, len,  
     305                                   &hdr, &payload, &payloadlen); 
     306        if (status != PJ_SUCCESS) { 
     307            TRACE_((THIS_FILE, "RTP decode_rtp() has returned error status %d", 
     308                    status)); 
    291309            continue; 
    292310        } 
    293         status = pj_rtp_session_update (&channel->rtp, hdr); 
    294         if (status != 0 && status != PJ_RTP_ERR_SESSION_PROBATION && status != PJ_RTP_ERR_SESSION_RESTARTED) { 
    295             pj_mutex_unlock (channel->mutex); 
    296             PJ_LOG(4,(THISFILE, "RTP session_update() has returned error status %d", status)); 
     311 
     312        status = pj_rtp_session_update(&channel->rtp, hdr); 
     313        if (status != 0 &&  
     314            status != PJMEDIA_RTP_ERR_SESSION_PROBATION &&  
     315            status != PJMEDIA_RTP_ERR_SESSION_RESTARTED)  
     316        { 
     317            TRACE_((THIS_FILE,  
     318                    "RTP session_update() has returned error status %d",  
     319                    status)); 
    297320            continue; 
    298321        } 
    299         pj_rtcp_rx_rtp (channel->rtcp, pj_ntohs(hdr->seq), pj_ntohl(hdr->ts)); 
     322        pj_rtcp_rx_rtp(&stream->rtcp, pj_ntohs(hdr->seq), pj_ntohl(hdr->ts)); 
    300323 
    301324        /* Update stat */ 
    302         channel->stat.pkt_rx++; 
    303         channel->stat.oct_rx += len; 
     325        stream->stat.dec.pkt++; 
     326        stream->stat.dec.bytes += len; 
    304327 
    305328        /* Copy to FIFO buffer. */ 
     
    307330        jb_frame = pj_fifobuf_alloc (&channel->fifobuf, size); 
    308331        if (jb_frame == NULL) { 
    309             pj_mutex_unlock (channel->mutex); 
    310             PJ_LOG(4,(THISFILE, "Unable to allocate %d bytes FIFO buffer", size)); 
     332            TRACE_((THIS_FILE, "Unable to allocate %d bytes FIFO buffer",  
     333                    size)); 
    311334            continue; 
    312335        } 
     
    318341 
    319342        /* Put to jitter buffer. */ 
    320         status = pj_jb_put (channel->jb, pj_ntohs(hdr->seq), jb_frame); 
     343        pj_mutex_lock( stream->jb_mutex ); 
     344        status = pj_jb_put(&stream->jb, pj_ntohs(hdr->seq), jb_frame); 
     345        pj_mutex_unlock( stream->jb_mutex ); 
     346 
    321347        if (status != 0) { 
    322348            pj_fifobuf_unalloc (&channel->fifobuf, jb_frame); 
    323             pj_mutex_unlock (channel->mutex); 
    324             PJ_LOG(4,(THISFILE, "Jitter buffer put() has returned error status %d", status)); 
     349             
     350            TRACE_((THIS_FILE,  
     351                    "Jitter buffer put() has returned error status %d",  
     352                    status)); 
    325353            continue; 
    326354        } 
    327  
    328         pj_mutex_unlock (channel->mutex); 
    329355    } 
    330356 
     
    332358} 
    333359 
    334 static void init_snd_param_from_codec_attr (pj_snd_stream_info *param, 
    335                                             const pj_codec_attr *attr) 
    336 { 
    337     param->bits_per_sample = attr->pcm_bits_per_sample; 
    338     param->bytes_per_frame = 2; 
    339     param->frames_per_packet = attr->sample_rate * attr->ptime / 1000; 
    340     param->samples_per_frame = 1; 
    341     param->samples_per_sec = attr->sample_rate; 
    342 } 
    343  
    344 static pj_media_stream_t *create_channel ( pj_pool_t *pool, 
    345                                            pj_media_dir_t dir, 
    346                                            pj_media_stream_t *peer, 
    347                                            pj_codec_id *codec_id, 
    348                                            pj_media_stream_create_param *param) 
    349 { 
    350     pj_media_stream_t *channel; 
    351     pj_codec_attr codec_attr; 
    352     void *ptr; 
    353     unsigned size; 
     360 
     361/* 
     362 * Create sound stream parameter from codec attributes. 
     363 */ 
     364static void init_snd_param( pj_snd_stream_info *snd_param, 
     365                            const pjmedia_codec_param *codec_param) 
     366{ 
     367    pj_memset(snd_param, 0, sizeof(*snd_param)); 
     368 
     369    snd_param->bits_per_sample   = codec_param->pcm_bits_per_sample; 
     370    snd_param->bytes_per_frame   = 2; 
     371    snd_param->frames_per_packet = codec_param->sample_rate *  
     372                                   codec_param->ptime /  
     373                                   1000; 
     374    snd_param->samples_per_frame = 1; 
     375    snd_param->samples_per_sec   = codec_param->sample_rate; 
     376} 
     377 
     378 
     379/* 
     380 * Create media channel. 
     381 */ 
     382static pj_status_t create_channel( pj_pool_t *pool, 
     383                                   pjmedia_stream *stream, 
     384                                   pjmedia_dir dir, 
     385                                   const pjmedia_stream_info *param, 
     386                                   const pjmedia_codec_param *codec_param, 
     387                                   pjmedia_channel **p_channel) 
     388{ 
     389    pjmedia_channel *channel; 
    354390    pj_status_t status; 
    355391     
    356392    /* Allocate memory for channel descriptor */ 
    357     size = sizeof(pj_media_stream_t); 
    358     channel = pj_pool_calloc(pool, 1, size); 
    359     if (!channel) { 
    360         PJ_LOG(1,(THISFILE, "Unable to allocate %u bytes channel descriptor",  
    361                          size)); 
    362         return NULL; 
    363     } 
    364  
     393 
     394    channel = pj_pool_zalloc(pool, sizeof(pjmedia_channel)); 
     395    PJ_ASSERT_RETURN(channel != NULL, PJ_ENOMEM); 
     396 
     397    /* Init channel info. */ 
     398 
     399    channel->stream = stream; 
    365400    channel->dir = dir; 
    366     channel->pt = codec_id->pt; 
    367     channel->peer = peer; 
    368     channel->codec_mgr = pj_med_mgr_get_codec_mgr (param->mediamgr); 
    369     channel->rtp_sock = param->rtp_sock; 
    370     channel->rtcp_sock = param->rtcp_sock; 
    371     channel->dst_addr = *param->remote_addr; 
    372     channel->state = STREAM_STOPPED; 
    373  
    374     /* Create mutex for the channel. */ 
    375     status = pj_mutex_create_simple(pool, NULL, &channel->mutex); 
    376     if (status != PJ_SUCCESS) 
    377         goto err_cleanup; 
    378  
    379     /* Create and initialize codec, only if peer is not present. 
    380        We only use one codec instance for both encoder and decoder. 
    381      */ 
    382     if (peer && peer->codec) { 
    383         channel->codec = peer->codec; 
    384         status = channel->codec->factory->op->default_attr(channel->codec->factory, codec_id,  
    385                                                            &codec_attr); 
    386         if (status != 0) { 
    387             goto err_cleanup; 
    388         } 
    389  
    390     } else { 
    391         channel->codec = pj_codec_mgr_alloc_codec(channel->codec_mgr, codec_id); 
    392         if (channel->codec == NULL) { 
    393             goto err_cleanup; 
    394         } 
    395  
    396         status = channel->codec->factory->op->default_attr(channel->codec->factory, codec_id,  
    397                                                            &codec_attr); 
    398         if (status != 0) { 
    399             goto err_cleanup; 
    400         } 
    401  
    402         codec_attr.pt = codec_id->pt; 
    403         status = channel->codec->op->open(channel->codec, &codec_attr); 
    404         if (status != 0) { 
    405             goto err_cleanup; 
    406         } 
    407     } 
     401    channel->paused = 1; 
     402    channel->pt = param->fmt.pt; 
    408403 
    409404    /* Allocate buffer for incoming packet. */ 
    410     channel->in_pkt_size = PJ_MAX_MTU; 
    411     channel->in_pkt = pj_pool_alloc(pool, channel->in_pkt_size); 
    412     if (!channel->in_pkt) { 
    413         PJ_LOG(1, (THISFILE, "Unable to allocate %u bytes incoming packet buffer",  
    414                           channel->in_pkt_size)); 
    415         goto err_cleanup; 
    416     } 
    417  
     405 
     406    channel->in_pkt_size = PJMEDIA_MAX_MTU; 
     407    channel->in_pkt = pj_pool_alloc( pool, channel->in_pkt_size ); 
     408    PJ_ASSERT_RETURN(channel->in_pkt != NULL, PJ_ENOMEM); 
     409 
     410     
    418411    /* Allocate buffer for outgoing packet. */ 
     412 
    419413    channel->out_pkt_size = sizeof(pj_rtp_hdr) +  
    420                             codec_attr.avg_bps / 8 * PJ_MAX_FRAME_DURATION_MS / 1000; 
    421     if (channel->out_pkt_size > PJ_MAX_MTU) 
    422         channel->out_pkt_size = PJ_MAX_MTU; 
     414                            codec_param->avg_bps/8 *  
     415                            PJMEDIA_MAX_FRAME_DURATION_MS /  
     416                            1000; 
     417 
     418    if (channel->out_pkt_size > PJMEDIA_MAX_MTU) 
     419        channel->out_pkt_size = PJMEDIA_MAX_MTU; 
     420 
    423421    channel->out_pkt = pj_pool_alloc(pool, channel->out_pkt_size); 
    424     if (!channel->out_pkt) { 
    425         PJ_LOG(1, (THISFILE, "Unable to allocate %u bytes encoding buffer",  
    426                           channel->out_pkt_size)); 
    427         goto err_cleanup; 
    428     } 
    429  
    430     /* Allocate buffer for decoding to PCM */ 
    431     channel->pcm_buf_size = codec_attr.sample_rate *  
    432                             codec_attr.pcm_bits_per_sample / 8 * 
    433                             PJ_MAX_FRAME_DURATION_MS / 1000; 
     422    PJ_ASSERT_RETURN(channel->out_pkt != NULL, PJ_ENOMEM); 
     423 
     424 
     425    /* Allocate buffer for decoding to PCM: */ 
     426 
     427    channel->pcm_buf_size = codec_param->sample_rate *  
     428                            codec_param->pcm_bits_per_sample / 8 * 
     429                            PJMEDIA_MAX_FRAME_DURATION_MS / 1000; 
    434430    channel->pcm_buf = pj_pool_alloc (pool, channel->pcm_buf_size); 
    435     if (!channel->pcm_buf) { 
    436         PJ_LOG(1, (THISFILE, "Unable to allocate %u bytes PCM buffer",  
    437                           channel->pcm_buf_size)); 
    438         goto err_cleanup; 
    439     } 
    440  
    441     /* Allocate buffer for frames put in jitter buffer. */ 
    442     size = codec_attr.avg_bps / 8 * PJ_MAX_BUFFER_SIZE_MS / 1000; 
    443     ptr = pj_pool_alloc(pool, size); 
    444     if (!ptr) { 
    445         PJ_LOG(1, (THISFILE, "Unable to allocate %u bytes jitter buffer",  
    446                           channel->pcm_buf_size)); 
    447         goto err_cleanup; 
    448     } 
    449     //pj_fifobuf_init (&channel->fifobuf, ptr, size); 
     431    PJ_ASSERT_RETURN(channel->pcm_buf != NULL, PJ_ENOMEM); 
     432 
     433 
     434    /* Create RTP and RTCP sessions: */ 
     435 
     436    status = pj_rtp_session_init(&channel->rtp, param->fmt.pt,  
     437                                 param->ssrc); 
     438    if (status != PJ_SUCCESS) 
     439        return status; 
    450440 
    451441    /* Create and initialize sound device */ 
    452     init_snd_param_from_codec_attr (&channel->snd_info, &codec_attr); 
    453  
    454     if (dir == PJ_MEDIA_DIR_ENCODING) 
     442 
     443    init_snd_param(&channel->snd_info, codec_param); 
     444 
     445    if (dir == PJMEDIA_DIR_ENCODING) 
    455446        channel->snd_stream = pj_snd_open_recorder(-1, &channel->snd_info,  
    456447                                                   &rec_callback, channel); 
     
    460451 
    461452    if (!channel->snd_stream) 
    462         goto err_cleanup; 
    463  
    464     /* Create RTP and RTCP sessions. */ 
    465     if (pj_rtp_session_init(&channel->rtp, codec_id->pt, param->ssrc) != 0) { 
    466         PJ_LOG(1, (THISFILE, "RTP session initialization error")); 
    467         goto err_cleanup; 
    468     } 
    469  
    470     /* For decoder, create RTCP session, jitter buffer, and transport thread. */ 
    471     if (dir == PJ_MEDIA_DIR_DECODING) { 
    472         channel->rtcp = pj_pool_calloc(pool, 1, sizeof(pj_rtcp_session)); 
    473         if (!channel->rtcp) { 
    474             PJ_LOG(1, (THISFILE, "Unable to allocate RTCP session")); 
    475             goto err_cleanup; 
    476         } 
    477  
    478         pj_rtcp_init(channel->rtcp, param->ssrc); 
    479  
    480         channel->jb = pj_pool_calloc(pool, 1, sizeof(pj_jitter_buffer)); 
    481         if (!channel->jb) { 
    482             PJ_LOG(1, (THISFILE, "Unable to allocate jitter buffer descriptor")); 
    483             goto err_cleanup; 
    484         } 
    485         if (pj_jb_init(channel->jb, pool, param->jb_min, param->jb_max, param->jb_maxcnt)) { 
    486             PJ_LOG(1, (THISFILE, "Unable to allocate jitter buffer")); 
    487             goto err_cleanup; 
    488         } 
    489  
    490         status = pj_thread_create(pool, "decode",  
    491                                   &stream_decoder_transport_thread, channel, 
    492                                   0, 0, &channel->transport_thread); 
    493         if (status != PJ_SUCCESS) { 
    494             //pj_perror(THISFILE, "Unable to create transport thread"); 
    495             goto err_cleanup; 
    496         } 
    497     } 
     453        return -1; 
     454 
    498455 
    499456    /* Done. */ 
    500     return channel; 
     457    *p_channel = channel; 
     458    return PJ_SUCCESS; 
     459} 
     460 
     461 
     462/* 
     463 * Create media stream. 
     464 */ 
     465PJ_DEF(pj_status_t) pjmedia_stream_create( pjmedia_endpt *endpt, 
     466                                           pj_pool_t *pool, 
     467                                           const pjmedia_stream_info *info, 
     468                                           pjmedia_stream **p_stream) 
     469 
     470{ 
     471    pjmedia_stream *stream; 
     472    pjmedia_codec_param codec_param; 
     473    pj_status_t status; 
     474 
     475    PJ_ASSERT_RETURN(pool && info && p_stream, PJ_EINVAL); 
     476 
     477 
     478    /* Allocate the media stream: */ 
     479 
     480    stream = pj_pool_zalloc(pool, sizeof(pjmedia_stream)); 
     481    PJ_ASSERT_RETURN(stream != NULL, PJ_ENOMEM); 
     482 
     483 
     484    /* Init stream: */ 
     485    
     486    stream->dir = info->dir; 
     487    stream->codec_mgr = pjmedia_endpt_get_codec_mgr(endpt); 
     488 
     489    /* Create mutex to protect jitter buffer: */ 
     490 
     491    status = pj_mutex_create_simple(pool, NULL, &stream->jb_mutex); 
     492    if (status != PJ_SUCCESS) 
     493        goto err_cleanup; 
     494 
     495 
     496    /* Create and initialize codec: */ 
     497 
     498    status = pjmedia_codec_mgr_alloc_codec( stream->codec_mgr, 
     499                                            &info->fmt, &stream->codec); 
     500    if (status != PJ_SUCCESS) 
     501        goto err_cleanup; 
     502 
     503 
     504    /* Get default codec param: */ 
     505 
     506    status = stream->codec->op->default_attr(stream->codec, &codec_param); 
     507    if (status != PJ_SUCCESS) 
     508        goto err_cleanup; 
     509 
     510 
     511    /* Open the codec: */ 
     512 
     513    status = stream->codec->op->open(stream->codec, &codec_param); 
     514    if (status != PJ_SUCCESS) 
     515        goto err_cleanup; 
     516 
     517 
     518    /* Init RTCP session: */ 
     519 
     520    pj_rtcp_init(&stream->rtcp, info->ssrc); 
     521 
     522 
     523    /* Init jitter buffer: */ 
     524 
     525    status = pj_jb_init(&stream->jb, pool,  
     526                        info->jb_min, info->jb_max, info->jb_maxcnt); 
     527    if (status != PJ_SUCCESS) 
     528        goto err_cleanup; 
     529 
     530 
     531    /*  Create jitter buffer thread: */ 
     532 
     533    status = pj_thread_create(pool, "decode",  
     534                              &jitter_buffer_thread, stream, 
     535                              0, 0, &stream->thread); 
     536    if (status != PJ_SUCCESS) 
     537        goto err_cleanup; 
     538 
     539 
     540    /* Create decoder channel: */ 
     541 
     542    status = create_channel( pool, stream, PJMEDIA_DIR_DECODING, info, 
     543                             &codec_param, &stream->dec); 
     544    if (status != PJ_SUCCESS) 
     545        goto err_cleanup; 
     546 
     547 
     548    /* Create encoder channel: */ 
     549 
     550    status = create_channel( pool, stream, PJMEDIA_DIR_ENCODING, info, 
     551                             &codec_param, &stream->enc); 
     552    if (status != PJ_SUCCESS) 
     553        goto err_cleanup; 
     554 
     555 
     556    /* Success! */ 
     557    *p_stream = stream; 
     558    return PJ_SUCCESS; 
     559 
    501560 
    502561err_cleanup: 
    503     pj_media_stream_destroy(channel); 
    504     return NULL; 
    505 } 
    506  
    507  
    508 PJ_DEF(pj_status_t) pj_media_stream_create (pj_pool_t *pool, 
    509                                             pj_media_stream_t **enc_stream, 
    510                                             pj_media_stream_t **dec_stream, 
    511                                             pj_media_stream_create_param *param) 
    512 { 
    513     *dec_stream = *enc_stream = NULL; 
    514  
    515     if (param->dir & PJ_MEDIA_DIR_DECODING) { 
    516         *dec_stream =  
    517             create_channel(pool, PJ_MEDIA_DIR_DECODING, NULL, param->codec_id, param); 
    518         if (!*dec_stream) 
    519             return -1; 
    520     } 
    521  
    522     if (param->dir & PJ_MEDIA_DIR_ENCODING) { 
    523         *enc_stream =  
    524             create_channel(pool, PJ_MEDIA_DIR_ENCODING, *dec_stream, param->codec_id, param); 
    525         if (!*enc_stream) { 
    526             if (*dec_stream) { 
    527                 pj_media_stream_destroy(*dec_stream); 
    528                 *dec_stream = NULL; 
    529             } 
    530             return -1; 
    531         } 
    532  
    533         if (*dec_stream) { 
    534             (*dec_stream)->peer = *enc_stream; 
    535         } 
    536     } 
    537  
    538     return 0; 
    539 } 
    540  
    541 PJ_DEF(pj_status_t) pj_media_stream_start (pj_media_stream_t *channel) 
    542 { 
    543     pj_status_t status; 
    544  
    545     status = pj_snd_stream_start(channel->snd_stream); 
    546  
    547     if (status == 0) 
    548         channel->state = STREAM_STARTED; 
     562    pjmedia_stream_destroy(stream); 
    549563    return status; 
    550564} 
    551565 
    552 PJ_DEF(pj_status_t)  pj_media_stream_get_stat (const pj_media_stream_t *stream, 
    553                                                pj_media_stream_stat *stat) 
    554 { 
    555     if (stream->dir == PJ_MEDIA_DIR_ENCODING) { 
    556         pj_memcpy (stat, &stream->stat, sizeof(*stat)); 
    557     } else { 
    558         pj_rtcp_pkt *rtcp_pkt; 
    559         int len; 
    560  
    561         pj_memset (stat, 0, sizeof(*stat)); 
    562         pj_assert (stream->rtcp != 0); 
    563         pj_rtcp_build_rtcp (stream->rtcp, &rtcp_pkt, &len); 
    564  
    565         stat->pkt_rx = stream->stat.pkt_rx; 
    566         stat->oct_rx = stream->stat.oct_rx; 
    567  
    568         PJ_TODO(SUPPORT_JITTER_CALCULATION_FOR_NON_8KHZ_SAMPLE_RATE) 
    569         stat->jitter = pj_ntohl(rtcp_pkt->rr.jitter) / 8; 
    570         stat->pkt_lost = (rtcp_pkt->rr.total_lost_2 << 16) + 
    571                          (rtcp_pkt->rr.total_lost_1 << 8) + 
    572                          rtcp_pkt->rr.total_lost_0; 
    573     } 
    574     return 0; 
    575 } 
    576  
    577 PJ_DEF(pj_status_t) pj_media_stream_pause (pj_media_stream_t *channel) 
    578 { 
    579     PJ_UNUSED_ARG(channel); 
    580     return -1; 
    581 } 
    582  
    583 PJ_DEF(pj_status_t) pj_media_stream_resume (pj_media_stream_t *channel) 
    584 { 
    585     PJ_UNUSED_ARG(channel); 
    586     return -1; 
    587 } 
    588  
    589 PJ_DEF(pj_status_t) pj_media_stream_destroy (pj_media_stream_t *channel) 
    590 { 
    591     channel->thread_quit_flag = 1; 
    592  
    593     pj_mutex_lock (channel->mutex); 
    594     if (channel->peer) 
    595         pj_mutex_lock (channel->peer->mutex); 
    596  
    597     if (channel->jb) { 
    598         /* No need to deinitialize jitter buffer. */ 
    599     } 
    600     if (channel->transport_thread) { 
    601         pj_thread_join(channel->transport_thread); 
    602         pj_thread_destroy(channel->transport_thread); 
    603         channel->transport_thread = NULL; 
    604     } 
    605     if (channel->snd_stream != NULL) { 
    606         pj_mutex_unlock (channel->mutex); 
    607         pj_snd_stream_stop(channel->snd_stream); 
    608         pj_mutex_lock (channel->mutex); 
    609         pj_snd_stream_close(channel->snd_stream); 
    610         channel->snd_stream = NULL; 
    611     } 
    612     if (channel->codec) { 
    613         channel->codec->op->close(channel->codec); 
    614         pj_codec_mgr_dealloc_codec(channel->codec_mgr, channel->codec); 
    615         channel->codec = NULL; 
    616     } 
    617     if (channel->peer) { 
    618         pj_media_stream_t *peer = channel->peer; 
    619         peer->peer = NULL; 
    620         peer->codec = NULL; 
    621         peer->thread_quit_flag = 1; 
    622         if (peer->transport_thread) { 
    623             pj_mutex_unlock (peer->mutex); 
    624             pj_thread_join(peer->transport_thread); 
    625             pj_mutex_lock (peer->mutex); 
    626             pj_thread_destroy(peer->transport_thread); 
    627             peer->transport_thread = NULL; 
    628         } 
    629         if (peer->snd_stream) { 
    630             pj_mutex_unlock (peer->mutex); 
    631             pj_snd_stream_stop(peer->snd_stream); 
    632             pj_mutex_lock (peer->mutex); 
    633             pj_snd_stream_close(peer->snd_stream); 
    634             peer->snd_stream = NULL; 
    635         } 
    636     } 
    637  
    638     channel->state = STREAM_STOPPED; 
    639  
    640     if (channel->peer) 
    641         pj_mutex_unlock (channel->peer->mutex); 
    642     pj_mutex_unlock(channel->mutex); 
    643     pj_mutex_destroy(channel->mutex); 
    644  
    645     return 0; 
    646 } 
    647  
     566 
     567/* 
     568 * Destroy stream. 
     569 */ 
     570PJ_DEF(pj_status_t) pjmedia_stream_destroy( pjmedia_stream *stream ) 
     571{ 
     572 
     573    PJ_ASSERT_RETURN(stream != NULL, PJ_EINVAL); 
     574 
     575    /* Signal threads to quit. */ 
     576 
     577    stream->quit_flag = 1; 
     578 
     579 
     580    /* Close encoding sound stream. */ 
     581     
     582    if (stream->enc && stream->enc->snd_stream) { 
     583 
     584        pj_snd_stream_stop(stream->enc->snd_stream); 
     585        pj_snd_stream_close(stream->enc->snd_stream); 
     586        stream->enc->snd_stream = NULL; 
     587 
     588    } 
     589 
     590    /* Close decoding sound stream. */ 
     591 
     592    if (stream->dec && stream->dec->snd_stream) { 
     593 
     594        pj_snd_stream_stop(stream->dec->snd_stream); 
     595        pj_snd_stream_close(stream->dec->snd_stream); 
     596        stream->dec->snd_stream = NULL; 
     597 
     598    } 
     599 
     600    /* Wait for jitter buffer thread to quit: */ 
     601 
     602    if (stream->thread) { 
     603        pj_thread_join(stream->thread); 
     604        pj_thread_destroy(stream->thread); 
     605        stream->thread = NULL; 
     606    } 
     607 
     608    /* Free codec. */ 
     609 
     610    if (stream->codec) { 
     611        stream->codec->op->close(stream->codec); 
     612        pjmedia_codec_mgr_dealloc_codec(stream->codec_mgr, stream->codec); 
     613        stream->codec = NULL; 
     614    } 
     615 
     616    /* Free mutex */ 
     617     
     618    if (stream->jb_mutex) { 
     619        pj_mutex_destroy(stream->jb_mutex); 
     620        stream->jb_mutex = NULL; 
     621    } 
     622 
     623    return PJ_SUCCESS; 
     624} 
     625 
     626 
     627 
     628/* 
     629 * Start stream. 
     630 */ 
     631PJ_DEF(pj_status_t) pjmedia_stream_start(pjmedia_stream *stream) 
     632{ 
     633 
     634    PJ_ASSERT_RETURN(stream && stream->enc && stream->dec, PJ_EINVALIDOP); 
     635 
     636    if (stream->enc && (stream->dir & PJMEDIA_DIR_ENCODING)) { 
     637        stream->enc->paused = 0; 
     638        pj_snd_stream_start(stream->enc->snd_stream); 
     639    } 
     640 
     641    if (stream->dec && (stream->dir & PJMEDIA_DIR_DECODING)) { 
     642        stream->dec->paused = 0; 
     643        pj_snd_stream_start(stream->dec->snd_stream); 
     644    } 
     645 
     646    return PJ_SUCCESS; 
     647} 
     648 
     649 
     650/* 
     651 * Get stream statistics. 
     652 */ 
     653PJ_DEF(pj_status_t) pjmedia_stream_get_stat( const pjmedia_stream *stream, 
     654                                             pjmedia_stream_stat *stat) 
     655{ 
     656    PJ_ASSERT_RETURN(stream && stat, PJ_EINVAL); 
     657 
     658    pj_memcpy(stat, &stream->stat, sizeof(pjmedia_stream_stat)); 
     659 
     660    return PJ_SUCCESS; 
     661} 
     662 
     663 
     664/* 
     665 * Pause stream. 
     666 */ 
     667PJ_DEF(pj_status_t) pjmedia_stream_pause( pjmedia_stream *stream, 
     668                                          pjmedia_dir dir) 
     669{ 
     670    PJ_ASSERT_RETURN(stream, PJ_EINVAL); 
     671 
     672    if ((dir & PJMEDIA_DIR_ENCODING) && stream->enc) 
     673        stream->enc->paused = 1; 
     674 
     675    if ((dir & PJMEDIA_DIR_DECODING) && stream->dec) 
     676        stream->dec->paused = 1; 
     677 
     678    return PJ_SUCCESS; 
     679} 
     680 
     681 
     682/* 
     683 * Resume stream 
     684 */ 
     685PJ_DEF(pj_status_t) pjmedia_stream_resume( pjmedia_stream *stream, 
     686                                           pjmedia_dir dir) 
     687{ 
     688    PJ_ASSERT_RETURN(stream, PJ_EINVAL); 
     689 
     690    if ((dir & PJMEDIA_DIR_ENCODING) && stream->enc) 
     691        stream->enc->paused = 1; 
     692 
     693    if ((dir & PJMEDIA_DIR_DECODING) && stream->dec) 
     694        stream->dec->paused = 1; 
     695 
     696    return PJ_SUCCESS; 
     697} 
     698 
  • pjproject/trunk/pjmedia/src/test/audio_tool.c

    r65 r159  
    2727static FILE *fhnd; 
    2828static pj_med_mgr_t *mm; 
    29 static pj_codec *codec; 
    30 static pj_codec_attr cattr; 
     29static pjmedia_codec *codec; 
     30static pjmedia_codec_param cattr; 
    3131 
    3232 
     
    6161{ 
    6262    char pkt[160]; 
    63     struct pj_audio_frame in, out; 
     63    struct pjmedia_frame in, out; 
    6464    int frmsz = cattr.avg_bps / 8 * cattr.ptime / 1000; 
    6565 
     
    6868        return -1; 
    6969    } else { 
    70         in.type = PJ_AUDIO_FRAME_AUDIO; 
     70        in.type = PJMEDIA_FRAME_TYPE_AUDIO; 
    7171        in.buf = pkt; 
    7272        in.size = frmsz; 
     
    8686{ 
    8787    char pkt[160]; 
    88     struct pj_audio_frame in, out; 
     88    struct pjmedia_frame in, out; 
    8989    //int frmsz = cattr.avg_bps / 8 * cattr.ptime / 1000; 
    9090 
     
    9393#endif 
    9494 
    95     in.type = PJ_AUDIO_FRAME_AUDIO; 
     95    in.type = PJMEDIA_FRAME_TYPE_AUDIO; 
    9696    in.buf = (void*)frame; 
    9797    in.size = size; 
     
    108108static pj_status_t init() 
    109109{ 
    110     pj_codec_mgr *cm; 
    111     pj_codec_id id; 
     110    pjmedia_codec_mgr *cm; 
     111    pjmedia_codec_info id; 
    112112    int i; 
    113113 
     
    130130    cm = pj_med_mgr_get_codec_mgr (mm); 
    131131 
    132     id.type = PJ_MEDIA_TYPE_AUDIO; 
     132    id.type = PJMEDIA_TYPE_AUDIO; 
    133133    id.pt = 0; 
    134134    id.encoding_name = pj_str("PCMU"); 
    135135    id.sample_rate = 8000; 
    136136 
    137     codec = pj_codec_mgr_alloc_codec (cm, &id); 
     137    codec = pjmedia_codec_mgr_alloc_codec (cm, &id); 
    138138    codec->op->default_attr(codec, &cattr); 
    139139    codec->op->open(codec, &cattr); 
     
    143143static pj_status_t deinit() 
    144144{ 
    145     pj_codec_mgr *cm; 
     145    pjmedia_codec_mgr *cm; 
    146146    cm = pj_med_mgr_get_codec_mgr (mm); 
    147147    codec->op->close(codec); 
    148     pj_codec_mgr_dealloc_codec (cm, codec); 
     148    pjmedia_codec_mgr_dealloc_codec (cm, codec); 
    149149    pj_med_mgr_destroy (mm); 
    150150    pj_caching_pool_destroy(&caching_pool); 
     
    301301 
    302302        switch (info[i]->dir) { 
    303         case PJ_MEDIA_DIR_NONE: 
     303        case PJMEDIA_DIR_NONE: 
    304304            dir = "- NONE -"; break; 
    305         case PJ_MEDIA_DIR_ENCODING: 
     305        case PJMEDIA_DIR_ENCODING: 
    306306            dir = "SENDONLY"; break; 
    307         case PJ_MEDIA_DIR_DECODING: 
     307        case PJMEDIA_DIR_DECODING: 
    308308            dir = "RECVONLY"; break; 
    309         case PJ_MEDIA_DIR_ENCODING_DECODING: 
     309        case PJMEDIA_DIR_ENCODING_DECODING: 
    310310            dir = "SENDRECV"; break; 
    311311        default: 
     
    346346    char pcm[320]; 
    347347    char frame[160]; 
    348     struct pj_audio_frame in, out; 
     348    struct pjmedia_frame in, out; 
    349349 
    350350    fhnd_pcm = fopen(src, "rb"); 
     
    357357    while (fread(pcm, 320, 1, fhnd_pcm) == 1) { 
    358358 
    359         in.type = PJ_AUDIO_FRAME_AUDIO; 
     359        in.type = PJMEDIA_FRAME_TYPE_AUDIO; 
    360360        in.buf = pcm; 
    361361        in.size = 320; 
  • pjproject/trunk/pjmedia/src/test/session_test.c

    r65 r159  
    4545 
    4646    // Set caller's media to send-only. 
    47     sd_info.dir = PJ_MEDIA_DIR_ENCODING; 
    48     pj_media_session_modify_stream (s1, 0, PJ_MEDIA_STREAM_MODIFY_DIR, &sd_info); 
     47    sd_info.dir = PJMEDIA_DIR_ENCODING; 
     48    pj_media_session_modify_stream (s1, 0, PJMEDIA_STREAM_MODIFY_DIR, &sd_info); 
    4949 
    5050    // Create caller SDP. 
Note: See TracChangeset for help on using the changeset viewer.