Changeset 4215


Ignore:
Timestamp:
Jul 26, 2012 3:31:55 AM (8 years ago)
Author:
ming
Message:

Re #1518: Add Android configuration interface and volume capability

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/branches/projects/android/pjmedia/src/pjmedia-audiodev/opensl_dev.c

    r4193 r4215  
    3535#include <SLES/OpenSLES.h> 
    3636#include <SLES/OpenSLES_Android.h> 
     37#include <sys/system_properties.h> 
     38#include <android/api-level.h> 
    3739 
    3840#define THIS_FILE       "opensl_dev.c" 
     
    7072    pjmedia_aud_play_cb play_cb; 
    7173 
     74    pj_timestamp        play_timestamp; 
     75    pj_timestamp        rec_timestamp; 
     76     
    7277    pj_bool_t           rec_thread_initialized; 
    7378    pj_thread_desc      rec_thread_desc; 
     
    8186    SLObjectItf         playerObj; 
    8287    SLPlayItf           playerPlay; 
     88    SLVolumeItf         playerVol; 
    8389    unsigned            playerBufferSize; 
    8490    char               *playerBuffer[NUM_BUFFERS]; 
     
    174180        frame.buf = buf = stream->playerBuffer[stream->playerBufIdx++]; 
    175181        frame.size = stream->playerBufferSize; 
     182        frame.timestamp.u64 = stream->play_timestamp.u64; 
    176183        frame.bit_info = 0; 
    177184         
     
    179186        if (status != PJ_SUCCESS || frame.type != PJMEDIA_FRAME_TYPE_AUDIO) 
    180187            pj_bzero(buf, stream->playerBufferSize); 
     188         
     189        stream->play_timestamp.u64 += stream->param.samples_per_frame / 
     190                                      stream->param.channel_count; 
    181191         
    182192        result = (*bq)->Enqueue(bq, buf, stream->playerBufferSize); 
     
    216226        frame.buf = buf = stream->recordBuffer[stream->recordBufIdx++]; 
    217227        frame.size = stream->recordBufferSize; 
    218         frame.timestamp.u64 = 0; 
     228        frame.timestamp.u64 = stream->rec_timestamp.u64; 
    219229        frame.bit_info = 0; 
    220230         
    221231        status = (*stream->rec_cb)(stream->user_data, &frame); 
     232         
     233        stream->rec_timestamp.u64 += stream->param.samples_per_frame / 
     234                                     stream->param.channel_count; 
    222235         
    223236        /* And now enqueue next buffer */ 
     
    379392     
    380393    pj_ansi_strcpy(info->name, "OpenSL ES Audio"); 
    381     info->default_samples_per_sec = 16000; 
    382     info->caps = PJMEDIA_AUD_DEV_CAP_INPUT_VOLUME_SETTING | 
    383                  PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING; 
     394    info->default_samples_per_sec = 8000; 
     395    info->caps = PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING; 
    384396    info->input_count = 1; 
    385397    info->output_count = 1; 
     
    422434    param->samples_per_frame = adi.default_samples_per_sec * 20 / 1000; 
    423435    param->bits_per_sample = 16; 
    424     param->flags = adi.caps; 
    425436    param->input_latency_ms = PJMEDIA_SND_DEFAULT_REC_LATENCY; 
    426437    param->output_latency_ms = PJMEDIA_SND_DEFAULT_PLAY_LATENCY; 
     
    486497        SLDataSink audioSnk = {&loc_outmix, NULL}; 
    487498        /* Audio interface */ 
    488         const SLInterfaceID ids[2] = {SL_IID_BUFFERQUEUE, 
    489                                       SL_IID_VOLUME/*, 
    490                                       SL_IID_ANDROIDCONFIGURATION*/}; 
    491         const SLboolean req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE}; 
     499        const SLInterfaceID ids[3] = {SL_IID_BUFFERQUEUE, 
     500                                      SL_IID_VOLUME, 
     501                                      SL_IID_ANDROIDCONFIGURATION}; 
     502        const SLboolean req[3] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, 
     503                                  SL_BOOLEAN_FALSE}; 
     504        SLAndroidConfigurationItf playerConfig; 
     505        SLint32 streamType = SL_ANDROID_STREAM_VOICE; 
    492506         
    493507        /* Create audio player */ 
     
    495509                                                        &stream->playerObj, 
    496510                                                        &audioSrc, &audioSnk, 
    497                                                         2, ids, req); 
     511                                                        3, ids, req); 
    498512        if (result != SL_RESULT_SUCCESS) { 
    499513            PJ_LOG(3, (THIS_FILE, "Cannot create audio player: %d", result)); 
     
    501515        } 
    502516 
    503         /* 
    504         SLAndroidConfigurationItf playerConfig; 
    505         SLint32 streamType = SL_ANDROID_STREAM_VOICE; 
     517        /* Set Android configuration */ 
    506518        result = (*stream->playerObj)->GetInterface(stream->playerObj, 
    507519                                                    SL_IID_ANDROIDCONFIGURATION, 
    508520                                                    &playerConfig); 
    509         if (result != SL_RESULT_SUCCESS) { 
    510             PJ_LOG(4, (THIS_FILE, "Cannot get android configuration iface")); 
    511         } 
    512         result = (*playerConfig)->SetConfiguration(playerConfig, 
    513                                                    SL_ANDROID_KEY_STREAM_TYPE, 
    514                                                    &streamType, 
    515                                                    sizeof(SLint32)); 
    516         */ 
     521        if (result == SL_RESULT_SUCCESS && playerConfig) { 
     522            result = (*playerConfig)->SetConfiguration( 
     523                         playerConfig, SL_ANDROID_KEY_STREAM_TYPE, 
     524                         &streamType, sizeof(SLint32)); 
     525        } 
     526        if (result != SL_RESULT_SUCCESS) { 
     527            PJ_LOG(4, (THIS_FILE, "Warning: Unable to set android " 
     528                                  "player configuration")); 
     529        } 
    517530         
    518531        /* Realize the player */ 
     
    541554            goto on_error; 
    542555        } 
     556         
     557        /* Get the volume interface */ 
     558        result = (*stream->playerObj)->GetInterface(stream->playerObj, 
     559                                                    SL_IID_VOLUME, 
     560                                                    &stream->playerVol); 
    543561         
    544562        /* Register callback on the buffer queue */ 
     
    569587        SLDataSink audioSnk = {&loc_bq, &format_pcm}; 
    570588        /* Audio interface */ 
    571         const SLInterfaceID ids[1] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE}; 
    572         const SLboolean req[1] = {SL_BOOLEAN_TRUE}; 
     589        const SLInterfaceID ids[2] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE, 
     590                                      SL_IID_ANDROIDCONFIGURATION}; 
     591        const SLboolean req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_FALSE}; 
     592        SLAndroidConfigurationItf recorderConfig; 
    573593         
    574594        /* Create audio recorder 
     
    578598                                                          &stream->recordObj, 
    579599                                                          &audioSrc, &audioSnk, 
    580                                                           1, ids, req); 
     600                                                          2, ids, req); 
    581601        if (result != SL_RESULT_SUCCESS) { 
    582602            PJ_LOG(3, (THIS_FILE, "Cannot create recorder: %d", result)); 
     
    584604        } 
    585605 
    586         /* 
    587         SLAndroidConfigurationItf recorderConfig; 
     606        /* Set Android configuration */ 
    588607        result = (*stream->recordObj)->GetInterface(stream->recordObj, 
    589608                                                    SL_IID_ANDROIDCONFIGURATION, 
     
    591610        if (result == SL_RESULT_SUCCESS) { 
    592611            SLint32 streamType = SL_ANDROID_RECORDING_PRESET_GENERIC; 
     612#if __ANDROID_API__ >= 14 
    593613            char sdk_version[PROP_VALUE_MAX]; 
    594614            pj_str_t pj_sdk_version; 
     
    598618            pj_sdk_version = pj_str(sdk_version); 
    599619            sdk_v = pj_strtoul(&pj_sdk_version); 
    600             if (sdk_v >= 10) 
    601                 streamType = 0x7; 
    602          
    603             PJ_LOG(4, (THIS_FILE, "We have a stream type %d SDK : %d", 
     620            if (sdk_v >= 14) 
     621                streamType = SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION; 
     622            PJ_LOG(4, (THIS_FILE, "Recording stream type %d, SDK : %d", 
    604623                                  streamType, sdk_v)); 
     624#endif 
    605625            result = (*recorderConfig)->SetConfiguration( 
    606626                         recorderConfig, SL_ANDROID_KEY_RECORDING_PRESET, 
    607627                         &streamType, sizeof(SLint32)); 
    608         } else { 
    609             PJ_LOG(4, (THIS_FILE, "Cannot get recorder config interface")); 
    610         } 
    611          */ 
     628        } 
     629        if (result != SL_RESULT_SUCCESS) { 
     630            PJ_LOG(4, (THIS_FILE, "Warning: Unable to set android " 
     631                                  "recorder configuration")); 
     632        } 
    612633         
    613634        /* Realize the recorder */ 
     
    655676    } 
    656677     
     678    if (param->flags & PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING) { 
     679        strm_set_cap(&stream->base, PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING, 
     680                     &param->output_vol); 
     681    } 
     682     
    657683    /* Done */ 
    658684    stream->base.op = &opensl_strm_op; 
     
    672698    PJ_ASSERT_RETURN(strm && pi, PJ_EINVAL); 
    673699    pj_memcpy(pi, &strm->param, sizeof(*pi)); 
     700 
     701    if (strm_get_cap(s, PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING, 
     702                     &pi->output_vol) == PJ_SUCCESS) 
     703    { 
     704        pi->flags |= PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING; 
     705    }     
    674706     
    675707    return PJ_SUCCESS; 
     
    686718    PJ_ASSERT_RETURN(s && pval, PJ_EINVAL); 
    687719     
    688     PJ_UNUSED_ARG(strm); 
    689      
    690     switch (cap) { 
    691         case PJMEDIA_AUD_DEV_CAP_INPUT_VOLUME_SETTING: 
    692             status = PJ_SUCCESS; 
    693             break; 
    694         case PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING: 
    695             status = PJ_SUCCESS; 
    696             break; 
    697         default: 
    698             break; 
     720    if (cap==PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING && 
     721        (strm->param.dir & PJMEDIA_DIR_PLAYBACK)) 
     722    { 
     723        if (strm->playerVol) { 
     724            SLresult res; 
     725            SLmillibel vol, mvol; 
     726             
     727            res = (*strm->playerVol)->GetMaxVolumeLevel(strm->playerVol, 
     728                                                        &mvol); 
     729            if (res == SL_RESULT_SUCCESS) { 
     730                res = (*strm->playerVol)->GetVolumeLevel(strm->playerVol, 
     731                                                         &vol); 
     732                if (res == SL_RESULT_SUCCESS) { 
     733                    *(int *)pval = ((int)vol - SL_MILLIBEL_MIN) * 100 / 
     734                                   ((int)mvol - SL_MILLIBEL_MIN); 
     735                    return PJ_SUCCESS; 
     736                } 
     737            } 
     738        } 
    699739    } 
    700740     
     
    703743 
    704744/* API: set capability */ 
    705 static pj_status_t strm_set_cap(pjmedia_aud_stream *strm, 
     745static pj_status_t strm_set_cap(pjmedia_aud_stream *s, 
    706746                                pjmedia_aud_dev_cap cap, 
    707747                                const void *value) 
    708748{ 
    709     PJ_UNUSED_ARG(strm); 
    710     PJ_UNUSED_ARG(cap); 
    711     PJ_UNUSED_ARG(value); 
     749    struct opensl_aud_stream *strm = (struct opensl_aud_stream*)s; 
     750     
     751    PJ_ASSERT_RETURN(s && value, PJ_EINVAL); 
     752 
     753    if (cap==PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING && 
     754        (strm->param.dir & PJMEDIA_DIR_PLAYBACK)) 
     755    { 
     756        if (strm->playerVol) { 
     757            SLresult res; 
     758            SLmillibel vol, mvol; 
     759             
     760            res = (*strm->playerVol)->GetMaxVolumeLevel(strm->playerVol, 
     761                                                        &mvol); 
     762            if (res == SL_RESULT_SUCCESS) { 
     763                vol = (SLmillibel)(*(int *)value * 
     764                      ((int)mvol - SL_MILLIBEL_MIN) / 100 + SL_MILLIBEL_MIN); 
     765                res = (*strm->playerVol)->SetVolumeLevel(strm->playerVol, 
     766                                                         vol); 
     767                if (res == SL_RESULT_SUCCESS) 
     768                    return PJ_SUCCESS; 
     769            } 
     770        } 
     771    } 
    712772 
    713773    return PJMEDIA_EAUD_INVCAP; 
     
    795855    if (stream->playerBufQ && stream->playerPlay) { 
    796856        /* Wait until the PCM data is done playing, the buffer queue callback 
    797          will continue to queue buffers until the entire PCM data has been 
    798          played. This is indicated by waiting for the count member of the 
    799          SLBufferQueueState to go to zero. 
     857         * will continue to queue buffers until the entire PCM data has been 
     858         * played. This is indicated by waiting for the count member of the 
     859         * SLBufferQueueState to go to zero. 
    800860         */ 
    801861/*       
     
    829889        /* Destroy the player */ 
    830890        (*stream->playerObj)->Destroy(stream->playerObj); 
     891        /* Invalidate all associated interfaces */ 
    831892        stream->playerObj = NULL; 
    832893        stream->playerPlay = NULL; 
    833894        stream->playerBufQ = NULL; 
     895        stream->playerVol = NULL; 
    834896    } 
    835897     
     
    837899        /* Destroy the recorder */ 
    838900        (*stream->recordObj)->Destroy(stream->recordObj); 
     901        /* Invalidate all associated interfaces */ 
    839902        stream->recordObj = NULL; 
    840903        stream->recordRecord = NULL; 
Note: See TracChangeset for help on using the changeset viewer.