Ignore:
Timestamp:
Jul 19, 2011 3:42:28 AM (13 years ago)
Author:
nanang
Message:

Re #1326: Initial code integration from branch 2.0-dev to trunk as "2.0-pre-alpha-svn".

Location:
pjproject/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk

  • pjproject/trunk/pjmedia/src/pjmedia/stream.c

    r3553 r3664  
    2323#include <pjmedia/rtcp.h> 
    2424#include <pjmedia/jbuf.h> 
     25#include <pjmedia/stream_common.h> 
    2526#include <pj/array.h> 
    2627#include <pj/assert.h> 
     
    6566#endif 
    6667 
     68#ifndef PJMEDIA_STREAM_SIZE 
     69#   define PJMEDIA_STREAM_SIZE  1000 
     70#endif 
     71 
     72#ifndef PJMEDIA_STREAM_INC 
     73#   define PJMEDIA_STREAM_INC   1000 
     74#endif 
    6775 
    6876 
     
    7886    unsigned                out_pkt_size;   /**< Size of output buffer.     */ 
    7987    void                   *out_pkt;        /**< Output buffer.             */ 
     88    unsigned                out_pkt_len;    /**< Length of data in buffer.  */ 
    8089    pjmedia_rtp_session     rtp;            /**< RTP session.               */ 
    8190}; 
     
    99108    pjmedia_endpt           *endpt;         /**< Media endpoint.            */ 
    100109    pjmedia_codec_mgr       *codec_mgr;     /**< Codec manager instance.    */ 
    101  
     110    pjmedia_stream_info      si;            /**< Creation parameter.        */ 
    102111    pjmedia_port             port;          /**< Port interface.            */ 
    103112    pjmedia_channel         *enc;           /**< Encoding channel.          */ 
    104113    pjmedia_channel         *dec;           /**< Decoding channel.          */ 
     114 
     115    pj_pool_t               *own_pool;      /**< Only created if not given  */ 
    105116 
    106117    pjmedia_dir              dir;           /**< Stream direction.          */ 
     
    178189                                                 received according to  
    179190                                                 'erroneous' definition     */ 
    180     pj_uint32_t              rtp_rx_last_ts;/**< Last received RTP timestamp 
    181                                                  for timestamp checking     */ 
    182191    unsigned                 rtp_rx_last_cnt;/**< Nb of frames in last pkt  */ 
    183192    unsigned                 rtp_rx_check_cnt; 
     
    209218    char                   *trace_jb_buf;           /**< Jitter tracing buffer.     */ 
    210219#endif 
     220 
     221    pj_uint32_t              rtp_rx_last_ts;        /**< Last received RTP timestamp*/ 
    211222}; 
    212223 
     
    472483    pj_mutex_lock( stream->jb_mutex ); 
    473484 
    474     samples_required = stream->port.info.samples_per_frame; 
     485    samples_required = PJMEDIA_PIA_SPF(&stream->port.info); 
    475486    samples_per_frame = stream->codec_param.info.frm_ptime * 
    476487                        stream->codec_param.info.clock_rate * 
     
    505516                frame_out.buf = p_out_samp + samples_count; 
    506517                frame_out.size = frame->size - samples_count*2; 
    507                 status = (*stream->codec->op->recover)(stream->codec, 
    508                                                        frame_out.size, 
    509                                                        &frame_out); 
     518                status = pjmedia_codec_recover(stream->codec, 
     519                                               frame_out.size, 
     520                                               &frame_out); 
    510521 
    511522                ++stream->plc_cnt; 
     
    554565                        frame_out.buf = p_out_samp + samples_count; 
    555566                        frame_out.size = frame->size - samples_count*2; 
    556                         status = (*stream->codec->op->recover)(stream->codec, 
    557                                                                frame_out.size, 
    558                                                                &frame_out); 
     567                        status = pjmedia_codec_recover(stream->codec, 
     568                                                       frame_out.size, 
     569                                                       &frame_out); 
    559570                        if (status != PJ_SUCCESS) 
    560571                            break; 
     
    609620                    frame_out.buf = p_out_samp + samples_count; 
    610621                    frame_out.size = frame->size - samples_count*2; 
    611                     status = (*stream->codec->op->recover)(stream->codec, 
    612                                                            frame_out.size, 
    613                                                            &frame_out); 
     622                    status = pjmedia_codec_recover(stream->codec, 
     623                                                   frame_out.size, 
     624                                                   &frame_out); 
    614625                    if (status != PJ_SUCCESS) 
    615626                        break; 
     
    660671            frame_out.buf = p_out_samp + samples_count; 
    661672            frame_out.size = frame->size - samples_count*BYTES_PER_SAMPLE; 
    662             status = stream->codec->op->decode( stream->codec, &frame_in, 
    663                                                 frame_out.size, &frame_out); 
     673            status = pjmedia_codec_decode( stream->codec, &frame_in, 
     674                                           frame_out.size, &frame_out); 
    664675            if (status != 0) { 
    665676                LOGERR_((port->info.name.ptr, "codec decode() error",  
     
    726737     */ 
    727738 
    728     samples_required = stream->port.info.samples_per_frame; 
     739    samples_required = PJMEDIA_PIA_SPF(&stream->port.info); 
    729740    samples_per_frame = stream->codec_param.info.frm_ptime * 
    730741                        stream->codec_param.info.clock_rate * 
     
    764775            frame_in.type = PJMEDIA_FRAME_TYPE_AUDIO; 
    765776 
    766             status = stream->codec->op->decode( stream->codec, &frame_in, 
    767                                                 0, frame); 
     777            status = pjmedia_codec_decode( stream->codec, &frame_in, 
     778                                           0, frame); 
    768779            if (status != PJ_SUCCESS) { 
    769780                LOGERR_((port->info.name.ptr, "codec decode() error",  
     
    791802            status = PJ_SUCCESS; 
    792803            if (stream->codec->op->recover) { 
    793                 status = (*stream->codec->op->recover)(stream->codec, 
    794                                                        0, frame); 
     804                status = pjmedia_codec_recover(stream->codec, 0, frame); 
    795805            } 
    796806             
     
    877887    } 
    878888 
    879     digit->duration += stream->port.info.samples_per_frame; 
     889    digit->duration += PJMEDIA_PIA_SPF(&stream->port.info); 
    880890 
    881891    event->event = (pj_uint8_t)digit->event; 
     
    10881098    /* How many samples are needed */ 
    10891099    count = stream->codec_param.info.enc_ptime *  
    1090                 stream->port.info.clock_rate / 1000; 
     1100            PJMEDIA_PIA_SRATE(&stream->port.info) / 1000; 
    10911101 
    10921102    /* See if we have enough samples */ 
     
    11111121 */ 
    11121122static pj_status_t put_frame_imp( pjmedia_port *port,  
    1113                                   const pjmedia_frame *frame ) 
     1123                                  pjmedia_frame *frame ) 
    11141124{ 
    11151125    pjmedia_stream *stream = (pjmedia_stream*) port->port_data.pdata; 
     
    11521162        ts_len = (frame->size >> 1) / stream->codec_param.info.channel_cnt; 
    11531163    else if (frame->type == PJMEDIA_FRAME_TYPE_EXTENDED) 
    1154         ts_len = stream->port.info.samples_per_frame /  
    1155                  stream->port.info.channel_count; 
     1164        ts_len = PJMEDIA_PIA_SPF(&stream->port.info) / 
     1165                 PJMEDIA_PIA_CCNT(&stream->port.info); 
    11561166    else 
    11571167        ts_len = 0; 
     
    12201230    } else if (frame->type == PJMEDIA_FRAME_TYPE_AUDIO && 
    12211231               frame->buf == NULL && 
    1222                stream->port.info.format.id == PJMEDIA_FORMAT_L16 && 
     1232               stream->port.info.fmt.id == PJMEDIA_FORMAT_L16 && 
    12231233               (stream->dir & PJMEDIA_DIR_ENCODING) && 
    12241234               stream->codec_param.info.frm_ptime * 
     
    12381248         
    12391249        /* Encode! */ 
    1240         status = stream->codec->op->encode( stream->codec, &silence_frame, 
    1241                                             channel->out_pkt_size -  
    1242                                             sizeof(pjmedia_rtp_hdr), 
    1243                                             &frame_out); 
     1250        status = pjmedia_codec_encode( stream->codec, &silence_frame, 
     1251                                       channel->out_pkt_size -  
     1252                                       sizeof(pjmedia_rtp_hdr), 
     1253                                       &frame_out); 
    12441254        if (status != PJ_SUCCESS) { 
    12451255            LOGERR_((stream->port.info.name.ptr,  
     
    12621272    { 
    12631273        /* Encode! */ 
    1264         status = stream->codec->op->encode( stream->codec, frame,  
    1265                                             channel->out_pkt_size -  
    1266                                             sizeof(pjmedia_rtp_hdr), 
    1267                                             &frame_out); 
     1274        status = pjmedia_codec_encode( stream->codec, frame,  
     1275                                       channel->out_pkt_size -  
     1276                                       sizeof(pjmedia_rtp_hdr), 
     1277                                       &frame_out); 
    12681278        if (status != PJ_SUCCESS) { 
    12691279            LOGERR_((stream->port.info.name.ptr,  
     
    13631373 */ 
    13641374static pj_status_t put_frame( pjmedia_port *port,  
    1365                               const pjmedia_frame *frame ) 
     1375                              pjmedia_frame *frame ) 
    13661376{ 
    13671377    pjmedia_stream *stream = (pjmedia_stream*) port->port_data.pdata; 
     
    14111421    if (stream->vad_enabled != stream->codec_param.setting.vad && 
    14121422        (stream->tx_duration - stream->ts_vad_disabled) >  
    1413         stream->port.info.clock_rate * PJMEDIA_STREAM_VAD_SUSPEND_MSEC / 1000) 
     1423           PJMEDIA_PIA_SRATE(&stream->port.info) * 
     1424          PJMEDIA_STREAM_VAD_SUSPEND_MSEC / 1000) 
    14141425    { 
    14151426        stream->codec_param.setting.vad = stream->vad_enabled; 
    1416         stream->codec->op->modify(stream->codec, &stream->codec_param); 
     1427        pjmedia_codec_modify(stream->codec, &stream->codec_param); 
    14171428        PJ_LOG(4,(stream->port.info.name.ptr,"VAD re-enabled")); 
    14181429    } 
     
    15741585    unsigned payloadlen; 
    15751586    pjmedia_rtp_status seq_st; 
    1576     pj_bool_t check_pt; 
    15771587    pj_status_t status; 
    15781588    pj_bool_t pkt_discarded = PJ_FALSE; 
     
    16041614     * the incoming packet. 
    16051615     */ 
    1606     check_pt = (hdr->pt != stream->rx_event_pt) && PJMEDIA_STREAM_CHECK_RTP_PT; 
    1607     pjmedia_rtp_session_update2(&channel->rtp, hdr, &seq_st, check_pt); 
    1608 #if !PJMEDIA_STREAM_CHECK_RTP_PT 
    1609     if (!check_pt && hdr->pt != channel->rtp.out_pt && 
    1610         hdr->pt != stream->rx_event_pt) 
    1611     { 
    1612         seq_st.status.flag.badpt = 1; 
    1613     } 
    1614 #endif 
     1616    pjmedia_rtp_session_update2(&channel->rtp, hdr, &seq_st, 
     1617                                hdr->pt != stream->rx_event_pt); 
    16151618    if (seq_st.status.value) { 
    16161619        TRC_  ((stream->port.info.name.ptr,  
     
    16721675        status = pjmedia_jbuf_reset(stream->jb); 
    16731676        PJ_LOG(4,(stream->port.info.name.ptr, "Jitter buffer reset")); 
    1674  
    16751677    } else { 
    16761678        /* 
     
    16891691 
    16901692        /* Parse the payload. */ 
    1691         status = (*stream->codec->op->parse)(stream->codec, 
    1692                                              (void*)payload, 
    1693                                              payloadlen, 
    1694                                              &ts, 
    1695                                              &count, 
    1696                                              frames); 
     1693        status = pjmedia_codec_parse(stream->codec, (void*)payload, 
     1694                                     payloadlen, &ts, &count, frames); 
    16971695        if (status != PJ_SUCCESS) { 
    16981696            LOGERR_((stream->port.info.name.ptr,  
     
    17221720 
    17231721                    /* Calculate actual frame timestamp span */ 
    1724                     frm_ts_span = stream->port.info.samples_per_frame / 
     1722                    frm_ts_span = PJMEDIA_PIA_SPF(&stream->port.info) / 
    17251723                                  stream->codec_param.setting.frm_per_pkt/ 
    1726                                   stream->port.info.channel_count; 
     1724                                  PJMEDIA_PIA_CCNT(&stream->port.info); 
    17271725 
    17281726                    /* Get remote frame timestamp span */ 
     
    18961894    /* Allocate buffer for outgoing packet. */ 
    18971895 
    1898     channel->out_pkt_size = sizeof(pjmedia_rtp_hdr) +  
    1899                             stream->codec_param.info.max_bps *  
    1900                             PJMEDIA_MAX_FRAME_DURATION_MS /  
    1901                             8 / 1000; 
    1902  
    1903     if (channel->out_pkt_size > PJMEDIA_MAX_MTU) 
    1904         channel->out_pkt_size = PJMEDIA_MAX_MTU; 
     1896    if (param->type == PJMEDIA_TYPE_AUDIO) { 
     1897        channel->out_pkt_size = sizeof(pjmedia_rtp_hdr) +  
     1898                                stream->codec_param.info.max_bps *  
     1899                                PJMEDIA_MAX_FRAME_DURATION_MS /  
     1900                                8 / 1000; 
     1901        if (channel->out_pkt_size > PJMEDIA_MAX_MTU - 
     1902                                    PJMEDIA_STREAM_RESV_PAYLOAD_LEN) 
     1903        { 
     1904            channel->out_pkt_size = PJMEDIA_MAX_MTU - 
     1905                                    PJMEDIA_STREAM_RESV_PAYLOAD_LEN; 
     1906        } 
     1907    } else { 
     1908        return PJ_ENOTSUP; 
     1909    } 
    19051910 
    19061911    /* It should big enough to hold (minimally) RTCP SR with an SDES. */ 
     
    19561961    pj_str_t name; 
    19571962    unsigned jb_init, jb_max, jb_min_pre, jb_max_pre, len; 
     1963    pjmedia_audio_format_detail *afd; 
     1964    pj_pool_t *own_pool = NULL; 
    19581965    char *p; 
    19591966    pj_status_t status; 
    19601967 
    1961     PJ_ASSERT_RETURN(pool && info && p_stream, PJ_EINVAL); 
    1962  
     1968    PJ_ASSERT_RETURN(endpt && info && p_stream, PJ_EINVAL); 
     1969 
     1970    if (pool == NULL) { 
     1971        own_pool = pjmedia_endpt_create_pool( endpt, "strm%p", 
     1972                                              PJMEDIA_STREAM_SIZE, 
     1973                                              PJMEDIA_STREAM_INC); 
     1974        PJ_ASSERT_RETURN(own_pool != NULL, PJ_ENOMEM); 
     1975        pool = own_pool; 
     1976    } 
    19631977 
    19641978    /* Allocate the media stream: */ 
     
    19661980    stream = PJ_POOL_ZALLOC_T(pool, pjmedia_stream); 
    19671981    PJ_ASSERT_RETURN(stream != NULL, PJ_ENOMEM); 
     1982    stream->own_pool = own_pool; 
     1983    pj_memcpy(&stream->si, info, sizeof(*info)); 
    19681984 
    19691985    /* Init stream/port name */ 
     
    19751991     */ 
    19761992    pjmedia_port_info_init(&stream->port.info, &name, 
    1977                            PJMEDIA_PORT_SIGNATURE('S', 'T', 'R', 'M'), 
     1993                           PJMEDIA_SIG_PORT_STREAM, 
    19781994                           info->fmt.clock_rate, info->fmt.channel_cnt, 
    19791995                           16, 80); 
     1996    afd = pjmedia_format_get_audio_format_detail(&stream->port.info.fmt, 1); 
    19801997 
    19811998    /* Init port. */ 
    19821999 
    1983     pj_strdup(pool, &stream->port.info.encoding_name, &info->fmt.encoding_name); 
    1984     stream->port.info.clock_rate = info->fmt.clock_rate; 
    1985     stream->port.info.channel_count = info->fmt.channel_cnt; 
     2000    //No longer there in 2.0 
     2001    //pj_strdup(pool, &stream->port.info.encoding_name, &info->fmt.encoding_name); 
     2002    afd->clock_rate = info->fmt.clock_rate; 
     2003    afd->channel_count = info->fmt.channel_cnt; 
    19862004    stream->port.port_data.pdata = stream; 
    19872005 
     
    20492067 
    20502068    /* Open the codec. */ 
    2051     status = stream->codec->op->open(stream->codec, &stream->codec_param); 
     2069    status = pjmedia_codec_open(stream->codec, &stream->codec_param); 
    20522070    if (status != PJ_SUCCESS) 
    20532071        goto err_cleanup; 
    20542072 
    20552073    /* Set additional info and callbacks. */ 
    2056     stream->port.info.bits_per_sample = 16; 
    2057     stream->port.info.samples_per_frame = info->fmt.clock_rate *  
    2058                                           stream->codec_param.info.channel_cnt * 
    2059                                           stream->codec_param.info.frm_ptime * 
    2060                                           stream->codec_param.setting.frm_per_pkt / 
    2061                                           1000; 
    2062     stream->port.info.format.id = stream->codec_param.info.fmt_id; 
     2074    afd->bits_per_sample = 16; 
     2075    afd->frame_time_usec = stream->codec_param.info.frm_ptime * 
     2076                           stream->codec_param.setting.frm_per_pkt * 1000; 
     2077    stream->port.info.fmt.id = stream->codec_param.info.fmt_id; 
    20632078    if (stream->codec_param.info.fmt_id == PJMEDIA_FORMAT_L16) { 
    20642079        /* Raw format */ 
    2065         stream->port.info.bytes_per_frame = stream->port.info.samples_per_frame * 
    2066                                             stream->port.info.bits_per_sample / 8; 
     2080        afd->avg_bps = afd->max_bps = afd->clock_rate * 
     2081                                      afd->bits_per_sample / 8; 
     2082 
    20672083 
    20682084        stream->port.put_frame = &put_frame; 
     
    20702086    } else { 
    20712087        /* Encoded format */ 
    2072         stream->port.info.bytes_per_frame = stream->codec_param.info.max_bps *  
    2073                                             stream->codec_param.info.frm_ptime * 
    2074                                             stream->codec_param.setting.frm_per_pkt / 
    2075                                             8 / 1000; 
    2076         if ((stream->codec_param.info.max_bps * stream->codec_param.info.frm_ptime * 
    2077             stream->codec_param.setting.frm_per_pkt) % 8000 != 0) 
     2088        afd->avg_bps = stream->codec_param.info.avg_bps; 
     2089        afd->max_bps = stream->codec_param.info.max_bps; 
     2090 
     2091        /* Not applicable for 2.0 
     2092        if ((stream->codec_param.info.max_bps * 
     2093             stream->codec_param.info.frm_ptime * 
     2094             stream->codec_param.setting.frm_per_pkt) % 8000 != 0) 
    20782095        { 
    20792096            ++stream->port.info.bytes_per_frame; 
     
    20812098        stream->port.info.format.bitrate = stream->codec_param.info.avg_bps; 
    20822099        stream->port.info.format.vad = (stream->codec_param.setting.vad != 0); 
     2100        */ 
    20832101 
    20842102        stream->port.put_frame = &put_frame; 
     
    20972115        stream->enc_samples_per_pkt = stream->codec_param.info.enc_ptime * 
    20982116                                      stream->codec_param.info.channel_cnt * 
    2099                                       stream->port.info.clock_rate / 1000; 
     2117                                      afd->clock_rate / 1000; 
    21002118 
    21012119        /* Set buffer size as twice the largest ptime value between 
     
    21032121         */ 
    21042122 
    2105         ptime = stream->port.info.samples_per_frame * 1000 / 
    2106                 stream->port.info.clock_rate; 
     2123        ptime = afd->frame_time_usec / 1000; 
    21072124 
    21082125        if (stream->codec_param.info.enc_ptime > ptime) 
     
    21152132 
    21162133        /* Allocate buffer */ 
    2117         stream->enc_buf_size = stream->port.info.clock_rate * ptime / 1000; 
     2134        stream->enc_buf_size = afd->clock_rate * ptime / 1000; 
    21182135        stream->enc_buf = (pj_int16_t*) 
    21192136                          pj_pool_alloc(pool, stream->enc_buf_size * 2); 
    21202137 
    21212138    } else { 
    2122         stream->enc_samples_per_pkt = stream->port.info.samples_per_frame; 
     2139        stream->enc_samples_per_pkt = PJMEDIA_AFD_SPF(afd); 
    21232140    } 
    21242141 
     
    21292146        stream->codec_param.setting.vad = 0; 
    21302147        stream->ts_vad_disabled = 0; 
    2131         stream->codec->op->modify(stream->codec, &stream->codec_param); 
     2148        pjmedia_codec_modify(stream->codec, &stream->codec_param); 
    21322149        PJ_LOG(4,(stream->port.info.name.ptr,"VAD temporarily disabled")); 
    21332150    } 
     
    21532170    stream->rtp_tx_ts_len_per_pkt = stream->enc_samples_per_pkt / 
    21542171                                     stream->codec_param.info.channel_cnt; 
    2155     stream->rtp_rx_ts_len_per_frame = stream->port.info.samples_per_frame / 
     2172    stream->rtp_rx_ts_len_per_frame = PJMEDIA_AFD_SPF(afd) / 
    21562173                                      stream->codec_param.setting.frm_per_pkt / 
    21572174                                      stream->codec_param.info.channel_cnt; 
     
    22272244        rtcp_setting.rtp_ts_base = pj_ntohl(stream->enc->rtp.out_hdr.ts); 
    22282245        rtcp_setting.clock_rate = info->fmt.clock_rate; 
    2229         rtcp_setting.samples_per_frame = stream->port.info.samples_per_frame; 
     2246        rtcp_setting.samples_per_frame = PJMEDIA_AFD_SPF(afd); 
    22302247 
    22312248#if defined(PJMEDIA_HANDLE_G722_MPEG_BUG) && (PJMEDIA_HANDLE_G722_MPEG_BUG!=0) 
     
    24332450 
    24342451    if (stream->codec) { 
    2435         stream->codec->op->close(stream->codec); 
     2452        pjmedia_codec_close(stream->codec); 
    24362453        pjmedia_codec_mgr_dealloc_codec(stream->codec_mgr, stream->codec); 
    24372454        stream->codec = NULL; 
     
    24562473#endif 
    24572474 
     2475    if (stream->own_pool) { 
     2476        pj_pool_t *pool = stream->own_pool; 
     2477        stream->own_pool = NULL; 
     2478        pj_pool_release(pool); 
     2479    } 
    24582480    return PJ_SUCCESS; 
    24592481} 
     
    25162538} 
    25172539 
     2540 
     2541PJ_DEF(pj_status_t) pjmedia_stream_get_info( const pjmedia_stream *stream, 
     2542                                             pjmedia_stream_info *info) 
     2543{ 
     2544    PJ_ASSERT_RETURN(stream && info, PJ_EINVAL); 
     2545 
     2546    pj_memcpy(info, &stream->si, sizeof(pjmedia_stream_info)); 
     2547    return PJ_SUCCESS; 
     2548} 
    25182549 
    25192550/* 
     
    27612792} 
    27622793 
     2794 
     2795static const pj_str_t ID_AUDIO = { "audio", 5}; 
     2796static const pj_str_t ID_IN = { "IN", 2 }; 
     2797static const pj_str_t ID_IP4 = { "IP4", 3}; 
     2798static const pj_str_t ID_IP6 = { "IP6", 3}; 
     2799static const pj_str_t ID_RTP_AVP = { "RTP/AVP", 7 }; 
     2800static const pj_str_t ID_RTP_SAVP = { "RTP/SAVP", 8 }; 
     2801//static const pj_str_t ID_SDP_NAME = { "pjmedia", 7 }; 
     2802static const pj_str_t ID_RTPMAP = { "rtpmap", 6 }; 
     2803static const pj_str_t ID_TELEPHONE_EVENT = { "telephone-event", 15 }; 
     2804 
     2805static const pj_str_t STR_INACTIVE = { "inactive", 8 }; 
     2806static const pj_str_t STR_SENDRECV = { "sendrecv", 8 }; 
     2807static const pj_str_t STR_SENDONLY = { "sendonly", 8 }; 
     2808static const pj_str_t STR_RECVONLY = { "recvonly", 8 }; 
     2809 
     2810 
     2811/* 
     2812 * Internal function for collecting codec info and param from the SDP media. 
     2813 */ 
     2814static pj_status_t get_audio_codec_info_param(pjmedia_stream_info *si, 
     2815                                              pj_pool_t *pool, 
     2816                                              pjmedia_codec_mgr *mgr, 
     2817                                              const pjmedia_sdp_media *local_m, 
     2818                                              const pjmedia_sdp_media *rem_m) 
     2819{ 
     2820    const pjmedia_sdp_attr *attr; 
     2821    pjmedia_sdp_rtpmap *rtpmap; 
     2822    unsigned i, fmti, pt = 0; 
     2823    pj_status_t status; 
     2824 
     2825    /* Find the first codec which is not telephone-event */ 
     2826    for ( fmti = 0; fmti < local_m->desc.fmt_count; ++fmti ) { 
     2827        if ( !pj_isdigit(*local_m->desc.fmt[fmti].ptr) ) 
     2828            return PJMEDIA_EINVALIDPT; 
     2829        pt = pj_strtoul(&local_m->desc.fmt[fmti]); 
     2830        if ( PJMEDIA_RTP_PT_TELEPHONE_EVENTS == 0 || 
     2831                pt != PJMEDIA_RTP_PT_TELEPHONE_EVENTS ) 
     2832                break; 
     2833    } 
     2834    if ( fmti >= local_m->desc.fmt_count ) 
     2835        return PJMEDIA_EINVALIDPT; 
     2836 
     2837    /* Get codec info. 
     2838     * For static payload types, get the info from codec manager. 
     2839     * For dynamic payload types, MUST get the rtpmap. 
     2840     */ 
     2841    if (pt < 96) { 
     2842        pj_bool_t has_rtpmap; 
     2843 
     2844        rtpmap = NULL; 
     2845        has_rtpmap = PJ_TRUE; 
     2846 
     2847        attr = pjmedia_sdp_media_find_attr(local_m, &ID_RTPMAP,  
     2848                                           &local_m->desc.fmt[fmti]); 
     2849        if (attr == NULL) { 
     2850            has_rtpmap = PJ_FALSE; 
     2851        } 
     2852        if (attr != NULL) { 
     2853            status = pjmedia_sdp_attr_to_rtpmap(pool, attr, &rtpmap); 
     2854            if (status != PJ_SUCCESS) 
     2855                has_rtpmap = PJ_FALSE; 
     2856        } 
     2857 
     2858        /* Build codec format info: */ 
     2859        if (has_rtpmap) { 
     2860            si->fmt.type = si->type; 
     2861            si->fmt.pt = pj_strtoul(&local_m->desc.fmt[fmti]); 
     2862            pj_strdup(pool, &si->fmt.encoding_name, &rtpmap->enc_name); 
     2863            si->fmt.clock_rate = rtpmap->clock_rate; 
     2864             
     2865#if defined(PJMEDIA_HANDLE_G722_MPEG_BUG) && (PJMEDIA_HANDLE_G722_MPEG_BUG != 0) 
     2866            /* The session info should have the actual clock rate, because  
     2867             * this info is used for calculationg buffer size, etc in stream  
     2868             */ 
     2869            if (si->fmt.pt == PJMEDIA_RTP_PT_G722) 
     2870                si->fmt.clock_rate = 16000; 
     2871#endif 
     2872 
     2873            /* For audio codecs, rtpmap parameters denotes the number of 
     2874             * channels. 
     2875             */ 
     2876            if (si->type == PJMEDIA_TYPE_AUDIO && rtpmap->param.slen) { 
     2877                si->fmt.channel_cnt = (unsigned) pj_strtoul(&rtpmap->param); 
     2878            } else { 
     2879                si->fmt.channel_cnt = 1; 
     2880            } 
     2881 
     2882        } else {             
     2883            const pjmedia_codec_info *p_info; 
     2884 
     2885            status = pjmedia_codec_mgr_get_codec_info( mgr, pt, &p_info); 
     2886            if (status != PJ_SUCCESS) 
     2887                return status; 
     2888 
     2889            pj_memcpy(&si->fmt, p_info, sizeof(pjmedia_codec_info)); 
     2890        } 
     2891 
     2892        /* For static payload type, pt's are symetric */ 
     2893        si->tx_pt = pt; 
     2894 
     2895    } else { 
     2896 
     2897        attr = pjmedia_sdp_media_find_attr(local_m, &ID_RTPMAP,  
     2898                                           &local_m->desc.fmt[fmti]); 
     2899        if (attr == NULL) 
     2900            return PJMEDIA_EMISSINGRTPMAP; 
     2901 
     2902        status = pjmedia_sdp_attr_to_rtpmap(pool, attr, &rtpmap); 
     2903        if (status != PJ_SUCCESS) 
     2904            return status; 
     2905 
     2906        /* Build codec format info: */ 
     2907 
     2908        si->fmt.type = si->type; 
     2909        si->fmt.pt = pj_strtoul(&local_m->desc.fmt[fmti]); 
     2910        pj_strdup(pool, &si->fmt.encoding_name, &rtpmap->enc_name); 
     2911        si->fmt.clock_rate = rtpmap->clock_rate; 
     2912 
     2913        /* For audio codecs, rtpmap parameters denotes the number of 
     2914         * channels. 
     2915         */ 
     2916        if (si->type == PJMEDIA_TYPE_AUDIO && rtpmap->param.slen) { 
     2917            si->fmt.channel_cnt = (unsigned) pj_strtoul(&rtpmap->param); 
     2918        } else { 
     2919            si->fmt.channel_cnt = 1; 
     2920        } 
     2921 
     2922        /* Determine payload type for outgoing channel, by finding 
     2923         * dynamic payload type in remote SDP that matches the answer. 
     2924         */ 
     2925        si->tx_pt = 0xFFFF; 
     2926        for (i=0; i<rem_m->desc.fmt_count; ++i) { 
     2927            unsigned rpt; 
     2928            pjmedia_sdp_attr *r_attr; 
     2929            pjmedia_sdp_rtpmap r_rtpmap; 
     2930 
     2931            rpt = pj_strtoul(&rem_m->desc.fmt[i]); 
     2932            if (rpt < 96) 
     2933                continue; 
     2934 
     2935            r_attr = pjmedia_sdp_media_find_attr(rem_m, &ID_RTPMAP, 
     2936                                                 &rem_m->desc.fmt[i]); 
     2937            if (!r_attr) 
     2938                continue; 
     2939 
     2940            if (pjmedia_sdp_attr_get_rtpmap(r_attr, &r_rtpmap) != PJ_SUCCESS) 
     2941                continue; 
     2942 
     2943            if (!pj_stricmp(&rtpmap->enc_name, &r_rtpmap.enc_name) && 
     2944                rtpmap->clock_rate == r_rtpmap.clock_rate) 
     2945            { 
     2946                /* Found matched codec. */ 
     2947                si->tx_pt = rpt; 
     2948 
     2949                break; 
     2950            } 
     2951        } 
     2952 
     2953        if (si->tx_pt == 0xFFFF) 
     2954            return PJMEDIA_EMISSINGRTPMAP; 
     2955    } 
     2956 
     2957   
     2958    /* Now that we have codec info, get the codec param. */ 
     2959    si->param = PJ_POOL_ALLOC_T(pool, pjmedia_codec_param); 
     2960    status = pjmedia_codec_mgr_get_default_param(mgr, &si->fmt, 
     2961                                                 si->param); 
     2962 
     2963    /* Get remote fmtp for our encoder. */ 
     2964    pjmedia_stream_info_parse_fmtp(pool, rem_m, si->tx_pt, 
     2965                                   &si->param->setting.enc_fmtp); 
     2966 
     2967    /* Get local fmtp for our decoder. */ 
     2968    pjmedia_stream_info_parse_fmtp(pool, local_m, si->fmt.pt, 
     2969                                   &si->param->setting.dec_fmtp); 
     2970 
     2971    /* Get the remote ptime for our encoder. */ 
     2972    attr = pjmedia_sdp_attr_find2(rem_m->attr_count, rem_m->attr, 
     2973                                  "ptime", NULL); 
     2974    if (attr) { 
     2975        pj_str_t tmp_val = attr->value; 
     2976        unsigned frm_per_pkt; 
     2977  
     2978        pj_strltrim(&tmp_val); 
     2979 
     2980        /* Round up ptime when the specified is not multiple of frm_ptime */ 
     2981        frm_per_pkt = (pj_strtoul(&tmp_val) +  
     2982                      si->param->info.frm_ptime/2) / 
     2983                      si->param->info.frm_ptime; 
     2984        if (frm_per_pkt != 0) { 
     2985            si->param->setting.frm_per_pkt = (pj_uint8_t)frm_per_pkt; 
     2986        } 
     2987    } 
     2988 
     2989    /* Get remote maxptime for our encoder. */ 
     2990    attr = pjmedia_sdp_attr_find2(rem_m->attr_count, rem_m->attr, 
     2991                                  "maxptime", NULL); 
     2992    if (attr) { 
     2993        pj_str_t tmp_val = attr->value; 
     2994 
     2995        pj_strltrim(&tmp_val); 
     2996        si->tx_maxptime = pj_strtoul(&tmp_val); 
     2997    } 
     2998 
     2999    /* When direction is NONE (it means SDP negotiation has failed) we don't 
     3000     * need to return a failure here, as returning failure will cause 
     3001     * the whole SDP to be rejected. See ticket #: 
     3002     *  http:// 
     3003     * 
     3004     * Thanks Alain Totouom  
     3005     */ 
     3006    if (status != PJ_SUCCESS && si->dir != PJMEDIA_DIR_NONE) 
     3007        return status; 
     3008 
     3009 
     3010    /* Get incomming payload type for telephone-events */ 
     3011    si->rx_event_pt = -1; 
     3012    for (i=0; i<local_m->attr_count; ++i) { 
     3013        pjmedia_sdp_rtpmap r; 
     3014 
     3015        attr = local_m->attr[i]; 
     3016        if (pj_strcmp(&attr->name, &ID_RTPMAP) != 0) 
     3017            continue; 
     3018        if (pjmedia_sdp_attr_get_rtpmap(attr, &r) != PJ_SUCCESS) 
     3019            continue; 
     3020        if (pj_strcmp(&r.enc_name, &ID_TELEPHONE_EVENT) == 0) { 
     3021            si->rx_event_pt = pj_strtoul(&r.pt); 
     3022            break; 
     3023        } 
     3024    } 
     3025 
     3026    /* Get outgoing payload type for telephone-events */ 
     3027    si->tx_event_pt = -1; 
     3028    for (i=0; i<rem_m->attr_count; ++i) { 
     3029        pjmedia_sdp_rtpmap r; 
     3030 
     3031        attr = rem_m->attr[i]; 
     3032        if (pj_strcmp(&attr->name, &ID_RTPMAP) != 0) 
     3033            continue; 
     3034        if (pjmedia_sdp_attr_get_rtpmap(attr, &r) != PJ_SUCCESS) 
     3035            continue; 
     3036        if (pj_strcmp(&r.enc_name, &ID_TELEPHONE_EVENT) == 0) { 
     3037            si->tx_event_pt = pj_strtoul(&r.pt); 
     3038            break; 
     3039        } 
     3040    } 
     3041 
     3042    return PJ_SUCCESS; 
     3043} 
     3044 
     3045 
     3046 
     3047/* 
     3048 * Create stream info from SDP media line. 
     3049 */ 
     3050PJ_DEF(pj_status_t) pjmedia_stream_info_from_sdp( 
     3051                                           pjmedia_stream_info *si, 
     3052                                           pj_pool_t *pool, 
     3053                                           pjmedia_endpt *endpt, 
     3054                                           const pjmedia_sdp_session *local, 
     3055                                           const pjmedia_sdp_session *remote, 
     3056                                           unsigned stream_idx) 
     3057{ 
     3058    pjmedia_codec_mgr *mgr; 
     3059    const pjmedia_sdp_attr *attr; 
     3060    const pjmedia_sdp_media *local_m; 
     3061    const pjmedia_sdp_media *rem_m; 
     3062    const pjmedia_sdp_conn *local_conn; 
     3063    const pjmedia_sdp_conn *rem_conn; 
     3064    int rem_af, local_af; 
     3065    pj_sockaddr local_addr; 
     3066    pj_status_t status; 
     3067 
     3068     
     3069    /* Validate arguments: */ 
     3070    PJ_ASSERT_RETURN(pool && si && local && remote, PJ_EINVAL); 
     3071    PJ_ASSERT_RETURN(stream_idx < local->media_count, PJ_EINVAL); 
     3072    PJ_ASSERT_RETURN(stream_idx < remote->media_count, PJ_EINVAL); 
     3073 
     3074    /* Keep SDP shortcuts */ 
     3075    local_m = local->media[stream_idx]; 
     3076    rem_m = remote->media[stream_idx]; 
     3077 
     3078    local_conn = local_m->conn ? local_m->conn : local->conn; 
     3079    if (local_conn == NULL) 
     3080        return PJMEDIA_SDP_EMISSINGCONN; 
     3081 
     3082    rem_conn = rem_m->conn ? rem_m->conn : remote->conn; 
     3083    if (rem_conn == NULL) 
     3084        return PJMEDIA_SDP_EMISSINGCONN; 
     3085 
     3086    /* Media type must be audio */ 
     3087    if (pj_stricmp(&local_m->desc.media, &ID_AUDIO) != 0) 
     3088        return PJMEDIA_EINVALIMEDIATYPE; 
     3089 
     3090    /* Get codec manager. */ 
     3091    mgr = pjmedia_endpt_get_codec_mgr(endpt); 
     3092 
     3093    /* Reset: */ 
     3094 
     3095    pj_bzero(si, sizeof(*si)); 
     3096 
     3097#if PJMEDIA_HAS_RTCP_XR && PJMEDIA_STREAM_ENABLE_XR 
     3098    /* Set default RTCP XR enabled/disabled */ 
     3099    si->rtcp_xr_enabled = PJ_TRUE; 
     3100#endif 
     3101 
     3102    /* Media type: */ 
     3103    si->type = PJMEDIA_TYPE_AUDIO; 
     3104 
     3105    /* Transport protocol */ 
     3106 
     3107    /* At this point, transport type must be compatible,  
     3108     * the transport instance will do more validation later. 
     3109     */ 
     3110    status = pjmedia_sdp_transport_cmp(&rem_m->desc.transport,  
     3111                                       &local_m->desc.transport); 
     3112    if (status != PJ_SUCCESS) 
     3113        return PJMEDIA_SDPNEG_EINVANSTP; 
     3114 
     3115    if (pj_stricmp(&local_m->desc.transport, &ID_RTP_AVP) == 0) { 
     3116 
     3117        si->proto = PJMEDIA_TP_PROTO_RTP_AVP; 
     3118 
     3119    } else if (pj_stricmp(&local_m->desc.transport, &ID_RTP_SAVP) == 0) { 
     3120 
     3121        si->proto = PJMEDIA_TP_PROTO_RTP_SAVP; 
     3122 
     3123    } else { 
     3124 
     3125        si->proto = PJMEDIA_TP_PROTO_UNKNOWN; 
     3126        return PJ_SUCCESS; 
     3127    } 
     3128 
     3129 
     3130    /* Check address family in remote SDP */ 
     3131    rem_af = pj_AF_UNSPEC(); 
     3132    if (pj_stricmp(&rem_conn->net_type, &ID_IN)==0) { 
     3133        if (pj_stricmp(&rem_conn->addr_type, &ID_IP4)==0) { 
     3134            rem_af = pj_AF_INET(); 
     3135        } else if (pj_stricmp(&rem_conn->addr_type, &ID_IP6)==0) { 
     3136            rem_af = pj_AF_INET6(); 
     3137        } 
     3138    } 
     3139 
     3140    if (rem_af==pj_AF_UNSPEC()) { 
     3141        /* Unsupported address family */ 
     3142        return PJ_EAFNOTSUP; 
     3143    } 
     3144 
     3145    /* Set remote address: */ 
     3146    status = pj_sockaddr_init(rem_af, &si->rem_addr, &rem_conn->addr,  
     3147                              rem_m->desc.port); 
     3148    if (status != PJ_SUCCESS) { 
     3149        /* Invalid IP address. */ 
     3150        return PJMEDIA_EINVALIDIP; 
     3151    } 
     3152 
     3153    /* Check address family of local info */ 
     3154    local_af = pj_AF_UNSPEC(); 
     3155    if (pj_stricmp(&local_conn->net_type, &ID_IN)==0) { 
     3156        if (pj_stricmp(&local_conn->addr_type, &ID_IP4)==0) { 
     3157            local_af = pj_AF_INET(); 
     3158        } else if (pj_stricmp(&local_conn->addr_type, &ID_IP6)==0) { 
     3159            local_af = pj_AF_INET6(); 
     3160        } 
     3161    } 
     3162 
     3163    if (local_af==pj_AF_UNSPEC()) { 
     3164        /* Unsupported address family */ 
     3165        return PJ_SUCCESS; 
     3166    } 
     3167 
     3168    /* Set remote address: */ 
     3169    status = pj_sockaddr_init(local_af, &local_addr, &local_conn->addr,  
     3170                              local_m->desc.port); 
     3171    if (status != PJ_SUCCESS) { 
     3172        /* Invalid IP address. */ 
     3173        return PJMEDIA_EINVALIDIP; 
     3174    } 
     3175 
     3176    /* Local and remote address family must match */ 
     3177    if (local_af != rem_af) 
     3178        return PJ_EAFNOTSUP; 
     3179 
     3180    /* Media direction: */ 
     3181 
     3182    if (local_m->desc.port == 0 ||  
     3183        pj_sockaddr_has_addr(&local_addr)==PJ_FALSE || 
     3184        pj_sockaddr_has_addr(&si->rem_addr)==PJ_FALSE || 
     3185        pjmedia_sdp_media_find_attr(local_m, &STR_INACTIVE, NULL)!=NULL) 
     3186    { 
     3187        /* Inactive stream. */ 
     3188 
     3189        si->dir = PJMEDIA_DIR_NONE; 
     3190 
     3191    } else if (pjmedia_sdp_media_find_attr(local_m, &STR_SENDONLY, NULL)!=NULL) { 
     3192 
     3193        /* Send only stream. */ 
     3194 
     3195        si->dir = PJMEDIA_DIR_ENCODING; 
     3196 
     3197    } else if (pjmedia_sdp_media_find_attr(local_m, &STR_RECVONLY, NULL)!=NULL) { 
     3198 
     3199        /* Recv only stream. */ 
     3200 
     3201        si->dir = PJMEDIA_DIR_DECODING; 
     3202 
     3203    } else { 
     3204 
     3205        /* Send and receive stream. */ 
     3206 
     3207        si->dir = PJMEDIA_DIR_ENCODING_DECODING; 
     3208 
     3209    } 
     3210 
     3211    /* No need to do anything else if stream is rejected */ 
     3212    if (local_m->desc.port == 0) { 
     3213        return PJ_SUCCESS; 
     3214    } 
     3215 
     3216    /* If "rtcp" attribute is present in the SDP, set the RTCP address 
     3217     * from that attribute. Otherwise, calculate from RTP address. 
     3218     */ 
     3219    attr = pjmedia_sdp_attr_find2(rem_m->attr_count, rem_m->attr, 
     3220                                  "rtcp", NULL); 
     3221    if (attr) { 
     3222        pjmedia_sdp_rtcp_attr rtcp; 
     3223        status = pjmedia_sdp_attr_get_rtcp(attr, &rtcp); 
     3224        if (status == PJ_SUCCESS) { 
     3225            if (rtcp.addr.slen) { 
     3226                status = pj_sockaddr_init(rem_af, &si->rem_rtcp, &rtcp.addr, 
     3227                                          (pj_uint16_t)rtcp.port); 
     3228            } else { 
     3229                pj_sockaddr_init(rem_af, &si->rem_rtcp, NULL,  
     3230                                 (pj_uint16_t)rtcp.port); 
     3231                pj_memcpy(pj_sockaddr_get_addr(&si->rem_rtcp), 
     3232                          pj_sockaddr_get_addr(&si->rem_addr), 
     3233                          pj_sockaddr_get_addr_len(&si->rem_addr)); 
     3234            } 
     3235        } 
     3236    } 
     3237     
     3238    if (!pj_sockaddr_has_addr(&si->rem_rtcp)) { 
     3239        int rtcp_port; 
     3240 
     3241        pj_memcpy(&si->rem_rtcp, &si->rem_addr, sizeof(pj_sockaddr)); 
     3242        rtcp_port = pj_sockaddr_get_port(&si->rem_addr) + 1; 
     3243        pj_sockaddr_set_port(&si->rem_rtcp, (pj_uint16_t)rtcp_port); 
     3244    } 
     3245 
     3246 
     3247    /* Get the payload number for receive channel. */ 
     3248    /* 
     3249       Previously we used to rely on fmt[0] being the selected codec, 
     3250       but some UA sends telephone-event as fmt[0] and this would 
     3251       cause assert failure below. 
     3252 
     3253       Thanks Chris Hamilton <chamilton .at. cs.dal.ca> for this patch. 
     3254 
     3255    // And codec must be numeric! 
     3256    if (!pj_isdigit(*local_m->desc.fmt[0].ptr) ||  
     3257        !pj_isdigit(*rem_m->desc.fmt[0].ptr)) 
     3258    { 
     3259        return PJMEDIA_EINVALIDPT; 
     3260    } 
     3261 
     3262    pt = pj_strtoul(&local_m->desc.fmt[0]); 
     3263    pj_assert(PJMEDIA_RTP_PT_TELEPHONE_EVENTS==0 || 
     3264              pt != PJMEDIA_RTP_PT_TELEPHONE_EVENTS); 
     3265    */ 
     3266 
     3267    /* Get codec info and param */ 
     3268    status = get_audio_codec_info_param(si, pool, mgr, local_m, rem_m); 
     3269 
     3270    /* Leave SSRC to random. */ 
     3271    si->ssrc = pj_rand(); 
     3272 
     3273    /* Set default jitter buffer parameter. */ 
     3274    si->jb_init = si->jb_max = si->jb_min_pre = si->jb_max_pre = -1; 
     3275 
     3276    return status; 
     3277} 
Note: See TracChangeset for help on using the changeset viewer.