Changeset 2677


Ignore:
Timestamp:
May 6, 2009 3:44:12 PM (10 years ago)
Author:
nanang
Message:

Ticket #819:

  • Updated APS to supports for sampling rate 16kHz and stereo (using resample).
  • Fixed buffer len calculations in Symbian MDA.
  • Disabled multichannel support on Symbian MDA (since its input device doesn't support for stereo?).
Location:
pjproject/trunk/pjmedia/src/pjmedia-audiodev
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/src/pjmedia-audiodev/symb_aps_dev.cpp

    r2506 r2677  
    2121#include <pjmedia-audiodev/errno.h> 
    2222#include <pjmedia/alaw_ulaw.h> 
     23#include <pjmedia/resample.h> 
     24#include <pjmedia/stereo.h> 
    2325#include <pj/assert.h> 
    2426#include <pj/log.h> 
     
    8183 
    8284    // Common settings. 
    83     pjmedia_aud_param param;            /**< Stream param.      */ 
     85    pjmedia_aud_param    param;                 /**< Stream param.      */ 
    8486    pjmedia_aud_rec_cb   rec_cb;                /**< Record callback.   */ 
    8587    pjmedia_aud_play_cb  play_cb;               /**< Playback callback. */ 
     
    98100    pj_uint16_t          rec_buf_len;           /**< Record buffer length. */ 
    99101    void                *strm_data;             /**< Stream data.       */ 
     102 
     103    /* Resampling is needed, in case audio device is opened with clock rate  
     104     * other than 8kHz (only for PCM format). 
     105     */ 
     106    pjmedia_resample    *play_resample;         /**< Resampler for playback. */ 
     107    pjmedia_resample    *rec_resample;          /**< Resampler for recording */ 
     108    pj_uint16_t          resample_factor;       /**< Resample factor, requested 
     109                                                     clock rate / 8000       */ 
     110 
     111    /* When stream is working in PCM format, where the samples may need to be 
     112     * resampled from/to different clock rate and/or channel count, PCM buffer 
     113     * is needed to perform such resampling operations. 
     114     */ 
     115    pj_int16_t          *pcm_buf;               /**< PCM buffer.             */ 
    100116}; 
    101117 
     
    678694} 
    679695 
    680  
     696/**************************************************************************** 
     697 * Internal APS callbacks for PCM format 
     698 */ 
    681699 
    682700static void RecCbPcm(TAPSCommBuffer &buf, void *user_data) 
     
    699717     * Whenever rec_buf is full, call parent stream callback. 
    700718     */ 
    701     unsigned dec_len = 0; 
    702  
    703     while (dec_len < aps_g711_frame_len) { 
    704         unsigned tmp; 
    705  
    706         tmp = PJ_MIN(strm->param.samples_per_frame - strm->rec_buf_len, 
    707                      aps_g711_frame_len - dec_len); 
     719    unsigned samples_processed = 0; 
     720 
     721    while (samples_processed < aps_g711_frame_len) { 
     722        unsigned samples_to_process; 
     723        unsigned samples_req; 
     724 
     725        samples_to_process = aps_g711_frame_len - samples_processed; 
     726        samples_req = (strm->param.samples_per_frame / 
     727                       strm->param.channel_count / 
     728                       strm->resample_factor) - 
     729                      strm->rec_buf_len; 
     730        if (samples_to_process > samples_req) 
     731            samples_to_process = samples_req; 
     732 
    708733        pjmedia_ulaw_decode(&strm->rec_buf[strm->rec_buf_len], 
    709                             buf.iBuffer.Ptr() + 2 + dec_len, 
    710                             tmp); 
    711         strm->rec_buf_len += tmp; 
    712         dec_len += tmp; 
    713  
    714         pj_assert(strm->rec_buf_len <= strm->param.samples_per_frame); 
    715  
    716         if (strm->rec_buf_len == strm->param.samples_per_frame) { 
     734                            buf.iBuffer.Ptr() + 2 + samples_processed, 
     735                            samples_to_process); 
     736 
     737        strm->rec_buf_len += samples_to_process; 
     738        samples_processed += samples_to_process; 
     739 
     740        /* Buffer is full, time to call parent callback */ 
     741        if (strm->rec_buf_len == strm->param.samples_per_frame /  
     742                                 strm->param.channel_count / 
     743                                 strm->resample_factor)  
     744        { 
    717745            pjmedia_frame f; 
    718              
     746 
     747            /* Need to resample clock rate? */ 
     748            if (strm->rec_resample) { 
     749                unsigned resampled = 0; 
     750                 
     751                while (resampled < strm->rec_buf_len) { 
     752                    pjmedia_resample_run(strm->rec_resample,  
     753                                &strm->rec_buf[resampled], 
     754                                strm->pcm_buf +  
     755                                resampled * strm->resample_factor); 
     756                    resampled += 80; 
     757                } 
     758                f.buf = strm->pcm_buf; 
     759            } else { 
     760                f.buf = strm->rec_buf; 
     761            } 
     762 
     763            /* Need to convert channel count? */ 
     764            if (strm->param.channel_count != 1) { 
     765                pjmedia_convert_channel_1ton((pj_int16_t*)f.buf, 
     766                                             (pj_int16_t*)f.buf, 
     767                                             strm->param.channel_count, 
     768                                             strm->param.samples_per_frame / 
     769                                             strm->param.channel_count, 
     770                                             0); 
     771            } 
     772 
     773            /* Call parent callback */ 
    719774            f.type = PJMEDIA_FRAME_TYPE_AUDIO; 
    720             f.buf = strm->rec_buf; 
    721             f.size = strm->rec_buf_len << 1; 
    722              
     775            f.size = strm->param.samples_per_frame << 1; 
    723776            strm->rec_cb(strm->user_data, &f); 
    724777            strm->rec_buf_len = 0; 
     
    746799     * encode the PCM samples into G.711 and put it into APS buffer. 
    747800     */ 
    748     unsigned enc_len = 0; 
    749     while (enc_len < g711_frame_len) { 
     801    unsigned samples_processed = 0; 
     802     
     803    while (samples_processed < g711_frame_len) { 
     804        /* Need more samples to play, time to call parent callback */ 
    750805        if (strm->play_buf_len == 0) { 
    751806            pjmedia_frame f; 
    752              
    753             f.buf = strm->play_buf; 
     807            unsigned samples_got; 
     808             
    754809            f.size = strm->param.samples_per_frame << 1; 
    755              
     810            if (strm->play_resample || strm->param.channel_count != 1) 
     811                f.buf = strm->pcm_buf; 
     812            else 
     813                f.buf = strm->play_buf; 
     814 
     815            /* Call parent callback */ 
    756816            strm->play_cb(strm->user_data, &f); 
    757817            if (f.type != PJMEDIA_FRAME_TYPE_AUDIO) { 
    758                 pjmedia_zero_samples(strm->play_buf,  
     818                pjmedia_zero_samples((pj_int16_t*)f.buf,  
    759819                                     strm->param.samples_per_frame); 
    760820            } 
    761821             
    762             strm->play_buf_len = strm->param.samples_per_frame; 
     822            samples_got = strm->param.samples_per_frame /  
     823                          strm->param.channel_count / 
     824                          strm->resample_factor; 
     825 
     826            /* Need to convert channel count? */ 
     827            if (strm->param.channel_count != 1) { 
     828                pjmedia_convert_channel_nto1((pj_int16_t*)f.buf, 
     829                                             (pj_int16_t*)f.buf, 
     830                                             strm->param.channel_count, 
     831                                             strm->param.samples_per_frame, 
     832                                             PJ_FALSE, 
     833                                             0); 
     834            } 
     835 
     836            /* Need to resample clock rate? */ 
     837            if (strm->play_resample) { 
     838                unsigned resampled = 0; 
     839                 
     840                while (resampled < samples_got)  
     841                { 
     842                    pjmedia_resample_run(strm->play_resample,  
     843                                strm->pcm_buf +  
     844                                resampled * strm->resample_factor, 
     845                                &strm->play_buf[resampled]); 
     846                    resampled += 80; 
     847                } 
     848            } 
     849             
     850            strm->play_buf_len = samples_got; 
    763851            strm->play_buf_start = 0; 
    764852        } 
     
    766854        unsigned tmp; 
    767855 
    768         tmp = PJ_MIN(strm->play_buf_len, g711_frame_len - enc_len); 
     856        tmp = PJ_MIN(strm->play_buf_len, g711_frame_len - samples_processed); 
    769857        pjmedia_ulaw_encode((pj_uint8_t*)&strm->play_buf[strm->play_buf_start], 
    770858                            &strm->play_buf[strm->play_buf_start], 
    771859                            tmp); 
    772860        buf.iBuffer.Append((TUint8*)&strm->play_buf[strm->play_buf_start], tmp); 
    773         enc_len += tmp; 
     861        samples_processed += tmp; 
    774862        strm->play_buf_len -= tmp; 
    775863        strm->play_buf_start += tmp; 
     
    778866 
    779867/**************************************************************************** 
    780  * Internal APS callbacks 
     868 * Internal APS callbacks for non-PCM format 
    781869 */ 
    782870 
     
    12631351    PJ_ASSERT_RETURN(param->bits_per_sample == BITS_PER_SAMPLE, PJ_EINVAL); 
    12641352 
     1353    /* Supported clock rates: 
     1354     * - for non-PCM format: 8kHz   
     1355     * - for PCM format: 8kHz and 16kHz   
     1356     */ 
     1357    PJ_ASSERT_RETURN(param->clock_rate == 8000 || 
     1358                     (param->clock_rate == 16000 &&  
     1359                      param->ext_fmt.id == PJMEDIA_FORMAT_L16), 
     1360                     PJ_EINVAL); 
     1361 
     1362    /* Supported channels number: 
     1363     * - for non-PCM format: mono 
     1364     * - for PCM format: mono and stereo   
     1365     */ 
     1366    PJ_ASSERT_RETURN(param->channel_count == 1 ||  
     1367                     (param->channel_count == 2 && 
     1368                      param->ext_fmt.id == PJMEDIA_FORMAT_L16), 
     1369                     PJ_EINVAL); 
     1370 
    12651371    /* Create and Initialize stream descriptor */ 
    12661372    pool = pj_pool_create(af->pf, "aps-dev", 1000, 1000, NULL); 
     
    13421448    } 
    13431449 
     1450    strm->rec_cb = rec_cb; 
     1451    strm->play_cb = play_cb; 
     1452    strm->user_data = user_data; 
     1453    strm->resample_factor = strm->param.clock_rate / 8000; 
     1454 
     1455    /* play_buf size is samples per frame scaled in to 8kHz mono. */ 
     1456    strm->play_buf = (pj_int16_t*)pj_pool_zalloc( 
     1457                                        pool,  
     1458                                        (strm->param.samples_per_frame /  
     1459                                        strm->resample_factor / 
     1460                                        strm->param.channel_count) << 1); 
     1461    strm->play_buf_len = 0; 
     1462    strm->play_buf_start = 0; 
     1463 
     1464    /* rec_buf size is samples per frame scaled in to 8kHz mono. */ 
     1465    strm->rec_buf  = (pj_int16_t*)pj_pool_zalloc( 
     1466                                        pool,  
     1467                                        (strm->param.samples_per_frame /  
     1468                                        strm->resample_factor / 
     1469                                        strm->param.channel_count) << 1); 
     1470    strm->rec_buf_len = 0; 
     1471 
     1472    if (strm->param.ext_fmt.id == PJMEDIA_FORMAT_G729) { 
     1473        TBitStream *g729_bitstream = new TBitStream; 
     1474         
     1475        PJ_ASSERT_RETURN(g729_bitstream, PJ_ENOMEM); 
     1476        strm->strm_data = (void*)g729_bitstream; 
     1477    } 
     1478         
     1479    /* Init resampler when format is PCM and clock rate is not 8kHz */ 
     1480    if (strm->param.clock_rate != 8000 &&  
     1481        strm->param.ext_fmt.id == PJMEDIA_FORMAT_L16) 
     1482    { 
     1483        pj_status_t status; 
     1484         
     1485        if (strm->param.dir & PJMEDIA_DIR_CAPTURE) { 
     1486            /* Create resample for recorder */ 
     1487            status = pjmedia_resample_create( pool, PJ_TRUE, PJ_FALSE, 1,  
     1488                                              8000, 
     1489                                              strm->param.clock_rate, 
     1490                                              80, 
     1491                                              &strm->rec_resample); 
     1492            if (status != PJ_SUCCESS) 
     1493                return status; 
     1494        } 
     1495     
     1496        if (strm->param.dir & PJMEDIA_DIR_PLAYBACK) { 
     1497            /* Create resample for player */ 
     1498            status = pjmedia_resample_create( pool, PJ_TRUE, PJ_FALSE, 1,  
     1499                                              strm->param.clock_rate, 
     1500                                              8000, 
     1501                                              80 * strm->resample_factor, 
     1502                                              &strm->play_resample); 
     1503            if (status != PJ_SUCCESS) 
     1504                return status; 
     1505        } 
     1506    } 
     1507 
     1508    /* Create PCM buffer, when the clock rate is not 8kHz or not mono */ 
     1509    if (strm->param.ext_fmt.id == PJMEDIA_FORMAT_L16 && 
     1510        (strm->resample_factor > 1 || strm->param.channel_count != 1))  
     1511    { 
     1512        strm->pcm_buf = (pj_int16_t*)pj_pool_zalloc(pool,  
     1513                                        strm->param.samples_per_frame << 1); 
     1514    } 
     1515 
     1516     
    13441517    /* Create the audio engine. */ 
    13451518    TRAPD(err, strm->engine = CPjAudioEngine::NewL(strm, 
     
    13571530    } 
    13581531 
    1359     strm->rec_cb = rec_cb; 
    1360     strm->play_cb = play_cb; 
    1361     strm->user_data = user_data; 
    1362  
    1363     /* play_buf size is samples per frame. */ 
    1364     strm->play_buf = (pj_int16_t*)pj_pool_zalloc(pool,  
    1365                                         strm->param.samples_per_frame << 1); 
    1366     strm->play_buf_len = 0; 
    1367     strm->play_buf_start = 0; 
    1368  
    1369     /* rec_buf size is samples per frame. */ 
    1370     strm->rec_buf  = (pj_int16_t*)pj_pool_zalloc(pool,  
    1371                                         strm->param.samples_per_frame << 1); 
    1372     strm->rec_buf_len = 0; 
    1373  
    1374     if (strm->param.ext_fmt.id == PJMEDIA_FORMAT_G729) { 
    1375         TBitStream *g729_bitstream = new TBitStream; 
    1376          
    1377         PJ_ASSERT_RETURN(g729_bitstream, PJ_ENOMEM); 
    1378         strm->strm_data = (void*)g729_bitstream; 
    1379     } 
    1380          
    13811532    /* Done */ 
    13821533    strm->base.op = &stream_op; 
  • pjproject/trunk/pjmedia/src/pjmedia-audiodev/symb_mda_dev.cpp

    r2668 r2677  
    271271      lastError_(KErrNone), timeStamp_(0), 
    272272      frameLen_(parent_strm->param.samples_per_frame *  
    273                 parent_strm->param.channel_count *  
    274273                BYTES_PER_SAMPLE), 
    275274      frameRecBuf_(NULL), frameRecBufLen_(0) 
     
    426425    } 
    427426 
    428     if (frameRecBufLen_ || aBuffer.Size() < frameLen_) { 
    429         pj_memcpy(frameRecBuf_ + frameRecBufLen_, (void*) aBuffer.Ptr(), aBuffer.Size()); 
    430         frameRecBufLen_ += aBuffer.Size(); 
     427    if (frameRecBufLen_ || aBuffer.Length() < frameLen_) { 
     428        pj_memcpy(frameRecBuf_ + frameRecBufLen_, (void*) aBuffer.Ptr(), aBuffer.Length()); 
     429        frameRecBufLen_ += aBuffer.Length(); 
    431430    } 
    432431 
     
    454453        f.type = PJMEDIA_FRAME_TYPE_AUDIO; 
    455454        f.buf = (void*)aBuffer.Ptr(); 
    456         f.size = aBuffer.Size(); 
     455        f.size = aBuffer.Length(); 
    457456        f.timestamp.u32.lo = timeStamp_; 
    458457        f.bit_info = 0; 
     
    572571{ 
    573572    frameBufSize_ = parentStrm_->param.samples_per_frame * 
    574                     parentStrm_->param.channel_count *  
    575573                    BYTES_PER_SAMPLE; 
    576574    frameBuf_ = new TUint8[frameBufSize_]; 
     
    898896                     param->ext_fmt.id == PJMEDIA_FORMAT_L16, 
    899897                     PJ_ENOTSUP); 
     898     
     899    /* It seems that MDA recorder only supports for mono channel. */ 
     900    PJ_ASSERT_RETURN(param->channel_count == 1, PJ_EINVAL); 
    900901 
    901902    /* Create and Initialize stream descriptor */ 
Note: See TracChangeset for help on using the changeset viewer.