Changeset 1983


Ignore:
Timestamp:
Jun 5, 2008 10:50:40 AM (16 years ago)
Author:
nanang
Message:

Ticket #473:

  • fixed issue on Speex multiple frames (encoding: encoded bits concatenation & decoding: frames parsing)
  • updated pjmedia stream & codecs on encoding multiple frames
  • introduced bit_info in pjmedia_frame and jitter buffer
Location:
pjproject/trunk/pjmedia
Files:
10 edited

Legend:

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

    r974 r1983  
    376376    /**  
    377377     * Instruct the codec to encode the specified input frame. The input 
    378      * PCM samples MUST have ptime that is exactly equal to base frame 
     378     * PCM samples MUST have ptime that is multiplication of base frame 
    379379     * ptime (i.e. the value of info.frm_ptime in #pjmedia_codec_param). 
    380380     * 
  • pjproject/trunk/pjmedia/include/pjmedia/jbuf.h

    r1961 r1983  
    220220 *                      buffer. 
    221221 * @param size          The frame size. 
     222 * @param bit_info      Bit precise info of the frame, e.g: a frame may not  
     223 *                      exactly start and end at the octet boundary, so this 
     224 *                      field may be used for specifying start & end bit offset. 
    222225 * @param frame_seq     The frame sequence number. 
    223226 * @param discarded     Flag whether the frame is discarded by jitter buffer. 
     
    226229                                       const void *frame,  
    227230                                       pj_size_t size,  
     231                                       pj_uint32_t bit_info, 
    228232                                       int frame_seq, 
    229233                                       pj_bool_t *discarded); 
     
    268272 * @param p_frm_type    Pointer to receive frame type. 
    269273 *                      @see pjmedia_jbuf_get_frame().     
     274 * @param bit_info      Bit precise info of the frame, e.g: a frame may not  
     275 *                      exactly start and end at the octet boundary, so this 
     276 *                      field may be used for specifying start & end bit offset. 
    270277 */ 
    271278PJ_DECL(void) pjmedia_jbuf_get_frame2(pjmedia_jbuf *jb,  
    272279                                      void *frame,  
    273280                                      pj_size_t *size,  
    274                                       char *p_frm_type); 
     281                                      char *p_frm_type, 
     282                                      pj_uint32_t *bit_info); 
    275283 
    276284 
  • pjproject/trunk/pjmedia/include/pjmedia/port.h

    r974 r1983  
    299299struct pjmedia_frame 
    300300{ 
    301     pjmedia_frame_type   type;      /**< Frame type.                */ 
    302     void                *buf;       /**< Pointer to buffer.         */ 
    303     pj_size_t            size;      /**< Frame size in bytes.       */ 
    304     pj_timestamp         timestamp; /**< Frame timestamp.           */ 
     301    pjmedia_frame_type   type;      /**< Frame type.                        */ 
     302    void                *buf;       /**< Pointer to buffer.                 */ 
     303    pj_size_t            size;      /**< Frame size in bytes.               */ 
     304    pj_timestamp         timestamp; /**< Frame timestamp.                   */ 
     305    pj_uint32_t          bit_info;  /**< Bit info of the frame, sample case: 
     306                                         a frame may not exactly start and end 
     307                                         at the octet boundary, so this field  
     308                                         may be used for specifying start &  
     309                                         end bit offset.                    */ 
    305310}; 
    306311 
  • pjproject/trunk/pjmedia/src/pjmedia-codec/g722.c

    r1977 r1983  
    533533    pj_status_t status; 
    534534 
    535     pj_assert(g722_data != NULL); 
    536     PJ_ASSERT_RETURN(input && output, PJ_EINVAL); 
    537  
    538     if (output_buf_len < FRAME_LEN) 
    539         return PJMEDIA_CODEC_EFRMTOOSHORT; 
    540  
    541     PJ_ASSERT_RETURN(input->size/2 == SAMPLES_PER_FRAME,  
    542                      PJMEDIA_CODEC_EPCMFRMINLEN); 
     535    pj_assert(g722_data && input && output); 
     536 
     537    PJ_ASSERT_RETURN((input->size >> 2) <= output_buf_len,  
     538                     PJMEDIA_CODEC_EFRMTOOSHORT); 
    543539 
    544540    /* Detect silence */ 
     
    571567    output->size = output_buf_len; 
    572568    status = g722_enc_encode(&g722_data->encoder, (pj_int16_t*)input->buf,  
    573                              SAMPLES_PER_FRAME, output->buf, &output->size); 
     569                             (input->size >> 1), output->buf, &output->size); 
    574570    if (status != PJ_SUCCESS) { 
    575571        output->size = 0; 
  • pjproject/trunk/pjmedia/src/pjmedia-codec/gsm.c

    r1846 r1983  
    516516{ 
    517517    struct gsm_data *gsm_data = (struct gsm_data*) codec->codec_data; 
    518  
    519     pj_assert(gsm_data != NULL); 
    520     PJ_ASSERT_RETURN(input && output, PJ_EINVAL); 
    521  
    522     if (output_buf_len < 33) 
    523         return PJMEDIA_CODEC_EFRMTOOSHORT; 
    524  
    525     PJ_ASSERT_RETURN(input->size==320, PJMEDIA_CODEC_EPCMFRMINLEN); 
     518    pj_int16_t *pcm_in; 
     519    unsigned in_size; 
     520 
     521    pj_assert(gsm_data && input && output); 
     522     
     523    pcm_in = (pj_int16_t*)input->buf; 
     524    in_size = input->size; 
     525 
     526    PJ_ASSERT_RETURN(in_size % 320 == 0, PJMEDIA_CODEC_EPCMFRMINLEN); 
     527    PJ_ASSERT_RETURN(output_buf_len >= 33 * in_size/320,  
     528                     PJMEDIA_CODEC_EFRMTOOSHORT); 
    526529 
    527530    /* Detect silence */ 
     
    552555 
    553556    /* Encode */ 
    554     gsm_encode(gsm_data->encoder, (short*)input->buf,  
    555                (unsigned char*)output->buf); 
    556  
    557     output->size = 33; 
     557    output->size = 0; 
     558    while (in_size >= 320) { 
     559        gsm_encode(gsm_data->encoder, pcm_in,  
     560                   (unsigned char*)output->buf + output->size); 
     561        pcm_in += 160; 
     562        output->size += 33; 
     563        in_size -= 320; 
     564    } 
     565 
    558566    output->type = PJMEDIA_FRAME_TYPE_AUDIO; 
    559567 
  • pjproject/trunk/pjmedia/src/pjmedia-codec/ilbc.c

    r1266 r1983  
    511511{ 
    512512    struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec; 
    513     unsigned i; 
    514  
    515     pj_assert(ilbc_codec != NULL); 
    516     PJ_ASSERT_RETURN(input && output, PJ_EINVAL); 
    517  
    518     if (output_buf_len < ilbc_codec->enc_frame_size) 
    519         return PJMEDIA_CODEC_EFRMTOOSHORT; 
    520  
    521     if (input->size != (ilbc_codec->enc_samples_per_frame << 1)) 
    522         return PJMEDIA_CODEC_EPCMFRMINLEN; 
     513    pj_int16_t *pcm_in; 
     514    unsigned nsamples; 
     515 
     516    pj_assert(ilbc_codec && input && output); 
     517 
     518    pcm_in = (pj_int16_t*)input->buf; 
     519    nsamples = input->size >> 1; 
     520 
     521    PJ_ASSERT_RETURN(nsamples % ilbc_codec->enc_samples_per_frame == 0,  
     522                     PJMEDIA_CODEC_EPCMFRMINLEN); 
     523    PJ_ASSERT_RETURN(output_buf_len >= ilbc_codec->enc_frame_size * nsamples / 
     524                     ilbc_codec->enc_samples_per_frame, 
     525                     PJMEDIA_CODEC_EFRMTOOSHORT); 
    523526 
    524527    /* Detect silence */ 
     
    548551    } 
    549552 
    550     /* Convert to float */ 
    551     for (i=0; i<ilbc_codec->enc_samples_per_frame; ++i) { 
    552         ilbc_codec->enc_block[i] = (float) (((pj_int16_t*)input->buf)[i]); 
    553     } 
    554  
    555553    /* Encode */ 
    556     iLBC_encode((unsigned char *)output->buf,  
    557                 ilbc_codec->enc_block,  
    558                 &ilbc_codec->enc); 
     554    output->size = 0; 
     555    while (nsamples >= ilbc_codec->enc_samples_per_frame) { 
     556        unsigned i; 
     557         
     558        /* Convert to float */ 
     559        for (i=0; i<ilbc_codec->enc_samples_per_frame; ++i) { 
     560            ilbc_codec->enc_block[i] = (float) (*pcm_in++); 
     561        } 
     562 
     563        iLBC_encode((unsigned char *)output->buf + output->size,  
     564                    ilbc_codec->enc_block,  
     565                    &ilbc_codec->enc); 
     566 
     567        output->size += ilbc_codec->enc.no_of_bytes; 
     568        nsamples -= ilbc_codec->enc_samples_per_frame; 
     569    } 
    559570 
    560571    output->type = PJMEDIA_FRAME_TYPE_AUDIO; 
    561     output->size = ilbc_codec->enc.no_of_bytes; 
    562572    output->timestamp = input->timestamp; 
    563573 
  • pjproject/trunk/pjmedia/src/pjmedia-codec/l16.c

    r1266 r1983  
    565565    while (samp!=samp_end) 
    566566        *samp_out++ = pj_htons(*samp++); 
     567#else 
     568    pjmedia_copy_samples(samp_out, samp, input->size >> 1); 
    567569#endif 
    568570 
     
    597599    while (samp!=samp_end) 
    598600        *samp_out++ = pj_htons(*samp++); 
     601#else 
     602    pjmedia_copy_samples(samp_out, samp, input->size >> 1); 
    599603#endif 
    600604 
  • pjproject/trunk/pjmedia/src/pjmedia-codec/speex_codec.c

    r1965 r1983  
    161161        return PJMEDIA_CODEC_EFAILED; 
    162162 
    163     /* Set the quality */ 
    164     if (p->quality != -1) 
    165         speex_encoder_ctl(state, SPEEX_SET_QUALITY, &p->quality); 
     163    /* We have to get maximum bitrate, so let's set maximum quality */ 
     164    tmp = 10; 
     165    speex_encoder_ctl(state, SPEEX_SET_QUALITY, &tmp); 
    166166 
    167167    /* Sampling rate. */ 
     
    596596    id = spx->param_id; 
    597597 
    598     /* Only supports one frame per packet */ 
    599     PJ_ASSERT_RETURN(attr->setting.frm_per_pkt==1, PJ_EINVAL); 
    600  
    601598    /*  
    602599     * Create and initialize encoder.  
     
    688685    spx = (struct spx_private*) codec->codec_data; 
    689686 
    690     /* Only supports one frame per packet */ 
    691     PJ_ASSERT_RETURN(attr->setting.frm_per_pkt==1, PJ_EINVAL); 
    692  
    693687    /* VAD */ 
    694688    tmp = (attr->setting.vad != 0); 
     
    701695 
    702696    return PJ_SUCCESS; 
     697} 
     698 
     699#if 0 
     700#  define TRACE__(args)     PJ_LOG(5,args) 
     701#else 
     702#  define TRACE__(args) 
     703#endif 
     704 
     705#undef THIS_FUNC 
     706#define THIS_FUNC "speex_get_next_frame" 
     707 
     708#define NB_SUBMODES 16 
     709#define NB_SUBMODE_BITS 4 
     710 
     711#define SB_SUBMODES 8 
     712#define SB_SUBMODE_BITS 3 
     713 
     714/* This function will iterate frames & submodes in the Speex bits. 
     715 * Returns 0 if a frame found, otherwise returns -1. 
     716 */ 
     717int speex_get_next_frame(SpeexBits *bits) 
     718{ 
     719    static const int inband_skip_table[NB_SUBMODES] = 
     720       {1, 1, 4, 4, 4, 4, 4, 4, 8, 8, 16, 16, 32, 32, 64, 64 }; 
     721    static const int wb_skip_table[SB_SUBMODES] = 
     722       {SB_SUBMODE_BITS+1, 36, 112, 192, 352, -1, -1, -1}; 
     723 
     724    unsigned submode; 
     725    unsigned nb_count = 0; 
     726 
     727    while (speex_bits_remaining(bits) >= 5) { 
     728        unsigned wb_count = 0; 
     729        unsigned bit_ptr = bits->bitPtr; 
     730        unsigned char_ptr = bits->charPtr; 
     731 
     732        /* WB frame */ 
     733        while ((speex_bits_remaining(bits) >= 4) 
     734            && speex_bits_unpack_unsigned(bits, 1)) 
     735        { 
     736            int advance; 
     737 
     738            submode = speex_bits_unpack_unsigned(bits, 3); 
     739            advance = wb_skip_table[submode]; 
     740            if (advance < 0) { 
     741                TRACE__((THIS_FUNC, "Invalid mode encountered. " 
     742                         "The stream is corrupted.")); 
     743                return -1; 
     744            }  
     745            TRACE__((THIS_FUNC, "WB layer skipped: %d bits", advance)); 
     746            advance -= (SB_SUBMODE_BITS+1); 
     747            speex_bits_advance(bits, advance); 
     748 
     749            bit_ptr = bits->bitPtr; 
     750            char_ptr = bits->charPtr; 
     751 
     752            /* Consecutive subband frames may not exceed 2 frames */ 
     753            if (++wb_count > 2) 
     754                return -1; 
     755        } 
     756 
     757        /* End of bits, return the frame */ 
     758        if (speex_bits_remaining(bits) < 4) { 
     759            TRACE__((THIS_FUNC, "End of stream")); 
     760            return 0; 
     761        } 
     762 
     763        /* Stop iteration, return the frame */ 
     764        if (nb_count > 0) { 
     765            bits->bitPtr = bit_ptr; 
     766            bits->charPtr = char_ptr; 
     767            return 0; 
     768        } 
     769 
     770        /* Get control bits */ 
     771        submode = speex_bits_unpack_unsigned(bits, 4); 
     772        TRACE__((THIS_FUNC, "Control bits: %d at %d",  
     773                 submode, bits->charPtr*8+bits->bitPtr)); 
     774 
     775        if (submode == 15) { 
     776            TRACE__((THIS_FUNC, "Found submode: terminator")); 
     777            return 0; 
     778        } else if (submode == 14) { 
     779            /* in-band signal; next 4 bits contain signal id */ 
     780            submode = speex_bits_unpack_unsigned(bits, 4); 
     781            TRACE__((THIS_FUNC, "Found submode: in-band %d bits",  
     782                     inband_skip_table[submode])); 
     783            speex_bits_advance(bits, inband_skip_table[submode]); 
     784        } else if (submode == 13) { 
     785            /* user in-band; next 5 bits contain msg len */ 
     786            submode = speex_bits_unpack_unsigned(bits, 5); 
     787            TRACE__((THIS_FUNC, "Found submode: user-band %d bytes", submode)); 
     788            speex_bits_advance(bits, submode * 8); 
     789        } else if (submode > 8) { 
     790            TRACE__((THIS_FUNC, "Unknown sub-mode %d", submode)); 
     791            return 0; 
     792        } else { 
     793            /* NB frame */ 
     794            unsigned int advance = submode; 
     795            speex_mode_query(&speex_nb_mode, SPEEX_SUBMODE_BITS_PER_FRAME, &advance); 
     796            if (advance < 0) { 
     797                TRACE__((THIS_FUNC, "Invalid mode encountered. " 
     798                         "The stream is corrupted.")); 
     799                return -1; 
     800            } 
     801            TRACE__((THIS_FUNC, "Submode %d: %d bits", submode, advance)); 
     802            advance -= (NB_SUBMODE_BITS+1); 
     803            speex_bits_advance(bits, advance); 
     804 
     805            ++nb_count; 
     806        } 
     807    } 
     808 
     809    return 0; 
    703810} 
    704811 
     
    714821                                     pjmedia_frame frames[]) 
    715822{ 
    716     struct spx_private *spx; 
    717     unsigned frame_size, samples_per_frame; 
    718     unsigned count; 
    719  
    720     spx = (struct spx_private*) codec->codec_data; 
    721  
    722     frame_size = spx_factory.speex_param[spx->param_id].framesize; 
    723     samples_per_frame = spx_factory.speex_param[spx->param_id].samples_per_frame; 
    724  
    725     /* Don't really know how to do this... */ 
    726     count = 0; 
    727     while (pkt_size >= frame_size && count < *frame_cnt) { 
    728         frames[count].buf = pkt; 
    729         frames[count].size = frame_size; 
     823    struct spx_private *spx = (struct spx_private*) codec->codec_data; 
     824    unsigned samples_per_frame; 
     825    unsigned count = 0; 
     826    int char_ptr = 0; 
     827    int bit_ptr = 0; 
     828 
     829    samples_per_frame=spx_factory.speex_param[spx->param_id].samples_per_frame; 
     830 
     831    /* Copy the data into the speex bit-stream */ 
     832    speex_bits_read_from(&spx->dec_bits, (char*)pkt, pkt_size); 
     833 
     834    while (speex_get_next_frame(&spx->dec_bits) == 0 &&  
     835           spx->dec_bits.charPtr != char_ptr) 
     836    { 
     837        frames[count].buf = (char*)pkt + char_ptr; 
     838        /* Bit info contains start bit offset of the frame */ 
     839        frames[count].bit_info = bit_ptr; 
    730840        frames[count].type = PJMEDIA_FRAME_TYPE_AUDIO; 
    731841        frames[count].timestamp.u64 = ts->u64 + count * samples_per_frame; 
    732  
    733         pkt_size -= frame_size; 
     842        frames[count].size = spx->dec_bits.charPtr - char_ptr; 
     843        if (spx->dec_bits.bitPtr) 
     844            ++frames[count].size; 
     845 
     846        bit_ptr = spx->dec_bits.bitPtr; 
     847        char_ptr = spx->dec_bits.charPtr; 
     848 
    734849        ++count; 
    735         pkt = ((char*)pkt) + frame_size; 
    736     } 
    737  
    738     /* Just in case speex has silence frame which size is less than normal 
    739      * frame size... 
    740      */ 
    741     if (pkt_size && count < *frame_cnt) { 
    742         frames[count].buf = pkt; 
    743         frames[count].size = pkt_size; 
    744         frames[count].type = PJMEDIA_FRAME_TYPE_AUDIO; 
    745         frames[count].timestamp.u64 = ts->u64 + count * samples_per_frame; 
    746         ++count; 
    747850    } 
    748851 
    749852    *frame_cnt = count; 
    750     return PJ_SUCCESS; 
    751 } 
    752  
    753 /* 
    754  * Encode frame. 
     853 
     854    return PJ_SUCCESS; 
     855} 
     856 
     857/* 
     858 * Encode frames. 
    755859 */ 
    756860static pj_status_t spx_codec_encode( pjmedia_codec *codec,  
     
    760864{ 
    761865    struct spx_private *spx; 
    762     unsigned sz; 
    763     int tx; 
     866    unsigned samples_per_frame; 
     867    int tx = 0; 
     868    spx_int16_t *pcm_in = (spx_int16_t*)input->buf; 
     869    unsigned nsamples; 
    764870 
    765871    spx = (struct spx_private*) codec->codec_data; 
     
    773879    } 
    774880 
     881    nsamples = input->size >> 1; 
     882    samples_per_frame=spx_factory.speex_param[spx->param_id].samples_per_frame; 
     883 
     884    PJ_ASSERT_RETURN(nsamples % samples_per_frame == 0,  
     885                     PJMEDIA_CODEC_EPCMFRMINLEN); 
     886 
    775887    /* Flush all the bits in the struct so we can encode a new frame */ 
    776888    speex_bits_reset(&spx->enc_bits); 
    777889 
    778     /* Encode the frame */ 
    779     tx = speex_encode_int(spx->enc, (spx_int16_t*)input->buf,  
    780                           &spx->enc_bits); 
     890    /* Encode the frames */ 
     891    while (nsamples >= samples_per_frame) { 
     892        tx += speex_encode_int(spx->enc, pcm_in, &spx->enc_bits); 
     893        pcm_in += samples_per_frame; 
     894        nsamples -= samples_per_frame; 
     895    } 
    781896 
    782897    /* Check if we need not to transmit the frame (DTX) */ 
     
    790905 
    791906    /* Check size. */ 
    792     sz = speex_bits_nbytes(&spx->enc_bits); 
    793     pj_assert(sz <= output_buf_len); 
     907    pj_assert(speex_bits_nbytes(&spx->enc_bits) <= (int)output_buf_len); 
    794908 
    795909    /* Copy the bits to an array of char that can be written */ 
     
    811925{ 
    812926    struct spx_private *spx; 
     927    unsigned samples_per_frame; 
    813928 
    814929    spx = (struct spx_private*) codec->codec_data; 
    815  
    816     PJ_ASSERT_RETURN(output_buf_len >= 320, PJMEDIA_CODEC_EPCMTOOSHORT); 
     930    samples_per_frame=spx_factory.speex_param[spx->param_id].samples_per_frame; 
     931 
     932    PJ_ASSERT_RETURN(output_buf_len >= samples_per_frame << 1, 
     933                     PJMEDIA_CODEC_EPCMTOOSHORT); 
    817934 
    818935    if (input->type != PJMEDIA_FRAME_TYPE_AUDIO) { 
    819         pjmedia_zero_samples((pj_int16_t*)output->buf, 160); 
    820         output->size = 320; 
     936        pjmedia_zero_samples((pj_int16_t*)output->buf, samples_per_frame); 
     937        output->size = samples_per_frame << 1; 
    821938        output->timestamp.u64 = input->timestamp.u64; 
    822939        output->type = PJMEDIA_FRAME_TYPE_AUDIO; 
     
    826943    /* Copy the data into the bit-stream struct */ 
    827944    speex_bits_read_from(&spx->dec_bits, (char*)input->buf, input->size); 
     945     
     946    /* Set Speex dec_bits pointer to the start bit of the frame */ 
     947    speex_bits_advance(&spx->dec_bits, input->bit_info); 
    828948 
    829949    /* Decode the data */ 
     
    831951 
    832952    output->type = PJMEDIA_FRAME_TYPE_AUDIO; 
    833     output->size = 320; 
     953    output->size = samples_per_frame << 1; 
    834954    output->timestamp.u64 = input->timestamp.u64; 
    835  
    836955 
    837956    return PJ_SUCCESS; 
  • pjproject/trunk/pjmedia/src/pjmedia/jbuf.c

    r1961 r1983  
    3939    int         *flist_frame_type; 
    4040    pj_size_t   *flist_content_len; 
     41    pj_uint32_t *flist_bit_info; 
    4142    unsigned     flist_frame_size; 
    4243    unsigned     flist_max_count; 
     
    109110                                framelist->flist_max_count); 
    110111 
     112    framelist->flist_bit_info = (pj_uint32_t*) 
     113        pj_pool_zalloc(pool, sizeof(framelist->flist_bit_info[0]) *  
     114                                framelist->flist_max_count); 
     115 
    111116    framelist->flist_empty = 1; 
    112117 
     
    135140static pj_bool_t jb_framelist_get(jb_framelist_t *framelist, 
    136141                                  void *frame, pj_size_t *size, 
    137                                   pjmedia_jb_frame_type *p_type)  
     142                                  pjmedia_jb_frame_type *p_type, 
     143                                  pj_uint32_t *bit_info)  
    138144{ 
    139145    if (!framelist->flist_empty) { 
     
    144150        *p_type = (pjmedia_jb_frame_type)  
    145151                  framelist->flist_frame_type[framelist->flist_head]; 
    146         *size   = framelist->flist_content_len[framelist->flist_head]; 
     152        if (size) 
     153            *size   = framelist->flist_content_len[framelist->flist_head]; 
     154        if (bit_info) 
     155            *bit_info = framelist->flist_bit_info[framelist->flist_head]; 
    147156 
    148157        pj_bzero(framelist->flist_buffer +  
     
    222231                                     unsigned index, 
    223232                                     const void *frame, 
    224                                      unsigned frame_size)  
     233                                     unsigned frame_size, 
     234                                     pj_uint32_t bit_info) 
    225235{ 
    226236    unsigned where; 
     
    264274    framelist->flist_frame_type[where] = PJMEDIA_JB_NORMAL_FRAME; 
    265275    framelist->flist_content_len[where] = frame_size; 
     276    framelist->flist_bit_info[where] = bit_info; 
    266277 
    267278    return PJ_TRUE; 
     
    479490                                     int frame_seq) 
    480491{ 
    481     pjmedia_jbuf_put_frame2(jb, frame, frame_size, frame_seq, NULL); 
     492    pjmedia_jbuf_put_frame2(jb, frame, frame_size, 0, frame_seq, NULL); 
    482493} 
    483494 
     
    485496                                     const void *frame,  
    486497                                     pj_size_t frame_size,  
     498                                     pj_uint32_t bit_info, 
    487499                                     int frame_seq, 
    488500                                     pj_bool_t *discarded) 
     
    509521    if (seq_diff > 0) { 
    510522 
    511         while (jb_framelist_put_at(&jb->jb_framelist, 
    512                                    frame_seq,frame,min_frame_size) == PJ_FALSE) 
     523        while (jb_framelist_put_at(&jb->jb_framelist, frame_seq, frame, 
     524                                   min_frame_size, bit_info) == PJ_FALSE) 
    513525        { 
    514526            jb_framelist_remove_head(&jb->jb_framelist, 
     
    526538        pj_bool_t res; 
    527539        res = jb_framelist_put_at(&jb->jb_framelist,frame_seq,frame, 
    528                                   min_frame_size); 
     540                                  min_frame_size, bit_info); 
    529541        if (discarded) 
    530542            *discarded = !res; 
     
    539551                                     char *p_frame_type) 
    540552{ 
    541     pj_size_t size; 
    542  
    543     pjmedia_jbuf_get_frame2(jb, frame, &size, p_frame_type); 
     553    pjmedia_jbuf_get_frame2(jb, frame, NULL, p_frame_type, NULL); 
    544554} 
    545555 
     
    550560                                     void *frame,  
    551561                                     pj_size_t *size, 
    552                                      char *p_frame_type) 
     562                                     char *p_frame_type, 
     563                                     pj_uint32_t *bit_info) 
    553564{ 
    554565    pjmedia_jb_frame_type ftype; 
     
    582593 
    583594    /* Retrieve a frame from frame list */ 
    584     if (jb_framelist_get(&jb->jb_framelist,frame,size,&ftype) == PJ_FALSE) { 
     595    if (jb_framelist_get(&jb->jb_framelist,frame,size,&ftype,bit_info) == 
     596        PJ_FALSE)  
     597    { 
    585598        /* Can't return frame because jitter buffer is empty! */ 
    586599        pj_bzero(frame, jb->jb_frame_size); 
  • pjproject/trunk/pjmedia/src/pjmedia/stream.c

    r1961 r1983  
    230230        char frame_type; 
    231231        pj_size_t frame_size; 
     232        pj_uint32_t bit_info; 
    232233 
    233234        /* Get frame from jitter buffer. */ 
    234235        pjmedia_jbuf_get_frame2(stream->jb, channel->out_pkt, &frame_size, 
    235                                 &frame_type); 
     236                                &frame_type, &bit_info); 
    236237         
    237238        if (frame_type == PJMEDIA_JB_MISSING_FRAME) { 
     
    365366            frame_in.buf = channel->out_pkt; 
    366367            frame_in.size = frame_size; 
     368            frame_in.bit_info = bit_info; 
    367369            frame_in.type = PJMEDIA_FRAME_TYPE_AUDIO;  /* ignored */ 
    368370 
     
    678680               frame->buf != NULL)  
    679681    { 
    680         unsigned ts, codec_samples_per_frame; 
    681  
    682         /* Repeatedly call encode if there are multiple frames to be 
    683          * sent. 
    684          */ 
    685         codec_samples_per_frame = stream->codec_param.info.enc_ptime * 
    686                                   stream->codec_param.info.clock_rate / 
    687                                   1000; 
    688         if (codec_samples_per_frame == 0) { 
    689             codec_samples_per_frame = stream->codec_param.info.frm_ptime * 
    690                                       stream->codec_param.info.clock_rate / 
    691                                       1000; 
    692         } 
    693  
    694         for (ts=0; ts<ts_len; ts += codec_samples_per_frame) { 
    695             pjmedia_frame tmp_out_frame, tmp_in_frame; 
    696             unsigned bytes_per_sample, max_size; 
    697  
    698             /* Nb of bytes in PCM sample */ 
    699             bytes_per_sample = stream->codec_param.info.pcm_bits_per_sample/8; 
    700  
    701             /* Split original PCM input frame into base frame size */ 
    702             tmp_in_frame.timestamp.u64 = frame->timestamp.u64 + ts; 
    703             tmp_in_frame.buf = ((char*)frame->buf) + ts * bytes_per_sample; 
    704             tmp_in_frame.size = codec_samples_per_frame * bytes_per_sample; 
    705             tmp_in_frame.type = PJMEDIA_FRAME_TYPE_AUDIO; 
    706  
    707             /* Set output frame position */ 
    708             tmp_out_frame.buf = ((char*)frame_out.buf) + frame_out.size; 
    709  
    710             max_size = channel->out_pkt_size - sizeof(pjmedia_rtp_hdr) - 
    711                        frame_out.size; 
    712  
    713             /* Encode! */ 
    714             status = stream->codec->op->encode( stream->codec, &tmp_in_frame,  
    715                                                 max_size, &tmp_out_frame); 
    716             if (status != PJ_SUCCESS) { 
    717                 LOGERR_((stream->port.info.name.ptr,  
    718                         "Codec encode() error", status)); 
    719                 return status; 
    720             } 
    721  
    722             /* tmp_out_frame.size may be zero for silence frame. */ 
    723             frame_out.size += tmp_out_frame.size; 
    724  
    725             /* Stop processing next PCM frame when encode() returns either  
    726              * CNG frame or NULL frame. 
    727              */ 
    728             if (tmp_out_frame.type!=PJMEDIA_FRAME_TYPE_AUDIO ||  
    729                 tmp_out_frame.size==0)  
    730             { 
    731                 break; 
    732             } 
    733  
     682        /* Encode! */ 
     683        status = stream->codec->op->encode( stream->codec, frame,  
     684                                            channel->out_pkt_size -  
     685                                            sizeof(pjmedia_rtp_hdr), 
     686                                            &frame_out); 
     687        if (status != PJ_SUCCESS) { 
     688            LOGERR_((stream->port.info.name.ptr,  
     689                    "Codec encode() error", status)); 
     690            return status; 
    734691        } 
    735692 
     
    12181175            ext_seq = (unsigned)(frames[i].timestamp.u64 / ts_span); 
    12191176            pjmedia_jbuf_put_frame2(stream->jb, frames[i].buf, frames[i].size, 
    1220                                     ext_seq, &discarded); 
     1177                                    frames[i].bit_info, ext_seq, &discarded); 
    12211178            if (discarded) 
    12221179                pkt_discarded = PJ_TRUE; 
Note: See TracChangeset for help on using the changeset viewer.