Changeset 874


Ignore:
Timestamp:
Dec 30, 2006 2:46:57 AM (17 years ago)
Author:
bennylp
Message:

Implement ticket #40: support for asymmetric encoding/decoding ptime (e.g. with iLBC when local and remote have different mode)

Location:
pjproject/trunk/pjmedia
Files:
7 edited

Legend:

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

    r867 r874  
    254254       unsigned    channel_cnt;         /**< Channel count.                 */ 
    255255       pj_uint32_t avg_bps;             /**< Average bandwidth in bits/sec  */ 
    256        pj_uint16_t frm_ptime;           /**< Base frame ptime in msec.      */ 
     256       pj_uint16_t frm_ptime;           /**< Decoder frame ptime in msec.   */ 
     257       pj_uint16_t enc_ptime;           /**< Encoder ptime, or zero if it's 
     258                                             equal to decoder ptime.        */ 
    257259       pj_uint8_t  pcm_bits_per_sample; /**< Bits/sample in the PCM side    */ 
    258260       pj_uint8_t  pt;                  /**< Payload type.                  */ 
     
    307309 
    308310    /**  
    309      * Open the codec and initialize with the specified parameter.. 
     311     * Open the codec and initialize with the specified parameter. 
     312     * Upon successful initialization, the codec may modify the parameter 
     313     * and fills in the unspecified values (such as enc_ptime, when 
     314     * encoder ptime is different than decoder ptime). 
    310315     * 
    311316     * @param codec     The codec instance. 
     
    315320     */ 
    316321    pj_status_t (*open)(pjmedia_codec *codec,  
    317                         const pjmedia_codec_param *param ); 
     322                        pjmedia_codec_param *param ); 
    318323 
    319324    /**  
  • pjproject/trunk/pjmedia/src/pjmedia-codec/gsm.c

    r867 r874  
    5555                                    pj_pool_t *pool ); 
    5656static pj_status_t  gsm_codec_open( pjmedia_codec *codec,  
    57                                     const pjmedia_codec_param *attr ); 
     57                                    pjmedia_codec_param *attr ); 
    5858static pj_status_t  gsm_codec_close( pjmedia_codec *codec ); 
    5959static pj_status_t  gsm_codec_modify(pjmedia_codec *codec,  
     
    389389 */ 
    390390static pj_status_t gsm_codec_open( pjmedia_codec *codec,  
    391                                    const pjmedia_codec_param *attr ) 
     391                                   pjmedia_codec_param *attr ) 
    392392{ 
    393393    struct gsm_data *gsm_data = codec->codec_data; 
     
    441441 
    442442    pj_assert(gsm_data != NULL); 
    443     pj_assert(gsm_data->encoder == NULL && gsm_data->decoder == NULL); 
     443    pj_assert(gsm_data->encoder != NULL && gsm_data->decoder != NULL); 
    444444 
    445445    gsm_data->vad_enabled = (attr->setting.vad != 0); 
  • pjproject/trunk/pjmedia/src/pjmedia-codec/ilbc.c

    r867 r874  
    6464                                    pj_pool_t *pool ); 
    6565static pj_status_t  ilbc_codec_open(pjmedia_codec *codec,  
    66                                     const pjmedia_codec_param *attr ); 
     66                                    pjmedia_codec_param *attr ); 
    6767static pj_status_t  ilbc_codec_close(pjmedia_codec *codec ); 
    6868static pj_status_t  ilbc_codec_modify(pjmedia_codec *codec,  
     
    365365 */ 
    366366static pj_status_t ilbc_codec_open(pjmedia_codec *codec,  
    367                                    const pjmedia_codec_param *param_attr ) 
     367                                   pjmedia_codec_param *attr ) 
    368368{ 
    369369    struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec; 
    370     pjmedia_codec_param attr_copy, *attr; 
    371370    pj_status_t status; 
    372371 
     
    374373    pj_assert(ilbc_codec->enc_ready == PJ_FALSE &&  
    375374              ilbc_codec->dec_ready == PJ_FALSE); 
    376  
    377     /* Copy param to temporary location since we need to modify fmtp_mode */ 
    378     pj_memcpy(&attr_copy, param_attr, sizeof(*param_attr)); 
    379     attr = &attr_copy; 
    380375 
    381376    /* Decoder mode must be set */ 
     
    392387    PJ_ASSERT_RETURN(attr->setting.enc_fmtp_mode==20 || 
    393388                     attr->setting.enc_fmtp_mode==30, PJMEDIA_CODEC_EINMODE); 
     389 
     390    /* Update enc_ptime in the param */ 
     391    if (attr->setting.enc_fmtp_mode != attr->setting.dec_fmtp_mode) { 
     392        attr->info.enc_ptime = attr->setting.enc_fmtp_mode; 
     393    } else { 
     394        attr->info.enc_ptime = 0; 
     395    } 
    394396 
    395397    /* Create enc */ 
  • pjproject/trunk/pjmedia/src/pjmedia-codec/l16.c

    r867 r874  
    6060                               pj_pool_t *pool ); 
    6161static pj_status_t  l16_open( pjmedia_codec *codec,  
    62                                const pjmedia_codec_param *attr ); 
     62                              pjmedia_codec_param *attr ); 
    6363static pj_status_t  l16_close( pjmedia_codec *codec ); 
    6464static pj_status_t  l16_modify(pjmedia_codec *codec,  
     
    490490 
    491491static pj_status_t l16_open(pjmedia_codec *codec,  
    492                             const pjmedia_codec_param *attr ) 
     492                            pjmedia_codec_param *attr ) 
    493493{ 
    494494    /* Nothing to do.. */ 
  • pjproject/trunk/pjmedia/src/pjmedia-codec/speex_codec.c

    r867 r874  
    6060                                    pj_pool_t *pool ); 
    6161static pj_status_t  spx_codec_open( pjmedia_codec *codec,  
    62                                     const pjmedia_codec_param *attr ); 
     62                                    pjmedia_codec_param *attr ); 
    6363static pj_status_t  spx_codec_close( pjmedia_codec *codec ); 
    6464static pj_status_t  spx_codec_modify(pjmedia_codec *codec,  
     
    548548 */ 
    549549static pj_status_t spx_codec_open( pjmedia_codec *codec,  
    550                                    const pjmedia_codec_param *attr ) 
     550                                   pjmedia_codec_param *attr ) 
    551551{ 
    552552    struct spx_private *spx; 
  • pjproject/trunk/pjmedia/src/pjmedia/g711.c

    r867 r874  
    6363                               pj_pool_t *pool ); 
    6464static pj_status_t  g711_open( pjmedia_codec *codec,  
    65                                const pjmedia_codec_param *attr ); 
     65                               pjmedia_codec_param *attr ); 
    6666static pj_status_t  g711_close( pjmedia_codec *codec ); 
    6767static pj_status_t  g711_modify(pjmedia_codec *codec,  
     
    398398 
    399399static pj_status_t g711_open(pjmedia_codec *codec,  
    400                              const pjmedia_codec_param *attr ) 
     400                             pjmedia_codec_param *attr ) 
    401401{ 
    402402    struct g711_private *priv = codec->codec_data; 
  • pjproject/trunk/pjmedia/src/pjmedia/stream.c

    r868 r874  
    8989    pjmedia_codec           *codec;         /**< Codec instance being used. */ 
    9090    pjmedia_codec_param      codec_param;   /**< Codec param.               */ 
     91    pj_int16_t              *enc_buf;       /**< Encoding buffer, when enc's 
     92                                                 ptime is different than dec. 
     93                                                 Otherwise it's NULL.       */ 
     94 
     95    unsigned                 enc_samples_per_frame; 
     96    unsigned                 enc_buf_size;  /**< Encoding buffer size, in 
     97                                                 samples.                   */ 
     98    unsigned                 enc_buf_pos;   /**< First position in buf.     */ 
     99    unsigned                 enc_buf_count; /**< Number of samples in the 
     100                                                 encoding buffer.           */ 
     101 
    91102    unsigned                 vad_enabled;   /**< VAD enabled in param.      */ 
    92103    unsigned                 frame_size;    /**< Size of encoded base frame.*/ 
     
    443454 
    444455/** 
     456 * Rebuffer the frame when encoder and decoder has different ptime 
     457 * (such as when different iLBC modes are used by local and remote) 
     458 */ 
     459static void rebuffer(pjmedia_stream *stream, 
     460                     pjmedia_frame *frame) 
     461{ 
     462    /* How many samples are needed */ 
     463    unsigned count; 
     464 
     465    /* Normalize frame */ 
     466    if (frame->type != PJMEDIA_FRAME_TYPE_AUDIO) 
     467        frame->size = 0; 
     468 
     469    /* Remove used frame from the buffer. */ 
     470    if (stream->enc_buf_pos) { 
     471        if (stream->enc_buf_count) { 
     472            pj_memmove(stream->enc_buf, 
     473                       stream->enc_buf + stream->enc_buf_pos, 
     474                       (stream->enc_buf_count << 1)); 
     475        } 
     476        stream->enc_buf_pos = 0; 
     477    } 
     478 
     479    /* Make sure we have space to store the new frame */ 
     480    pj_assert(stream->enc_buf_count + (frame->size >> 1) < 
     481                stream->enc_buf_size); 
     482 
     483    /* Append new frame to the buffer */ 
     484    if (frame->size) { 
     485        pj_memcpy(stream->enc_buf + stream->enc_buf_count, 
     486                  frame->buf, frame->size); 
     487        stream->enc_buf_count += (frame->size >> 1); 
     488    } 
     489 
     490    /* How many samples are needed */ 
     491    count = stream->codec_param.info.enc_ptime *  
     492                stream->port.info.clock_rate / 1000; 
     493 
     494    /* See if we have enough samples */ 
     495    if (stream->enc_buf_count >= count) { 
     496 
     497        frame->type = PJMEDIA_FRAME_TYPE_AUDIO; 
     498        frame->buf = stream->enc_buf; 
     499        frame->size = (count << 1); 
     500 
     501        stream->enc_buf_pos = count; 
     502        stream->enc_buf_count -= count; 
     503 
     504    } else { 
     505        /* We don't have enough samples */ 
     506        frame->type = PJMEDIA_FRAME_TYPE_NONE; 
     507    } 
     508} 
     509 
     510 
     511/** 
     512 * put_frame_imp() 
     513 */ 
     514static pj_status_t put_frame_imp( pjmedia_port *port,  
     515                                  const pjmedia_frame *frame ) 
     516{ 
     517    pjmedia_stream *stream = port->port_data.pdata; 
     518    pjmedia_channel *channel = stream->enc; 
     519    pj_status_t status = 0; 
     520    pjmedia_frame frame_out; 
     521    unsigned ts_len, samples_per_frame; 
     522    void *rtphdr; 
     523    int rtphdrlen; 
     524 
     525 
     526    /* Don't do anything if stream is paused */ 
     527    if (channel->paused) { 
     528        stream->enc_buf_pos = stream->enc_buf_count = 0; 
     529        return PJ_SUCCESS; 
     530    } 
     531 
     532    /* Number of samples in the frame */ 
     533    if (frame->type == PJMEDIA_FRAME_TYPE_AUDIO) 
     534        ts_len = (frame->size >> 1); 
     535    else 
     536        ts_len = 0; 
     537 
     538    /* Increment transmit duration */ 
     539    stream->tx_duration += ts_len; 
     540 
     541    /* Init frame_out buffer. */ 
     542    frame_out.buf = ((char*)channel->out_pkt) + sizeof(pjmedia_rtp_hdr); 
     543    frame_out.size = 0; 
     544 
     545    /* Calculate number of samples per frame */ 
     546    samples_per_frame = stream->enc_samples_per_frame; 
     547 
     548 
     549    /* If we have DTMF digits in the queue, transmit the digits.  
     550     * Otherwise encode the PCM buffer. 
     551     */ 
     552    if (stream->tx_dtmf_count) { 
     553 
     554        create_dtmf_payload(stream, &frame_out); 
     555 
     556        /* Encapsulate. */ 
     557        status = pjmedia_rtp_encode_rtp( &channel->rtp,  
     558                                         stream->tx_event_pt, 0,  
     559                                         frame_out.size, ts_len,  
     560                                         (const void**)&rtphdr,  
     561                                         &rtphdrlen); 
     562 
     563    } else if (frame->type != PJMEDIA_FRAME_TYPE_NONE) { 
     564        unsigned ts; 
     565 
     566        /* Repeatedly call encode if there are multiple frames to be 
     567         * sent. 
     568         */ 
     569 
     570        for (ts=0; ts<ts_len; ts += samples_per_frame) { 
     571            pjmedia_frame tmp_out_frame, tmp_in_frame; 
     572            unsigned bytes_per_sample, max_size; 
     573 
     574            /* Nb of bytes in PCM sample */ 
     575            bytes_per_sample = stream->codec_param.info.pcm_bits_per_sample/8; 
     576 
     577            /* Split original PCM input frame into base frame size */ 
     578            tmp_in_frame.buf = ((char*)frame->buf) + ts * bytes_per_sample; 
     579            tmp_in_frame.size = samples_per_frame * bytes_per_sample; 
     580            tmp_in_frame.type = PJMEDIA_FRAME_TYPE_AUDIO; 
     581 
     582            /* Set output frame position */ 
     583            tmp_out_frame.buf = ((char*)frame_out.buf) + frame_out.size; 
     584 
     585            max_size = channel->out_pkt_size - sizeof(pjmedia_rtp_hdr) - 
     586                       frame_out.size; 
     587 
     588            /* Encode! */ 
     589            status = stream->codec->op->encode( stream->codec, &tmp_in_frame,  
     590                                                max_size, &tmp_out_frame); 
     591            if (status != PJ_SUCCESS) { 
     592                LOGERR_((stream->port.info.name.ptr,  
     593                        "Codec encode() error", status)); 
     594                return status; 
     595            } 
     596 
     597            /* tmp_out_frame.size may be zero for silence frame. */ 
     598            frame_out.size += tmp_out_frame.size; 
     599 
     600            /* Stop processing next PCM frame when encode() returns either  
     601             * CNG frame or NULL frame. 
     602             */ 
     603            if (tmp_out_frame.type!=PJMEDIA_FRAME_TYPE_AUDIO ||  
     604                tmp_out_frame.size==0)  
     605            { 
     606                break; 
     607            } 
     608 
     609        } 
     610 
     611        /* Encapsulate. */ 
     612        status = pjmedia_rtp_encode_rtp( &channel->rtp,  
     613                                         channel->pt, 0,  
     614                                         frame_out.size, ts_len,  
     615                                         (const void**)&rtphdr,  
     616                                         &rtphdrlen); 
     617    } else { 
     618 
     619        /* Just update RTP session's timestamp. */ 
     620        status = pjmedia_rtp_encode_rtp( &channel->rtp,  
     621                                         0, 0,  
     622                                         0, ts_len,  
     623                                         (const void**)&rtphdr,  
     624                                         &rtphdrlen); 
     625 
     626    } 
     627 
     628    if (status != PJ_SUCCESS) { 
     629        LOGERR_((stream->port.info.name.ptr,  
     630                "RTP encode_rtp() error", status)); 
     631        return status; 
     632    } 
     633 
     634    /* Check if now is the time to transmit RTCP SR/RR report.  
     635     * We only do this when stream direction is not "decoding only", because 
     636     * when it is, check_tx_rtcp() will be handled by get_frame(). 
     637     */ 
     638    if (stream->dir != PJMEDIA_DIR_DECODING) { 
     639        check_tx_rtcp(stream, pj_ntohl(channel->rtp.out_hdr.ts)); 
     640    } 
     641 
     642    /* Do nothing if we have nothing to transmit */ 
     643    if (frame_out.size == 0) { 
     644        if (stream->is_streaming) { 
     645            PJ_LOG(5,(stream->port.info.name.ptr,"Starting silence")); 
     646            stream->is_streaming = PJ_FALSE; 
     647        } 
     648 
     649        return PJ_SUCCESS; 
     650    } 
     651 
     652 
     653    /* Copy RTP header to the beginning of packet */ 
     654    pj_memcpy(channel->out_pkt, rtphdr, sizeof(pjmedia_rtp_hdr)); 
     655 
     656 
     657    /* Set RTP marker bit if currently not streaming */ 
     658    if (stream->is_streaming == PJ_FALSE) { 
     659        pjmedia_rtp_hdr *rtp = channel->out_pkt; 
     660 
     661        rtp->m = 1; 
     662        PJ_LOG(5,(stream->port.info.name.ptr,"Start talksprut..")); 
     663    } 
     664 
     665    stream->is_streaming = PJ_TRUE; 
     666 
     667    /* Send the RTP packet to the transport. */ 
     668    (*stream->transport->op->send_rtp)(stream->transport, 
     669                                       channel->out_pkt,  
     670                                       frame_out.size +  
     671                                            sizeof(pjmedia_rtp_hdr)); 
     672 
     673 
     674    /* Update stat */ 
     675    pjmedia_rtcp_tx_rtp(&stream->rtcp, frame_out.size); 
     676 
     677    return PJ_SUCCESS; 
     678} 
     679 
     680 
     681/** 
    445682 * put_frame() 
    446683 * 
     
    453690{ 
    454691    pjmedia_stream *stream = port->port_data.pdata; 
    455     pjmedia_channel *channel = stream->enc; 
    456     pj_status_t status = 0; 
    457     struct pjmedia_frame frame_out; 
    458     unsigned ts_len, samples_per_frame; 
    459692    pjmedia_frame tmp_in_frame; 
    460     void *rtphdr; 
    461     int rtphdrlen; 
    462  
    463  
    464     /* Don't do anything if stream is paused */ 
    465     if (channel->paused) 
    466         return PJ_SUCCESS; 
    467  
    468  
    469     /* Number of samples in the frame */ 
    470     //ts_len = frame->size / 2; 
    471     ts_len = port->info.samples_per_frame; 
    472  
    473     /* Increment transmit duration */ 
    474     stream->tx_duration += ts_len; 
    475  
    476     /* Init frame_out buffer. */ 
    477     frame_out.buf = ((char*)channel->out_pkt) + sizeof(pjmedia_rtp_hdr); 
    478     frame_out.size = 0; 
    479  
    480     /* Calculate number of samples per frame */ 
    481     samples_per_frame = stream->codec_param.info.frm_ptime * 
    482                         stream->codec_param.info.clock_rate * 
    483                         stream->codec_param.info.channel_cnt / 
    484                         1000; 
     693    unsigned samples_per_frame; 
     694 
     695    samples_per_frame = stream->enc_samples_per_frame; 
    485696 
    486697    /* If VAD is temporarily disabled during creation, feed zero PCM frame 
     
    500711    } 
    501712 
    502  
    503     /* If we have DTMF digits in the queue, transmit the digits.  
    504      * Otherwise encode the PCM buffer. 
    505      */ 
    506     if (stream->tx_dtmf_count) { 
    507  
    508         create_dtmf_payload(stream, &frame_out); 
    509  
    510         /* Encapsulate. */ 
    511         status = pjmedia_rtp_encode_rtp( &channel->rtp,  
    512                                          stream->tx_event_pt, 0,  
    513                                          frame_out.size, ts_len,  
    514                                          (const void**)&rtphdr,  
    515                                          &rtphdrlen); 
    516  
    517     } else if (frame->type != PJMEDIA_FRAME_TYPE_NONE) { 
    518         unsigned ts; 
    519  
    520         /* Repeatedly call encode if there are multiple frames to be 
    521          * sent. 
    522          */ 
    523  
    524         for (ts=0; ts<ts_len; ts += samples_per_frame) { 
    525             pjmedia_frame tmp_out_frame, tmp_in_frame; 
    526             unsigned bytes_per_sample, max_size; 
    527  
    528             /* Nb of bytes in PCM sample */ 
    529             bytes_per_sample = stream->codec_param.info.pcm_bits_per_sample/8; 
    530  
    531             /* Split original PCM input frame into base frame size */ 
    532             tmp_in_frame.buf = ((char*)frame->buf) + ts * bytes_per_sample; 
    533             tmp_in_frame.size = samples_per_frame * bytes_per_sample; 
    534             tmp_in_frame.type = PJMEDIA_FRAME_TYPE_AUDIO; 
    535  
    536             /* Set output frame position */ 
    537             tmp_out_frame.buf = ((char*)frame_out.buf) + frame_out.size; 
    538  
    539             max_size = channel->out_pkt_size - sizeof(pjmedia_rtp_hdr) - 
    540                        frame_out.size; 
    541  
    542             /* Encode! */ 
    543             status = stream->codec->op->encode( stream->codec, &tmp_in_frame,  
    544                                                 max_size, &tmp_out_frame); 
    545             if (status != PJ_SUCCESS) { 
    546                 LOGERR_((stream->port.info.name.ptr,  
    547                         "Codec encode() error", status)); 
    548                 return status; 
    549             } 
    550  
    551             /* tmp_out_frame.size may be zero for silence frame. */ 
    552             frame_out.size += tmp_out_frame.size; 
    553  
    554             /* Stop processing next PCM frame when encode() returns either  
    555              * CNG frame or NULL frame. 
    556              */ 
    557             if (tmp_out_frame.type!=PJMEDIA_FRAME_TYPE_AUDIO ||  
    558                 tmp_out_frame.size==0)  
    559             { 
    560                 break; 
    561             } 
    562  
    563         } 
    564  
    565         /* Encapsulate. */ 
    566         status = pjmedia_rtp_encode_rtp( &channel->rtp,  
    567                                          channel->pt, 0,  
    568                                          frame_out.size, ts_len,  
    569                                          (const void**)&rtphdr,  
    570                                          &rtphdrlen); 
    571     } else { 
    572  
    573         /* Just update RTP session's timestamp. */ 
    574         status = pjmedia_rtp_encode_rtp( &channel->rtp,  
    575                                          0, 0,  
    576                                          0, ts_len,  
    577                                          (const void**)&rtphdr,  
    578                                          &rtphdrlen); 
    579  
    580     } 
    581  
    582     if (status != PJ_SUCCESS) { 
    583         LOGERR_((stream->port.info.name.ptr,  
    584                 "RTP encode_rtp() error", status)); 
    585         return status; 
    586     } 
    587  
    588     /* Check if now is the time to transmit RTCP SR/RR report.  
    589      * We only do this when stream direction is not "decoding only", because 
    590      * when it is, check_tx_rtcp() will be handled by get_frame(). 
    591      */ 
    592     if (stream->dir != PJMEDIA_DIR_DECODING) { 
    593         check_tx_rtcp(stream, pj_ntohl(channel->rtp.out_hdr.ts)); 
    594     } 
    595  
    596     /* Do nothing if we have nothing to transmit */ 
    597     if (frame_out.size == 0) { 
    598         if (stream->is_streaming) { 
    599             PJ_LOG(5,(stream->port.info.name.ptr,"Starting silence")); 
    600             stream->is_streaming = PJ_FALSE; 
    601         } 
    602  
    603         return PJ_SUCCESS; 
    604     } 
    605  
    606  
    607     /* Copy RTP header to the beginning of packet */ 
    608     pj_memcpy(channel->out_pkt, rtphdr, sizeof(pjmedia_rtp_hdr)); 
    609  
    610  
    611     /* Set RTP marker bit if currently not streaming */ 
    612     if (stream->is_streaming == PJ_FALSE) { 
    613         pjmedia_rtp_hdr *rtp = channel->out_pkt; 
    614  
    615         rtp->m = 1; 
    616         PJ_LOG(5,(stream->port.info.name.ptr,"Start talksprut..")); 
    617     } 
    618  
    619     stream->is_streaming = PJ_TRUE; 
    620  
    621     /* Send the RTP packet to the transport. */ 
    622     (*stream->transport->op->send_rtp)(stream->transport, 
    623                                        channel->out_pkt,  
    624                                        frame_out.size +  
    625                                             sizeof(pjmedia_rtp_hdr)); 
    626  
    627  
    628     /* Update stat */ 
    629     pjmedia_rtcp_tx_rtp(&stream->rtcp, frame_out.size); 
    630  
    631713    /* If VAD is temporarily disabled during creation, enable it 
    632714     * after transmitting for VAD_SUSPEND_SEC seconds. 
     
    642724 
    643725 
    644     return PJ_SUCCESS; 
    645 } 
     726    /* If encoder has different ptime than decoder, then the frame must 
     727     * be passed through the encoding buffer via rebuffer() function. 
     728     */ 
     729    if (stream->enc_buf != NULL) { 
     730        pjmedia_frame tmp_rebuffer_frame; 
     731        pj_status_t status = PJ_SUCCESS; 
     732 
     733        /* Copy original frame to temporary frame since we need  
     734         * to modify it. 
     735         */ 
     736        pj_memcpy(&tmp_rebuffer_frame, frame, sizeof(pjmedia_frame)); 
     737 
     738        /* Loop while we have full frame in enc_buffer */ 
     739        for (;;) { 
     740            pj_status_t st; 
     741 
     742            /* Run rebuffer() */ 
     743            rebuffer(stream, &tmp_rebuffer_frame); 
     744 
     745            /* Process this frame */ 
     746            st = put_frame_imp(port, &tmp_rebuffer_frame); 
     747            if (st != PJ_SUCCESS) 
     748                status = st; 
     749 
     750            /* If we still have full frame in the buffer, re-run 
     751             * rebuffer() with NULL frame. 
     752             */ 
     753            if (stream->enc_buf_count >= stream->enc_samples_per_frame) { 
     754 
     755                tmp_rebuffer_frame.type = PJMEDIA_FRAME_TYPE_NONE; 
     756 
     757            } else { 
     758 
     759                /* Otherwise break */ 
     760                break; 
     761            } 
     762        } 
     763 
     764        return status; 
     765 
     766    } else { 
     767        return put_frame_imp(port, frame); 
     768    } 
     769} 
     770 
    646771 
    647772#if 0 
     
    10721197        goto err_cleanup; 
    10731198 
     1199    /* If encoder and decoder's ptime are asymmetric, then we need to 
     1200     * create buffer on the encoder side. This could happen for example 
     1201     * with iLBC  
     1202     */ 
     1203    if (stream->codec_param.info.enc_ptime!=0 && 
     1204        stream->codec_param.info.enc_ptime!=stream->codec_param.info.frm_ptime) 
     1205    { 
     1206        unsigned ptime; 
     1207 
     1208        stream->enc_samples_per_frame = stream->codec_param.info.enc_ptime * 
     1209                                        stream->port.info.clock_rate / 1000; 
     1210 
     1211        /* Set buffer size as twice the largest ptime value between 
     1212         * stream's ptime, encoder ptime, or decoder ptime. 
     1213         */ 
     1214 
     1215        ptime = stream->port.info.samples_per_frame * 1000 / 
     1216                stream->port.info.clock_rate; 
     1217 
     1218        if (stream->codec_param.info.enc_ptime > ptime) 
     1219            ptime = stream->codec_param.info.enc_ptime; 
     1220 
     1221        if (stream->codec_param.info.frm_ptime > ptime) 
     1222            ptime = stream->codec_param.info.frm_ptime; 
     1223 
     1224        ptime <<= 1; 
     1225 
     1226        /* Allocate buffer */ 
     1227        stream->enc_buf_size = stream->port.info.clock_rate * ptime / 1000; 
     1228        stream->enc_buf = pj_pool_alloc(pool, stream->enc_buf_size * 2); 
     1229 
     1230    } else { 
     1231        stream->enc_samples_per_frame = stream->port.info.samples_per_frame; 
     1232    } 
    10741233 
    10751234    /* Initially disable the VAD in the stream, to help traverse NAT better */ 
     
    10841243    /* Get the frame size: */ 
    10851244 
    1086     stream->frame_size = (stream->codec_param.info.avg_bps / 8) *  
     1245    stream->frame_size = ((stream->codec_param.info.avg_bps + 7) / 8) *  
    10871246                          stream->codec_param.info.frm_ptime / 1000; 
     1247 
    10881248 
    10891249    /* Init RTCP session: */ 
Note: See TracChangeset for help on using the changeset viewer.