/** * Returns whether a block of memory starts and ends on AAC ADTS frame boundaries * @param data pointer to the compressed audio data * @param size the size in bytes of the data block to validate * @return SL_RESULT_SUCCESS if there is AAC ADTS data, and it starts and ends on frame boundaries, * or an appropriate error code otherwise: * SL_RESULT_PARAMETER_INVALID if not possible to attempt validation of even one frame * SL_RESULT_CONTENT_CORRUPTED if the frame contents are otherwise invalid */ SLresult AacBqToPcmCbRenderer::validateBufferStartEndOnFrameBoundaries(void* data, size_t size) { off64_t offset = 0; size_t frameSize = 0; if ((NULL == data) || (size == 0)) { SL_LOGE("No ADTS to validate"); return SL_RESULT_PARAMETER_INVALID; } while (offset < (off64_t) size) { if ((frameSize = getAdtsFrameSize((uint8_t *)data, offset, size)) == 0) { SL_LOGE("found ADTS frame of size 0 at offset %lld", (long long) offset); return SL_RESULT_CONTENT_CORRUPTED; } //SL_LOGV("last good offset %llu", offset); offset += frameSize; if (offset > (off64_t) size) { SL_LOGE("found incomplete ADTS frame at end of data"); return SL_RESULT_CONTENT_CORRUPTED; } } if (offset != (off64_t) size) { SL_LOGE("ADTS parsing error: reached end of incomplete frame"); } assert(offset == (off64_t) size); return SL_RESULT_SUCCESS; }
//----------------------------------------------------------------------------- SLresult android_audioRecorder_setConfig(CAudioRecorder* ar, const SLchar *configKey, const void *pConfigValue, SLuint32 valueSize) { SLresult result; assert(NULL != ar && NULL != configKey && NULL != pConfigValue); if (strcmp((const char*)configKey, (const char*)SL_ANDROID_KEY_RECORDING_PRESET) == 0) { // recording preset if (KEY_RECORDING_PRESET_PARAMSIZE > valueSize) { SL_LOGE(ERROR_CONFIG_VALUESIZE_TOO_LOW); result = SL_RESULT_BUFFER_INSUFFICIENT; } else { result = audioRecorder_setPreset(ar, *(SLuint32*)pConfigValue); } } else if (strcmp((const char*)configKey, (const char*)SL_ANDROID_KEY_PERFORMANCE_MODE) == 0) { // performance mode if (KEY_PERFORMANCE_MODE_PARAMSIZE > valueSize) { SL_LOGE(ERROR_CONFIG_VALUESIZE_TOO_LOW); result = SL_RESULT_BUFFER_INSUFFICIENT; } else { result = audioRecorder_setPerformanceMode(ar, *(SLuint32*)pConfigValue); } } else { SL_LOGE(ERROR_CONFIG_UNKNOWN_KEY); result = SL_RESULT_PARAMETER_INVALID; } return result; }
SLresult audioRecorder_setPreset(CAudioRecorder* ar, SLuint32 recordPreset) { SLresult result = SL_RESULT_SUCCESS; audio_source_t newRecordSource = AUDIO_SOURCE_DEFAULT; switch (recordPreset) { case SL_ANDROID_RECORDING_PRESET_GENERIC: newRecordSource = AUDIO_SOURCE_DEFAULT; break; case SL_ANDROID_RECORDING_PRESET_CAMCORDER: newRecordSource = AUDIO_SOURCE_CAMCORDER; break; case SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION: newRecordSource = AUDIO_SOURCE_VOICE_RECOGNITION; break; case SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION: newRecordSource = AUDIO_SOURCE_VOICE_COMMUNICATION; break; case SL_ANDROID_RECORDING_PRESET_NONE: // it is an error to set preset "none" default: SL_LOGE(ERROR_RECORDERPRESET_SET_UNKNOWN_PRESET); result = SL_RESULT_PARAMETER_INVALID; } // recording preset needs to be set before the object is realized // (ap->mAudioRecord is supposed to be 0 until then) if (SL_OBJECT_STATE_UNREALIZED != ar->mObject.mState) { SL_LOGE(ERROR_RECORDERPRESET_REALIZED); result = SL_RESULT_PRECONDITIONS_VIOLATED; } else { ar->mRecordSource = newRecordSource; } return result; }
//----------------------------------------------------------------------------- SLresult audioRecorder_setPerformanceMode(CAudioRecorder* ar, SLuint32 mode) { SLresult result = SL_RESULT_SUCCESS; SL_LOGV("performance mode set to %d", mode); SLuint32 perfMode = ANDROID_PERFORMANCE_MODE_DEFAULT; switch (mode) { case SL_ANDROID_PERFORMANCE_LATENCY: perfMode = ANDROID_PERFORMANCE_MODE_LATENCY; break; case SL_ANDROID_PERFORMANCE_LATENCY_EFFECTS: perfMode = ANDROID_PERFORMANCE_MODE_LATENCY_EFFECTS; break; case SL_ANDROID_PERFORMANCE_NONE: perfMode = ANDROID_PERFORMANCE_MODE_NONE; break; case SL_ANDROID_PERFORMANCE_POWER_SAVING: perfMode = ANDROID_PERFORMANCE_MODE_POWER_SAVING; break; default: SL_LOGE(ERROR_CONFIG_PERF_MODE_UNKNOWN); result = SL_RESULT_PARAMETER_INVALID; break; } // performance mode needs to be set before the object is realized // (ar->mAudioRecord is supposed to be NULL until then) if (SL_OBJECT_STATE_UNREALIZED != ar->mObject.mState) { SL_LOGE(ERROR_CONFIG_PERF_MODE_REALIZED); result = SL_RESULT_PRECONDITIONS_VIOLATED; } else { ar->mPerformanceMode = perfMode; } return result; }
//----------------------------------------------------------------------------- SLresult android_audioRecorder_getConfig(CAudioRecorder* ar, const SLchar *configKey, SLuint32* pValueSize, void *pConfigValue) { SLresult result; assert(NULL != ar && NULL != configKey && NULL != pValueSize); if (strcmp((const char*)configKey, (const char*)SL_ANDROID_KEY_RECORDING_PRESET) == 0) { // recording preset if (NULL == pConfigValue) { result = SL_RESULT_SUCCESS; } else if (KEY_RECORDING_PRESET_PARAMSIZE > *pValueSize) { SL_LOGE(ERROR_CONFIG_VALUESIZE_TOO_LOW); result = SL_RESULT_BUFFER_INSUFFICIENT; } else { result = audioRecorder_getPreset(ar, (SLuint32*)pConfigValue); } *pValueSize = KEY_RECORDING_PRESET_PARAMSIZE; } else { SL_LOGE(ERROR_CONFIG_UNKNOWN_KEY); result = SL_RESULT_PARAMETER_INVALID; } return result; }
void CEngine_Destroy(void *self) { CEngine *thiz = (CEngine *) self; // Verify that there are no extant objects unsigned instanceCount = thiz->mEngine.mInstanceCount; unsigned instanceMask = thiz->mEngine.mInstanceMask; if ((0 < instanceCount) || (0 != instanceMask)) { SL_LOGE("Object::Destroy(%p) for engine ignored; %u total active objects", thiz, instanceCount); while (0 != instanceMask) { unsigned i = ctz(instanceMask); assert(MAX_INSTANCE > i); SL_LOGE("Object::Destroy(%p) for engine ignored; active object ID %u at %p", thiz, i + 1, thiz->mEngine.mInstances[i]); instanceMask &= ~(1 << i); } } // If engine was created but not realized, there will be no sync thread yet pthread_t zero; memset(&zero, 0, sizeof(pthread_t)); if (0 != memcmp(&zero, &thiz->mSyncThread, sizeof(pthread_t))) { // Announce to the sync thread that engine is shutting down; it polls so should see it soon thiz->mEngine.mShutdown = SL_BOOLEAN_TRUE; // Wait for the sync thread to acknowledge the shutdown while (!thiz->mEngine.mShutdownAck) { object_cond_wait(&thiz->mObject); } // The sync thread should have exited by now, so collect it by joining (void) pthread_join(thiz->mSyncThread, (void **) NULL); } // Shutdown the thread pool used for asynchronous operations (there should not be any) ThreadPool_deinit(&thiz->mThreadPool); #if defined(ANDROID) // free equalizer preset names if (NULL != thiz->mEqPresetNames) { for (unsigned i = 0; i < thiz->mEqNumPresets; ++i) { if (NULL != thiz->mEqPresetNames[i]) { delete[] thiz->mEqPresetNames[i]; thiz->mEqPresetNames[i] = NULL; } } delete[] thiz->mEqPresetNames; thiz->mEqPresetNames = NULL; } thiz->mEqNumPresets = 0; #endif #ifdef USE_SDL SDL_close(); #endif }
//----------------------------------------------------------------------------- XAresult android_Player_checkSourceSink(CMediaPlayer *mp) { XAresult result = XA_RESULT_SUCCESS; const SLDataSource *pSrc = &mp->mDataSource.u.mSource; const SLDataSink *pAudioSnk = &mp->mAudioSink.u.mSink; // format check: const SLuint32 sourceLocatorType = *(SLuint32 *)pSrc->pLocator; const SLuint32 sourceFormatType = *(SLuint32 *)pSrc->pFormat; const SLuint32 audioSinkLocatorType = *(SLuint32 *)pAudioSnk->pLocator; //const SLuint32 sinkFormatType = *(SLuint32 *)pAudioSnk->pFormat; // Source check switch(sourceLocatorType) { case XA_DATALOCATOR_ANDROIDBUFFERQUEUE: { switch (sourceFormatType) { case XA_DATAFORMAT_MIME: { SLDataFormat_MIME *df_mime = (SLDataFormat_MIME *) pSrc->pFormat; if (SL_CONTAINERTYPE_MPEG_TS != df_mime->containerType) { SL_LOGE("Cannot create player with XA_DATALOCATOR_ANDROIDBUFFERQUEUE data source " "that is not fed MPEG-2 TS data"); return SL_RESULT_CONTENT_UNSUPPORTED; } } break; default: SL_LOGE("Cannot create player with XA_DATALOCATOR_ANDROIDBUFFERQUEUE data source " "without SL_DATAFORMAT_MIME format"); return XA_RESULT_CONTENT_UNSUPPORTED; } } break; case XA_DATALOCATOR_URI: // intended fall-through case XA_DATALOCATOR_ANDROIDFD: break; default: SL_LOGE("Cannot create media player with data locator type 0x%x", (unsigned) sourceLocatorType); return SL_RESULT_PARAMETER_INVALID; }// switch (locatorType) // Audio sink check: only playback is supported here switch(audioSinkLocatorType) { case XA_DATALOCATOR_OUTPUTMIX: break; default: SL_LOGE("Cannot create media player with audio sink data locator of type 0x%x", (unsigned) audioSinkLocatorType); return XA_RESULT_PARAMETER_INVALID; }// switch (locaaudioSinkLocatorTypeorType) return result; }
/** * pre-condition: gp != 0 */ XAresult android_Player_setPlayState(const android::sp<android::GenericPlayer> &gp, SLuint32 playState, AndroidObjectState* pObjState) { XAresult result = XA_RESULT_SUCCESS; AndroidObjectState objState = *pObjState; switch (playState) { case SL_PLAYSTATE_STOPPED: { SL_LOGV("setting AVPlayer to SL_PLAYSTATE_STOPPED"); gp->stop(); } break; case SL_PLAYSTATE_PAUSED: { SL_LOGV("setting AVPlayer to SL_PLAYSTATE_PAUSED"); switch(objState) { case ANDROID_UNINITIALIZED: *pObjState = ANDROID_PREPARING; gp->prepare(); break; case ANDROID_PREPARING: break; case ANDROID_READY: gp->pause(); break; default: SL_LOGE("Android object in invalid state"); break; } } break; case SL_PLAYSTATE_PLAYING: { SL_LOGV("setting AVPlayer to SL_PLAYSTATE_PLAYING"); switch(objState) { case ANDROID_UNINITIALIZED: *pObjState = ANDROID_PREPARING; gp->prepare(); // intended fall through case ANDROID_PREPARING: // intended fall through case ANDROID_READY: gp->play(); break; default: SL_LOGE("Android object in invalid state"); break; } } break; default: // checked by caller, should not happen break; } return result; }
static SLresult IAndroidBufferQueue_Enqueue(SLAndroidBufferQueueItf self, void *pBufferContext, void *pData, SLuint32 dataLength, const SLAndroidBufferItem *pItems, SLuint32 itemsLength) { SL_ENTER_INTERFACE SL_LOGD("IAndroidBufferQueue_Enqueue pData=%p dataLength=%d", pData, dataLength); if ((dataLength > 0) && (NULL == pData)) { SL_LOGE("Enqueue failure: non-zero data length %u but NULL data pointer", dataLength); result = SL_RESULT_PARAMETER_INVALID; } else if ((itemsLength > 0) && (NULL == pItems)) { SL_LOGE("Enqueue failure: non-zero items length %u but NULL items pointer", itemsLength); result = SL_RESULT_PARAMETER_INVALID; } else if ((0 == dataLength) && (0 == itemsLength)) { // no data and no msg SL_LOGE("Enqueue failure: trying to enqueue buffer with no data and no items."); result = SL_RESULT_PARAMETER_INVALID; // Note that a non-NULL data pointer with zero data length is allowed. // We track that data pointer as it moves through the queue // to assist the application in accounting for data buffers. // A non-NULL items pointer with zero items length is also allowed, but has no value. } else { IAndroidBufferQueue *thiz = (IAndroidBufferQueue *) self; // buffer size check, can be done outside of lock because buffer type can't change switch (thiz->mBufferType) { case kAndroidBufferTypeMpeg2Ts: if (dataLength % MPEG2_TS_BLOCK_SIZE == 0) { break; } SL_LOGE("Error enqueueing MPEG-2 TS data: size must be a multiple of %d (block size)", MPEG2_TS_BLOCK_SIZE); result = SL_RESULT_PARAMETER_INVALID; SL_LEAVE_INTERFACE break; case kAndroidBufferTypeAacadts: // non-zero dataLength is permitted in case of EOS command only if (dataLength > 0) { result = android::AacBqToPcmCbRenderer::validateBufferStartEndOnFrameBoundaries( pData, dataLength); if (SL_RESULT_SUCCESS != result) { SL_LOGE("Error enqueueing ADTS data: data must start and end on frame " "boundaries"); SL_LEAVE_INTERFACE } } break; case kAndroidBufferTypeInvalid: default: result = SL_RESULT_PARAMETER_INVALID; SL_LEAVE_INTERFACE }
//----------------------------------------------------------------------------- SLresult android_audioRecorder_realize(CAudioRecorder* ar, SLboolean async) { SL_LOGV("android_audioRecorder_realize(%p) entering", ar); SLresult result = SL_RESULT_SUCCESS; // initialize platform-independent CAudioRecorder fields if (SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE != ar->mDataSink.mLocator.mLocatorType) { SL_LOGE(ERROR_RECORDER_SINK_MUST_BE_ANDROIDSIMPLEBUFFERQUEUE); return SL_RESULT_CONTENT_UNSUPPORTED; } // the following platform-independent fields have been initialized in CreateAudioRecorder() // ar->mNumChannels // ar->mSampleRateMilliHz SL_LOGV("new AudioRecord %u channels, %u mHz", ar->mNumChannels, ar->mSampleRateMilliHz); // currently nothing analogous to canUseFastTrack() for recording audio_input_flags_t policy = AUDIO_INPUT_FLAG_FAST; // initialize platform-specific CAudioRecorder fields ar->mAudioRecord = new android::AudioRecord(); ar->mAudioRecord->set(ar->mRecordSource, // source sles_to_android_sampleRate(ar->mSampleRateMilliHz), // sample rate in Hertz AUDIO_FORMAT_PCM_16_BIT, //FIXME use format from buffer queue sink sles_to_android_channelMaskIn(ar->mNumChannels, 0 /*no channel mask*/), // channel config 0, //frameCount min audioRecorder_callback,// callback_t (void*)ar, // user, callback data, here the AudioRecorder 0, // notificationFrames false, // threadCanCallJava, note: this will prevent direct Java // callbacks, but we don't want them in the recording loop 0, // session ID android::AudioRecord::TRANSFER_CALLBACK, // transfer type policy); // audio_input_flags_t if (android::NO_ERROR != ar->mAudioRecord->initCheck()) { SL_LOGE("android_audioRecorder_realize(%p) error creating AudioRecord object", ar); result = SL_RESULT_CONTENT_UNSUPPORTED; } #ifdef MONITOR_RECORDING gMonitorFp = fopen(MONITOR_TARGET, "w"); if (NULL == gMonitorFp) { SL_LOGE("error opening %s", MONITOR_TARGET); } else { SL_LOGE("recording to %s", MONITOR_TARGET); } // SL_LOGE so it's always displayed #endif return result; }
//----------------------------------------------------------------------------- SLresult android_audioRecorder_checkSourceSinkSupport(CAudioRecorder* ar) { const SLDataSource *pAudioSrc = &ar->mDataSource.u.mSource; const SLDataSink *pAudioSnk = &ar->mDataSink.u.mSink; // Sink check: // only buffer queue sinks are supported, regardless of the data source if (SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE != *(SLuint32 *)pAudioSnk->pLocator) { SL_LOGE(ERROR_RECORDER_SINK_MUST_BE_ANDROIDSIMPLEBUFFERQUEUE); return SL_RESULT_PARAMETER_INVALID; } else { // only PCM buffer queues are supported SLuint32 formatType = *(SLuint32 *)pAudioSnk->pFormat; if (SL_DATAFORMAT_PCM == formatType) { SLDataFormat_PCM *df_pcm = (SLDataFormat_PCM *)ar->mDataSink.u.mSink.pFormat; ar->mSampleRateMilliHz = df_pcm->samplesPerSec; ar->mNumChannels = df_pcm->numChannels; SL_LOGV("AudioRecorder requested sample rate = %u mHz, %u channel(s)", ar->mSampleRateMilliHz, ar->mNumChannels); } else { SL_LOGE(ERROR_RECORDER_SINK_FORMAT_MUST_BE_PCM); return SL_RESULT_PARAMETER_INVALID; } } // Source check: // only input device sources are supported // check it's an IO device if (SL_DATALOCATOR_IODEVICE != *(SLuint32 *)pAudioSrc->pLocator) { SL_LOGE(ERROR_RECORDER_SOURCE_MUST_BE_IODEVICE); return SL_RESULT_PARAMETER_INVALID; } else { // check it's an input device SLDataLocator_IODevice *dl_iod = (SLDataLocator_IODevice *) pAudioSrc->pLocator; if (SL_IODEVICE_AUDIOINPUT != dl_iod->deviceType) { SL_LOGE(ERROR_RECORDER_IODEVICE_MUST_BE_AUDIOINPUT); return SL_RESULT_PARAMETER_INVALID; } // check it's the default input device, others aren't supported here if (SL_DEFAULTDEVICEID_AUDIOINPUT != dl_iod->deviceID) { SL_LOGE(ERROR_RECORDER_INPUT_ID_MUST_BE_DEFAULT); return SL_RESULT_PARAMETER_INVALID; } } return SL_RESULT_SUCCESS; }
//----------------------------------------------------------------------------- SLresult android_genericFx_queryNumEffects(SLuint32 *pNumSupportedAudioEffects) { if (NULL == pNumSupportedAudioEffects) { return SL_RESULT_PARAMETER_INVALID; } android::status_t status = android::AudioEffect::queryNumberEffects((uint32_t*)pNumSupportedAudioEffects); SLresult result = SL_RESULT_SUCCESS; switch (status) { case android::NO_ERROR: result = SL_RESULT_SUCCESS; break; case android::PERMISSION_DENIED: result = SL_RESULT_PERMISSION_DENIED; break; case android::NO_INIT: result = SL_RESULT_RESOURCE_ERROR; break; case android::BAD_VALUE: result = SL_RESULT_PARAMETER_INVALID; break; default: result = SL_RESULT_INTERNAL_ERROR; SL_LOGE("received invalid status %d from AudioEffect::queryNumberEffects()", status); break; } return result; }
//----------------------------------------------------------------------------- SLresult android_genericFx_createEffect(IAndroidEffect* iae, SLInterfaceID pUuid, audio_session_t sessionId) { SLresult result = SL_RESULT_SUCCESS; // does this effect already exist? if (0 <= iae->mEffects->indexOfKey(KEY_FROM_GUID(pUuid))) { return result; } // create new effect android::sp<android::AudioEffect> pFx = new android::AudioEffect( NULL, // not using type to create effect android::String16(), (const effect_uuid_t*)pUuid, 0,// priority 0,// effect callback 0,// callback data sessionId, 0 );// output // verify effect was successfully created before storing it android::status_t status = pFx->initCheck(); if (android::NO_ERROR != status) { SL_LOGE("AudioEffect initCheck() returned %d, effect will not be stored", status); result = SL_RESULT_RESOURCE_ERROR; } else { SL_LOGV("AudioEffect successfully created on session %d", sessionId); iae->mEffects->add(KEY_FROM_GUID(pUuid), pFx); } return result; }
static uint32_t eq_valueSize(int32_t param) { uint32_t size; switch (param) { case EQ_PARAM_NUM_BANDS: case EQ_PARAM_CUR_PRESET: case EQ_PARAM_GET_NUM_OF_PRESETS: case EQ_PARAM_BAND_LEVEL: case EQ_PARAM_GET_BAND: size = sizeof(int16_t); break; case EQ_PARAM_LEVEL_RANGE: size = 2 * sizeof(int16_t); break; case EQ_PARAM_CENTER_FREQ: size = sizeof(int32_t); break; case EQ_PARAM_BAND_FREQ_RANGE: size = 2 * sizeof(int32_t); break; case EQ_PARAM_GET_PRESET_NAME: size = EFFECT_STRING_LEN_MAX; break; default: size = sizeof(int32_t); SL_LOGE("Trying to access an unknown EQ parameter %d", param); break; } return size; }
bool COutputMix_PreDestroy(void *self) { // Ignore destroy requests if there are any players attached to this output mix COutputMix *outputMix = (COutputMix *) self; // See design document for explanation if (0 == outputMix->mObject.mStrongRefCount) { #ifdef USE_OUTPUTMIXEXT // We only support a single active output mix per engine, so check if this is the active mix IEngine *thisEngine = outputMix->mObject.mEngine; interface_lock_exclusive(thisEngine); bool thisIsTheActiveOutputMix = false; if (outputMix == thisEngine->mOutputMix) { thisIsTheActiveOutputMix = true; } interface_unlock_exclusive(thisEngine); if (thisIsTheActiveOutputMix) { // Tell the asynchronous mixer callback that we want to destroy the output mix outputMix->mOutputMixExt.mDestroyRequested = true; while (outputMix->mOutputMixExt.mDestroyRequested) { object_cond_wait(&outputMix->mObject); } #ifdef USE_SDL // Mixer callback has acknowledged our request and unlinked output mix from engine. // Disable SDL_callback from being called periodically by SDL's internal thread. SDL_PauseAudio(1); #endif } #endif return true; } SL_LOGE("Object::Destroy(%p) for OutputMix ignored; %u players attached", outputMix, outputMix->mObject.mStrongRefCount); return false; }
//----------------------------------------------------------------------------- SLresult android_genericFx_queryEffect(SLuint32 index, effect_descriptor_t* pDescriptor) { if (NULL == pDescriptor) { return SL_RESULT_PARAMETER_INVALID; } android::status_t status = android::AudioEffect::queryEffect(index, pDescriptor); SLresult result = SL_RESULT_SUCCESS; if (android::NO_ERROR != status) { switch (status) { case android::PERMISSION_DENIED: result = SL_RESULT_PERMISSION_DENIED; break; case android::NO_INIT: case android::INVALID_OPERATION: result = SL_RESULT_RESOURCE_ERROR; break; case android::BAD_VALUE: result = SL_RESULT_PARAMETER_INVALID; break; default: result = SL_RESULT_INTERNAL_ERROR; SL_LOGE("received invalid status %d from AudioEffect::queryNumberEffects()", status); break; } // an error occurred, reset the effect descriptor memset(pDescriptor, 0, sizeof(effect_descriptor_t)); } return result; }
//----------------------------------------------------------------------------- static uint32_t eq_paramSize(int32_t param) { uint32_t size; switch (param) { case EQ_PARAM_NUM_BANDS: case EQ_PARAM_LEVEL_RANGE: case EQ_PARAM_CUR_PRESET: case EQ_PARAM_GET_NUM_OF_PRESETS: size = sizeof(int32_t); break; case EQ_PARAM_BAND_LEVEL: case EQ_PARAM_CENTER_FREQ: case EQ_PARAM_BAND_FREQ_RANGE: case EQ_PARAM_GET_BAND: case EQ_PARAM_GET_PRESET_NAME: size = 2 * sizeof(int32_t); break; default: size = 2 * sizeof(int32_t); SL_LOGE("Trying to use an unknown EQ parameter %d", param); break; } return size; }
CallbackProtector::~CallbackProtector() { Mutex::Autolock _l(mLock); if (mCbCount) { SL_LOGE("Callback protector detected an active callback after destroy"); } }
/** * returns the size in bytes of the value of each environmental reverb parameter */ static uint32_t erev_valueSize(int32_t param) { uint32_t size; switch (param) { case REVERB_PARAM_ROOM_LEVEL: case REVERB_PARAM_ROOM_HF_LEVEL: case REVERB_PARAM_REFLECTIONS_LEVEL: case REVERB_PARAM_REVERB_LEVEL: size = sizeof(int16_t); // millibel break; case REVERB_PARAM_DECAY_TIME: case REVERB_PARAM_REFLECTIONS_DELAY: case REVERB_PARAM_REVERB_DELAY: size = sizeof(uint32_t); // milliseconds break; case REVERB_PARAM_DECAY_HF_RATIO: case REVERB_PARAM_DIFFUSION: case REVERB_PARAM_DENSITY: size = sizeof(int16_t); // permille break; case REVERB_PARAM_PROPERTIES: size = sizeof(s_reverb_settings); // struct of all reverb properties break; default: size = sizeof(int32_t); SL_LOGE("Trying to access an unknown Environmental Reverb parameter %d", param); break; } return size; }
// static bool CallbackProtector::enterCbIfOk(const sp<CallbackProtector> &protector) { if (protector != 0) { return protector->enterCb(); } else { SL_LOGE("Callback protector is missing"); return false; } }
//----------------------------------------------------------------------------- void android_ns_init(audio_session_t sessionId, IAndroidNoiseSuppression* ins) { SL_LOGV("android_ns_init on session %d", sessionId); if (!android_fx_initEffectObj(sessionId, ins->mNSEffect, &ins->mNSDescriptor.type)) { SL_LOGE("NS effect initialization failed"); return; } }
//----------------------------------------------------------------------------- void android_agc_init(audio_session_t sessionId, IAndroidAutomaticGainControl* iagc) { SL_LOGV("android_agc_init on session %d", sessionId); if (!android_fx_initEffectObj(sessionId, iagc->mAGCEffect, &iagc->mAGCDescriptor.type)) { SL_LOGE("AGC effect initialization failed"); return; } }
//----------------------------------------------------------------------------- void android_aec_init(audio_session_t sessionId, IAndroidAcousticEchoCancellation* iaec) { SL_LOGV("android_aec_init on session %d", sessionId); if (!android_fx_initEffectObj(sessionId, iaec->mAECEffect, &iaec->mAECDescriptor.type)) { SL_LOGE("AEC effect initialization failed"); return; } }
__attribute__((destructor)) static void onDlClose(void) { // a memory barrier would be sufficient, but the mutex is easier (void) pthread_mutex_lock(&theOneTrueMutex); if ((NULL != theOneTrueEngine) || (0 < theOneTrueRefCount)) { SL_LOGE("Object::Destroy omitted for engine %p", theOneTrueEngine); } (void) pthread_mutex_unlock(&theOneTrueMutex); }
//-------------------------------------------------- // Event handlers void StreamPlayer::onPrepare() { SL_LOGD("StreamPlayer::onPrepare()"); sp<IMediaPlayerService> mediaPlayerService(getMediaPlayerService()); if (mediaPlayerService != NULL) { mPlayer = mediaPlayerService->create(getpid(), mPlayerClient /*IMediaPlayerClient*/, mPlaybackParams.sessionId); if (mPlayer == NULL) { SL_LOGE("media player service failed to create player by app proxy"); } else if (mPlayer->setDataSource(mAppProxy /*IStreamSource*/) != NO_ERROR) { SL_LOGE("setDataSource failed"); mPlayer.clear(); } } if (mPlayer == NULL) { mStateFlags |= kFlagPreparedUnsuccessfully; } GenericMediaPlayer::onPrepare(); SL_LOGD("StreamPlayer::onPrepare() done"); }
/* * pre-conditions: * mp != NULL * mp->mAVPlayer != 0 (player is realized) * nativeWindow can be NULL, but if NULL it is treated as an error */ SLresult android_Player_setNativeWindow(CMediaPlayer *mp, ANativeWindow *nativeWindow) { assert(mp != NULL); assert(mp->mAVPlayer != 0); if (nativeWindow == NULL) { SL_LOGE("ANativeWindow is NULL"); return SL_RESULT_PARAMETER_INVALID; } SLresult result; int err; int value; // this could crash if app passes in a bad parameter, but that's OK err = (*nativeWindow->query)(nativeWindow, NATIVE_WINDOW_CONCRETE_TYPE, &value); if (0 != err) { SL_LOGE("Query NATIVE_WINDOW_CONCRETE_TYPE on ANativeWindow * %p failed; " "errno %d", nativeWindow, err); result = SL_RESULT_PARAMETER_INVALID; } else { switch (value) { case NATIVE_WINDOW_SURFACE: { // Surface SL_LOGV("Displaying on ANativeWindow of type NATIVE_WINDOW_SURFACE"); android::sp<android::Surface> surface( static_cast<android::Surface *>(nativeWindow)); android::sp<android::IGraphicBufferProducer> nativeSurfaceTexture( surface->getIGraphicBufferProducer()); mp->mAVPlayer->setVideoSurfaceTexture(nativeSurfaceTexture); result = SL_RESULT_SUCCESS; } break; case NATIVE_WINDOW_FRAMEBUFFER: // FramebufferNativeWindow // fall through default: SL_LOGE("ANativeWindow * %p has unknown or unsupported concrete type %d", nativeWindow, value); result = SL_RESULT_PARAMETER_INVALID; break; } } return result; }
//----------------------------------------------------------------------------- bool android_fx_initEffectDescriptor(const SLInterfaceID effectId, effect_descriptor_t* fxDescrLoc) { uint32_t numEffects = 0; effect_descriptor_t descriptor; bool foundEffect = false; // any effects? android::status_t res = android::AudioEffect::queryNumberEffects(&numEffects); if (android::NO_ERROR != res) { SL_LOGE("unable to find any effects."); goto effectError; } // request effect in the effects? for (uint32_t i=0 ; i < numEffects ; i++) { res = android::AudioEffect::queryEffect(i, &descriptor); if ((android::NO_ERROR == res) && (0 == memcmp(effectId, &descriptor.type, sizeof(effect_uuid_t)))) { SL_LOGV("found effect %d %s", i, descriptor.name); foundEffect = true; break; } } if (foundEffect) { memcpy(fxDescrLoc, &descriptor, sizeof(effect_descriptor_t)); } else { SL_LOGE("unable to find an implementation for the requested effect."); goto effectError; } return true; effectError: // the requested effect wasn't found memset(fxDescrLoc, 0, sizeof(effect_descriptor_t)); return false; }
/** * returns the size in bytes of the value of each noise suppression parameter */ uint32_t ns_valueSize(int32_t param) { uint32_t size; switch (param) { case NS_PARAM_LEVEL: size = sizeof(int32_t); break; default: size = sizeof(int32_t); SL_LOGE("Trying to access an unknown Noise suppression parameter %d", param); break; } return size; }
/** * returns the size in bytes of the value of each acoustic echo cancellation parameter */ uint32_t aec_valueSize(int32_t param) { uint32_t size; switch (param) { case AEC_PARAM_ECHO_DELAY: size = sizeof(int32_t); break; default: size = sizeof(int32_t); SL_LOGE("Trying to access an unknown Acoustic Echo Cancellation parameter %d", param); break; } return size; }
SLresult AcquireStrongRef(IObject *object, SLuint32 expectedObjectID) { if (NULL == object) { return SL_RESULT_PARAMETER_INVALID; } // NTH additional validity checks on address here SLresult result; object_lock_exclusive(object); SLuint32 actualObjectID = IObjectToObjectID(object); if (expectedObjectID != actualObjectID) { SL_LOGE("object %p has object ID %u but expected %u", object, actualObjectID, expectedObjectID); result = SL_RESULT_PARAMETER_INVALID; } else if (SL_OBJECT_STATE_REALIZED != object->mState) { SL_LOGE("object %p with object ID %u is not realized", object, actualObjectID); result = SL_RESULT_PRECONDITIONS_VIOLATED; } else { ++object->mStrongRefCount; result = SL_RESULT_SUCCESS; } object_unlock_exclusive(object); return result; }