Changeset 2236 for pjproject/trunk


Ignore:
Timestamp:
Aug 25, 2008 1:58:25 PM (16 years ago)
Author:
nanang
Message:

Ticket #599:

  • Added "dec_fmtp" and "enc_fmtp" fields to pjmedia_codec_param.setting.
  • Codec factory puts its default parameters in "dec_fmtp" field.
  • pjmedia_stream_info_from_sdp() puts the "fmtp" attribute in SDP to pjmedia_codec_param.
  • Special treatment for fmtp "bitrate" parameter (of G722.1) during SDP negotiation
  • Added maxptime field in stream_info.
  • Replaced iLBC's fmtp "mode" implementation to use general fmtp mechanism.
  • Added some test scripts for G722.1 bitrate negotiation.
Location:
pjproject/trunk
Files:
3 added
8 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/include/pjmedia-codec/types.h

    r2218 r2236  
    6262    /* PJMEDIA_RTP_PT_G726_32,*/                /**< G726 @ 32Kbps, static? */ 
    6363    PJMEDIA_RTP_PT_G726_40,                     /**< G726 @ 40Kbps          */ 
    64     PJMEDIA_RTP_PT_G722_1,                      /**< G722.1 (16-32Kbps)     */ 
     64    PJMEDIA_RTP_PT_G722_1_16,                   /**< G722.1 (16Kbps)        */ 
     65    PJMEDIA_RTP_PT_G722_1_24,                   /**< G722.1 (24Kbps)        */ 
     66    PJMEDIA_RTP_PT_G722_1_32,                   /**< G722.1 (32Kbps)        */ 
    6567}; 
    6668 
  • pjproject/trunk/pjmedia/include/pjmedia/codec.h

    r2218 r2236  
    239239} pjmedia_codec_info; 
    240240 
     241#define PJMEDIA_CODEC_MAX_FMTP_CNT  8 
     242 
     243/**  
     244 * Structure of codec specific parameters which contains name=value pairs. 
     245 * The codec specific parameters are to be used with SDP according to  
     246 * the standards (e.g: RFC 3555). 
     247 */ 
     248typedef struct pjmedia_codec_fmtp 
     249{ 
     250    pj_uint8_t      cnt; 
     251    struct param { 
     252        pj_str_t    name; 
     253        pj_str_t    val; 
     254    } param [PJMEDIA_CODEC_MAX_FMTP_CNT]; 
     255} pjmedia_codec_fmtp; 
    241256 
    242257/**  
     
    278293        unsigned    plc:1;          /**< Packet loss concealment        */ 
    279294        unsigned    reserved:1;     /**< Reserved, must be zero.        */ 
    280         pj_uint8_t  enc_fmtp_mode;  /**< Mode param in fmtp (def:0)     */ 
    281         pj_uint8_t  dec_fmtp_mode;  /**< Mode param in fmtp (def:0)     */ 
     295        pjmedia_codec_fmtp enc_fmtp;/**< Encoder's fmtp params.         */ 
     296        pjmedia_codec_fmtp dec_fmtp;/**< Decoder's fmtp params.         */ 
    282297    } setting; 
    283298} pjmedia_codec_param; 
  • pjproject/trunk/pjmedia/include/pjmedia/stream.h

    r2039 r2236  
    109109    pjmedia_codec_param *param;     /**< Optional codec param.              */ 
    110110    unsigned            tx_pt;      /**< Outgoing codec paylaod type.       */ 
     111    unsigned            tx_maxptime;/**< Outgoing codec max ptime.          */ 
    111112    int                 tx_event_pt;/**< Outgoing pt for telephone-events.  */ 
    112113    int                 rx_event_pt;/**< Incoming pt for telephone-events.  */ 
  • pjproject/trunk/pjmedia/src/pjmedia-codec/ilbc.c

    r2039 r2236  
    144144}; 
    145145 
    146  
     146static pj_str_t STR_MODE = {"mode", 4}; 
    147147 
    148148/* 
     
    274274    attr->setting.plc = 1; 
    275275    attr->setting.penh = 1; 
    276     attr->setting.dec_fmtp_mode = (pj_uint8_t)ilbc_factory.mode; 
     276    attr->setting.dec_fmtp.cnt = 1; 
     277    attr->setting.dec_fmtp.param[0].name = STR_MODE; 
     278    if (ilbc_factory.mode == 30) 
     279        attr->setting.dec_fmtp.param[0].val = pj_str("30"); 
     280    else 
     281        attr->setting.dec_fmtp.param[0].val = pj_str("20"); 
    277282 
    278283    return PJ_SUCCESS; 
     
    371376    struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec; 
    372377    pj_status_t status; 
     378    unsigned i, dec_fmtp_mode = 0, enc_fmtp_mode = 0; 
    373379 
    374380    pj_assert(ilbc_codec != NULL); 
     
    376382              ilbc_codec->dec_ready == PJ_FALSE); 
    377383 
     384    /* Get decoder mode */ 
     385    for (i = 0; i < attr->setting.dec_fmtp.cnt; ++i) { 
     386        if (pj_stricmp(&attr->setting.dec_fmtp.param[i].name, &STR_MODE) == 0) 
     387        { 
     388            dec_fmtp_mode = (unsigned) 
     389                            pj_strtoul(&attr->setting.dec_fmtp.param[i].val); 
     390            break; 
     391        } 
     392    } 
     393 
    378394    /* Decoder mode must be set */ 
    379     PJ_ASSERT_RETURN(attr->setting.dec_fmtp_mode==20 || 
    380                      attr->setting.dec_fmtp_mode==30, PJMEDIA_CODEC_EINMODE); 
     395    PJ_ASSERT_RETURN(dec_fmtp_mode == 20 || dec_fmtp_mode == 30,  
     396                     PJMEDIA_CODEC_EINMODE); 
     397 
     398    /* Get encoder mode */ 
     399    for (i = 0; i < attr->setting.enc_fmtp.cnt; ++i) { 
     400        if (pj_stricmp(&attr->setting.enc_fmtp.param[i].name, &STR_MODE) == 0) 
     401        { 
     402            enc_fmtp_mode = (unsigned) 
     403                            pj_strtoul(&attr->setting.enc_fmtp.param[i].val); 
     404            break; 
     405        } 
     406    } 
    381407 
    382408    /* The enc mode must be set in the attribute  
     
    384410     * received from remote)  
    385411     */ 
    386     if (attr->setting.enc_fmtp_mode == 0) 
    387         attr->setting.enc_fmtp_mode = attr->setting.dec_fmtp_mode; 
    388  
    389     PJ_ASSERT_RETURN(attr->setting.enc_fmtp_mode==20 || 
    390                      attr->setting.enc_fmtp_mode==30, PJMEDIA_CODEC_EINMODE); 
     412    if (enc_fmtp_mode == 0) 
     413        enc_fmtp_mode = dec_fmtp_mode; 
     414 
     415    PJ_ASSERT_RETURN(enc_fmtp_mode==20 || 
     416                     enc_fmtp_mode==30, PJMEDIA_CODEC_EINMODE); 
    391417 
    392418    /* Update enc_ptime in the param */ 
    393     if (attr->setting.enc_fmtp_mode != attr->setting.dec_fmtp_mode) { 
    394         attr->info.enc_ptime = attr->setting.enc_fmtp_mode; 
     419    if (enc_fmtp_mode != dec_fmtp_mode) { 
     420        attr->info.enc_ptime = (pj_uint16_t)enc_fmtp_mode; 
    395421    } else { 
    396422        attr->info.enc_ptime = 0; 
     
    398424 
    399425    /* Create enc */ 
    400     ilbc_codec->enc_frame_size = initEncode(&ilbc_codec->enc,  
    401                                             attr->setting.enc_fmtp_mode); 
    402     ilbc_codec->enc_samples_per_frame = CLOCK_RATE*attr->setting.enc_fmtp_mode/ 
    403                                         1000; 
     426    ilbc_codec->enc_frame_size = initEncode(&ilbc_codec->enc, enc_fmtp_mode); 
     427    ilbc_codec->enc_samples_per_frame = CLOCK_RATE * enc_fmtp_mode / 1000; 
    404428    ilbc_codec->enc_ready = PJ_TRUE; 
    405429 
    406430    /* Create decoder */ 
    407431    ilbc_codec->dec_samples_per_frame = initDecode(&ilbc_codec->dec, 
    408                                                    attr->setting.dec_fmtp_mode, 
     432                                                   dec_fmtp_mode, 
    409433                                                   attr->setting.penh); 
    410     if (attr->setting.dec_fmtp_mode == 20) 
     434    if (dec_fmtp_mode == 20) 
    411435        ilbc_codec->dec_frame_size = 38; 
    412     else if (attr->setting.dec_fmtp_mode == 30) 
     436    else if (dec_fmtp_mode == 30) 
    413437        ilbc_codec->dec_frame_size = 50; 
    414438    else { 
     
    436460    PJ_LOG(5,(ilbc_codec->obj_name,  
    437461              "iLBC codec opened, encoder mode=%d, decoder mode=%d", 
    438               attr->setting.enc_fmtp_mode, attr->setting.dec_fmtp_mode)); 
     462              enc_fmtp_mode, dec_fmtp_mode)); 
    439463 
    440464    return PJ_SUCCESS; 
  • pjproject/trunk/pjmedia/src/pjmedia-codec/ipp_codecs.c

    r2231 r2236  
    3030#include <pj/os.h> 
    3131 
     32 
    3233/* 
    3334 * Only build this file if PJMEDIA_HAS_INTEL_IPP != 0 
     
    211212 
    212213    predecode_cb     predecode;         /* Callback to translate RTP frame 
    213                                            into USC frame                   */ 
    214     parse_cb         parse;             /* Callback to parse bitstream      */ 
    215     pack_cb          pack;              /* Callback to pack bitstream       */ 
    216 }  
     214                                           into USC frame.                  */ 
     215    parse_cb         parse;             /* Callback to parse bitstream.     */ 
     216    pack_cb          pack;              /* Callback to pack bitstream.      */ 
     217 
     218    pjmedia_codec_fmtp dec_fmtp;        /* Decoder's fmtp params.           */ 
     219} 
    217220 
    218221ipp_codec[] =  
     
    233236 
    234237#   if PJMEDIA_HAS_INTEL_IPP_CODEC_G729 
    235     /* G.729 actually has internal VAD, but for now we need to disable it,  
    236      * since its RTP packaging (multiple frames per packet) requires  
    237      * SID frame to only be occured in the last frame, while controling  
    238      * encoder on each loop (to enable/disable VAD) is considered inefficient. 
    239      * This should still be interoperable with other implementations. 
    240      */ 
    241238    {1, "G729",     PJMEDIA_RTP_PT_G729,      &USC_G729AFP_Fxns, 8000, 1,  80,   
    242                     8000, 11800, 2, 0, 1,  
     239                    8000, 11800, 2, 1, 1,  
    243240                    &predecode_g729, NULL, NULL 
    244241    }, 
     
    280277 
    281278#   if PJMEDIA_HAS_INTEL_IPP_CODEC_G722_1 
    282     {0, "G7221",    PJMEDIA_RTP_PT_G722_1,    &USC_G722_Fxns,   16000, 1, 320,  
    283                     16000, 32000, 1, 0, 1, 
    284                     NULL, NULL, NULL 
     279    {0, "G7221",    PJMEDIA_RTP_PT_G722_1_16, &USC_G722_Fxns,   16000, 1, 320,  
     280                    16000, 16000, 1, 0, 1, 
     281                    NULL, NULL, NULL, 
     282                    {1, {{{"bitrate", 7}, {"16000", 5}}} } 
     283    }, 
     284    {1, "G7221",    PJMEDIA_RTP_PT_G722_1_24, &USC_G722_Fxns,   16000, 1, 320,  
     285                    24000, 24000, 1, 0, 1, 
     286                    NULL, NULL, NULL, 
     287                    {1, {{{"bitrate", 7}, {"24000", 5}}} } 
     288    }, 
     289    {1, "G7221",    PJMEDIA_RTP_PT_G722_1_32, &USC_G722_Fxns,   16000, 1, 320,  
     290                    32000, 32000, 1, 0, 1, 
     291                    NULL, NULL, NULL, 
     292                    {1, {{{"bitrate", 7}, {"32000", 5}}} } 
    285293    }, 
    286294#   endif 
     
    423431        if ((pj_stricmp(&id->encoding_name, &name) == 0) && 
    424432            (id->clock_rate == (unsigned)ipp_codec[i].clock_rate) && 
    425             (id->channel_cnt == (unsigned)ipp_codec[i].channel_count)) 
     433            (id->channel_cnt == (unsigned)ipp_codec[i].channel_count) && 
     434            (id->pt == (unsigned)ipp_codec[i].pt)) 
    426435        { 
    427436            attr->info.pt = (pj_uint8_t)id->pt; 
     
    438447 
    439448            /* Default flags. */ 
    440             attr->setting.cng = 0; 
    441449            attr->setting.plc = 1; 
    442450            attr->setting.penh= 0; 
    443             attr->setting.vad = 1; /* Always disable for now */ 
     451            attr->setting.vad = 1; 
     452            attr->setting.cng = attr->setting.vad; 
     453            attr->setting.dec_fmtp = ipp_codec[i].dec_fmtp; 
     454 
     455            if (attr->setting.vad == 0) { 
     456#if PJMEDIA_HAS_INTEL_IPP_CODEC_G729 
     457                if (id->pt == PJMEDIA_RTP_PT_G729) { 
     458                    /* Signal G729 Annex B is being disabled */ 
     459                    attr->setting.dec_fmtp.cnt = 1; 
     460                    pj_strset2(&attr->setting.dec_fmtp.param[0].name, "annexb"); 
     461                    pj_strset2(&attr->setting.dec_fmtp.param[0].val, "no"); 
     462                } 
     463#endif 
     464            } 
    444465 
    445466            return PJ_SUCCESS; 
     
    632653    codec_data->info->params.direction = USC_ENCODE; 
    633654    codec_data->info->params.modes.vad = attr->setting.vad &&  
    634                                            ippc->has_native_vad; 
     655                                         ippc->has_native_vad; 
    635656    codec_data->info->params.modes.bitrate = attr->info.avg_bps; 
    636657    codec_data->info->params.law = 0; /* Linear PCM input */ 
     658 
     659#if PJMEDIA_HAS_INTEL_IPP_CODEC_G729 
     660    if (ippc->pt == PJMEDIA_RTP_PT_G729) { 
     661        /* Check if G729 Annex B is signaled to be disabled */ 
     662        for (i = 0; i < attr->setting.enc_fmtp.cnt; ++i) { 
     663            if (pj_stricmp2(&attr->setting.enc_fmtp.param[i].name, "annexb")==0) 
     664            { 
     665                if (pj_stricmp2(&attr->setting.enc_fmtp.param[i].val, "no")==0) 
     666                    codec_data->info->params.modes.vad = 0; 
     667                break; 
     668            } 
     669        } 
     670    } 
     671#endif 
    637672 
    638673    /* Get number of memory blocks needed by the encoder */ 
     
    673708    /* Setting the decoder params */ 
    674709    codec_data->info->params.direction = USC_DECODE; 
     710 
     711    /* Not sure if VAD affects decoder, just try to be safe */ 
     712    codec_data->info->params.modes.vad = ippc->has_native_vad; 
    675713 
    676714    /* Get number of memory blocks needed by the decoder */ 
     
    926964        tx += out.nbytes; 
    927965        bits_out += out.nbytes; 
     966 
     967#if PJMEDIA_HAS_INTEL_IPP_CODEC_G729 
     968        if (out.frametype == 1) { 
     969            /* SID */ 
     970            break; 
     971        } else if (out.frametype == 0) { 
     972            /* Untransmitted */ 
     973            tx -= out.nbytes; 
     974            break; 
     975        } 
     976#endif 
     977 
    928978    } 
    929979 
  • pjproject/trunk/pjmedia/src/pjmedia/endpoint.c

    r2072 r2236  
    425425        } 
    426426 
    427         /* Add fmtp mode where applicable */ 
    428         if (codec_param.setting.dec_fmtp_mode != 0) { 
    429             const pj_str_t fmtp = { "fmtp", 4 }; 
     427        /* Add fmtp params */ 
     428        if (codec_param.setting.dec_fmtp.cnt > 0) { 
     429            enum { MAX_FMTP_STR_LEN = 160 }; 
     430            char buf[MAX_FMTP_STR_LEN]; 
     431            unsigned buf_len = 0, i; 
     432            pjmedia_codec_fmtp *dec_fmtp = &codec_param.setting.dec_fmtp; 
     433 
     434            /* Print codec PT */ 
     435            buf_len += pj_ansi_snprintf(buf,  
     436                                        MAX_FMTP_STR_LEN - buf_len,  
     437                                        "%d",  
     438                                        codec_info->pt); 
     439 
     440            for (i = 0; i < dec_fmtp->cnt; ++i) { 
     441                unsigned test_len = 2; 
     442 
     443                /* Check if buf still available */ 
     444                test_len = dec_fmtp->param[i].val.slen +  
     445                           dec_fmtp->param[i].name.slen; 
     446                if (test_len + buf_len >= MAX_FMTP_STR_LEN) 
     447                    return PJ_ETOOBIG; 
     448 
     449                /* Print delimiter */ 
     450                buf_len += pj_ansi_snprintf(&buf[buf_len],  
     451                                            MAX_FMTP_STR_LEN - buf_len, 
     452                                            (i == 0?" ":";")); 
     453 
     454                /* Print an fmtp param */ 
     455                if (dec_fmtp->param[i].name.slen) 
     456                    buf_len += pj_ansi_snprintf( 
     457                                            &buf[buf_len], 
     458                                            MAX_FMTP_STR_LEN - buf_len, 
     459                                            "%.*s=%.*s", 
     460                                            (int)dec_fmtp->param[i].name.slen, 
     461                                            dec_fmtp->param[i].name.ptr, 
     462                                            (int)dec_fmtp->param[i].val.slen, 
     463                                            dec_fmtp->param[i].val.ptr); 
     464                else 
     465                    buf_len += pj_ansi_snprintf(&buf[buf_len],  
     466                                            MAX_FMTP_STR_LEN - buf_len, 
     467                                            "%.*s",  
     468                                            (int)dec_fmtp->param[i].val.slen, 
     469                                            dec_fmtp->param[i].val.ptr); 
     470            } 
     471 
    430472            attr = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_attr); 
    431473 
    432             attr->name = fmtp; 
    433             attr->value.ptr = (char*) pj_pool_alloc(pool, 32); 
    434             attr->value.slen =  
    435                 pj_ansi_snprintf( attr->value.ptr, 32, 
    436                                   "%d mode=%d", 
    437                                   codec_info->pt, 
    438                                   codec_param.setting.dec_fmtp_mode); 
     474            attr->name = pj_str("fmtp"); 
     475            attr->value = pj_strdup3(pool, buf); 
    439476            m->attr[m->attr_count++] = attr; 
    440477        } 
  • pjproject/trunk/pjmedia/src/pjmedia/sdp_neg.c

    r2039 r2236  
    534534} 
    535535 
     536/* Matching G722.1 bitrates between offer and answer. 
     537 */ 
     538static pj_bool_t match_g7221( const pjmedia_sdp_media *offer, 
     539                              unsigned o_fmt_idx, 
     540                              const pjmedia_sdp_media *answer, 
     541                              unsigned a_fmt_idx) 
     542{ 
     543    const pjmedia_sdp_attr *a_ans; 
     544    const pjmedia_sdp_attr *a_off; 
     545    pjmedia_sdp_fmtp fmtp; 
     546    unsigned a_bitrate = 0, o_bitrate = 0; 
     547    const pj_str_t bitrate = {"bitrate=", 8}; 
     548    const char *p; 
     549 
     550    a_ans = pjmedia_sdp_media_find_attr2(answer, "fmtp",  
     551                                         &answer->desc.fmt[a_fmt_idx]); 
     552    if (!a_ans) 
     553        return PJ_FALSE; 
     554 
     555    if (pjmedia_sdp_attr_get_fmtp(a_ans, &fmtp) != PJ_SUCCESS) 
     556        return PJ_FALSE; 
     557 
     558    p = pj_stristr(&fmtp.fmt_param, &bitrate); 
     559    if (p == NULL) 
     560        return PJ_FALSE; 
     561 
     562    a_bitrate = atoi(p + bitrate.slen); 
     563 
     564    a_off = pjmedia_sdp_media_find_attr2(offer, "fmtp",  
     565                                         &offer->desc.fmt[o_fmt_idx]); 
     566    if (!a_off) 
     567        return PJ_FALSE; 
     568 
     569    if (pjmedia_sdp_attr_get_fmtp(a_off, &fmtp) != PJ_SUCCESS) 
     570        return PJ_FALSE; 
     571 
     572    p = pj_stristr(&fmtp.fmt_param, &bitrate); 
     573    if (p == NULL) 
     574        return PJ_FALSE; 
     575 
     576    o_bitrate = atoi(p + bitrate.slen); 
     577 
     578    return (a_bitrate == o_bitrate); 
     579} 
     580 
    536581/* Update single local media description to after receiving answer 
    537582 * from remote. 
     
    658703                             (ar.param.slen==1 && *ar.param.ptr=='1'))) 
    659704                        { 
    660                             /* Match! */ 
    661                             break; 
     705                            /* Further check for G7221, negotiate bitrate. */ 
     706                            if (pj_strcmp2(&or_.enc_name, "G7221") == 0) { 
     707                                if (match_g7221(offer, i, answer, j)) 
     708                                    break; 
     709                            } else { 
     710                                /* Match! */ 
     711                                break; 
     712                            } 
    662713                        } 
    663714                    } 
     
    872923                        { 
    873924                            /* Match! */ 
    874                             if (is_codec) 
     925                            if (is_codec) { 
     926                                /* Further check for G7221, negotiate bitrate. */ 
     927                                if (pj_strcmp2(&or_.enc_name, "G7221")  == 0 && 
     928                                    match_g7221(offer, i, preanswer, j) == 0) 
     929                                { 
     930                                    continue; 
     931                                } 
    875932                                found_matching_codec = 1; 
    876                             else 
     933                            } else { 
    877934                                found_matching_telephone_event = 1; 
     935                            } 
     936 
    878937                            pt_answer[pt_answer_count++] = preanswer->desc.fmt[j]; 
    879938                            break; 
  • pjproject/trunk/pjmedia/src/pjmedia/session.c

    r2153 r2236  
    6868 
    6969/* 
    70  * Get fmtp mode parameter associated with the codec. 
    71  */ 
    72 static pj_status_t get_fmtp_mode(const pjmedia_sdp_media *m, 
    73                                  const pj_str_t *fmt, 
    74                                  int *p_mode) 
     70 * Parse fmtp for specified format/payload type. 
     71 */ 
     72static void parse_fmtp( pj_pool_t *pool, 
     73                        const pjmedia_sdp_media *m, 
     74                        unsigned pt, 
     75                        pjmedia_codec_fmtp *fmtp) 
    7576{ 
    7677    const pjmedia_sdp_attr *attr; 
    77     pjmedia_sdp_fmtp fmtp; 
    78     const pj_str_t str_mode = { "mode=", 5 }; 
    79     char *pos; 
     78    pjmedia_sdp_fmtp sdp_fmtp; 
     79    char *p, *p_end, fmt_buf[8]; 
     80    pj_str_t fmt; 
     81 
     82    pj_assert(m && fmtp); 
     83 
     84    pj_bzero(fmtp, sizeof(pjmedia_codec_fmtp)); 
    8085 
    8186    /* Get "fmtp" attribute for the format */ 
    82     attr = pjmedia_sdp_media_find_attr2(m, "fmtp", fmt); 
     87    pj_ansi_sprintf(fmt_buf, "%d", pt); 
     88    fmt = pj_str(fmt_buf); 
     89    attr = pjmedia_sdp_media_find_attr2(m, "fmtp", &fmt); 
    8390    if (attr == NULL) 
    84         return -1; 
     91        return; 
    8592 
    8693    /* Parse "fmtp" attribute */ 
    87     if (pjmedia_sdp_attr_get_fmtp(attr, &fmtp) != PJ_SUCCESS) 
    88         return -1; 
    89  
    90     /* Look for "mode=" string in the fmtp */ 
    91     while (fmtp.fmt_param.slen >= str_mode.slen + 1) { 
    92         if (pj_strnicmp(&fmtp.fmt_param, &str_mode, str_mode.slen)==0) { 
    93             /* Found "mode=" string */ 
     94    if (pjmedia_sdp_attr_get_fmtp(attr, &sdp_fmtp) != PJ_SUCCESS) 
     95        return; 
     96 
     97    /* Prepare parsing */ 
     98    p = sdp_fmtp.fmt_param.ptr; 
     99    p_end = p + sdp_fmtp.fmt_param.slen; 
     100 
     101    /* Parse */ 
     102    while (p < p_end) { 
     103        char *token, *start, *end; 
     104 
     105        /* Skip whitespaces */ 
     106        while (p < p_end && (*p == ' ' || *p == '\t')) ++p; 
     107        if (p == p_end) 
    94108            break; 
    95         } 
    96  
    97         fmtp.fmt_param.ptr++; 
    98         fmtp.fmt_param.slen--; 
    99     } 
    100  
    101     if (fmtp.fmt_param.slen < str_mode.slen + 1) { 
    102         /* "mode=" param not found */ 
    103         return -1; 
    104     } 
    105  
    106     /* Get the mode */ 
    107     pos = fmtp.fmt_param.ptr + str_mode.slen; 
    108     *p_mode = 0; 
    109     while (pj_isdigit(*pos)) { 
    110         *p_mode = *p_mode * 10 + (*pos - '0'); 
    111         ++pos; 
    112     } 
    113  
    114     return PJ_SUCCESS; 
     109 
     110        /* Get token */ 
     111        start = p; 
     112        while (p < p_end && *p != ';' && *p != '=') ++p; 
     113        end = p - 1; 
     114 
     115        /* Right trim */ 
     116        while (end >= start && (*end == ' '  || *end == '\t' ||  
     117                                *end == '\r' || *end == '\n' )) 
     118            --end; 
     119 
     120        /* Forward a char after trimming */ 
     121        ++end; 
     122 
     123        /* Store token */ 
     124        if (end > start) { 
     125            token = (char*)pj_pool_alloc(pool, end - start); 
     126            pj_ansi_strncpy(token, start, end - start); 
     127            if (*p == '=') 
     128                /* Got param name */ 
     129                pj_strset(&fmtp->param[fmtp->cnt].name, token, end - start); 
     130            else 
     131                /* Got param value */ 
     132                pj_strset(&fmtp->param[fmtp->cnt++].val, token, end - start); 
     133        } else if (*p != '=') { 
     134            ++fmtp->cnt; 
     135        } 
     136 
     137        /* Next */ 
     138        ++p; 
     139    } 
    115140} 
    116141 
     
    136161    pj_sockaddr local_addr; 
    137162    pjmedia_sdp_rtpmap *rtpmap; 
    138     int local_fmtp_mode = 0, rem_fmtp_mode = 0; 
    139163    unsigned i, pt, fmti; 
    140164    pj_status_t status; 
     
    401425#if defined(PJMEDIA_HANDLE_G722_MPEG_BUG) && (PJMEDIA_HANDLE_G722_MPEG_BUG != 0) 
    402426            /* The session info should have the actual clock rate, because  
    403              * this info is used for calculationg buffer size, etc in stream */ 
     427             * this info is used for calculationg buffer size, etc in stream  
     428             */ 
    404429            if (si->fmt.pt == PJMEDIA_RTP_PT_G722) 
    405430                si->fmt.clock_rate = 16000; 
     
    464489        } 
    465490 
    466         /* Get fmtp mode= param in local SDP, if any */ 
    467         get_fmtp_mode(local_m, &local_m->desc.fmt[fmti], &local_fmtp_mode); 
    468  
    469491        /* Determine payload type for outgoing channel, by finding 
    470492         * dynamic payload type in remote SDP that matches the answer. 
     
    494516                si->tx_pt = rpt; 
    495517 
    496                 /* Get fmtp mode param in remote SDP, if any */ 
    497                 get_fmtp_mode(rem_m, &rtpmap->pt, &rem_fmtp_mode); 
    498  
    499518                break; 
    500519            } 
     
    509528    si->param = PJ_POOL_ALLOC_T(pool, pjmedia_codec_param); 
    510529    status = pjmedia_codec_mgr_get_default_param(mgr, &si->fmt, si->param); 
     530 
     531    /* Get remote fmtp for our encoder. */ 
     532    parse_fmtp(pool, rem_m, si->tx_pt, &si->param->setting.enc_fmtp); 
     533 
     534    /* Get local fmtp for our decoder. */ 
     535    parse_fmtp(pool, local_m, si->fmt.pt, &si->param->setting.dec_fmtp); 
     536 
     537    /* Get remote maxptime for our encoder. */ 
     538    attr = pjmedia_sdp_attr_find2(rem_m->attr_count, rem_m->attr, 
     539                                  "maxptime", NULL); 
     540    if (attr) { 
     541        pj_str_t tmp_val = attr->value; 
     542 
     543        pj_strltrim(&tmp_val); 
     544        si->tx_maxptime = pj_strtoul(&tmp_val); 
     545    } 
    511546 
    512547    /* When direction is NONE (it means SDP negotiation has failed) we don't 
     
    520555        return status; 
    521556 
    522     /* Set fmtp mode for both local and remote */ 
    523     if (local_fmtp_mode != 0) 
    524         si->param->setting.dec_fmtp_mode = (pj_int8_t)local_fmtp_mode; 
    525     if (rem_fmtp_mode != 0) 
    526         si->param->setting.enc_fmtp_mode = (pj_int8_t)rem_fmtp_mode; 
    527  
    528557 
    529558    /* Get incomming payload type for telephone-events */ 
Note: See TracChangeset for help on using the changeset viewer.