Ticket #486: ticket486.3.patch

File ticket486.3.patch, 11.5 KB (added by nanang, 17 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    unsigned                 rtp_rx_check_cnt; 
     155                                            /**< Counter of remote timestamp 
     156                                                 checking */ 
     157#endif 
     158 
    134159}; 
    135160 
    136161 
     
    521546    pjmedia_channel *channel = stream->enc; 
    522547    pj_status_t status = 0; 
    523548    pjmedia_frame frame_out; 
    524     unsigned ts_len, samples_per_frame; 
     549    unsigned ts_len, rtp_ts_len, samples_per_frame; 
    525550    void *rtphdr; 
    526551    int rtphdrlen; 
    527552    int inc_timestamp = 0; 
     
    541566    /* Increment transmit duration */ 
    542567    stream->tx_duration += ts_len; 
    543568 
     569#if defined(PJMEDIA_HANDLE_G722_MPEG_BUG) && (PJMEDIA_HANDLE_G722_MPEG_BUG != 0) 
     570    /* Handle special case for audio codec with RTP timestamp inconsistence  
     571     * e.g: G722, MPEG audio. 
     572     */ 
     573    if (stream->has_g722_mpeg_bug) 
     574        rtp_ts_len = stream->rtp_tx_samples_per_pkt; 
     575    else 
     576        rtp_ts_len = ts_len; 
     577#else 
     578    rtp_ts_len = ts_len; 
     579#endif 
     580 
    544581    /* Init frame_out buffer. */ 
    545582    frame_out.buf = ((char*)channel->out_pkt) + sizeof(pjmedia_rtp_hdr); 
    546583    frame_out.size = 0; 
    547584 
    548585    /* Calculate number of samples per frame */ 
    549     samples_per_frame = stream->enc_samples_per_frame; 
     586    samples_per_frame = stream->enc_samples_per_pkt; 
    550587 
    551588 
    552589    /* If we have DTMF digits in the queue, transmit the digits.  
     
    563600         */ 
    564601        status = pjmedia_rtp_encode_rtp( &channel->rtp,  
    565602                                         stream->tx_event_pt, first,  
    566                                          frame_out.size, (first?ts_len:0),  
     603                                         frame_out.size, 
     604                                         (first ? rtp_ts_len : 0),  
    567605                                         (const void**)&rtphdr,  
    568606                                         &rtphdrlen); 
    569607 
     
    572610             * Increment the RTP timestamp of the RTP session, for next 
    573611             * RTP packets. 
    574612             */ 
    575             inc_timestamp = PJMEDIA_DTMF_DURATION - ts_len; 
     613            inc_timestamp = PJMEDIA_DTMF_DURATION - rtp_ts_len; 
    576614        } 
    577615 
    578616        /* No need to encode if this is a zero frame. 
     
    640678        /* Encapsulate. */ 
    641679        status = pjmedia_rtp_encode_rtp( &channel->rtp,  
    642680                                         channel->pt, 0,  
    643                                          frame_out.size, ts_len,  
     681                                         frame_out.size, rtp_ts_len,  
    644682                                         (const void**)&rtphdr,  
    645683                                         &rtphdrlen); 
    646684    } else { 
     
    648686        /* Just update RTP session's timestamp. */ 
    649687        status = pjmedia_rtp_encode_rtp( &channel->rtp,  
    650688                                         0, 0,  
    651                                          0, ts_len,  
     689                                         0, rtp_ts_len,  
    652690                                         (const void**)&rtphdr,  
    653691                                         &rtphdrlen); 
    654692 
     
    729767    pjmedia_frame tmp_zero_frame; 
    730768    unsigned samples_per_frame; 
    731769 
    732     samples_per_frame = stream->enc_samples_per_frame; 
     770    samples_per_frame = stream->enc_samples_per_pkt; 
    733771 
    734772    /* http://www.pjsip.org/trac/ticket/56: 
    735773     *  when input is PJMEDIA_FRAME_TYPE_NONE, feed zero PCM frame 
     
    806844            /* If we still have full frame in the buffer, re-run 
    807845             * rebuffer() with NULL frame. 
    808846             */ 
    809             if (stream->enc_buf_count >= stream->enc_samples_per_frame) { 
     847            if (stream->enc_buf_count >= stream->enc_samples_per_pkt) { 
    810848 
    811849                tmp_rebuffer_frame.type = PJMEDIA_FRAME_TYPE_NONE; 
    812850 
     
    10261064        enum { MAX = 16 }; 
    10271065        pj_timestamp ts; 
    10281066        unsigned i, count = MAX; 
    1029         unsigned samples_per_frame; 
     1067        unsigned ts_span; 
    10301068        pjmedia_frame frames[MAX]; 
    10311069 
    10321070        /* Get the timestamp of the first sample */ 
     
    10461084            count = 0; 
    10471085        } 
    10481086 
     1087#if defined(PJMEDIA_HANDLE_G722_MPEG_BUG) && (PJMEDIA_HANDLE_G722_MPEG_BUG != 0) 
     1088        /* Check inconsistency of RTP timestamp with actual codec timestamp */ 
     1089        if (stream->has_g722_mpeg_bug) { 
     1090            if (stream->rtp_rx_check_cnt) { 
     1091                /* Make sure the detection performed only on two consecutive  
     1092                 * packets with valid RTP sequence and no wrapped timestamp. 
     1093                 */ 
     1094                if (seq_st.diff == 1 && stream->rtp_rx_last_ts &&  
     1095                    ts.u64 > stream->rtp_rx_last_ts) 
     1096                { 
     1097                    unsigned peer_frm_ts_diff; 
     1098 
     1099                    peer_frm_ts_diff =  
     1100                        ((pj_uint32_t)ts.u64-stream->rtp_rx_last_ts) / count; 
     1101 
     1102                    /* Possibilities remote's samples per frame for G.722  
     1103                     * are only 160 and 320, this validation is needed 
     1104                     * to avoid wrong decision because of silence frames. 
     1105                     */ 
     1106                    if (stream->codec_param.info.pt == PJMEDIA_RTP_PT_G722 && 
     1107                        (peer_frm_ts_diff == stream->port.info.samples_per_frame 
     1108                        || peer_frm_ts_diff ==  
     1109                                         stream->port.info.samples_per_frame/2)) 
     1110                    { 
     1111                        if (peer_frm_ts_diff < stream->rtp_rx_samples_per_frame) 
     1112                            stream->rtp_rx_samples_per_frame = peer_frm_ts_diff; 
     1113 
     1114                        if (--stream->rtp_rx_check_cnt == 0) { 
     1115                            PJ_LOG(4, (THIS_FILE, "G722 codec used, remote" 
     1116                                       " samples per frame detected = %d",  
     1117                                       stream->rtp_rx_samples_per_frame)); 
     1118                             
     1119                            /* Reset jitter buffer once detection done */ 
     1120                            pjmedia_jbuf_reset(stream->jb); 
     1121                        } 
     1122                    } 
     1123                } 
     1124 
     1125                stream->rtp_rx_last_ts = (pj_uint32_t)ts.u64; 
     1126            } 
     1127 
     1128            ts_span = stream->rtp_rx_samples_per_frame; 
     1129 
     1130        } else { 
     1131            ts_span = stream->codec_param.info.frm_ptime *  
     1132                      stream->codec_param.info.clock_rate * 
     1133                      stream->codec_param.info.channel_cnt / 
     1134                      1000; 
     1135        } 
     1136#else 
     1137        ts_span = stream->codec_param.info.frm_ptime *  
     1138                  stream->codec_param.info.clock_rate * 
     1139                  stream->codec_param.info.channel_cnt / 
     1140                  1000; 
     1141#endif 
     1142 
    10491143        /* Put each frame to jitter buffer. */ 
    1050         samples_per_frame = stream->codec_param.info.frm_ptime *  
    1051                             stream->codec_param.info.clock_rate * 
    1052                             stream->codec_param.info.channel_cnt / 
    1053                             1000; 
    1054                              
    10551144        for (i=0; i<count; ++i) { 
    10561145            unsigned ext_seq; 
    10571146 
    1058             ext_seq = (unsigned)(frames[i].timestamp.u64 / 
    1059                                  samples_per_frame); 
     1147            ext_seq = (unsigned)(frames[i].timestamp.u64 / ts_span); 
    10601148            pjmedia_jbuf_put_frame(stream->jb, frames[i].buf,  
    10611149                                   frames[i].size, ext_seq); 
    10621150 
     
    11901278    name.ptr = (char*) pj_pool_alloc(pool, M); 
    11911279    name.slen = pj_ansi_snprintf(name.ptr, M, "strm%p", stream); 
    11921280 
    1193  
    11941281    /* Init some port-info. Some parts of the info will be set later 
    11951282     * once we have more info about the codec. 
    11961283     */ 
     
    12631350                                        stream->codec_param.setting.frm_per_pkt / 
    12641351                                        1000; 
    12651352 
    1266  
    12671353    /* Open the codec: */ 
    12681354 
    12691355    status = stream->codec->op->open(stream->codec, &stream->codec_param); 
     
    12791365    { 
    12801366        unsigned ptime; 
    12811367 
    1282         stream->enc_samples_per_frame = stream->codec_param.info.enc_ptime * 
    1283                                         stream->port.info.clock_rate / 1000; 
     1368        stream->enc_samples_per_pkt = stream->codec_param.info.enc_ptime * 
     1369                                      stream->port.info.clock_rate / 1000; 
    12841370 
    12851371        /* Set buffer size as twice the largest ptime value between 
    12861372         * stream's ptime, encoder ptime, or decoder ptime. 
     
    13031389                          pj_pool_alloc(pool, stream->enc_buf_size * 2); 
    13041390 
    13051391    } else { 
    1306         stream->enc_samples_per_frame = stream->port.info.samples_per_frame; 
     1392        stream->enc_samples_per_pkt = stream->port.info.samples_per_frame; 
    13071393    } 
    13081394 
     1395 
    13091396    /* Initially disable the VAD in the stream, to help traverse NAT better */ 
    13101397    stream->vad_enabled = stream->codec_param.setting.vad; 
    13111398    if (stream->vad_enabled) { 
     
    13211408                          stream->codec_param.info.frm_ptime / 1000; 
    13221409 
    13231410 
     1411#if defined(PJMEDIA_HANDLE_G722_MPEG_BUG) && (PJMEDIA_HANDLE_G722_MPEG_BUG != 0) 
     1412    stream->rtp_rx_check_cnt = 5; 
     1413    stream->has_g722_mpeg_bug = PJ_FALSE; 
     1414    stream->rtp_rx_last_ts = 0; 
     1415    stream->rtp_tx_samples_per_pkt = stream->enc_samples_per_pkt; 
     1416    stream->rtp_rx_samples_per_frame = stream->port.info.samples_per_frame; 
     1417 
    13241418    /* Init RTCP session: */ 
    13251419 
     1420    /* Special case for G.722 */ 
     1421    if (info->fmt.pt == PJMEDIA_RTP_PT_G722) { 
     1422        pjmedia_rtcp_init(&stream->rtcp, stream->port.info.name.ptr, 
     1423                          8000,  
     1424                          160, 
     1425                          info->ssrc); 
     1426        stream->has_g722_mpeg_bug = PJ_TRUE; 
     1427        /* RTP clock rate = 1/2 real clock rate */ 
     1428        stream->rtp_tx_samples_per_pkt /= 2; 
     1429    } else { 
     1430        pjmedia_rtcp_init(&stream->rtcp, stream->port.info.name.ptr, 
     1431                          info->fmt.clock_rate,  
     1432                          stream->port.info.samples_per_frame,  
     1433                          info->ssrc); 
     1434    } 
     1435#else 
    13261436    pjmedia_rtcp_init(&stream->rtcp, stream->port.info.name.ptr, 
    13271437                      info->fmt.clock_rate,  
    13281438                      stream->port.info.samples_per_frame,  
    13291439                      info->ssrc); 
     1440#endif 
    13301441 
    1331  
    13321442    /* Init jitter buffer parameters: */ 
    13331443    if (info->jb_max > 0) 
    13341444        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             */