Ignore:
Timestamp:
Feb 5, 2009 10:59:14 AM (12 years ago)
Author:
nanang
Message:
  • Added new API for sound & sound port to create/open sound device with extended setting, to allow opening sound device with non-PCM format and other settings.
  • Updated symbian_ua/ua.cpp to be able to reopen sound device when audio stream session is using non-PCM data/passthrough codec.
  • Updated stream.c to allow it works with non-PCM data.
  • Added PCMU/A frames processing into non-PCM play/record callbacks in symbian_audio_aps.cpp.
  • Added passthrough codec init/deinitialization in pjsua-lib.
  • Added a new pjmedia_frame_ext helper function, pjmedia_frame_ext_pop_subframes, to pop-out/remove some subframes.
  • Other minor updates/fixes.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/branches/projects/aps-direct/pjmedia/src/pjmedia/symbian_sound_aps.cpp

    r2434 r2438  
    1818 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA  
    1919 */ 
     20#include <pjmedia/sound.h> 
    2021#include <pjmedia/symbian_sound_aps.h> 
    21 #include <pjmedia/sound.h> 
    2222#include <pjmedia/alaw_ulaw.h> 
    2323#include <pjmedia/errno.h> 
     24#include <pjmedia/port.h> 
    2425#include <pj/assert.h> 
    2526#include <pj/log.h> 
     
    5960/* App UID to open global APS queues to communicate with the APS server. */ 
    6061extern TPtrC                APP_UID; 
    61  
    62 /* Default setting */ 
    63 static pjmedia_snd_aps_setting def_setting; 
    6462 
    6563/* APS G.711 frame length */ 
     
    8886    pjmedia_snd_play_cb  play_cb; 
    8987    void                *user_data; 
     88    pjmedia_snd_setting  setting; 
    9089 
    9190    // Audio engine 
     
    405404    // the client session. 
    406405    TTime start, now; 
    407     enum { APS_CLOSE_WAIT_TIME = 200 }; 
     406    enum { APS_CLOSE_WAIT_TIME = 200 }; /* in msecs */ 
     407     
    408408    start.UniversalTime(); 
    409     now.UniversalTime(); 
    410     while (now.MicroSecondsFrom(start) < APS_CLOSE_WAIT_TIME * 1000) { 
     409    do { 
    411410        pj_symbianos_poll(-1, APS_CLOSE_WAIT_TIME); 
    412411        now.UniversalTime(); 
    413     } 
     412    } while (now.MicroSecondsFrom(start) < APS_CLOSE_WAIT_TIME * 1000); 
    414413 
    415414    iSession.Close(); 
     
    618617    pjmedia_snd_stream *strm = (pjmedia_snd_stream*) user_data; 
    619618 
     619    /* Buffer has to contain normal speech. */ 
    620620    pj_assert(buf.iBuffer[0] == 1 && buf.iBuffer[1] == 0); 
    621621 
     
    660660    unsigned g711_frame_len = aps_g711_frame_len; 
    661661 
     662    /* Init buffer attributes and header. */ 
    662663    buf.iCommand = CQueueHandler::EAPSPlayData; 
    663664    buf.iStatus = 0; 
     
    697698static void RecCb(TAPSCommBuffer &buf, void *user_data) 
    698699{ 
     700    pjmedia_snd_stream *strm = (pjmedia_snd_stream*) user_data; 
     701    pjmedia_frame_ext *frame = (pjmedia_frame_ext*) strm->rec_buf; 
     702    unsigned samples_processed = 0; 
     703 
     704    switch(strm->setting.format.u32) { 
     705     
     706    case PJMEDIA_FOURCC_G711U: 
     707    case PJMEDIA_FOURCC_G711A: 
     708        pj_assert(buf.iBuffer[0] == 1 && buf.iBuffer[1] == 0); 
     709 
     710        /* Detect the recorder G.711 frame size, player frame size will follow 
     711         * this recorder frame size. 
     712         */ 
     713        if (aps_g711_frame_len == 0) { 
     714            aps_g711_frame_len = buf.iBuffer.Length() < 160? 80 : 160; 
     715            TRACE_((THIS_FILE, "Detected APS G.711 frame size = %u samples", 
     716                    aps_g711_frame_len)); 
     717        } 
     718         
     719        /* Convert APS buffer format into pjmedia_frame_ext. Whenever  
     720         * samples count in the frame is equal to stream's samples per frame, 
     721         * call parent stream callback. 
     722         */ 
     723        while (samples_processed < aps_g711_frame_len) { 
     724            unsigned tmp; 
     725            const pj_uint8_t *pb = (const pj_uint8_t*)buf.iBuffer.Ptr() + 2 + 
     726                                   samples_processed; 
     727 
     728            tmp = PJ_MIN(strm->samples_per_frame - frame->samples_cnt, 
     729                         aps_g711_frame_len - samples_processed); 
     730             
     731            pjmedia_frame_ext_append_subframe(frame, pb, tmp << 3, tmp); 
     732            samples_processed += tmp; 
     733 
     734            if (frame->samples_cnt == strm->samples_per_frame) { 
     735                frame->base.type = PJMEDIA_FRAME_TYPE_EXTENDED; 
     736                strm->rec_cb(strm->user_data, 0, strm->rec_buf, 0); 
     737                frame->samples_cnt = 0; 
     738                frame->subframe_cnt = 0; 
     739            } 
     740        } 
     741        break; 
     742         
     743    default: 
     744        break; 
     745    } 
    699746} 
    700747 
    701748static void PlayCb(TAPSCommBuffer &buf, void *user_data) 
    702749{ 
     750    pjmedia_snd_stream *strm = (pjmedia_snd_stream*) user_data; 
     751    pjmedia_frame_ext *frame = (pjmedia_frame_ext*) strm->play_buf; 
     752    unsigned g711_frame_len = aps_g711_frame_len; 
     753    unsigned samples_ready = 0; 
     754 
     755    /* Init buffer attributes and header. */ 
     756    buf.iCommand = CQueueHandler::EAPSPlayData; 
     757    buf.iStatus = 0; 
     758    buf.iBuffer.Zero(); 
     759 
     760    switch(strm->setting.format.u32) { 
     761     
     762    case PJMEDIA_FOURCC_G711U: 
     763    case PJMEDIA_FOURCC_G711A: 
     764        /* Add header. */ 
     765        buf.iBuffer.Append(1); 
     766        buf.iBuffer.Append(0); 
     767 
     768        /* Assume frame size is 10ms if frame size hasn't been known. */ 
     769        if (g711_frame_len == 0) 
     770            g711_frame_len = 80; 
     771         
     772        /* Call parent stream callback to get samples to play. */ 
     773        while (samples_ready < g711_frame_len) { 
     774            if (frame->samples_cnt == 0) { 
     775                frame->base.type = PJMEDIA_FRAME_TYPE_EXTENDED; 
     776                strm->play_cb(strm->user_data, 0, strm->play_buf, 
     777                              strm->samples_per_frame<<1); 
     778                 
     779                pj_assert(frame->base.type == PJMEDIA_FRAME_TYPE_EXTENDED || 
     780                          frame->base.type == PJMEDIA_FRAME_TYPE_NONE); 
     781            } 
     782 
     783            if (frame->base.type == PJMEDIA_FRAME_TYPE_EXTENDED) {  
     784                pjmedia_frame_ext_subframe *sf; 
     785                unsigned samples_cnt; 
     786                 
     787                sf = pjmedia_frame_ext_get_subframe(frame, 0); 
     788                samples_cnt = frame->samples_cnt / frame->subframe_cnt; 
     789                if (sf->data && sf->bitlen) 
     790                    buf.iBuffer.Append((TUint8*)sf->data, sf->bitlen>>3); 
     791                else  
     792                    buf.iBuffer.AppendFill(0, samples_cnt); 
     793                samples_ready += samples_cnt; 
     794                 
     795                pjmedia_frame_ext_pop_subframes(frame, 1); 
     796             
     797            } else { /* PJMEDIA_FRAME_TYPE_NONE */ 
     798                buf.iBuffer.AppendFill(0, g711_frame_len - samples_ready); 
     799                samples_ready = g711_frame_len; 
     800                frame->samples_cnt = 0; 
     801                frame->subframe_cnt = 0; 
     802            } 
     803        } 
     804        break; 
     805         
     806    default: 
     807        break; 
     808    } 
     809     
     810    unsigned tes = buf.iBuffer.Length(); 
    703811} 
    704812 
     
    709817{ 
    710818    snd_pool_factory = factory; 
    711  
    712     def_setting.format.u32 = PJMEDIA_FOURCC_L16; 
    713     def_setting.mode = 0; 
    714     def_setting.bitrate = 128000; 
    715     def_setting.plc = PJ_FALSE; 
    716     def_setting.vad = PJ_FALSE; 
    717     def_setting.cng = PJ_FALSE; 
    718     def_setting.loudspk = PJ_FALSE; 
    719819 
    720820    return PJ_SUCCESS; 
     
    751851                              pjmedia_snd_play_cb play_cb, 
    752852                              void *user_data, 
     853                              const pjmedia_snd_setting *setting, 
    753854                              pjmedia_snd_stream **p_snd_strm) 
    754855{ 
    755856    pj_pool_t *pool; 
    756857    pjmedia_snd_stream *strm; 
    757     CPjAudioSetting setting; 
     858    CPjAudioSetting aps_setting; 
    758859    PjAudioCallback aps_rec_cb; 
    759860    PjAudioCallback aps_play_cb; 
     
    779880    strm->channel_count = channel_count; 
    780881    strm->samples_per_frame = samples_per_frame; 
     882    strm->setting = *setting; 
     883 
     884    if (strm->setting.format.u32 == 0) 
     885        strm->setting.format.u32 = PJMEDIA_FOURCC_L16; 
    781886 
    782887    /* Set audio engine settings. */ 
    783     if (def_setting.format.u32 == PJMEDIA_FOURCC_G711U || 
    784         def_setting.format.u32 == PJMEDIA_FOURCC_L16) 
     888    if (strm->setting.format.u32 == PJMEDIA_FOURCC_G711U || 
     889        strm->setting.format.u32 == PJMEDIA_FOURCC_L16) 
    785890    { 
    786         setting.fourcc = TFourCC(KMCPFourCCIdG711); 
     891        aps_setting.fourcc = TFourCC(KMCPFourCCIdG711); 
    787892    } else { 
    788         setting.fourcc = TFourCC(def_setting.format.u32); 
    789     } 
    790  
    791     if (def_setting.format.u32 == PJMEDIA_FOURCC_AMR) 
     893        aps_setting.fourcc = TFourCC(strm->setting.format.u32); 
     894    } 
     895 
     896    if (strm->setting.format.u32 == PJMEDIA_FOURCC_AMR) 
    792897    { 
    793         setting.mode = (TAPSCodecMode)def_setting.bitrate; 
    794     } else if (def_setting.format.u32 == PJMEDIA_FOURCC_G711U || 
    795                def_setting.format.u32 == PJMEDIA_FOURCC_L16   || 
    796               (def_setting.format.u32 == PJMEDIA_FOURCC_ILBC  && 
    797                def_setting.mode == 30)) 
     898        aps_setting.mode = (TAPSCodecMode)strm->setting.bitrate; 
     899    } else if (strm->setting.format.u32 == PJMEDIA_FOURCC_G711U || 
     900               strm->setting.format.u32 == PJMEDIA_FOURCC_L16   || 
     901              (strm->setting.format.u32 == PJMEDIA_FOURCC_ILBC  && 
     902               strm->setting.mode == 30)) 
    798903    { 
    799         setting.mode = EULawOr30ms; 
     904        aps_setting.mode = EULawOr30ms; 
    800905    } else { 
    801         setting.mode = EALawOr20ms; 
    802     } 
    803  
    804     setting.vad = def_setting.vad; 
    805     setting.plc = def_setting.plc; 
    806     setting.cng = def_setting.cng; 
    807     setting.loudspk = def_setting.loudspk; 
    808  
    809     if (def_setting.format.u32 == PJMEDIA_FOURCC_AMR || 
    810         def_setting.format.u32 == PJMEDIA_FOURCC_G711A || 
    811         def_setting.format.u32 == PJMEDIA_FOURCC_G711U || 
    812         def_setting.format.u32 == PJMEDIA_FOURCC_G729 || 
    813         def_setting.format.u32 == PJMEDIA_FOURCC_ILBC) 
    814     { 
     906        aps_setting.mode = EALawOr20ms; 
     907    } 
     908 
     909    aps_setting.vad = strm->setting.format.u32==PJMEDIA_FOURCC_L16?  
     910                                        EFalse : strm->setting.vad; 
     911    aps_setting.plc = strm->setting.plc; 
     912    aps_setting.cng = strm->setting.cng; 
     913    aps_setting.loudspk = strm->setting.loudspk; 
     914 
     915    if (strm->setting.format.u32 == PJMEDIA_FOURCC_L16) { 
     916        aps_play_cb = &PlayCbPcm; 
     917        aps_rec_cb  = &RecCbPcm; 
     918    } else { 
    815919        aps_play_cb = &PlayCb; 
    816920        aps_rec_cb  = &RecCb; 
    817     } else { 
    818         aps_play_cb = &PlayCbPcm; 
    819         aps_rec_cb  = &RecCbPcm; 
    820921    } 
    821922 
     
    823924    TRAPD(err, strm->engine = CPjAudioEngine::NewL(strm, 
    824925                                                   aps_rec_cb, aps_play_cb, 
    825                                                    strm, setting)); 
     926                                                   strm, aps_setting)); 
    826927    if (err != KErrNone) { 
    827928        pj_pool_release(pool); 
     
    834935 
    835936    /* play_buf size is samples per frame. */ 
    836     strm->play_buf = (pj_int16_t*)pj_pool_alloc(pool, samples_per_frame << 1); 
     937    strm->play_buf = (pj_int16_t*)pj_pool_zalloc(pool, samples_per_frame << 1); 
    837938    strm->play_buf_len = 0; 
    838939    strm->play_buf_start = 0; 
    839940 
    840941    /* rec_buf size is samples per frame. */ 
    841     strm->rec_buf  = (pj_int16_t*)pj_pool_alloc(pool, samples_per_frame << 1); 
     942    strm->rec_buf  = (pj_int16_t*)pj_pool_zalloc(pool, samples_per_frame << 1); 
    842943    strm->rec_buf_len = 0; 
    843944 
     
    861962                                          pjmedia_snd_stream **p_snd_strm) 
    862963{ 
     964    pjmedia_snd_setting setting; 
     965     
    863966    if (index < 0) index = 0; 
    864967    PJ_ASSERT_RETURN(index == 0, PJ_EINVAL); 
    865968 
     969    pj_bzero(&setting, sizeof(setting)); 
     970    setting.format.u32 = PJMEDIA_FOURCC_L16; 
     971    setting.bitrate = 128000; 
     972     
    866973    return sound_open(PJMEDIA_DIR_CAPTURE, clock_rate, channel_count, 
    867974                      samples_per_frame, bits_per_sample, rec_cb, NULL, 
    868                       user_data, p_snd_strm); 
     975                      user_data, &setting, p_snd_strm); 
    869976} 
    870977 
     
    878985                                        pjmedia_snd_stream **p_snd_strm ) 
    879986{ 
     987    pjmedia_snd_setting setting; 
     988     
    880989    if (index < 0) index = 0; 
    881990    PJ_ASSERT_RETURN(index == 0, PJ_EINVAL); 
    882991 
     992    pj_bzero(&setting, sizeof(setting)); 
     993    setting.format.u32 = PJMEDIA_FOURCC_L16; 
     994    setting.bitrate = 128000; 
     995 
    883996    return sound_open(PJMEDIA_DIR_PLAYBACK, clock_rate, channel_count, 
    884997                      samples_per_frame, bits_per_sample, NULL, play_cb, 
    885                       user_data, p_snd_strm); 
     998                      user_data, &setting, p_snd_strm); 
    886999} 
    8871000 
     
    8971010                                      pjmedia_snd_stream **p_snd_strm) 
    8981011{ 
     1012    pjmedia_snd_setting setting; 
     1013 
    8991014    if (rec_id < 0) rec_id = 0; 
    9001015    if (play_id < 0) play_id = 0; 
    9011016    PJ_ASSERT_RETURN(play_id == 0 && rec_id == 0, PJ_EINVAL); 
    9021017 
     1018    pj_bzero(&setting, sizeof(setting)); 
     1019    setting.format.u32 = PJMEDIA_FOURCC_L16; 
     1020    setting.bitrate = 128000; 
     1021 
    9031022    return sound_open(PJMEDIA_DIR_CAPTURE_PLAYBACK, clock_rate, channel_count, 
    9041023                      samples_per_frame, bits_per_sample, rec_cb, play_cb, 
    905                       user_data, p_snd_strm); 
     1024                      user_data, &setting, p_snd_strm); 
     1025} 
     1026 
     1027PJ_DEF(pj_status_t) pjmedia_snd_open2( pjmedia_dir dir, 
     1028                                       int rec_id, 
     1029                                       int play_id, 
     1030                                       unsigned clock_rate, 
     1031                                       unsigned channel_count, 
     1032                                       unsigned samples_per_frame, 
     1033                                       unsigned bits_per_sample, 
     1034                                       pjmedia_snd_rec_cb rec_cb, 
     1035                                       pjmedia_snd_play_cb play_cb, 
     1036                                       void *user_data, 
     1037                                       const pjmedia_snd_setting *setting, 
     1038                                       pjmedia_snd_stream **p_snd_strm) 
     1039{ 
     1040    if (rec_id < 0) rec_id = 0; 
     1041    if (play_id < 0) play_id = 0; 
     1042    PJ_ASSERT_RETURN(play_id == 0 && rec_id == 0, PJ_EINVAL); 
     1043 
     1044    return sound_open(dir, clock_rate, channel_count, 
     1045                      samples_per_frame, bits_per_sample, rec_cb, play_cb, 
     1046                      user_data, setting, p_snd_strm); 
    9061047} 
    9071048 
     
    9941135} 
    9951136 
    996  
    9971137/* 
    9981138 * Activate/deactivate loudspeaker. 
     
    10021142                                        pj_bool_t active) 
    10031143{ 
    1004     if (stream == NULL) { 
    1005         def_setting.loudspk = active; 
    1006     } else { 
    1007         if (stream->engine == NULL) 
    1008             return PJ_EINVAL; 
    1009  
    1010         TInt err = stream->engine->ActivateSpeaker(active); 
    1011         if (err != KErrNone) 
    1012             return PJ_RETURN_OS_ERROR(err); 
    1013     } 
     1144    PJ_ASSERT_RETURN(stream && stream->engine, PJ_EINVAL); 
     1145     
     1146    TInt err = stream->engine->ActivateSpeaker(active); 
     1147    if (err != KErrNone) 
     1148        return PJ_RETURN_OS_ERROR(err); 
    10141149 
    10151150    return PJ_SUCCESS; 
    10161151} 
    10171152 
    1018 /** 
    1019  * Set a codec and its settings to be used on the next sound device session. 
    1020  */ 
    1021 PJ_DEF(pj_status_t) pjmedia_snd_aps_modify_setting( 
    1022                                     const pjmedia_snd_aps_setting *setting) 
    1023 { 
    1024     PJ_ASSERT_RETURN(setting, PJ_EINVAL); 
    1025  
    1026     def_setting = *setting; 
    1027  
    1028     return PJ_SUCCESS; 
    1029 } 
    1030  
    10311153#endif // PJMEDIA_SOUND_IMPLEMENTATION == PJMEDIA_SOUND_SYMB_APS_SOUND 
Note: See TracChangeset for help on using the changeset viewer.