Ticket #486: ticket486.patch

File ticket486.patch, 9.7 KB (added by nanang, 16 years ago)
  • pjmedia/src/pjmedia/stream.c

     
    4242 
    4343#define BYTES_PER_SAMPLE                2 
    4444 
     45#define HANDLE_G722_MPEG_BUG 
     46 
    4547/** 
    4648 * Media channel. 
    4749 */ 
     
    9294                                                 ptime is different than dec. 
    9395                                                 Otherwise it's NULL.       */ 
    9496 
    95     unsigned                 enc_samples_per_frame; 
     97    unsigned                 enc_samples_per_pkt; 
    9698    unsigned                 enc_buf_size;  /**< Encoding buffer size, in 
    9799                                                 samples.                   */ 
    98100    unsigned                 enc_buf_pos;   /**< First position in buf.     */ 
     
    131133    /* DTMF callback */ 
    132134    void                    (*dtmf_cb)(pjmedia_stream*, void*, int); 
    133135    void                     *dtmf_cb_user_data; 
     136 
     137#ifdef HANDLE_G722_MPEG_BUG 
     138    /* Handle codec with inconsistence clockrate between definition and 
     139     * implementation. This is possible because of error in RFC (e.g: G722) 
     140     * or video synchronization (MPEG audio). 
     141     */ 
     142    pj_bool_t                has_g722_mpeg_bug; 
     143                                            /**< Flag to specify whether  
     144                                                 normalization process  
     145                                                 is needed                  */ 
     146    unsigned                 rtp_tx_samples_per_pkt; 
     147                                            /**< Normalized samples per packet  
     148                                                 transmitted according to  
     149                                                 'erroneous' definition     */ 
     150    unsigned                 rtp_rx_samples_per_frame; 
     151                                            /**< Normalized samples per frame  
     152                                                 received according to  
     153                                                 'erroneous' definition     */ 
     154    pj_uint32_t              rtp_rx_last_ts;/**< Last received RTP timestamp 
     155                                                 for timestamp checking     */ 
     156    pj_bool_t                incons_checked;/**< Flag to specify whether 
     157                                                 timestamp checking is done */ 
     158#endif 
     159 
    134160}; 
    135161 
    136162 
     
    516542    pjmedia_channel *channel = stream->enc; 
    517543    pj_status_t status = 0; 
    518544    pjmedia_frame frame_out; 
    519     unsigned ts_len, samples_per_frame; 
     545    unsigned ts_len, rtp_ts_len, samples_per_frame; 
    520546    void *rtphdr; 
    521547    int rtphdrlen; 
    522548    int inc_timestamp = 0; 
     
    535561 
    536562    /* Increment transmit duration */ 
    537563    stream->tx_duration += ts_len; 
     564    rtp_ts_len = ts_len; 
    538565 
     566#ifdef HANDLE_G722_MPEG_BUG 
     567    /* Handle special case for audio codec with RTP timestamp inconsistence  
     568     * e.g: G722, MPEG audio. 
     569     */ 
     570    if (stream->has_g722_mpeg_bug &&  
     571        stream->rtp_tx_samples_per_pkt != stream->enc_samples_per_pkt)  
     572    { 
     573        rtp_ts_len /= stream->enc_samples_per_pkt; 
     574        rtp_ts_len *= stream->rtp_tx_samples_per_pkt; 
     575    } 
     576#endif 
     577 
    539578    /* Init frame_out buffer. */ 
    540579    frame_out.buf = ((char*)channel->out_pkt) + sizeof(pjmedia_rtp_hdr); 
    541580    frame_out.size = 0; 
    542581 
    543582    /* Calculate number of samples per frame */ 
    544     samples_per_frame = stream->enc_samples_per_frame; 
     583    samples_per_frame = stream->enc_samples_per_pkt; 
    545584 
    546585 
    547586    /* If we have DTMF digits in the queue, transmit the digits.  
     
    558597         */ 
    559598        status = pjmedia_rtp_encode_rtp( &channel->rtp,  
    560599                                         stream->tx_event_pt, first,  
    561                                          frame_out.size, (first?ts_len:0),  
     600                                         frame_out.size, 
     601                                         (first ? rtp_ts_len : 0),  
    562602                                         (const void**)&rtphdr,  
    563603                                         &rtphdrlen); 
    564604 
     
    567607             * Increment the RTP timestamp of the RTP session, for next 
    568608             * RTP packets. 
    569609             */ 
    570             inc_timestamp = PJMEDIA_DTMF_DURATION - ts_len; 
     610            inc_timestamp = PJMEDIA_DTMF_DURATION - rtp_ts_len; 
    571611        } 
    572612 
    573613        /* No need to encode if this is a zero frame. 
     
    635675        /* Encapsulate. */ 
    636676        status = pjmedia_rtp_encode_rtp( &channel->rtp,  
    637677                                         channel->pt, 0,  
    638                                          frame_out.size, ts_len,  
     678                                         frame_out.size, rtp_ts_len,  
    639679                                         (const void**)&rtphdr,  
    640680                                         &rtphdrlen); 
    641681    } else { 
     
    643683        /* Just update RTP session's timestamp. */ 
    644684        status = pjmedia_rtp_encode_rtp( &channel->rtp,  
    645685                                         0, 0,  
    646                                          0, ts_len,  
     686                                         0, rtp_ts_len,  
    647687                                         (const void**)&rtphdr,  
    648688                                         &rtphdrlen); 
    649689 
     
    724764    pjmedia_frame tmp_zero_frame; 
    725765    unsigned samples_per_frame; 
    726766 
    727     samples_per_frame = stream->enc_samples_per_frame; 
     767    samples_per_frame = stream->enc_samples_per_pkt; 
    728768 
    729769    /* http://www.pjsip.org/trac/ticket/56: 
    730770     *  when input is PJMEDIA_FRAME_TYPE_NONE, feed zero PCM frame 
     
    801841            /* If we still have full frame in the buffer, re-run 
    802842             * rebuffer() with NULL frame. 
    803843             */ 
    804             if (stream->enc_buf_count >= stream->enc_samples_per_frame) { 
     844            if (stream->enc_buf_count >= stream->enc_samples_per_pkt) { 
    805845 
    806846                tmp_rebuffer_frame.type = PJMEDIA_FRAME_TYPE_NONE; 
    807847 
     
    10211061        enum { MAX = 16 }; 
    10221062        pj_timestamp ts; 
    10231063        unsigned i, count = MAX; 
    1024         unsigned samples_per_frame; 
     1064        unsigned ts_span; 
    10251065        pjmedia_frame frames[MAX]; 
    10261066 
    10271067        /* Get the timestamp of the first sample */ 
     
    10411081            count = 0; 
    10421082        } 
    10431083 
     1084#ifdef HANDLE_G722_MPEG_BUG 
     1085        /* Check inconsistency of RTP timestamp with actual codec timestamp */ 
     1086        if (stream->has_g722_mpeg_bug) { 
     1087            if (!stream->incons_checked) { 
     1088                ts_span = stream->codec_param.info.frm_ptime *  
     1089                          stream->codec_param.info.clock_rate * 
     1090                          stream->codec_param.info.channel_cnt / 
     1091                          1000; 
     1092 
     1093                /* Make sure the calculation applied only when  
     1094                 * two consecutive packets have valid RTP sequence, 
     1095                 * and no wrapped timestamp. 
     1096                 */ 
     1097                if (seq_st.diff == 1 && stream->rtp_rx_last_ts &&  
     1098                    ts.u64 > stream->rtp_rx_last_ts) 
     1099                { 
     1100                    stream->incons_checked = PJ_TRUE; 
     1101                    stream->rtp_rx_samples_per_frame =  
     1102                                (ts.u32.lo - stream->rtp_rx_last_ts) / count;  
     1103 
     1104                    if ((ts.u64 - stream->rtp_rx_last_ts)/count != ts_span) 
     1105                    { 
     1106                        stream->rtp_tx_samples_per_pkt =  
     1107                                    stream->rtp_rx_samples_per_frame *  
     1108                                    stream->codec_param.info.enc_ptime / 
     1109                                    stream->codec_param.info.frm_ptime * 
     1110                                    stream->codec_param.setting.frm_per_pkt; 
     1111                        ts_span = stream->rtp_rx_samples_per_frame; 
     1112                    } 
     1113                } 
     1114                stream->rtp_rx_last_ts = (pj_uint32_t)ts.u64; 
     1115            } else { 
     1116                ts_span = stream->rtp_rx_samples_per_frame; 
     1117            } 
     1118        } else { 
     1119            ts_span = stream->codec_param.info.frm_ptime *  
     1120                      stream->codec_param.info.clock_rate * 
     1121                      stream->codec_param.info.channel_cnt / 
     1122                      1000; 
     1123        } 
     1124#else 
     1125        ts_span = stream->codec_param.info.frm_ptime *  
     1126                  stream->codec_param.info.clock_rate * 
     1127                  stream->codec_param.info.channel_cnt / 
     1128                  1000; 
     1129#endif 
     1130 
    10441131        /* 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                              
    10501132        for (i=0; i<count; ++i) { 
    10511133            unsigned ext_seq; 
    10521134 
    1053             ext_seq = (unsigned)(frames[i].timestamp.u64 / 
    1054                                  samples_per_frame); 
     1135            ext_seq = (unsigned)(frames[i].timestamp.u64 / ts_span); 
    10551136            pjmedia_jbuf_put_frame(stream->jb, frames[i].buf,  
    10561137                                   frames[i].size, ext_seq); 
    10571138 
     
    12581339                                        stream->codec_param.setting.frm_per_pkt / 
    12591340                                        1000; 
    12601341 
    1261  
    12621342    /* Open the codec: */ 
    12631343 
    12641344    status = stream->codec->op->open(stream->codec, &stream->codec_param); 
     
    12741354    { 
    12751355        unsigned ptime; 
    12761356 
    1277         stream->enc_samples_per_frame = stream->codec_param.info.enc_ptime * 
    1278                                         stream->port.info.clock_rate / 1000; 
     1357        stream->enc_samples_per_pkt = stream->codec_param.info.enc_ptime * 
     1358                                      stream->port.info.clock_rate / 1000; 
    12791359 
    12801360        /* Set buffer size as twice the largest ptime value between 
    12811361         * stream's ptime, encoder ptime, or decoder ptime. 
     
    12981378                          pj_pool_alloc(pool, stream->enc_buf_size * 2); 
    12991379 
    13001380    } else { 
    1301         stream->enc_samples_per_frame = stream->port.info.samples_per_frame; 
     1381        stream->enc_samples_per_pkt = stream->port.info.samples_per_frame; 
    13021382    } 
    13031383 
     1384#ifdef HANDLE_G722_MPEG_BUG 
     1385    stream->rtp_tx_samples_per_pkt = stream->enc_samples_per_pkt; 
     1386    stream->rtp_rx_samples_per_frame = 0; 
     1387    stream->incons_checked = PJ_FALSE; 
     1388    stream->has_g722_mpeg_bug = PJ_FALSE; 
     1389    stream->rtp_rx_last_ts = 0; 
     1390#endif 
     1391 
    13041392    /* Initially disable the VAD in the stream, to help traverse NAT better */ 
    13051393    stream->vad_enabled = stream->codec_param.setting.vad; 
    13061394    if (stream->vad_enabled) { 
     
    13181406 
    13191407    /* Init RTCP session: */ 
    13201408 
     1409#ifdef HANDLE_G722_MPEG_BUG 
     1410    /* Special case for G.722 */ 
     1411    if (info->fmt.pt == PJMEDIA_RTP_PT_G722) { 
     1412        pjmedia_rtcp_init(&stream->rtcp, stream->port.info.name.ptr, 
     1413                          8000,  
     1414                          160, 
     1415                          info->ssrc); 
     1416        stream->has_g722_mpeg_bug = PJ_TRUE; 
     1417    }  
     1418    else { 
     1419        pjmedia_rtcp_init(&stream->rtcp, stream->port.info.name.ptr, 
     1420                          info->fmt.clock_rate,  
     1421                          stream->port.info.samples_per_frame,  
     1422                          info->ssrc); 
     1423    } 
     1424#else 
    13211425    pjmedia_rtcp_init(&stream->rtcp, stream->port.info.name.ptr, 
    13221426                      info->fmt.clock_rate,  
    13231427                      stream->port.info.samples_per_frame,  
    13241428                      info->ssrc); 
     1429#endif 
    13251430 
    1326  
    13271431    /* Init jitter buffer parameters: */ 
    13281432    if (info->jb_max > 0) 
    13291433        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.clock_rate = codec_info->clock_rate; 
    416415        rtpmap.enc_name = codec_info->encoding_name; 
    417          
     416 
     417        /* RFC 3551 Section 4.5.2: 
     418         * Even though the actual sampling rate for G.722 audio is 16,000 Hz, 
     419         * the RTP clock rate for the G722 payload format is 8,000 Hz because 
     420         * that value was erroneously assigned in RFC 1890 and must remain 
     421         * unchanged for backward compatibility.  The octet rate or sample-pair 
     422         * rate is 8,000 Hz. 
     423         */ 
     424        if (codec_info->pt == PJMEDIA_RTP_PT_G722) 
     425            rtpmap.clock_rate = 8000; 
     426        else 
     427            rtpmap.clock_rate = codec_info->clock_rate; 
     428 
    418429        /* For audio codecs, rtpmap parameters denotes the number 
    419430         * of channels, which can be omited if the value is 1. 
    420431         */