Changeset 438


Ignore:
Timestamp:
May 13, 2006 10:46:23 PM (18 years ago)
Author:
bennylp
Message:

Another major modifications in PJMEDIA:

  • handle multiple frames in one packet
  • split stream creation into two steps to allow customization
  • PLC framework and implementation with G.711 and speex
  • stream returns NO_FRAME correctly.
  • added ptime argument in pjsua
Location:
pjproject/trunk
Files:
27 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjlib/src/pj/ioqueue_common_abs.c

    r433 r438  
    7171    pj_status_t rc; 
    7272    int optlen; 
     73 
     74    PJ_UNUSED_ARG(pool); 
    7375 
    7476    key->ioqueue = ioqueue; 
  • pjproject/trunk/pjmedia/include/pjmedia/codec.h

    r421 r438  
    111111struct pjmedia_codec_param 
    112112{ 
    113     unsigned    clock_rate;         /**< Sampling rate in Hz            */ 
    114     unsigned    channel_cnt;        /**< Channel count.                 */ 
    115     pj_uint32_t avg_bps;            /**< Average bandwidth in bits/sec  */ 
    116  
    117     pj_uint16_t ptime;              /**< Packet time in miliseconds     */ 
    118     pj_uint8_t  pcm_bits_per_sample;/**< Bits/sample in the PCM side    */ 
    119  
    120     unsigned    pt:8;               /**< Payload type.                  */ 
    121     unsigned    vad:1;              /**< Voice Activity Detector.       */ 
    122     unsigned    cng:1;              /**< Comfort Noise Generator.       */ 
    123     unsigned    lpf:1;              /**< Low pass filter                */ 
    124     unsigned    hpf:1;              /**< High pass filter               */ 
    125     unsigned    penh:1;             /**< Perceptual Enhancement         */ 
    126     unsigned    concl:1;            /**< Packet loss concealment        */ 
    127     unsigned    reserved:1;         /**< Reserved, must be NULL.        */ 
    128  
     113    /** 
     114     * The "info" part of codec param describes the capability of the codec, 
     115     * and the value should NOT be changed by application. 
     116     */ 
     117    struct { 
     118       unsigned    clock_rate;          /**< Sampling rate in Hz            */ 
     119       unsigned    channel_cnt;         /**< Channel count.                 */ 
     120       pj_uint32_t avg_bps;             /**< Average bandwidth in bits/sec  */ 
     121       pj_uint16_t frm_ptime;           /**< Base frame ptime in msec.      */ 
     122       pj_uint8_t  pcm_bits_per_sample; /**< Bits/sample in the PCM side    */ 
     123       pj_uint8_t  pt;                  /**< Payload type.                  */ 
     124    } info; 
     125 
     126    /** 
     127     * The "setting" part of codec param describes various settings to be 
     128     * applied to the codec. When the codec param is retrieved from the codec 
     129     * or codec factory, the values of these will be filled by the capability 
     130     * of the codec. Any features that are supported by the codec (e.g. vad 
     131     * or plc) will be turned on, so that application can query which  
     132     * capabilities are supported by the codec. Application may change the 
     133     * settings here before instantiating the codec/stream. 
     134     */ 
     135    struct { 
     136        pj_uint8_t  frm_per_pkt;    /**< Number of frames per packet.   */ 
     137        unsigned    vad:1;          /**< Voice Activity Detector.       */ 
     138        unsigned    cng:1;          /**< Comfort Noise Generator.       */ 
     139        unsigned    lpf:1;          /**< Low pass filter                */ 
     140        unsigned    hpf:1;          /**< High pass filter               */ 
     141        unsigned    penh:1;         /**< Perceptual Enhancement         */ 
     142        unsigned    plc:1;          /**< Packet loss concealment        */ 
     143        unsigned    reserved:1;     /**< Reserved, must be zero.        */ 
     144    } setting; 
    129145}; 
    130146 
     
    183199    /** 
    184200     * Instruct the codec to inspect the specified payload/packet and 
    185      * split the packet info individual frames. 
     201     * split the packet into individual base frames. Each output frames will 
     202     * have ptime that is equal to basic frame ptime (i.e. the value of 
     203     * info.frm_ptime in #pjmedia_codec_param). 
    186204     * 
    187205     * @param codec     The codec instance 
    188206     * @param pkt       The input packet. 
    189207     * @param pkt_size  Size of the packet. 
     208     * @param timestamp The timestamp of the first sample in the packet. 
    190209     * @param frame_cnt On input, specifies the maximum number of frames 
    191210     *                  in the array. On output, the codec must fill 
     
    196215     * @return          PJ_SUCCESS on success. 
    197216     */ 
    198     pj_status_t (*get_frames)(pjmedia_codec *codec, 
    199                               void *pkt, 
    200                               pj_size_t pkt_size, 
    201                               unsigned *frame_cnt, 
    202                               pjmedia_frame frames[]); 
    203  
    204     /**  
    205      * Instruct the codec to encode the specified input frame. 
     217    pj_status_t (*parse)( pjmedia_codec *codec, 
     218                          void *pkt, 
     219                          pj_size_t pkt_size, 
     220                          const pj_timestamp *timestamp, 
     221                          unsigned *frame_cnt, 
     222                          pjmedia_frame frames[]); 
     223 
     224    /**  
     225     * Instruct the codec to encode the specified input frame. The input 
     226     * PCM samples MUST have ptime that is exactly equal to base frame 
     227     * ptime (i.e. the value of info.frm_ptime in #pjmedia_codec_param). 
    206228     * 
    207229     * @param codec     The codec instance. 
     
    218240 
    219241    /**  
    220      * Instruct the codec to decode the specified input frame. 
     242     * Instruct the codec to decode the specified input frame. The input 
     243     * frame MUST have ptime that is exactly equal to base frame 
     244     * ptime (i.e. the value of info.frm_ptime in #pjmedia_codec_param). 
     245     * Application can achieve this by parsing the packet into base 
     246     * frames before decoding each frame. 
    221247     * 
    222248     * @param codec     The codec instance. 
     
    232258                          struct pjmedia_frame *output); 
    233259 
     260    /** 
     261     * Instruct the codec to recover a missing frame. Not all codec has 
     262     * this capability, so this function may be NULL. 
     263     * 
     264     * @param codec     The codec instance. 
     265     * @param out_size  The length of buffer in the output frame. 
     266     * @param output    The output frame. 
     267     * 
     268     * @return          PJ_SUCCESS on success; 
     269     */ 
     270    pj_status_t (*recover)(pjmedia_codec *codec, 
     271                           unsigned out_size, 
     272                           struct pjmedia_frame *output); 
    234273}; 
    235274 
  • pjproject/trunk/pjmedia/include/pjmedia/config.h

    r417 r438  
    7878/** 
    7979 * Maximum frame duration (in msec) to be supported. 
     80 * This (among other thing) will affect the size of buffers to be allocated 
     81 * for outgoing packets. 
    8082 */ 
    8183#ifndef PJMEDIA_MAX_FRAME_DURATION_MS    
  • pjproject/trunk/pjmedia/include/pjmedia/errno.h

    r420 r438  
    276276 */ 
    277277#define PJMEDIA_CODEC_EPCMTOOSHORT  (PJMEDIA_ERRNO_START+83)    /* 220083 */ 
     278/** 
     279 * @hideinitializer 
     280 * Invalid codec frame length. 
     281 */ 
     282#define PJMEDIA_CODEC_EFRMINLEN     (PJMEDIA_ERRNO_START+84)    /* 220084 */ 
    278283 
    279284 
  • pjproject/trunk/pjmedia/include/pjmedia/jbuf.h

    r436 r438  
    5656 
    5757/** 
     58 * @see pjmedia_jb_frame_type. 
     59 */ 
     60typedef enum pjmedia_jb_frame_type pjmedia_jb_frame_type; 
     61 
     62 
     63/** 
    5864 * This structure describes jitter buffer current status. 
    5965 */ 
     
    7985 */ 
    8086#define PJMEDIA_JB_DEFAULT_INIT_DELAY    15 
     87 
     88/** 
     89 * Opaque declaration for jitter buffer. 
     90 */ 
     91typedef struct pjmedia_jbuf pjmedia_jbuf; 
    8192 
    8293 
     
    182193 * @return              PJ_SUCCESS on success. 
    183194 */ 
    184 PJ_DECL(pj_status_t) pjmedia_jbuf_put_frame(pjmedia_jbuf *jb,  
    185                                             const void *frame,  
    186                                             pj_size_t size,  
    187                                             int frame_seq); 
     195PJ_DECL(void) pjmedia_jbuf_put_frame( pjmedia_jbuf *jb,  
     196                                      const void *frame,  
     197                                      pj_size_t size,  
     198                                      int frame_seq); 
    188199 
    189200/** 
     
    211222 *                      buffer will copy the frame to the buffer, and frame 
    212223 *                      type will be set to PJMEDIA_JB_NORMAL_FRAME. 
    213  * 
    214  * @return              Always returns PJ_SUCCESS. 
    215  */ 
    216 PJ_DECL(pj_status_t) pjmedia_jbuf_get_frame( pjmedia_jbuf *jb,  
    217                                              void *frame,  
    218                                              char *p_frm_type); 
     224 */ 
     225PJ_DECL(void) pjmedia_jbuf_get_frame( pjmedia_jbuf *jb,  
     226                                      void *frame,  
     227                                      char *p_frm_type); 
    219228 
    220229 
  • pjproject/trunk/pjmedia/include/pjmedia/session.h

    r414 r438  
    6767 
    6868 
    69 /** 
    70  * Initialize stream info from SDP media lines. 
    71  * 
    72  * @param si            Stream info structure to be initialized. 
    73  * @param pool          Pool. 
     69/**  
     70 * Opaque declaration of media session.  
     71 */ 
     72typedef struct pjmedia_session pjmedia_session; 
     73 
     74 
     75/** 
     76 * @see pjmedia_session_info. 
     77 */ 
     78typedef struct pjmedia_session_info pjmedia_session_info; 
     79 
     80 
     81/** 
     82 * This function will initialize the session info based on information 
     83 * in both SDP session descriptors. The remaining information will be 
     84 * taken from default codec parameters. If socket info array is specified, 
     85 * the socket will be copied to the session info as well. 
     86 * 
     87 * @param pool          Pool to allocate memory. 
    7488 * @param endpt         Pjmedia endpoint. 
     89 * @param max_streams   Maximum number of stream infos to be created. 
     90 * @param si            Session info structure to be initialized. 
     91 * @param skinfo        Optional array of media socket info to be copied 
     92 *                      to the stream info. If this argument is specified, 
     93 *                      the array must contain sufficient elements for 
     94 *                      each stream to be initialized. 
    7595 * @param local         Local SDP session descriptor. 
    7696 * @param remote        Remote SDP session descriptor. 
     
    7999 * @return              PJ_SUCCESS if stream info is successfully initialized. 
    80100 */ 
    81 PJ_DECL(pj_status_t) pjmedia_stream_info_from_sdp(  
    82                                            pjmedia_stream_info *si, 
    83                                            pj_pool_t *pool, 
    84                                            pjmedia_endpt *endpt, 
    85                                            const pjmedia_sdp_session *local, 
    86                                            const pjmedia_sdp_session *remote, 
    87                                            unsigned stream_idx); 
    88  
     101PJ_DECL(pj_status_t) 
     102pjmedia_session_info_from_sdp( pj_pool_t *pool, 
     103                               pjmedia_endpt *endpt, 
     104                               unsigned max_streams, 
     105                               pjmedia_session_info *si, 
     106                               const pjmedia_sock_info skinfo[], 
     107                               const pjmedia_sdp_session *local, 
     108                               const pjmedia_sdp_session *remote); 
     109 
     110 
     111/* 
     112 * This function will initialize the stream info based on information 
     113 * in both SDP session descriptors for the specified stream index.  
     114 * The remaining information will be taken from default codec parameters.  
     115 * If socket info array is specified, the socket will be copied to the  
     116 * session info as well. 
     117 * 
     118 * @param si            Stream info structure to be initialized. 
     119 * @param pool          Pool to allocate memory. 
     120 * @param endpt         PJMEDIA endpoint instance. 
     121 * @param skinfo        Optional socket info to be copied to the stream info. 
     122 * @param local         Local SDP session descriptor. 
     123 * @param remote        Remote SDP session descriptor. 
     124 * @param stream_idx    Media stream index in the session descriptor. 
     125 * 
     126 * @return              PJ_SUCCESS if stream info is successfully initialized. 
     127 */ 
     128PJ_DECL(pj_status_t) 
     129pjmedia_stream_info_from_sdp( pjmedia_stream_info *si, 
     130                              pj_pool_t *pool, 
     131                              pjmedia_endpt *endpt, 
     132                              const pjmedia_sock_info *skinfo, 
     133                              const pjmedia_sdp_session *local, 
     134                              const pjmedia_sdp_session *remote, 
     135                              unsigned stream_idx); 
    89136 
    90137/** 
     
    102149 *                      also denotes the number of elements in the 
    103150 *                      socket information. 
    104  * @param skinfo        Array of socket informations. The argument stream_cnt 
    105  *                      specifies the number of elements in this array. One 
    106  *                      element is needed for each media stream to be 
    107  *                      created in the session. 
    108151 * @param local_sdp     The SDP describing local capability. 
    109152 * @param rem_sdp       The SDP describing remote capability. 
     
    116159PJ_DECL(pj_status_t)  
    117160pjmedia_session_create( pjmedia_endpt *endpt,  
    118                         unsigned stream_cnt, 
    119                         const pjmedia_sock_info skinfo[], 
    120                         const pjmedia_sdp_session *local_sdp, 
    121                         const pjmedia_sdp_session *rem_sdp, 
     161                        const pjmedia_session_info *si, 
    122162                        void *user_data, 
    123163                        pjmedia_session **p_session ); 
  • pjproject/trunk/pjmedia/include/pjmedia/stream.h

    r428 r438  
    7373    pj_sockaddr_in      rem_addr;   /**< Remote RTP address                 */ 
    7474    pjmedia_codec_info  fmt;        /**< Incoming codec format info.        */ 
     75    pjmedia_codec_param *param;     /**< Optional codec param.              */ 
    7576    unsigned            tx_pt;      /**< Outgoing codec paylaod type.       */ 
    7677    int                 tx_event_pt;/**< Outgoing pt for telephone-events.  */ 
    7778    int                 rx_event_pt;/**< Incoming pt for telephone-events.  */ 
    7879    pj_uint32_t         ssrc;       /**< RTP SSRC.                          */ 
    79     int                 jb_init;    /**< Jitter buffer init delay in msec.  */ 
     80    int                 jb_init;    /**< Jitter buffer init delay in msec.   
     81                                         (-1 for default).                  */ 
     82    int                 jb_min_pre; /**< Jitter buffer minimum prefetch 
     83                                         delay in msec (-1 for default).    */ 
     84    int                 jb_max_pre; /**< Jitter buffer maximum prefetch 
     85                                         delay in msec (-1 for default).    */ 
    8086    int                 jb_max;     /**< Jitter buffer max delay in msec.   */ 
    8187}; 
     88 
     89 
     90/** 
     91 * @see pjmedia_stream_info. 
     92 */ 
     93typedef struct pjmedia_stream_info pjmedia_stream_info; 
     94 
     95 
     96/** 
     97 * Opaque declaration for media stream. 
     98 */ 
     99typedef struct pjmedia_stream pjmedia_stream; 
    82100 
    83101 
  • pjproject/trunk/pjmedia/include/pjmedia/types.h

    r411 r438  
    115115 
    116116/** 
    117  * Typedef for media stream information. 
     117 * This is a general purpose function set PCM samples to zero. 
     118 * Since this function is needed by many parts of the library, it is important 
     119 * that the library should select the best performance for this. 
     120 * 
     121 * @param samples       The 16bit PCM samples. 
     122 * @param count         Number of samples. 
    118123 */ 
    119 typedef struct pjmedia_stream_info pjmedia_stream_info; 
     124PJ_INLINE(void) pjmedia_zero_samples(pj_int16_t *samples, unsigned count) 
     125{ 
     126    unsigned i; 
     127    for (i=0; i<count; ++i) 
     128        samples[i] = 0; 
     129} 
    120130 
    121 /** 
    122  * Typedef for media stream statistic. 
    123  */ 
    124 typedef struct pjmedia_stream_stat pjmedia_stream_stat; 
    125  
    126 /** 
    127  * Typedef for media stream. 
    128  */ 
    129 typedef struct pjmedia_stream pjmedia_stream; 
    130  
    131 /** 
    132  * Individual channel statistic. 
    133  */ 
    134 typedef struct pjmedia_channel_stat pjmedia_channel_stat; 
    135  
    136 /**  
    137  * Opaque declaration of media session.  
    138  */ 
    139 typedef struct pjmedia_session pjmedia_session; 
    140  
    141 /** 
    142  * Media session info. 
    143  */ 
    144 typedef struct pjmedia_session_info pjmedia_session_info; 
    145  
    146 /** 
    147  * Types of frame returned from jitter buffer (jbuf.h). 
    148  */ 
    149 typedef enum pjmedia_jb_frame_type pjmedia_jb_frame_type; 
    150  
    151 /** 
    152  * Opaque declaration for jitter buffer. 
    153  */ 
    154 typedef struct pjmedia_jbuf pjmedia_jbuf; 
    155131 
    156132#endif  /* __PJMEDIA_TYPES_H__ */ 
  • pjproject/trunk/pjmedia/src/pjmedia-codec/gsm.c

    r411 r438  
    5555                                    pjmedia_codec_param *attr ); 
    5656static pj_status_t  gsm_codec_close( pjmedia_codec *codec ); 
    57 static pj_status_t  gsm_codec_get_frames( pjmedia_codec *codec, 
    58                                           void *pkt, 
    59                                           pj_size_t pkt_size, 
    60                                           unsigned *frame_cnt, 
    61                                           pjmedia_frame frames[]); 
     57static pj_status_t  gsm_codec_parse( pjmedia_codec *codec, 
     58                                     void *pkt, 
     59                                     pj_size_t pkt_size, 
     60                                     const pj_timestamp *ts, 
     61                                     unsigned *frame_cnt, 
     62                                     pjmedia_frame frames[]); 
    6263static pj_status_t  gsm_codec_encode( pjmedia_codec *codec,  
    6364                                      const struct pjmedia_frame *input, 
     
    7576    &gsm_codec_open, 
    7677    &gsm_codec_close, 
    77     &gsm_codec_get_frames, 
     78    &gsm_codec_parse, 
    7879    &gsm_codec_encode, 
    7980    &gsm_codec_decode 
     
    231232 
    232233    pj_memset(attr, 0, sizeof(pjmedia_codec_param)); 
    233     attr->clock_rate = 8000; 
    234     attr->channel_cnt = 1; 
    235     attr->avg_bps = 13200; 
    236     attr->pcm_bits_per_sample = 16; 
    237     attr->ptime = 20; 
    238     attr->pt = PJMEDIA_RTP_PT_GSM; 
     234    attr->info.clock_rate = 8000; 
     235    attr->info.channel_cnt = 1; 
     236    attr->info.avg_bps = 13200; 
     237    attr->info.pcm_bits_per_sample = 16; 
     238    attr->info.frm_ptime = 20; 
     239    attr->info.pt = PJMEDIA_RTP_PT_GSM; 
     240 
     241    attr->setting.frm_per_pkt = 1; 
    239242 
    240243    /* Default all flag bits disabled. */ 
     
    387390 * Get frames in the packet. 
    388391 */ 
    389 static pj_status_t  gsm_codec_get_frames( pjmedia_codec *codec, 
    390                                           void *pkt, 
    391                                           pj_size_t pkt_size, 
    392                                           unsigned *frame_cnt, 
    393                                           pjmedia_frame frames[]) 
     392static pj_status_t  gsm_codec_parse( pjmedia_codec *codec, 
     393                                     void *pkt, 
     394                                     pj_size_t pkt_size, 
     395                                     const pj_timestamp *ts, 
     396                                     unsigned *frame_cnt, 
     397                                     pjmedia_frame frames[]) 
    394398{ 
    395399    unsigned count = 0; 
     
    400404 
    401405    while (pkt_size >= 33 && count < *frame_cnt) { 
    402         frames[0].type = PJMEDIA_FRAME_TYPE_AUDIO; 
    403         frames[0].buf = pkt; 
    404         frames[0].size = 33; 
     406        frames[count].type = PJMEDIA_FRAME_TYPE_AUDIO; 
     407        frames[count].buf = pkt; 
     408        frames[count].size = 33; 
     409        frames[count].timestamp.u64 = ts->u64 + count * 160; 
    405410 
    406411        pkt = ((char*)pkt) + 33; 
  • pjproject/trunk/pjmedia/src/pjmedia-codec/l16.c

    r411 r438  
    6262                               pjmedia_codec_param *attr ); 
    6363static pj_status_t  l16_close( pjmedia_codec *codec ); 
    64 static pj_status_t  l16_get_frames(pjmedia_codec *codec, 
    65                                     void *pkt, 
    66                                     pj_size_t pkt_size, 
    67                                     unsigned *frame_cnt, 
    68                                     pjmedia_frame frames[]); 
     64static pj_status_t  l16_parse(pjmedia_codec *codec, 
     65                              void *pkt, 
     66                              pj_size_t pkt_size, 
     67                              const pj_timestamp *ts, 
     68                              unsigned *frame_cnt, 
     69                              pjmedia_frame frames[]); 
    6970static pj_status_t  l16_encode( pjmedia_codec *codec,  
    7071                                 const struct pjmedia_frame *input, 
     
    8283    &l16_open, 
    8384    &l16_close, 
    84     &l16_get_frames, 
     85    &l16_parse, 
    8586    &l16_encode, 
    8687    &l16_decode 
     
    235236 
    236237    pj_memset(attr, 0, sizeof(pjmedia_codec_param)); 
    237     attr->pt = id->pt; 
    238     attr->clock_rate = id->clock_rate; 
    239     attr->channel_cnt = id->channel_cnt; 
    240     attr->avg_bps = id->clock_rate * id->channel_cnt * 16; 
    241     attr->pcm_bits_per_sample = 16; 
     238    attr->info.pt = (pj_uint8_t)id->pt; 
     239    attr->info.clock_rate = id->clock_rate; 
     240    attr->info.channel_cnt = id->channel_cnt; 
     241    attr->info.avg_bps = id->clock_rate * id->channel_cnt * 16; 
     242    attr->info.pcm_bits_per_sample = 16; 
    242243 
    243244    /* To keep frame size below 1400 MTU, set ptime to 10ms for 
    244245     * sampling rate > 35 KHz 
    245246     */ 
    246     attr->ptime = GET_PTIME(id->clock_rate); 
     247    attr->info.frm_ptime = GET_PTIME(id->clock_rate); 
     248 
     249    attr->setting.frm_per_pkt = 1; 
    247250 
    248251    /* Default all flag bits disabled. */ 
     
    499502} 
    500503 
    501 static pj_status_t  l16_get_frames( pjmedia_codec *codec, 
    502                                     void *pkt, 
    503                                     pj_size_t pkt_size, 
    504                                     unsigned *frame_cnt, 
    505                                     pjmedia_frame frames[]) 
     504static pj_status_t  l16_parse( pjmedia_codec *codec, 
     505                               void *pkt, 
     506                               pj_size_t pkt_size, 
     507                               const pj_timestamp *ts, 
     508                               unsigned *frame_cnt, 
     509                               pjmedia_frame frames[]) 
    506510{ 
    507511    unsigned count = 0; 
     
    512516 
    513517    while (pkt_size >= data->frame_size && count < *frame_cnt) { 
    514         frames[0].type = PJMEDIA_FRAME_TYPE_AUDIO; 
    515         frames[0].buf = pkt; 
    516         frames[0].size = data->frame_size; 
     518        frames[count].type = PJMEDIA_FRAME_TYPE_AUDIO; 
     519        frames[count].buf = pkt; 
     520        frames[count].size = data->frame_size; 
     521        frames[count].timestamp.u64 = ts->u64 + (count * data->frame_size); 
    517522 
    518523        pkt = ((char*)pkt) + data->frame_size; 
  • pjproject/trunk/pjmedia/src/pjmedia-codec/speex/ltp.c

    r278 r438  
    177177   VARDECL(spx_word32_t *energy); 
    178178   VARDECL(spx_word32_t *score); 
    179    VARDECL(spx_word16_t *swn2); 
     179   /*VARDECL(spx_word16_t *swn2);*/ 
    180180   spx_word16_t *swn; 
    181181 
  • pjproject/trunk/pjmedia/src/pjmedia-codec/speex_codec.c

    r411 r438  
    6262                                    pjmedia_codec_param *attr ); 
    6363static pj_status_t  spx_codec_close( pjmedia_codec *codec ); 
    64 static pj_status_t  spx_codec_get_frames( pjmedia_codec *codec, 
    65                                           void *pkt, 
    66                                           pj_size_t pkt_size, 
    67                                           unsigned *frame_cnt, 
    68                                           pjmedia_frame frames[]); 
     64static pj_status_t  spx_codec_parse( pjmedia_codec *codec, 
     65                                     void *pkt, 
     66                                     pj_size_t pkt_size, 
     67                                     const pj_timestamp *ts, 
     68                                     unsigned *frame_cnt, 
     69                                     pjmedia_frame frames[]); 
    6970static pj_status_t  spx_codec_encode( pjmedia_codec *codec,  
    7071                                      const struct pjmedia_frame *input, 
     
    7576                                      unsigned output_buf_len,  
    7677                                      struct pjmedia_frame *output); 
     78static pj_status_t  spx_codec_recover(pjmedia_codec *codec,  
     79                                      unsigned output_buf_len,  
     80                                      struct pjmedia_frame *output); 
    7781 
    7882/* Definition for Speex codec operations. */ 
     
    8286    &spx_codec_open, 
    8387    &spx_codec_close, 
    84     &spx_codec_get_frames, 
     88    &spx_codec_parse, 
    8589    &spx_codec_encode, 
    86     &spx_codec_decode 
     90    &spx_codec_decode, 
     91    &spx_codec_recover 
    8792}; 
    8893 
     
    378383 
    379384    pj_memset(attr, 0, sizeof(pjmedia_codec_param)); 
    380     attr->pt = id->pt; 
    381     attr->channel_cnt = 1; 
     385    attr->info.pt = (pj_uint8_t)id->pt; 
     386    attr->info.channel_cnt = 1; 
    382387 
    383388    if (id->clock_rate <= 8000) { 
    384         attr->clock_rate = spx_factory.speex_param[PARAM_NB].clock_rate; 
    385         attr->avg_bps = spx_factory.speex_param[PARAM_NB].bitrate; 
     389        attr->info.clock_rate = spx_factory.speex_param[PARAM_NB].clock_rate; 
     390        attr->info.avg_bps = spx_factory.speex_param[PARAM_NB].bitrate; 
    386391 
    387392    } else if (id->clock_rate <= 16000) { 
    388         attr->clock_rate = spx_factory.speex_param[PARAM_WB].clock_rate; 
    389         attr->avg_bps = spx_factory.speex_param[PARAM_WB].bitrate; 
     393        attr->info.clock_rate = spx_factory.speex_param[PARAM_WB].clock_rate; 
     394        attr->info.avg_bps = spx_factory.speex_param[PARAM_WB].bitrate; 
    390395 
    391396    } else { 
    392397        /* Wow.. somebody is doing ultra-wideband. Cool...! */ 
    393         attr->clock_rate = spx_factory.speex_param[PARAM_UWB].clock_rate; 
    394         attr->avg_bps = spx_factory.speex_param[PARAM_UWB].bitrate; 
    395     } 
    396  
    397     attr->pcm_bits_per_sample = 16; 
    398     attr->ptime = 20; 
    399     attr->pt = id->pt; 
     398        attr->info.clock_rate = spx_factory.speex_param[PARAM_UWB].clock_rate; 
     399        attr->info.avg_bps = spx_factory.speex_param[PARAM_UWB].bitrate; 
     400    } 
     401 
     402    attr->info.pcm_bits_per_sample = 16; 
     403    attr->info.frm_ptime = 20; 
     404    attr->info.pt = (pj_uint8_t)id->pt; 
     405 
     406    attr->setting.frm_per_pkt = 1; 
    400407 
    401408    /* Default flags. */ 
    402     attr->cng = 1; 
    403     attr->concl = 1; 
    404     attr->hpf = 1; 
    405     attr->lpf =1 ; 
    406     attr->penh =1 ; 
     409    attr->setting.cng = 1; 
     410    attr->setting.plc = 1; 
     411    attr->setting.hpf = 1; 
     412    attr->setting.lpf =1 ; 
     413    attr->setting.penh =1 ; 
    407414 
    408415    /* Default, set VAD off as it caused voice chip off */ 
    409     attr->vad = 0; 
     416    attr->setting.vad = 0; 
    410417 
    411418    return PJ_SUCCESS; 
     
    560567 
    561568    /* Sampling rate. */ 
    562     tmp = attr->clock_rate; 
     569    tmp = attr->info.clock_rate; 
    563570    speex_encoder_ctl(spx->enc, SPEEX_SET_SAMPLING_RATE,  
    564571                      &spx_factory.speex_param[id].clock_rate); 
    565572 
    566573    /* VAD */ 
    567     tmp = attr->vad; 
     574    tmp = attr->setting.vad; 
    568575    speex_encoder_ctl(spx->enc, SPEEX_SET_VAD, &tmp); 
    569576 
     
    589596 
    590597    /* PENH */ 
    591     tmp = attr->penh; 
     598    tmp = attr->setting.penh; 
    592599    speex_decoder_ctl(spx->dec, SPEEX_SET_ENH, &tmp); 
    593600 
     
    625632 * Get frames in the packet. 
    626633 */ 
    627 static pj_status_t  spx_codec_get_frames( pjmedia_codec *codec, 
    628                                           void *pkt, 
    629                                           pj_size_t pkt_size, 
    630                                           unsigned *frame_cnt, 
    631                                           pjmedia_frame frames[]) 
     634static pj_status_t  spx_codec_parse( pjmedia_codec *codec, 
     635                                     void *pkt, 
     636                                     pj_size_t pkt_size, 
     637                                     const pj_timestamp *ts, 
     638                                     unsigned *frame_cnt, 
     639                                     pjmedia_frame frames[]) 
    632640{ 
    633641    struct spx_private *spx; 
    634     unsigned speex_frame_size; 
     642    unsigned frame_size, samples_per_frame; 
    635643    unsigned count; 
    636644 
    637645    spx = (struct spx_private*) codec->codec_data; 
    638646 
    639     speex_frame_size = spx_factory.speex_param[spx->param_id].framesize; 
     647    frame_size = spx_factory.speex_param[spx->param_id].framesize; 
     648    samples_per_frame = spx_factory.speex_param[spx->param_id].samples_per_frame; 
    640649 
    641650    /* Don't really know how to do this... */ 
    642651    count = 0; 
    643     while (pkt_size >= speex_frame_size && count < *frame_cnt) { 
     652    while (pkt_size >= frame_size && count < *frame_cnt) { 
    644653        frames[count].buf = pkt; 
    645         frames[count].size = speex_frame_size; 
     654        frames[count].size = frame_size; 
    646655        frames[count].type = PJMEDIA_FRAME_TYPE_AUDIO; 
    647         frames[count].timestamp.u64 = 0; 
    648  
    649         pkt_size -= speex_frame_size; 
     656        frames[count].timestamp.u64 = ts->u64 + count * samples_per_frame; 
     657 
     658        pkt_size -= frame_size; 
    650659        ++count; 
    651         pkt = ((char*)pkt) + speex_frame_size; 
    652     } 
    653  
     660        pkt = ((char*)pkt) + frame_size; 
     661    } 
     662 
     663    /* Just in case speex has silence frame which size is less than normal 
     664     * frame size... 
     665     */ 
    654666    if (pkt_size && count < *frame_cnt) { 
    655667        frames[count].buf = pkt; 
    656668        frames[count].size = pkt_size; 
    657669        frames[count].type = PJMEDIA_FRAME_TYPE_AUDIO; 
    658         frames[count].timestamp.u64 = 0; 
     670        frames[count].timestamp.u64 = ts->u64 + count * samples_per_frame; 
    659671        ++count; 
    660672    } 
     
    765777} 
    766778 
     779/*  
     780 * Recover lost frame. 
     781 */ 
     782static pj_status_t  spx_codec_recover(pjmedia_codec *codec,  
     783                                      unsigned output_buf_len,  
     784                                      struct pjmedia_frame *output) 
     785{ 
     786    struct spx_private *spx; 
     787    float tmp[642]; /* 20ms at 32KHz + 2 */ 
     788    pj_int16_t *dst_buf; 
     789    unsigned i, count; 
     790 
     791    spx = (struct spx_private*) codec->codec_data; 
     792 
     793    count = spx_factory.speex_param[spx->param_id].clock_rate * 20 / 1000; 
     794    pj_assert((count <= output_buf_len/2) && count <= PJ_ARRAY_SIZE(tmp)); 
     795 
     796    /* Recover packet loss */ 
     797    speex_decode(spx->dec, NULL, tmp); 
     798 
     799    /* Copy from float to short samples. */ 
     800    dst_buf = output->buf; 
     801    for (i=0; i<count; ++i) { 
     802        dst_buf[i] = (pj_int16_t)tmp[i]; 
     803    } 
     804    output->size = count * 2; 
     805 
     806    return PJ_SUCCESS; 
     807} 
     808 
    767809 
    768810#endif  /* PJMEDIA_HAS_SPEEX_CODEC */ 
  • pjproject/trunk/pjmedia/src/pjmedia/endpoint.c

    r424 r438  
    474474                  codec_info[i].clock_rate/1000, 
    475475                  codec_info[i].channel_cnt, 
    476                   good_number(bps, param.avg_bps),  
    477                   param.ptime, 
    478                   (param.vad ? " vad" : ""), 
    479                   (param.cng ? " cng" : ""), 
    480                   (param.concl ? " plc" : ""), 
    481                   (param.penh ? " penh" : ""), 
     476                  good_number(bps, param.info.avg_bps),  
     477                  param.info.frm_ptime * param.setting.frm_per_pkt, 
     478                  (param.setting.vad ? " vad" : ""), 
     479                  (param.setting.cng ? " cng" : ""), 
     480                  (param.setting.plc ? " plc" : ""), 
     481                  (param.setting.penh ? " penh" : ""), 
    482482                  (prio[i]==PJMEDIA_CODEC_PRIO_DISABLED?" disabled":""))); 
    483483    } 
  • pjproject/trunk/pjmedia/src/pjmedia/errno.c

    r420 r438  
    8888    { PJMEDIA_CODEC_EFRMTOOSHORT,   "Codec frame is too short" }, 
    8989    { PJMEDIA_CODEC_EPCMTOOSHORT,   "PCM frame is too short" }, 
     90    { PJMEDIA_CODEC_EFRMINLEN,      "Invalid codec frame length" }, 
    9091 
    9192    /* Media errors. */ 
  • pjproject/trunk/pjmedia/src/pjmedia/g711.c

    r429 r438  
    2424#include <pjmedia/errno.h> 
    2525#include <pjmedia/port.h> 
     26#include <pjmedia/plc.h> 
    2627#include <pj/pool.h> 
    2728#include <pj/string.h> 
     
    3132 
    3233 
    33 #define G711_BPS        64000 
    34 #define G711_CODEC_CNT  0       /* number of codec to preallocate in memory */ 
    35 #define PTIME           20 
    36 #define FRAME_SIZE      (8000 * PTIME / 1000) 
     34#define G711_BPS            64000 
     35#define G711_CODEC_CNT      0   /* number of codec to preallocate in memory */ 
     36#define PTIME               10  /* basic frame size is 10 msec      */ 
     37#define FRAME_SIZE          (8000 * PTIME / 1000)   /* 80 bytes     */ 
     38#define SAMPLES_PER_FRAME   (8000 * PTIME / 1000)   /* 80 samples   */ 
    3739 
    3840/* These are the only public functions exported to applications */ 
    39 PJ_DECL(pj_status_t) g711_init_factory (pjmedia_codec_factory *factory, pj_pool_t *pool); 
     41PJ_DECL(pj_status_t) g711_init_factory (pjmedia_codec_factory *factory,  
     42                                        pj_pool_t *pool); 
    4043 
    4144/* Algorithm prototypes. */ 
    42 unsigned char linear2alaw(int           pcm_val);   /* 2's complement (16-bit range) */ 
     45unsigned char linear2alaw(int           pcm_val); 
    4346int           alaw2linear(unsigned char a_val); 
    4447unsigned char linear2ulaw(int           pcm_val); 
     
    6669                               pjmedia_codec_param *attr ); 
    6770static pj_status_t  g711_close( pjmedia_codec *codec ); 
    68 static pj_status_t  g711_get_frames(pjmedia_codec *codec, 
    69                                     void *pkt, 
    70                                     pj_size_t pkt_size, 
    71                                     unsigned *frame_cnt, 
    72                                     pjmedia_frame frames[]); 
     71static pj_status_t  g711_parse(pjmedia_codec *codec, 
     72                               void *pkt, 
     73                               pj_size_t pkt_size, 
     74                               const pj_timestamp *timestamp, 
     75                               unsigned *frame_cnt, 
     76                               pjmedia_frame frames[]); 
    7377static pj_status_t  g711_encode( pjmedia_codec *codec,  
    7478                                 const struct pjmedia_frame *input, 
     
    7983                                 unsigned output_buf_len,  
    8084                                 struct pjmedia_frame *output); 
     85static pj_status_t  g711_recover( pjmedia_codec *codec, 
     86                                  unsigned output_buf_len, 
     87                                  struct pjmedia_frame *output); 
    8188 
    8289/* Definition for G711 codec operations. */ 
     
    8693    &g711_open, 
    8794    &g711_close, 
    88     &g711_get_frames, 
     95    &g711_parse, 
    8996    &g711_encode, 
    90     &g711_decode 
     97    &g711_decode, 
     98    &g711_recover 
    9199}; 
    92100 
     
    114122struct g711_private 
    115123{ 
    116     unsigned pt; 
     124    unsigned        pt; 
     125    pj_bool_t       plc_enabled; 
     126    pjmedia_plc    *plc; 
    117127}; 
    118128 
     
    218228 
    219229    /* It's sufficient to check payload type only. */ 
    220     return (id->pt==PJMEDIA_RTP_PT_PCMU || id->pt==PJMEDIA_RTP_PT_PCMA) ? 0 : -1; 
     230    return (id->pt==PJMEDIA_RTP_PT_PCMU || id->pt==PJMEDIA_RTP_PT_PCMA)? 0:-1; 
    221231} 
    222232 
     
    228238 
    229239    pj_memset(attr, 0, sizeof(pjmedia_codec_param)); 
    230     attr->clock_rate = 8000; 
    231     attr->channel_cnt = 1; 
    232     attr->avg_bps = G711_BPS; 
    233     attr->pcm_bits_per_sample = 16; 
    234     attr->ptime = PTIME; 
    235     attr->pt = id->pt; 
     240    attr->info.clock_rate = 8000; 
     241    attr->info.channel_cnt = 1; 
     242    attr->info.avg_bps = G711_BPS; 
     243    attr->info.pcm_bits_per_sample = 16; 
     244    attr->info.frm_ptime = PTIME; 
     245    attr->info.pt = (pj_uint8_t)id->pt; 
     246 
     247    /* Set default frames per packet to 2 (or 20ms) */ 
     248    attr->setting.frm_per_pkt = 2; 
     249 
     250    /* Enable plc by default. */ 
     251    attr->setting.plc = 1; 
    236252 
    237253    /* Default all flag bits disabled. */ 
     
    275291{ 
    276292    pjmedia_codec *codec = NULL; 
     293    pj_status_t status; 
    277294 
    278295    PJ_ASSERT_RETURN(factory==&g711_factory.base, PJ_EINVAL); 
     
    293310        } 
    294311 
     312        /* Set the payload type */ 
    295313        codec_priv->pt = id->pt; 
     314 
     315        /* Create PLC, always with 10ms ptime */ 
     316        status = pjmedia_plc_create(g711_factory.pool, 8000, 80, 
     317                                    0, &codec_priv->plc); 
     318        if (status != PJ_SUCCESS) { 
     319            pj_mutex_unlock(g711_factory.mutex); 
     320            return status; 
     321        } 
    296322 
    297323        codec->factory = factory; 
     
    351377{ 
    352378    struct g711_private *priv = codec->codec_data; 
    353     priv->pt = attr->pt; 
     379    priv->pt = attr->info.pt; 
     380    priv->plc_enabled = (attr->setting.plc != 0); 
    354381    return PJ_SUCCESS; 
    355382} 
     
    362389} 
    363390 
    364 static pj_status_t  g711_get_frames(pjmedia_codec *codec, 
    365                                     void *pkt, 
    366                                     pj_size_t pkt_size, 
    367                                     unsigned *frame_cnt, 
    368                                     pjmedia_frame frames[]) 
     391static pj_status_t  g711_parse( pjmedia_codec *codec, 
     392                                void *pkt, 
     393                                pj_size_t pkt_size, 
     394                                const pj_timestamp *ts, 
     395                                unsigned *frame_cnt, 
     396                                pjmedia_frame frames[]) 
    369397{ 
    370398    unsigned count = 0; 
    371399 
    372400    PJ_UNUSED_ARG(codec); 
    373     PJ_ASSERT_RETURN(frame_cnt, PJ_EINVAL); 
     401 
     402    PJ_ASSERT_RETURN(ts && frame_cnt && frames, PJ_EINVAL); 
    374403 
    375404    while (pkt_size >= FRAME_SIZE && count < *frame_cnt) { 
    376         frames[0].type = PJMEDIA_FRAME_TYPE_AUDIO; 
    377         frames[0].buf = pkt; 
    378         frames[0].size = FRAME_SIZE; 
     405        frames[count].type = PJMEDIA_FRAME_TYPE_AUDIO; 
     406        frames[count].buf = pkt; 
     407        frames[count].size = FRAME_SIZE; 
     408        frames[count].timestamp.u64 = ts->u64 + SAMPLES_PER_FRAME * count; 
    379409 
    380410        pkt = ((char*)pkt) + FRAME_SIZE; 
     
    434464 
    435465    /* Check output buffer length */ 
    436     if (output_buf_len < input->size * 2) 
    437         return PJMEDIA_CODEC_EPCMTOOSHORT; 
     466    PJ_ASSERT_RETURN(output_buf_len >= input->size * 2, 
     467                     PJMEDIA_CODEC_EPCMTOOSHORT); 
     468 
     469    /* Input buffer MUST have exactly 80 bytes long */ 
     470    PJ_ASSERT_RETURN(input->size == FRAME_SIZE,  
     471                     PJMEDIA_CODEC_EFRMINLEN); 
    438472 
    439473    /* Decode */ 
     
    462496    output->size = input->size * 2; 
    463497 
    464     return PJ_SUCCESS; 
    465 } 
    466  
     498    if (priv->plc_enabled) 
     499        pjmedia_plc_save( priv->plc, output->buf); 
     500 
     501    return PJ_SUCCESS; 
     502} 
     503 
     504static pj_status_t  g711_recover( pjmedia_codec *codec, 
     505                                  unsigned output_buf_len, 
     506                                  struct pjmedia_frame *output) 
     507{ 
     508    struct g711_private *priv = codec->codec_data; 
     509 
     510    if (!priv->plc_enabled) 
     511        return PJ_EINVALIDOP; 
     512 
     513    PJ_ASSERT_RETURN(output_buf_len >= SAMPLES_PER_FRAME * 2,  
     514                     PJMEDIA_CODEC_EPCMTOOSHORT); 
     515 
     516    pjmedia_plc_generate(priv->plc, output->buf); 
     517    output->size = SAMPLES_PER_FRAME * 2; 
     518 
     519    return PJ_SUCCESS; 
     520} 
    467521 
    468522#endif  /* PJMEDIA_HAS_G711_CODEC */ 
  • pjproject/trunk/pjmedia/src/pjmedia/jbuf.c

    r436 r438  
    433433} 
    434434 
    435 PJ_DEF(pj_status_t) pjmedia_jbuf_put_frame(pjmedia_jbuf *jb,  
    436                                            const void *frame,  
    437                                            pj_size_t frame_size,  
    438                                            int frame_seq) 
     435PJ_DEF(void) pjmedia_jbuf_put_frame( pjmedia_jbuf *jb,  
     436                                     const void *frame,  
     437                                     pj_size_t frame_size,  
     438                                     int frame_seq) 
    439439{ 
    440440    pj_size_t min_frame_size; 
     
    476476        jb_framelist_put_at(&jb->jb_framelist,frame_seq,frame,min_frame_size); 
    477477    } 
    478  
    479     return PJ_SUCCESS; 
    480478} 
    481479 
     
    483481 * Get frame from jitter buffer. 
    484482 */ 
    485 PJ_DEF(pj_status_t) pjmedia_jbuf_get_frame( pjmedia_jbuf *jb,  
    486                                             void *frame,  
    487                                             char *p_frame_type) 
     483PJ_DEF(void) pjmedia_jbuf_get_frame( pjmedia_jbuf *jb,  
     484                                     void *frame,  
     485                                     char *p_frame_type) 
    488486{ 
    489487    pjmedia_jb_frame_type ftype; 
     
    507505            *p_frame_type = PJMEDIA_JB_ZERO_PREFETCH_FRAME; 
    508506 
    509         return PJ_SUCCESS; 
     507        return; 
    510508    } 
    511509 
     
    516514        *p_frame_type = PJMEDIA_JB_ZERO_EMPTY_FRAME; 
    517515 
    518         return PJ_SUCCESS; 
     516        return; 
    519517    } 
    520518 
     
    526524    else  
    527525        *p_frame_type   = PJMEDIA_JB_MISSING_FRAME; 
    528      
    529  
    530     return PJ_SUCCESS; 
    531526} 
    532527 
  • pjproject/trunk/pjmedia/src/pjmedia/plc_common.c

    r417 r438  
    2727static void  plc_replay_save(void*, pj_int16_t*); 
    2828static void  plc_replay_generate(void*, pj_int16_t*); 
    29  
    30 static void* noplc_create(pj_pool_t*, unsigned c, unsigned f); 
    31 static void  noplc_save(void*, pj_int16_t*); 
    32 static void  noplc_generate(void*, pj_int16_t*); 
    3329 
    3430extern void* pjmedia_plc_g711_create(pj_pool_t*, unsigned c, unsigned f); 
     
    6359    &plc_replay_save, 
    6460    &plc_replay_generate 
    65 }; 
    66  
    67  
    68 static struct plc_alg no_plc = 
    69 { 
    70     &noplc_create, 
    71     &noplc_save, 
    72     &noplc_generate 
    7361}; 
    7462 
     
    202190 
    203191 
    204 ////////////////////////////////////////////////////////////////////////////// 
    205 /* 
    206  * No PLC 
    207  */ 
    208 static void* noplc_create(pj_pool_t *pool, unsigned clock_rate,  
    209                           unsigned samples_per_sec) 
    210 { 
    211     PJ_UNUSED_ARG(pool);     
    212     PJ_UNUSED_ARG(clock_rate); 
    213     return (void*) samples_per_sec; 
    214 } 
    215  
    216 static void noplc_save(void *plc, pj_int16_t *frame) 
    217 { 
    218     PJ_UNUSED_ARG(plc); 
    219     PJ_UNUSED_ARG(frame); 
    220 } 
    221  
    222 static void  noplc_generate(void *plc, pj_int16_t *frame) 
    223 { 
    224     unsigned samples_per_sec = (unsigned)plc; 
    225     pj_memset(frame, 0, samples_per_sec); 
    226 } 
    227  
  • pjproject/trunk/pjmedia/src/pjmedia/session.c

    r435 r438  
    6565                                           pj_pool_t *pool, 
    6666                                           pjmedia_endpt *endpt, 
     67                                           const pjmedia_sock_info *skinfo, 
    6768                                           const pjmedia_sdp_session *local, 
    6869                                           const pjmedia_sdp_session *remote, 
    6970                                           unsigned stream_idx) 
    7071{ 
     72    pjmedia_codec_mgr *mgr; 
    7173    const pjmedia_sdp_attr *attr; 
    7274    const pjmedia_sdp_media *local_m; 
     
    8688 
    8789 
     90    /* Get codec manager. */ 
     91    mgr = pjmedia_endpt_get_codec_mgr(endpt); 
     92 
     93    /* Keep SDP shortcuts */ 
    8894    local_m = local->media[stream_idx]; 
    8995    rem_m = remote->media[stream_idx]; 
     
    216222            } 
    217223 
    218         } else { 
    219             pjmedia_codec_mgr *mgr; 
    220             pjmedia_codec_info *p_info; 
    221  
    222             mgr = pjmedia_endpt_get_codec_mgr(endpt); 
     224        } else {             
     225            const pjmedia_codec_info *p_info; 
    223226 
    224227            status = pjmedia_codec_mgr_get_codec_info( mgr, pt, &p_info); 
     
    302305 
    303306   
     307    /* Now that we have codec info, get the codec param. */ 
     308    si->param = pj_pool_alloc(pool, sizeof(*si->param)); 
     309    status = pjmedia_codec_mgr_get_default_param(mgr, &si->fmt, si->param); 
     310    if (status != PJ_SUCCESS) 
     311        return status; 
    304312 
    305313    /* Get incomming payload type for telephone-events */ 
     
    335343    } 
    336344 
     345    /* Copy skinfo */ 
     346    if (skinfo) 
     347        si->sock_info = *skinfo; 
    337348 
    338349    /* Leave SSRC to random. */ 
    339350    si->ssrc = pj_rand(); 
    340351 
    341     /* Leave jitter buffer parameter. */ 
    342      
     352    /* Set default jitter buffer parameter. */ 
     353    si->jb_init = si->jb_max = si->jb_min_pre = si->jb_max_pre = -1; 
     354 
     355    return PJ_SUCCESS; 
     356} 
     357 
     358 
     359/* 
     360 * Initialize session info from SDP session descriptors. 
     361 */ 
     362PJ_DEF(pj_status_t)  
     363pjmedia_session_info_from_sdp( pj_pool_t *pool, 
     364                               pjmedia_endpt *endpt, 
     365                               unsigned max_streams, 
     366                               pjmedia_session_info *si, 
     367                               const pjmedia_sock_info skinfo[], 
     368                               const pjmedia_sdp_session *local, 
     369                               const pjmedia_sdp_session *remote) 
     370{ 
     371    unsigned i; 
     372 
     373    PJ_ASSERT_RETURN(pool && endpt && si && local && remote, PJ_EINVAL); 
     374 
     375    si->stream_cnt = max_streams; 
     376    if (si->stream_cnt > local->media_count) 
     377        si->stream_cnt = local->media_count; 
     378 
     379    for (i=0; i<si->stream_cnt; ++i) { 
     380        pj_status_t status; 
     381 
     382        status = pjmedia_stream_info_from_sdp( &si->stream_info[i], pool, 
     383                                               endpt,  
     384                                               (skinfo ? &skinfo[i] : NULL), 
     385                                               local, remote, i); 
     386        if (status != PJ_SUCCESS) 
     387            return status; 
     388 
     389    } 
     390 
    343391    return PJ_SUCCESS; 
    344392} 
     
    349397 */ 
    350398PJ_DEF(pj_status_t) pjmedia_session_create( pjmedia_endpt *endpt,  
    351                                             unsigned stream_cnt, 
    352                                             const pjmedia_sock_info skinfo[], 
    353                                             const pjmedia_sdp_session *local_sdp, 
    354                                             const pjmedia_sdp_session *rem_sdp, 
     399                                            const pjmedia_session_info *si, 
    355400                                            void *user_data, 
    356401                                            pjmedia_session **p_session ) 
     
    362407 
    363408    /* Verify arguments. */ 
    364     PJ_ASSERT_RETURN(endpt && stream_cnt && skinfo && 
    365                      local_sdp && rem_sdp && p_session, PJ_EINVAL); 
     409    PJ_ASSERT_RETURN(endpt && si && p_session, PJ_EINVAL); 
    366410 
    367411    /* Create pool for the session. */ 
     
    374418    session->pool = pool; 
    375419    session->endpt = endpt; 
    376     session->stream_cnt = stream_cnt; 
     420    session->stream_cnt = si->stream_cnt; 
    377421    session->user_data = user_data; 
    378      
    379     /* Stream count is the lower number of stream_cnt or SDP m= lines count */ 
    380     if (stream_cnt < local_sdp->media_count) 
    381         stream_cnt = local_sdp->media_count; 
    382  
    383     /*  
    384      * Create streams:  
    385      */ 
    386     for (i=0; i<(int)stream_cnt; ++i) { 
    387  
    388         pjmedia_stream_info *si = &session->stream_info[i]; 
    389  
    390         /* Build stream info based on media line in local SDP */ 
    391         status = pjmedia_stream_info_from_sdp(si, session->pool, endpt, 
    392                                               local_sdp, rem_sdp, i); 
    393         if (status != PJ_SUCCESS) 
    394             return status; 
    395  
    396         /* Assign sockinfo */ 
    397         si->sock_info = skinfo[i]; 
    398     } 
     422 
     423    /* Copy stream info (this simple memcpy may break sometime) */ 
     424    pj_memcpy(session->stream_info, si->stream_info, 
     425              si->stream_cnt * sizeof(pjmedia_session_info)); 
    399426 
    400427    /* 
    401428     * Now create and start the stream! 
    402429     */ 
    403     for (i=0; i<(int)stream_cnt; ++i) { 
    404  
     430    for (i=0; i<(int)si->stream_cnt; ++i) { 
     431 
     432        /* Create the stream */ 
    405433        status = pjmedia_stream_create(endpt, session->pool, 
    406434                                       &session->stream_info[i], 
  • pjproject/trunk/pjmedia/src/pjmedia/stream.c

    r435 r438  
    5454    unsigned                out_pkt_size;   /**< Size of output buffer.     */ 
    5555    void                   *out_pkt;        /**< Output buffer.             */ 
    56     unsigned                pcm_buf_size;   /**< Size of PCM buffer.        */ 
    57     void                   *pcm_buf;        /**< PCM buffer.                */ 
    5856    pjmedia_rtp_session     rtp;            /**< RTP session.               */ 
    5957}; 
     
    8684 
    8785    pjmedia_codec           *codec;         /**< Codec instance being used. */ 
    88     pj_size_t                frame_size;    /**< Size of encoded frame.     */ 
     86    pjmedia_codec_param      codec_param;   /**< Codec param.               */ 
     87    unsigned                 frame_size;    /**< Size of encoded base frame.*/ 
    8988    pj_mutex_t              *jb_mutex; 
    9089    pjmedia_jbuf            *jb;            /**< Jitter buffer.             */ 
     
    155154    pjmedia_channel *channel = stream->dec; 
    156155     
    157     char frame_type; 
    158156    pj_status_t status; 
    159     struct pjmedia_frame frame_in, frame_out; 
     157    unsigned samples_count, samples_per_frame, samples_required; 
     158    pj_int16_t *p_out_samp; 
    160159 
    161160    /* Return no frame is channel is paused */ 
     
    165164    } 
    166165 
    167     /* Lock jitter buffer mutex */ 
     166    /* Repeat get frame from the jitter buffer and decode the frame 
     167     * until we have enough frames according to codec's ptime. 
     168     */ 
     169 
     170    /* Lock jitter buffer mutex first */ 
    168171    pj_mutex_lock( stream->jb_mutex ); 
    169172 
    170     /* Get frame from jitter buffer. */ 
    171     status = pjmedia_jbuf_get_frame(stream->jb, channel->out_pkt, 
    172                                     &frame_type); 
     173    samples_required = stream->port.info.samples_per_frame; 
     174    samples_per_frame = stream->codec_param.info.frm_ptime * 
     175                        stream->codec_param.info.clock_rate * 
     176                        stream->codec_param.info.channel_cnt /  
     177                        1000; 
     178    p_out_samp = frame->buf; 
     179 
     180    for (samples_count=0; samples_count < samples_required;  
     181         samples_count += samples_per_frame)  
     182    { 
     183         char frame_type; 
     184 
     185        /* Get frame from jitter buffer. */ 
     186        pjmedia_jbuf_get_frame(stream->jb, channel->out_pkt, &frame_type); 
     187         
     188        if (frame_type == PJMEDIA_JB_MISSING_FRAME) { 
     189             
     190            /* Activate PLC */ 
     191            if (stream->codec->op->recover &&  
     192                stream->codec_param.setting.plc)  
     193            { 
     194                pjmedia_frame frame_out; 
     195 
     196                frame_out.buf = p_out_samp + samples_count; 
     197                frame_out.size = frame->size - samples_count*2; 
     198                status = (*stream->codec->op->recover)(stream->codec, 
     199                                                       frame_out.size, 
     200                                                       &frame_out); 
     201            } else { 
     202                status = -1; 
     203            } 
     204 
     205            if (status != PJ_SUCCESS) { 
     206                /* Either PLC failed or PLC not supported/enabled */ 
     207                pjmedia_zero_samples(p_out_samp + samples_count, 
     208                                     samples_required - samples_count); 
     209            } 
     210             
     211        } else if (frame_type == PJMEDIA_JB_ZERO_EMPTY_FRAME) { 
     212 
     213            /* Jitter buffer is empty, zero the remaining samples and break 
     214             * the loop. 
     215             */ 
     216            pjmedia_zero_samples(p_out_samp + samples_count, 
     217                                 samples_required - samples_count); 
     218            break; 
     219 
     220        } else if (frame_type != PJMEDIA_JB_NORMAL_FRAME) { 
     221 
     222            /* It can only be PJMEDIA_JB_ZERO_PREFETCH frame */ 
     223            pj_assert(frame_type == PJMEDIA_JB_ZERO_PREFETCH_FRAME); 
     224 
     225            /* Zero frame returned. We should zero the PCM buffer then.. */ 
     226            pjmedia_zero_samples(p_out_samp + samples_count,  
     227                                 samples_per_frame); 
     228 
     229        } else { 
     230            /* Got "NORMAL" frame from jitter buffer */ 
     231            pjmedia_frame frame_in, frame_out; 
     232 
     233            /* Decode */ 
     234            frame_in.buf = channel->out_pkt; 
     235            frame_in.size = stream->frame_size; 
     236            frame_in.type = PJMEDIA_FRAME_TYPE_AUDIO;  /* ignored */ 
     237 
     238            frame_out.buf = p_out_samp + samples_count; 
     239            frame_out.size = frame->size - samples_count*2; 
     240            status = stream->codec->op->decode( stream->codec, &frame_in, 
     241                                                frame_out.size, &frame_out); 
     242            if (status != 0) { 
     243                LOGERR_((port->info.name.ptr, "codec decode() error",  
     244                         status)); 
     245 
     246                pjmedia_zero_samples(p_out_samp + samples_count,  
     247                                     samples_per_frame); 
     248            } 
     249        } 
     250    } 
     251 
    173252 
    174253    /* Unlock jitter buffer mutex. */ 
    175254    pj_mutex_unlock( stream->jb_mutex ); 
    176255 
    177     if (status != PJ_SUCCESS || frame_type != PJMEDIA_JB_NORMAL_FRAME) { 
     256    /* Return PJMEDIA_FRAME_TYPE_NONE if we have no frames at all 
     257     * (it can happen when jitter buffer returns PJMEDIA_JB_ZERO_EMPTY_FRAME). 
     258     */ 
     259    if (samples_count == 0) { 
    178260        frame->type = PJMEDIA_FRAME_TYPE_NONE; 
    179         return PJ_SUCCESS; 
    180     } 
    181  
    182     /* Decode */ 
    183     frame_in.buf = channel->out_pkt; 
    184     frame_in.size = stream->frame_size; 
    185     frame_in.type = PJMEDIA_FRAME_TYPE_AUDIO;  /* ignored */ 
    186     frame_out.buf = channel->pcm_buf; 
    187     status = stream->codec->op->decode( stream->codec, &frame_in, 
    188                                         channel->pcm_buf_size, &frame_out); 
    189     if (status != 0) { 
    190         LOGERR_((port->info.name.ptr, "codec decode() error", status)); 
    191  
    192         frame->type = PJMEDIA_FRAME_TYPE_NONE; 
    193         return PJ_SUCCESS; 
    194     } 
    195  
    196     /* Put in sound buffer. */ 
    197     if (frame_out.size > frame->size) { 
    198         PJ_LOG(4,(port->info.name.ptr,  
    199                   "Sound playout buffer truncated %d bytes",  
    200                   frame_out.size - frame->size)); 
    201         frame_out.size = frame->size; 
    202     } 
    203  
    204     frame->type = PJMEDIA_FRAME_TYPE_AUDIO; 
    205     frame->size = frame_out.size; 
    206     frame->timestamp.u64 = 0; 
    207     pj_memcpy(frame->buf, frame_out.buf, frame_out.size); 
     261        frame->size = 0; 
     262    } else { 
     263        frame->type = PJMEDIA_FRAME_TYPE_AUDIO; 
     264        frame->size = samples_count * 2; 
     265        frame->timestamp.u64 = 0; 
     266    } 
    208267 
    209268    return PJ_SUCCESS; 
     
    319378    pj_status_t status = 0; 
    320379    struct pjmedia_frame frame_out; 
    321     int ts_len; 
     380    unsigned ts_len; 
    322381    pj_bool_t has_tx; 
    323382    void *rtphdr; 
     
    356415 
    357416    } else if (frame->type != PJMEDIA_FRAME_TYPE_NONE) { 
    358         unsigned max_size; 
     417        unsigned ts, samples_per_frame; 
    359418 
    360419        has_tx = PJ_TRUE; 
    361         max_size = channel->out_pkt_size - sizeof(pjmedia_rtp_hdr); 
    362         status = stream->codec->op->encode( stream->codec, frame,  
    363                                             max_size,  
    364                                             &frame_out); 
    365         if (status != 0) { 
    366             LOGERR_((stream->port.info.name.ptr,  
    367                     "Codec encode() error", status)); 
    368             return status; 
     420 
     421        /* Repeatedly call encode if there are multiple frames to be 
     422         * sent. 
     423         */ 
     424        samples_per_frame = stream->codec_param.info.frm_ptime * 
     425                            stream->codec_param.info.clock_rate * 
     426                            stream->codec_param.info.channel_cnt / 
     427                            1000; 
     428 
     429        for (ts=0; ts<ts_len; ts += samples_per_frame) { 
     430            pjmedia_frame tmp_frame; 
     431            unsigned max_size; 
     432 
     433            tmp_frame.buf = ((char*)frame_out.buf) + frame_out.size; 
     434 
     435            max_size = channel->out_pkt_size - sizeof(pjmedia_rtp_hdr) - 
     436                       frame_out.size; 
     437 
     438            status = stream->codec->op->encode( stream->codec, frame,  
     439                                                max_size,  
     440                                                &tmp_frame); 
     441            if (status != PJ_SUCCESS) { 
     442                LOGERR_((stream->port.info.name.ptr,  
     443                        "Codec encode() error", status)); 
     444                return status; 
     445            } 
     446 
     447            frame_out.size += tmp_frame.size; 
    369448        } 
    370449 
     
    626705 
    627706        } else { 
    628             unsigned ext_seq; 
    629             ext_seq = channel->rtp.seq_ctrl.cycles | pj_ntohs(hdr->seq); 
    630             status = pjmedia_jbuf_put_frame(stream->jb, payload, payloadlen, 
    631                                             ext_seq); 
     707            /* 
     708             * Packets may contain more than one frames, while the jitter 
     709             * buffer can only take one frame per "put" operation. So we need 
     710             * to ask the codec to "parse" the payload into multiple frames. 
     711             */ 
     712            enum { MAX = 16 }; 
     713            pj_timestamp ts; 
     714            unsigned i, count; 
     715            pjmedia_frame frames[MAX]; 
     716 
     717            /* Get the timestamp of the first sample */ 
     718            ts.u64 = pj_ntohl(hdr->ts); 
     719 
     720            /* Parse the payload. */ 
     721            status = (*stream->codec->op->parse)(stream->codec, 
     722                                                 (void*)payload, 
     723                                                 payloadlen, 
     724                                                 &ts, 
     725                                                 &count, 
     726                                                 frames); 
     727            if (status != PJ_SUCCESS) { 
     728                LOGERR_((stream->port.info.name.ptr,  
     729                         "Codec parse() error",  
     730                         status)); 
     731                count = 0; 
     732            } 
     733 
     734            /* Put each frame to jitter buffer. */ 
     735            for (i=0; i<count; ++i) { 
     736                unsigned ext_seq; 
     737 
     738                ext_seq = (unsigned)(frames[i].timestamp.u64 / 
     739                                     stream->port.info.samples_per_frame); 
     740                pjmedia_jbuf_put_frame(stream->jb, frames[i].buf,  
     741                                       frames[i].size, ext_seq); 
     742 
     743            } 
    632744        } 
    633745        pj_mutex_unlock( stream->jb_mutex ); 
     
    728840                                   unsigned pt, 
    729841                                   const pjmedia_stream_info *param, 
    730                                    const pjmedia_codec_param *codec_param, 
    731842                                   pjmedia_channel **p_channel) 
    732843{ 
     
    756867 
    757868    channel->out_pkt_size = sizeof(pjmedia_rtp_hdr) +  
    758                             codec_param->avg_bps/8 *  
     869                            stream->codec_param.info.avg_bps/8 *  
    759870                            PJMEDIA_MAX_FRAME_DURATION_MS /  
    760871                            1000; 
     
    766877    PJ_ASSERT_RETURN(channel->out_pkt != NULL, PJ_ENOMEM); 
    767878 
    768  
    769     /* Allocate buffer for decoding to PCM: */ 
    770  
    771     channel->pcm_buf_size = codec_param->clock_rate *  
    772                             codec_param->channel_cnt * 
    773                             codec_param->pcm_bits_per_sample / 8 * 
    774                             PJMEDIA_MAX_FRAME_DURATION_MS / 1000; 
    775     channel->pcm_buf = pj_pool_alloc (pool, channel->pcm_buf_size); 
    776     PJ_ASSERT_RETURN(channel->pcm_buf != NULL, PJ_ENOMEM); 
    777879 
    778880 
     
    800902{ 
    801903    pjmedia_stream *stream; 
    802     pjmedia_codec_param codec_param; 
    803904    pj_ioqueue_callback ioqueue_cb; 
    804905    pj_uint16_t rtcp_port; 
    805     unsigned jbuf_init, jbuf_max; 
     906    unsigned jb_init, jb_max, jb_min_pre, jb_max_pre; 
    806907    pj_status_t status; 
    807908 
     
    867968 
    868969 
    869     /* Get default codec param: */ 
    870  
    871     //status = stream->codec->op->default_attr(stream->codec, &codec_param); 
    872     status = pjmedia_codec_mgr_get_default_param( stream->codec_mgr,  
    873                                                   &info->fmt, &codec_param); 
     970    /* Get codec param: */ 
     971    if (info->param) 
     972        stream->codec_param = *info->param; 
     973    else { 
     974        status = pjmedia_codec_mgr_get_default_param(stream->codec_mgr,  
     975                                                     &info->fmt,  
     976                                                     &stream->codec_param); 
     977        if (status != PJ_SUCCESS) 
     978            goto err_cleanup; 
     979    } 
     980 
     981    /* Check for invalid frame per packet. */ 
     982    if (stream->codec_param.setting.frm_per_pkt < 1) 
     983        stream->codec_param.setting.frm_per_pkt = 1; 
     984 
     985    /* Set additional info. */ 
     986    stream->port.info.bits_per_sample = 16; 
     987    stream->port.info.samples_per_frame = info->fmt.clock_rate *  
     988                                          stream->codec_param.info.frm_ptime * 
     989                                          stream->codec_param.setting.frm_per_pkt / 
     990                                          1000; 
     991    stream->port.info.bytes_per_frame = stream->codec_param.info.avg_bps/8 *  
     992                                        stream->codec_param.info.frm_ptime * 
     993                                        stream->codec_param.setting.frm_per_pkt / 
     994                                        1000; 
     995 
     996 
     997    /* Open the codec: */ 
     998 
     999    status = stream->codec->op->open(stream->codec, &stream->codec_param); 
    8741000    if (status != PJ_SUCCESS) 
    8751001        goto err_cleanup; 
    8761002 
    877     /* Set additional info. */ 
    878     stream->port.info.bits_per_sample = 16; 
    879     stream->port.info.samples_per_frame = info->fmt.clock_rate*codec_param.ptime/1000; 
    880     stream->port.info.bytes_per_frame = codec_param.avg_bps/8 * codec_param.ptime/1000; 
    881  
    882  
    883     /* Open the codec: */ 
    884  
    885     status = stream->codec->op->open(stream->codec, &codec_param); 
    886     if (status != PJ_SUCCESS) 
    887         goto err_cleanup; 
    888  
    8891003 
    8901004    /* Get the frame size: */ 
    8911005 
    892     stream->frame_size = (codec_param.avg_bps / 8) * codec_param.ptime / 1000; 
    893  
     1006    stream->frame_size = (stream->codec_param.info.avg_bps / 8) *  
     1007                          stream->codec_param.info.frm_ptime / 1000; 
    8941008 
    8951009    /* Init RTCP session: */ 
     
    9011015 
    9021016 
    903     /* Create jitter buffer: */ 
    904     if (info->jb_init) 
    905         jbuf_init = info->jb_init; 
     1017    /* Init jitter buffer parameters: */ 
     1018    if (info->jb_max > 0) 
     1019        jb_max = info->jb_max; 
    9061020    else 
    907         jbuf_init = 60 / (stream->port.info.samples_per_frame * 1000 /  
    908                           info->fmt.clock_rate); 
    909  
    910     if (info->jb_max) 
    911         jbuf_max = info->jb_max; 
     1021        jb_max = 240 / (stream->port.info.samples_per_frame * 1000 /  
     1022                           info->fmt.clock_rate); 
     1023 
     1024    if (info->jb_min_pre >= 0) 
     1025        jb_min_pre = info->jb_min_pre; 
    9121026    else 
    913         jbuf_max = 240 / (stream->port.info.samples_per_frame * 1000 /  
    914                            info->fmt.clock_rate); 
     1027        jb_min_pre = 0; 
     1028 
     1029    if (info->jb_max_pre > 0) 
     1030        jb_max_pre = info->jb_max_pre; 
     1031    else 
     1032        jb_max_pre = jb_max * 4 / 5; 
     1033 
     1034    if (info->jb_init >= 0) 
     1035        jb_init = info->jb_init; 
     1036    else 
     1037        jb_init = jb_min_pre; 
     1038 
     1039 
     1040    /* Create jitter buffer */ 
    9151041    status = pjmedia_jbuf_create(pool, &stream->port.info.name, 
    9161042                                 stream->frame_size,  
    917                                  jbuf_max, &stream->jb); 
     1043                                 jb_max, &stream->jb); 
    9181044    if (status != PJ_SUCCESS) 
    9191045        goto err_cleanup; 
    9201046 
    921     /* Set jitter buffer to adaptive */ 
    922     pjmedia_jbuf_set_adaptive( stream->jb, jbuf_init, 1, jbuf_max * 4 / 5); 
     1047 
     1048    /* Set up jitter buffer */ 
     1049    pjmedia_jbuf_set_adaptive( stream->jb, jb_init, jb_min_pre, jb_max_pre); 
    9231050 
    9241051    /* Create decoder channel: */ 
    9251052 
    9261053    status = create_channel( pool, stream, PJMEDIA_DIR_DECODING,  
    927                              info->fmt.pt, info, &codec_param, &stream->dec); 
     1054                             info->fmt.pt, info, &stream->dec); 
    9281055    if (status != PJ_SUCCESS) 
    9291056        goto err_cleanup; 
     
    9331060 
    9341061    status = create_channel( pool, stream, PJMEDIA_DIR_ENCODING,  
    935                              info->tx_pt, info, &codec_param, &stream->enc); 
     1062                             info->tx_pt, info, &stream->enc); 
    9361063    if (status != PJ_SUCCESS) 
    9371064        goto err_cleanup; 
  • pjproject/trunk/pjsip-apps/build/Samples.mak

    r408 r438  
    22include ../../build/common.mak 
    33 
    4 PJLIB_LIB:=../../pjlib/lib/libpj-$(MACHINE_NAME)-$(OS_NAME)-$(CC_NAME)$(LIBEXT) 
    5 PJLIB_UTIL_LIB:=../../pjlib-util/lib/libpjlib-util-$(MACHINE_NAME)-$(OS_NAME)-$(CC_NAME)$(LIBEXT) 
    6 PJMEDIA_LIB:=../../pjmedia/lib/libpjmedia-$(MACHINE_NAME)-$(OS_NAME)-$(CC_NAME)$(LIBEXT) 
    7 PJMEDIA_CODEC_LIB:=../../pjmedia/lib/libpjmedia-codec-$(MACHINE_NAME)-$(OS_NAME)-$(CC_NAME)$(LIBEXT) 
    8 PJSIP_LIB:=../../pjsip/lib/libpjsip-$(MACHINE_NAME)-$(OS_NAME)-$(CC_NAME)$(LIBEXT) 
    9 PJSIP_UA_LIB:=../../pjsip/lib/libpjsip-ua-$(MACHINE_NAME)-$(OS_NAME)-$(CC_NAME)$(LIBEXT) 
    10 PJSIP_SIMPLE_LIB:=../../pjsip/lib/libpjsip-simple-$(MACHINE_NAME)-$(OS_NAME)-$(CC_NAME)$(LIBEXT) 
    11 PJSUA_LIB_LIB=../../pjsip/lib/libpjsua-$(MACHINE_NAME)-$(OS_NAME)-$(CC_NAME)$(LIBEXT) 
     4PJLIB_LIB:=../../pjlib/lib/libpj-$(TARGET)$(LIBEXT) 
     5PJLIB_UTIL_LIB:=../../pjlib-util/lib/libpjlib-util-$(TARGET)$(LIBEXT) 
     6PJMEDIA_LIB:=../../pjmedia/lib/libpjmedia-$(TARGET)$(LIBEXT) 
     7PJMEDIA_CODEC_LIB:=../../pjmedia/lib/libpjmedia-codec-$(TARGET)$(LIBEXT) 
     8PJSIP_LIB:=../../pjsip/lib/libpjsip-$(TARGET)$(LIBEXT) 
     9PJSIP_UA_LIB:=../../pjsip/lib/libpjsip-ua-$(TARGET)$(LIBEXT) 
     10PJSIP_SIMPLE_LIB:=../../pjsip/lib/libpjsip-simple-$(TARGET)$(LIBEXT) 
     11PJSUA_LIB_LIB=../../pjsip/lib/libpjsua-$(TARGET)$(LIBEXT) 
    1212 
    1313 
     
    3636 
    3737SRCDIR := ../src/samples 
    38 OBJDIR := ./output/samples-$(MACHINE_NAME)-$(OS_NAME)-$(CC_NAME) 
     38OBJDIR := ./output/samples-$(TARGET) 
    3939BINDIR := ../bin/samples 
    4040 
     
    4242           siprtp streamutil 
    4343 
    44 EXES := $(foreach file, $(SAMPLES), $(BINDIR)/$(file)-$(MACHINE_NAME)-$(OS_NAME)-$(CC_NAME)$(HOST_EXE)) 
     44EXES := $(foreach file, $(SAMPLES), $(BINDIR)/$(file)-$(TARGET)$(HOST_EXE)) 
    4545 
    4646all: $(OBJDIR) $(EXES) 
    4747 
    48 $(BINDIR)/%-$(MACHINE_NAME)-$(OS_NAME)-$(CC_NAME)$(HOST_EXE): $(OBJDIR)/%$(OBJEXT) $(LIBS) 
     48$(BINDIR)/%-$(TARGET)$(HOST_EXE): $(OBJDIR)/%$(OBJEXT) $(LIBS) 
    4949        $(LD) $(LDOUT)$(subst /,$(HOST_PSEP),$@) \ 
    5050            $(subst /,$(HOST_PSEP),$<) \ 
  • pjproject/trunk/pjsip-apps/src/samples/debug.c

    r408 r438  
    2828 *  #include "playfile.c" 
    2929 */ 
    30 #include "streamutil.c" 
     30#include "sndinfo.c" 
    3131 
  • pjproject/trunk/pjsip-apps/src/samples/playfile.c

    r412 r438  
    7777 
    7878 
    79     PJ_UNUSED_ARG(argc); 
     79    if (argc != 2) { 
     80        puts("Error: filename required"); 
     81        puts(desc); 
     82        return 1; 
     83    } 
    8084 
    8185 
  • pjproject/trunk/pjsip-apps/src/samples/simpleua.c

    r412 r438  
    586586                                  pj_status_t status) 
    587587{ 
     588    pjmedia_session_info sess_info; 
    588589    const pjmedia_sdp_session *local_sdp; 
    589590    const pjmedia_sdp_session *remote_sdp; 
     
    608609 
    609610 
     611    /* Create session info based on the two SDPs.  
     612     * We only support one stream per session for now. 
     613     */ 
     614    status = pjmedia_session_info_from_sdp(inv->dlg->pool, g_med_endpt, 1, 
     615                                           &sess_info, &g_med_skinfo, 
     616                                           local_sdp, remote_sdp); 
     617    if (status != PJ_SUCCESS) { 
     618        app_perror( THIS_FILE, "Unable to create media session", status); 
     619        return; 
     620    } 
     621 
     622    /* If required, we can also change some settings in the session info, 
     623     * (such as jitter buffer settings, codec settings, etc) before we 
     624     * create the session. 
     625     */ 
     626 
    610627    /* Create new media session, passing the two SDPs, and also the 
    611628     * media socket that we created earlier. 
    612629     * The media session is active immediately. 
    613630     */ 
    614     status = pjmedia_session_create( g_med_endpt, 1,  
    615                                      &g_med_skinfo, 
    616                                      local_sdp, remote_sdp,  
     631    status = pjmedia_session_create( g_med_endpt, &sess_info, 
    617632                                     NULL, &g_med_session ); 
    618633    if (status != PJ_SUCCESS) { 
  • pjproject/trunk/pjsip-apps/src/samples/siprtp.c

    r437 r438  
    11691169                                             strm->bytes_per_frame,  
    11701170                                             strm->samples_per_frame, 
    1171                                              &hdr, &hdrlen); 
     1171                                             (const void**)&hdr, &hdrlen); 
    11721172            if (status == PJ_SUCCESS) { 
    11731173 
     
    12671267 
    12681268    status = pjmedia_stream_info_from_sdp(&audio->si, inv->pool, app.med_endpt, 
    1269                                           local_sdp, remote_sdp, 0); 
     1269                                          NULL, local_sdp, remote_sdp, 0); 
    12701270    if (status != PJ_SUCCESS) { 
    12711271        app_perror(THIS_FILE, "Error creating stream info from SDP", status); 
  • pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h

    r422 r438  
    196196    int              complexity;    /**< Codec complexity.              */ 
    197197    int              quality;       /**< Codec quality.                 */ 
     198    int              ptime;         /**< Codec ptime in msec.           */ 
    198199 
    199200 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c

    r422 r438  
    2727 */ 
    2828 
    29 #define THIS_FILE   "pjsua_inv.c" 
     29#define THIS_FILE   "pjsua_call.c" 
    3030 
    3131 
     
    154154        call->session = NULL; 
    155155 
    156     } 
    157  
    158     PJ_LOG(3,(THIS_FILE, "Media session for call %d is destroyed",  
    159                          call_index)); 
     156        PJ_LOG(3,(THIS_FILE, "Media session for call %d is destroyed",  
     157                             call_index)); 
     158 
     159    } 
    160160 
    161161    return PJ_SUCCESS; 
     
    524524            pj_gettimeofday(&call->dis_time); 
    525525            break; 
     526        default: 
     527            /* Nothing to do. Just to keep gcc from complaining about 
     528             * unused enums. 
     529             */  
     530            break; 
    526531    } 
    527532 
     
    557562            st_code = e->body.tsx_state.tsx->status_code; 
    558563            ev_state = PJSIP_EVSUB_STATE_TERMINATED; 
     564            break; 
     565 
     566        default: 
     567            /* Nothing to do. Just to keep gcc from complaining about 
     568             * unused enums. 
     569             */ 
    559570            break; 
    560571        } 
     
    916927} 
    917928 
     929#if 0 
    918930/* Disconnect call */ 
    919931static void call_disconnect(pjsip_inv_session *inv, 
     
    931943    } 
    932944} 
     945#endif 
    933946 
    934947/* 
     
    941954{ 
    942955    pjsua_call *call; 
     956    pjmedia_session_info sess_info; 
    943957    const pjmedia_sdp_session *local_sdp; 
    944958    const pjmedia_sdp_session *remote_sdp; 
     
    9911005    } 
    9921006 
    993     /* Create new media session.  
    994      * The media session is active immediately. 
    995      */ 
    9961007    if (pjsua.null_audio) 
    9971008        return; 
    998      
    999     status = pjmedia_session_create( pjsua.med_endpt, 1,  
    1000                                      &call->skinfo, 
    1001                                      local_sdp, remote_sdp,  
    1002                                      call, 
    1003                                      &call->session ); 
     1009 
     1010    /* Create media session info based on SDP parameters.  
     1011     * We only support one stream per session at the moment 
     1012     */     
     1013    status = pjmedia_session_info_from_sdp( call->inv->dlg->pool,  
     1014                                            pjsua.med_endpt, 1, 
     1015                                            &sess_info, &call->skinfo, 
     1016                                            local_sdp, remote_sdp); 
     1017    if (status != PJ_SUCCESS) { 
     1018        pjsua_perror(THIS_FILE, "Unable to create media session",  
     1019                     status); 
     1020        //call_disconnect(inv, PJSIP_SC_UNSUPPORTED_MEDIA_TYPE); 
     1021        return; 
     1022    } 
     1023 
     1024    /* Override ptime, if this option is specified. */ 
     1025    if (pjsua.ptime) { 
     1026        sess_info.stream_info[0].param->setting.frm_per_pkt = (pj_uint8_t) 
     1027            (pjsua.ptime / sess_info.stream_info[0].param->info.frm_ptime); 
     1028        if (sess_info.stream_info[0].param->setting.frm_per_pkt==0) 
     1029            sess_info.stream_info[0].param->setting.frm_per_pkt = 1; 
     1030    } 
     1031 
     1032    /* Optionally, application may modify other stream settings here 
     1033     * (such as jitter buffer parameters, codec ptime, etc.) 
     1034     */ 
     1035 
     1036    /* Create session based on session info. */ 
     1037    status = pjmedia_session_create( pjsua.med_endpt, &sess_info, 
     1038                                     call, &call->session ); 
    10041039    if (status != PJ_SUCCESS) { 
    10051040        pjsua_perror(THIS_FILE, "Unable to create media session",  
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_settings.c

    r422 r438  
    9595    puts  ("  --complexity=N      Specify encoding complexity (0-10, default=none(-1))"); 
    9696    puts  ("  --quality=N         Specify encoding quality (0-10, default=4)"); 
     97    puts  ("  --ptime=MSEC        Override codec ptime to MSEC (default=specific)"); 
    9798    puts  (""); 
    9899    puts  ("Buddy List (can be more than one):"); 
     
    228229           OPT_AUTO_CONF, OPT_CLOCK_RATE, 
    229230           OPT_PLAY_FILE, OPT_RTP_PORT, OPT_ADD_CODEC, 
    230            OPT_COMPLEXITY, OPT_QUALITY, 
     231           OPT_COMPLEXITY, OPT_QUALITY, OPT_PTIME, 
    231232           OPT_NEXT_ACCOUNT, OPT_NEXT_CRED, OPT_MAX_CALLS, OPT_UAS_REFRESH, 
    232233           OPT_UAS_DURATION, 
     
    267268        { "complexity", 1, 0, OPT_COMPLEXITY}, 
    268269        { "quality",    1, 0, OPT_QUALITY}, 
     270        { "ptime",      1, 0, OPT_PTIME}, 
    269271        { "next-account",0,0, OPT_NEXT_ACCOUNT}, 
    270272        { "next-cred",  0, 0, OPT_NEXT_CRED}, 
     
    556558                PJ_LOG(1,(THIS_FILE, 
    557559                          "Error: invalid --quality (expecting 0-10")); 
     560                return -1; 
     561            } 
     562            break; 
     563 
     564        case OPT_PTIME: 
     565            pjsua.ptime = my_atoi(pj_optarg); 
     566            if (pjsua.ptime < 10 || pjsua.ptime > 1000) { 
     567                PJ_LOG(1,(THIS_FILE, 
     568                          "Error: invalid --ptime option")); 
    558569                return -1; 
    559570            } 
     
    772783 
    773784        PJ_LOG(3,(THIS_FILE, 
    774                "                  TX pt=%d, stat last update: %s\n" 
     785               "                  TX pt=%d, ptime=%dms, stat last update: %s\n" 
    775786               "                     total %spkt %sB (%sB +IP hdr)%s\n" 
    776787               "                     pkt loss=%d (%3.1f%%), dup=%d (%3.1f%%), reorder=%d (%3.1f%%)%s\n" 
     
    779790               "                     jitter     : %7.3f %7.3f %7.3f %7.3f%s", 
    780791               info.stream_info[i].tx_pt, 
     792               info.stream_info[i].param->info.frm_ptime * 
     793                info.stream_info[i].param->setting.frm_per_pkt, 
    781794               last_update, 
    782795               good_number(packets, stat.tx.pkt), 
     
    970983    char line[128]; 
    971984 
     985    PJ_UNUSED_ARG(max); 
     986 
    972987    cfg.ptr = buf; 
    973988    cfg.slen = 0; 
     
    10971112    pj_strcat2(&cfg, line); 
    10981113 
     1114    /* ptime */ 
     1115    if (pjsua.ptime) { 
     1116        pj_ansi_sprintf(line, "--ptime %d\n", 
     1117                        pjsua.ptime); 
     1118        pj_strcat2(&cfg, line); 
     1119    } 
     1120 
    10991121    /* Start RTP port. */ 
    11001122    pj_ansi_sprintf(line, "--rtp-port %d\n", 
Note: See TracChangeset for help on using the changeset viewer.