Ticket #486: ticket486.2.patch

File ticket486.2.patch, 11.6 KB (added by nanang, 11 years ago)
  • pjmedia/include/pjmedia/config.h

     
    492492#   define PJMEDIA_HAS_SRTP                         1 
    493493#endif 
    494494 
     495/** 
     496 * Handle inconsitence sampling clockrate between SDP & actually used, 
     497 * identified codecs having this issue are G.722 and MPEG. 
     498 * See: 
     499 *  - G.722      : RFC 3551 4.5.2 
     500 *  - MPEG audio : RFC 3551 4.5.13 & RFC 3119 
     501 * 
     502 * By default it is enabled. 
     503 */ 
     504#ifndef PJMEDIA_HANDLE_G722_MPEG_BUG 
     505#   define PJMEDIA_HANDLE_G722_MPEG_BUG             1 
     506#endif 
    495507 
     508 
    496509/** 
    497510 * @} 
    498511 */ 
  • pjmedia/src/pjmedia/stream.c

     
    9292                                                 ptime is different than dec. 
    9393                                                 Otherwise it's NULL.       */ 
    9494 
    95     unsigned                 enc_samples_per_frame; 
     95    unsigned                 enc_samples_per_pkt; 
    9696    unsigned                 enc_buf_size;  /**< Encoding buffer size, in 
    9797                                                 samples.                   */ 
    9898    unsigned                 enc_buf_pos;   /**< First position in buf.     */ 
     
    131131    /* DTMF callback */ 
    132132    void                    (*dtmf_cb)(pjmedia_stream*, void*, int); 
    133133    void                     *dtmf_cb_user_data; 
     134 
     135#if defined(PJMEDIA_HANDLE_G722_MPEG_BUG) && (PJMEDIA_HANDLE_G722_MPEG_BUG != 0) 
     136    /* Handle codec with inconsistence clockrate between definition and 
     137     * implementation. This is possible because of error in RFC (e.g: G722) 
     138     * or video synchronization (MPEG audio). 
     139     */ 
     140    pj_bool_t                has_g722_mpeg_bug; 
     141                                            /**< Flag to specify whether  
     142                                                 normalization process  
     143                                                 is needed                  */ 
     144    unsigned                 rtp_tx_samples_per_pkt; 
     145                                            /**< Normalized samples per packet  
     146                                                 transmitted according to  
     147                                                 'erroneous' definition     */ 
     148    unsigned                 rtp_rx_samples_per_frame; 
     149                                            /**< Normalized samples per frame  
     150                                                 received according to  
     151                                                 'erroneous' definition     */ 
     152    pj_uint32_t              rtp_rx_last_ts;/**< Last received RTP timestamp 
     153                                                 for timestamp checking     */ 
     154    pj_bool_t                incons_checked;/**< Flag to specify whether 
     155                                                 timestamp checking is done */ 
     156#endif 
     157 
    134158}; 
    135159 
    136160 
     
    516540    pjmedia_channel *channel = stream->enc; 
    517541    pj_status_t status = 0; 
    518542    pjmedia_frame frame_out; 
    519     unsigned ts_len, samples_per_frame; 
     543    unsigned ts_len, rtp_ts_len, samples_per_frame; 
    520544    void *rtphdr; 
    521545    int rtphdrlen; 
    522546    int inc_timestamp = 0; 
     
    535559 
    536560    /* Increment transmit duration */ 
    537561    stream->tx_duration += ts_len; 
     562    rtp_ts_len = ts_len; 
    538563 
     564#if defined(PJMEDIA_HANDLE_G722_MPEG_BUG) && (PJMEDIA_HANDLE_G722_MPEG_BUG != 0) 
     565    /* Handle special case for audio codec with RTP timestamp inconsistence  
     566     * e.g: G722, MPEG audio. 
     567     */ 
     568    if (stream->has_g722_mpeg_bug &&  
     569        stream->rtp_tx_samples_per_pkt != stream->enc_samples_per_pkt)  
     570    { 
     571        rtp_ts_len /= stream->enc_samples_per_pkt; 
     572        rtp_ts_len *= stream->rtp_tx_samples_per_pkt; 
     573    } 
     574#endif 
     575 
    539576    /* Init frame_out buffer. */ 
    540577    frame_out.buf = ((char*)channel->out_pkt) + sizeof(pjmedia_rtp_hdr); 
    541578    frame_out.size = 0; 
    542579 
    543580    /* Calculate number of samples per frame */ 
    544     samples_per_frame = stream->enc_samples_per_frame; 
     581    samples_per_frame = stream->enc_samples_per_pkt; 
    545582 
    546583 
    547584    /* If we have DTMF digits in the queue, transmit the digits.  
     
    558595         */ 
    559596        status = pjmedia_rtp_encode_rtp( &channel->rtp,  
    560597                                         stream->tx_event_pt, first,  
    561                                          frame_out.size, (first?ts_len:0),  
     598                                         frame_out.size, 
     599                                         (first ? rtp_ts_len : 0),  
    562600                                         (const void**)&rtphdr,  
    563601                                         &rtphdrlen); 
    564602 
     
    567605             * Increment the RTP timestamp of the RTP session, for next 
    568606             * RTP packets. 
    569607             */ 
    570             inc_timestamp = PJMEDIA_DTMF_DURATION - ts_len; 
     608            inc_timestamp = PJMEDIA_DTMF_DURATION - rtp_ts_len; 
    571609        } 
    572610 
    573611        /* No need to encode if this is a zero frame. 
     
    635673        /* Encapsulate. */ 
    636674        status = pjmedia_rtp_encode_rtp( &channel->rtp,  
    637675                                         channel->pt, 0,  
    638                                          frame_out.size, ts_len,  
     676                                         frame_out.size, rtp_ts_len,  
    639677                                         (const void**)&rtphdr,  
    640678                                         &rtphdrlen); 
    641679    } else { 
     
    643681        /* Just update RTP session's timestamp. */ 
    644682        status = pjmedia_rtp_encode_rtp( &channel->rtp,  
    645683                                         0, 0,  
    646                                          0, ts_len,  
     684                                         0, rtp_ts_len,  
    647685                                         (const void**)&rtphdr,  
    648686                                         &rtphdrlen); 
    649687 
     
    724762    pjmedia_frame tmp_zero_frame; 
    725763    unsigned samples_per_frame; 
    726764 
    727     samples_per_frame = stream->enc_samples_per_frame; 
     765    samples_per_frame = stream->enc_samples_per_pkt; 
    728766 
    729767    /* http://www.pjsip.org/trac/ticket/56: 
    730768     *  when input is PJMEDIA_FRAME_TYPE_NONE, feed zero PCM frame 
     
    801839            /* If we still have full frame in the buffer, re-run 
    802840             * rebuffer() with NULL frame. 
    803841             */ 
    804             if (stream->enc_buf_count >= stream->enc_samples_per_frame) { 
     842            if (stream->enc_buf_count >= stream->enc_samples_per_pkt) { 
    805843 
    806844                tmp_rebuffer_frame.type = PJMEDIA_FRAME_TYPE_NONE; 
    807845 
     
    10211059        enum { MAX = 16 }; 
    10221060        pj_timestamp ts; 
    10231061        unsigned i, count = MAX; 
    1024         unsigned samples_per_frame; 
     1062        unsigned ts_span; 
    10251063        pjmedia_frame frames[MAX]; 
    10261064 
    10271065        /* Get the timestamp of the first sample */ 
     
    10411079            count = 0; 
    10421080        } 
    10431081 
     1082#if defined(PJMEDIA_HANDLE_G722_MPEG_BUG) && (PJMEDIA_HANDLE_G722_MPEG_BUG != 0) 
     1083        /* Check inconsistency of RTP timestamp with actual codec timestamp */ 
     1084        if (stream->has_g722_mpeg_bug) { 
     1085            if (!stream->incons_checked) { 
     1086                ts_span = stream->codec_param.info.frm_ptime *  
     1087                          stream->codec_param.info.clock_rate * 
     1088                          stream->codec_param.info.channel_cnt / 
     1089                          1000; 
     1090 
     1091                /* Make sure the calculation applied only when  
     1092                 * two consecutive packets have valid RTP sequence, 
     1093                 * and no wrapped timestamp. 
     1094                 */ 
     1095                if (seq_st.diff == 1 && stream->rtp_rx_last_ts &&  
     1096                    ts.u64 > stream->rtp_rx_last_ts) 
     1097                { 
     1098                    stream->incons_checked = PJ_TRUE; 
     1099                    stream->rtp_rx_samples_per_frame =  
     1100                                (ts.u32.lo - stream->rtp_rx_last_ts) / count;  
     1101 
     1102                    stream->rtp_tx_samples_per_pkt =  
     1103                                        stream->rtp_rx_samples_per_frame *  
     1104                                        stream->codec_param.setting.frm_per_pkt; 
     1105                    ts_span = stream->rtp_rx_samples_per_frame; 
     1106 
     1107                    /* Check for ptime difference on sending & receiving*/                       
     1108                    if (stream->codec_param.info.enc_ptime) 
     1109                        stream->rtp_tx_samples_per_pkt *=  
     1110                                        stream->codec_param.info.enc_ptime / 
     1111                                        stream->codec_param.info.frm_ptime; 
     1112 
     1113                    PJ_LOG(4, (THIS_FILE, "'Problematic codec' used, " 
     1114                                          "remote samples per frame: %d",  
     1115                                          stream->rtp_rx_samples_per_frame)); 
     1116                } 
     1117                if (!channel->rtp.seq_ctrl.probation) 
     1118                    stream->rtp_rx_last_ts = (pj_uint32_t)ts.u64; 
     1119                         
     1120            } else { 
     1121                ts_span = stream->rtp_rx_samples_per_frame; 
     1122            } 
     1123        } else { 
     1124            ts_span = stream->codec_param.info.frm_ptime *  
     1125                      stream->codec_param.info.clock_rate * 
     1126                      stream->codec_param.info.channel_cnt / 
     1127                      1000; 
     1128        } 
     1129#else 
     1130        ts_span = stream->codec_param.info.frm_ptime *  
     1131                  stream->codec_param.info.clock_rate * 
     1132                  stream->codec_param.info.channel_cnt / 
     1133                  1000; 
     1134#endif 
     1135 
    10441136        /* Put each frame to jitter buffer. */ 
    1045         samples_per_frame = stream->codec_param.info.frm_ptime *  
    1046                             stream->codec_param.info.clock_rate * 
    1047                             stream->codec_param.info.channel_cnt / 
    1048                             1000; 
    1049                              
    10501137        for (i=0; i<count; ++i) { 
    10511138            unsigned ext_seq; 
    10521139 
    1053             ext_seq = (unsigned)(frames[i].timestamp.u64 / 
    1054                                  samples_per_frame); 
     1140            ext_seq = (unsigned)(frames[i].timestamp.u64 / ts_span); 
    10551141            pjmedia_jbuf_put_frame(stream->jb, frames[i].buf,  
    10561142                                   frames[i].size, ext_seq); 
    10571143 
     
    11851271    name.ptr = (char*) pj_pool_alloc(pool, M); 
    11861272    name.slen = pj_ansi_snprintf(name.ptr, M, "strm%p", stream); 
    11871273 
    1188  
    11891274    /* Init some port-info. Some parts of the info will be set later 
    11901275     * once we have more info about the codec. 
    11911276     */ 
     
    12581343                                        stream->codec_param.setting.frm_per_pkt / 
    12591344                                        1000; 
    12601345 
    1261  
    12621346    /* Open the codec: */ 
    12631347 
    12641348    status = stream->codec->op->open(stream->codec, &stream->codec_param); 
     
    12741358    { 
    12751359        unsigned ptime; 
    12761360 
    1277         stream->enc_samples_per_frame = stream->codec_param.info.enc_ptime * 
    1278                                         stream->port.info.clock_rate / 1000; 
     1361        stream->enc_samples_per_pkt = stream->codec_param.info.enc_ptime * 
     1362                                      stream->port.info.clock_rate / 1000; 
    12791363 
    12801364        /* Set buffer size as twice the largest ptime value between 
    12811365         * stream's ptime, encoder ptime, or decoder ptime. 
     
    12981382                          pj_pool_alloc(pool, stream->enc_buf_size * 2); 
    12991383 
    13001384    } else { 
    1301         stream->enc_samples_per_frame = stream->port.info.samples_per_frame; 
     1385        stream->enc_samples_per_pkt = stream->port.info.samples_per_frame; 
    13021386    } 
    13031387 
     1388 
    13041389    /* Initially disable the VAD in the stream, to help traverse NAT better */ 
    13051390    stream->vad_enabled = stream->codec_param.setting.vad; 
    13061391    if (stream->vad_enabled) { 
     
    13161401                          stream->codec_param.info.frm_ptime / 1000; 
    13171402 
    13181403 
     1404#if defined(PJMEDIA_HANDLE_G722_MPEG_BUG) && (PJMEDIA_HANDLE_G722_MPEG_BUG != 0) 
     1405    stream->incons_checked = PJ_FALSE; 
     1406    stream->has_g722_mpeg_bug = PJ_FALSE; 
     1407    stream->rtp_rx_last_ts = 0; 
     1408    stream->rtp_tx_samples_per_pkt = stream->enc_samples_per_pkt; 
     1409    stream->rtp_rx_samples_per_frame = stream->port.info.samples_per_frame; 
     1410 
    13191411    /* Init RTCP session: */ 
    13201412 
     1413    /* Special case for G.722 */ 
     1414    if (info->fmt.pt == PJMEDIA_RTP_PT_G722) { 
     1415        pjmedia_rtcp_init(&stream->rtcp, stream->port.info.name.ptr, 
     1416                          8000,  
     1417                          160, 
     1418                          info->ssrc); 
     1419        stream->has_g722_mpeg_bug = PJ_TRUE; 
     1420        stream->rtp_tx_samples_per_pkt = 160 *  
     1421                                stream->codec_param.setting.frm_per_pkt; 
     1422        stream->rtp_rx_samples_per_frame = 160; 
     1423    } else { 
     1424        pjmedia_rtcp_init(&stream->rtcp, stream->port.info.name.ptr, 
     1425                          info->fmt.clock_rate,  
     1426                          stream->port.info.samples_per_frame,  
     1427                          info->ssrc); 
     1428    } 
     1429#else 
    13211430    pjmedia_rtcp_init(&stream->rtcp, stream->port.info.name.ptr, 
    13221431                      info->fmt.clock_rate,  
    13231432                      stream->port.info.samples_per_frame,  
    13241433                      info->ssrc); 
     1434#endif 
    13251435 
    1326  
    13271436    /* Init jitter buffer parameters: */ 
    13281437    if (info->jb_max > 0) 
    13291438        jb_max = info->jb_max; 
  • pjmedia/src/pjmedia/endpoint.c

     
    412412        fmt->slen = pj_utoa(codec_info->pt, fmt->ptr); 
    413413 
    414414        rtpmap.pt = *fmt; 
     415        rtpmap.enc_name = codec_info->encoding_name; 
     416 
     417#if defined(PJMEDIA_HANDLE_G722_MPEG_BUG) && (PJMEDIA_HANDLE_G722_MPEG_BUG != 0) 
     418        if (codec_info->pt == PJMEDIA_RTP_PT_G722) 
     419            rtpmap.clock_rate = 8000; 
     420        else 
     421            rtpmap.clock_rate = codec_info->clock_rate; 
     422#else 
    415423        rtpmap.clock_rate = codec_info->clock_rate; 
    416         rtpmap.enc_name = codec_info->encoding_name; 
    417          
     424#endif 
     425 
    418426        /* For audio codecs, rtpmap parameters denotes the number 
    419427         * of channels, which can be omited if the value is 1. 
    420428         */ 
  • pjmedia/src/pjmedia/session.c

     
    388388            pj_strdup(pool, &si->fmt.encoding_name, &rtpmap->enc_name); 
    389389            si->fmt.clock_rate = rtpmap->clock_rate; 
    390390             
     391#if defined(PJMEDIA_HANDLE_G722_MPEG_BUG) && (PJMEDIA_HANDLE_G722_MPEG_BUG != 0) 
     392            /* The session info should have the actual clock rate, because  
     393             * this info is used for calculationg buffer size, etc in stream */ 
     394            if (si->fmt.pt == PJMEDIA_RTP_PT_G722) 
     395                si->fmt.clock_rate = 16000; 
     396#endif 
     397 
    391398            /* For audio codecs, rtpmap parameters denotes the number of 
    392399             * channels. 
    393400             */