diff options
-rw-r--r-- | include/media/AudioRecord.h | 17 | ||||
-rw-r--r-- | include/media/AudioSystem.h | 2 | ||||
-rw-r--r-- | include/media/AudioTrack.h | 45 | ||||
-rw-r--r-- | include/media/EffectApi.h | 22 | ||||
-rw-r--r-- | include/media/EffectFactoryApi.h | 12 | ||||
-rw-r--r-- | include/media/IAudioFlinger.h | 27 | ||||
-rw-r--r-- | include/media/IAudioTrack.h | 5 | ||||
-rw-r--r-- | include/private/media/AudioEffectShared.h | 51 | ||||
-rw-r--r-- | include/private/media/AudioTrackShared.h | 3 | ||||
-rw-r--r-- | media/libeffects/EffectEqualizer.cpp | 2 | ||||
-rw-r--r-- | media/libeffects/EffectReverb.c | 5 | ||||
-rw-r--r-- | media/libeffects/EffectReverb.h | 2 | ||||
-rw-r--r-- | media/libeffects/EffectsFactory.c | 12 | ||||
-rw-r--r-- | media/libmedia/AudioRecord.cpp | 21 | ||||
-rw-r--r-- | media/libmedia/AudioSystem.cpp | 6 | ||||
-rw-r--r-- | media/libmedia/AudioTrack.cpp | 66 | ||||
-rw-r--r-- | media/libmedia/IAudioFlinger.cpp | 260 | ||||
-rw-r--r-- | media/libmedia/IAudioTrack.cpp | 24 |
18 files changed, 531 insertions, 51 deletions
diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h index 92bc126..d956882 100644 --- a/include/media/AudioRecord.h +++ b/include/media/AudioRecord.h @@ -142,7 +142,8 @@ public: uint32_t flags = 0, callback_t cbf = 0, void* user = 0, - int notificationFrames = 0); + int notificationFrames = 0, + int sessionId = 0); /* Terminates the AudioRecord and unregisters it from AudioFlinger. @@ -168,7 +169,8 @@ public: callback_t cbf = 0, void* user = 0, int notificationFrames = 0, - bool threadCanCallJava = false); + bool threadCanCallJava = false, + int sessionId = 0); /* Result of constructing the AudioRecord. This must be checked @@ -270,6 +272,16 @@ public: */ audio_io_handle_t getInput(); + /* returns the audio session ID associated to this AudioRecord. + * + * Parameters: + * none. + * + * Returned value: + * AudioRecord session ID. + */ + int getSessionId(); + /* obtains a buffer of "frameCount" frames. The buffer must be * filled entirely. If the track is stopped, obtainBuffer() returns * STOPPED instead of NO_ERROR as long as there are buffers availlable, @@ -356,6 +368,7 @@ private: uint32_t mFlags; uint32_t mChannels; audio_io_handle_t mInput; + int mSessionId; }; }; // namespace android diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h index 9caef8f..f21e83d 100644 --- a/include/media/AudioSystem.h +++ b/include/media/AudioSystem.h @@ -230,6 +230,8 @@ public: static status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, int stream = DEFAULT); static unsigned int getInputFramesLost(audio_io_handle_t ioHandle); + + static int newAudioSessionId(); // // AudioPolicyService interface // diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h index cc4ab74..c46df1e 100644 --- a/include/media/AudioTrack.h +++ b/include/media/AudioTrack.h @@ -138,7 +138,8 @@ public: uint32_t flags = 0, callback_t cbf = 0, void* user = 0, - int notificationFrames = 0); + int notificationFrames = 0, + int sessionId = 0); /* Creates an audio track and registers it with AudioFlinger. With this constructor, * The PCM data to be rendered by AudioTrack is passed in a shared memory buffer @@ -157,7 +158,8 @@ public: uint32_t flags = 0, callback_t cbf = 0, void* user = 0, - int notificationFrames = 0); + int notificationFrames = 0, + int sessionId = 0); /* Terminates the AudioTrack and unregisters it from AudioFlinger. * Also destroys all resources assotiated with the AudioTrack. @@ -182,7 +184,8 @@ public: void* user = 0, int notificationFrames = 0, const sp<IMemory>& sharedBuffer = 0, - bool threadCanCallJava = false); + bool threadCanCallJava = false, + int sessionId = 0); /* Result of constructing the AudioTrack. This must be checked @@ -239,10 +242,17 @@ public: /* set volume for this track, mostly used for games' sound effects + * left and right volumes. Levels must be <= 1.0. */ - void setVolume(float left, float right); + status_t setVolume(float left, float right); void getVolume(float* left, float* right); + /* set the send level for this track. An auxiliary effect should be attached + * to the track with attachEffect(). Level must be <= 1.0. + */ + status_t setSendLevel(float level); + void getSendLevel(float* level); + /* set sample rate for this track, mostly used for games' sound effects */ status_t setSampleRate(int sampleRate); @@ -340,6 +350,31 @@ public: */ audio_io_handle_t getOutput(); + /* returns the unique ID associated to this track. + * + * Parameters: + * none. + * + * Returned value: + * AudioTrack ID. + */ + int getSessionId(); + + + /* Attach track auxiliary output to specified effect. Used effectId = 0 + * to detach track from effect. + * + * Parameters: + * + * effectId: effectId obtained from AudioEffect::id(). + * + * Returned status (from utils/Errors.h) can be: + * - NO_ERROR: successful operation + * - INVALID_OPERATION: the effect is not an auxiliary effect. + * - BAD_VALUE: The specified effect ID is invalid + */ + status_t attachAuxEffect(int effectId); + /* obtains a buffer of "frameCount" frames. The buffer must be * filled entirely. If the track is stopped, obtainBuffer() returns * STOPPED instead of NO_ERROR as long as there are buffers availlable, @@ -406,6 +441,7 @@ private: sp<AudioTrackThread> mAudioTrackThread; float mVolume[2]; + float mSendLevel; uint32_t mFrameCount; audio_track_cblk_t* mCblk; @@ -431,6 +467,7 @@ private: uint32_t mNewPosition; uint32_t mUpdatePeriod; uint32_t mFlags; + int mSessionId; }; diff --git a/include/media/EffectApi.h b/include/media/EffectApi.h index a1bc3b8..97874f7 100644 --- a/include/media/EffectApi.h +++ b/include/media/EffectApi.h @@ -114,7 +114,8 @@ typedef struct effect_descriptor_s { // +---------------------------+-----------+----------------------------------- // | Volume management | 5..6 | 0 none // | | | 1 implements volume control -// | | | 2..3 reserved +// | | | 2 requires volume indication +// | | | 3 reserved // +---------------------------+-----------+----------------------------------- // | Device management | 7..8 | 0 none // | | | 1 requires device updates @@ -154,6 +155,7 @@ typedef struct effect_descriptor_s { // volume control #define EFFECT_FLAG_VOLUME_MASK 0x00000060 #define EFFECT_FLAG_VOLUME_CTRL 0x00000020 +#define EFFECT_FLAG_VOLUME_IND 0x00000040 #define EFFECT_FLAG_VOLUME_NONE 0x00000000 // device control @@ -296,10 +298,12 @@ struct effect_interface_s { // | Set and get volume. Used by | EFFECT_CMD_SET_VOLUME | size: n * sizeof(uint32_t) | size: n * sizeof(uint32_t) // | audio framework to delegate | | data: volume for each channel | data: volume for each channel // | volume control to effect engine| | defined in effect_config_t in | defined in effect_config_t in -// | The engine must return the | | 8.24 fixed point format | 8.24 fixed point format -// | volume that should be applied | | | -// | before the effect is processed | | | -// | The overall volume (the volume | | | +// | If volume control flag is set | | 8.24 fixed point format | 8.24 fixed point format +// | in the effect descriptor, the | | | It is legal to receive a null +// | effect engine must return the | | | pointer as pReplyData in which +// | volume that should be applied | | | case the effect framework has +// | before the effect is processed | | | delegated volume control to +// | The overall volume (the volume | | | another effect. // | actually applied by the effect | | | // | multiplied by the returned | | | // | value) should match the | | | @@ -370,7 +374,7 @@ typedef struct buffer_provider_s { // structure that defines both input and output buffer configurations and is // passed by the EFFECT_CMD_CONFIGURE command. typedef struct buffer_config_s { - audio_buffer_t buffer; // buffer for use by process() function is not passed explicitly + audio_buffer_t buffer; // buffer for use by process() function if not passed explicitly uint32_t samplingRate; // sampling rate uint32_t channels; // channel mask (see audio_channels_e in AudioCommon.h) buffer_provider_t bufferProvider; // buffer provider @@ -457,7 +461,7 @@ typedef struct effect_param_s { // // Function: EffectQueryNumberEffects // -// Description: Returns the number of different effect exposed by the +// Description: Returns the number of different effects exposed by the // library. Each effect must have a unique effect uuid (see // effect_descriptor_t). This function together with EffectQueryNext() // is used to enumerate all effects present in the library. @@ -475,7 +479,7 @@ typedef struct effect_param_s { // *pNumEffects: updated with number of effects in library // //////////////////////////////////////////////////////////////////////////////// -typedef int32_t (*effect_QueryNumberEffects_t)(int32_t *pNumEffects); +typedef int32_t (*effect_QueryNumberEffects_t)(uint32_t *pNumEffects); //////////////////////////////////////////////////////////////////////////////// // @@ -521,7 +525,7 @@ typedef int32_t (*effect_QueryNextEffect_t)(effect_descriptor_t *pDescriptor); // returned value: 0 successful operation. // -ENODEV library failed to initialize // -EINVAL invalid pEffectUuid or pInterface -// -ENOENT No effect with this uuid found +// -ENOENT no effect with this uuid found // *pInterface: updated with the effect interface handle. // //////////////////////////////////////////////////////////////////////////////// diff --git a/include/media/EffectFactoryApi.h b/include/media/EffectFactoryApi.h index 8179c23..6cc9932 100644 --- a/include/media/EffectFactoryApi.h +++ b/include/media/EffectFactoryApi.h @@ -34,7 +34,7 @@ extern "C" { // // Function: EffectQueryNumberEffects // -// Description: Returns the number of different effect in all loaded libraries. +// Description: Returns the number of different effects in all loaded libraries. // Each effect must have a different effect uuid (see // effect_descriptor_t). This function together with EffectQueryNext() // is used to enumerate all effects present in all loaded libraries. @@ -52,7 +52,7 @@ extern "C" { // *pNumEffects: updated with number of effects in factory // //////////////////////////////////////////////////////////////////////////////// -int EffectQueryNumberEffects(int *pNumEffects); +int EffectQueryNumberEffects(uint32_t *pNumEffects); //////////////////////////////////////////////////////////////////////////////// // @@ -98,7 +98,7 @@ int EffectQueryNext(effect_descriptor_t *pDescriptor); // returned value: 0 successful operation. // -ENODEV factory failed to initialize // -EINVAL invalid pEffectUuid or pInterface -// -ENOENT No effect with this uuid found +// -ENOENT no effect with this uuid found // *pInterface: updated with the effect interface. // //////////////////////////////////////////////////////////////////////////////// @@ -140,7 +140,7 @@ int EffectRelease(effect_interface_t interface); // // Output: // returned value: 0 successful operation. -// -ENODEV Effect factory not initialized or +// -ENODEV effect factory not initialized or // library could not be loaded or // library does not implement required functions // -EINVAL invalid libPath string or handle @@ -159,7 +159,7 @@ int EffectLoadLibrary(const char *libPath, int *handle); // // Output: // returned value: 0 successful operation. -// -ENODEV Effect factory not initialized +// -ENODEV effect factory not initialized // -ENOENT invalid handle // //////////////////////////////////////////////////////////////////////////////// @@ -184,7 +184,7 @@ int EffectUnloadLibrary(int handle); // returned value: 0 successful operation. // -ENODEV factory failed to initialize // -EINVAL invalid pEffectUuid or pDescriptor -// -ENOENT No effect with this uuid found +// -ENOENT no effect with this uuid found // *pDescriptor: updated with the effect descriptor. // //////////////////////////////////////////////////////////////////////////////// diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h index c147632..ccfa530 100644 --- a/include/media/IAudioFlinger.h +++ b/include/media/IAudioFlinger.h @@ -27,6 +27,9 @@ #include <media/IAudioTrack.h> #include <media/IAudioRecord.h> #include <media/IAudioFlingerClient.h> +#include <media/EffectApi.h> +#include <media/IEffect.h> +#include <media/IEffectClient.h> #include <utils/String8.h> namespace android { @@ -51,6 +54,7 @@ public: uint32_t flags, const sp<IMemory>& sharedBuffer, int output, + int *sessionId, status_t *status) = 0; virtual sp<IAudioRecord> openRecord( @@ -61,6 +65,7 @@ public: int channelCount, int frameCount, uint32_t flags, + int *sessionId, status_t *status) = 0; /* query the audio hardware state. This state never changes, @@ -134,6 +139,28 @@ public: virtual status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, int output) = 0; virtual unsigned int getInputFramesLost(int ioHandle) = 0; + + virtual int newAudioSessionId() = 0; + + virtual status_t loadEffectLibrary(const char *libPath, int *handle) = 0; + + virtual status_t unloadEffectLibrary(int handle) = 0; + + virtual status_t queryNumberEffects(uint32_t *numEffects) = 0; + + virtual status_t queryNextEffect(effect_descriptor_t *pDescriptor) = 0; + + virtual status_t getEffectDescriptor(effect_uuid_t *pEffectUUID, effect_descriptor_t *pDescriptor) = 0; + + virtual sp<IEffect> createEffect(pid_t pid, + effect_descriptor_t *pDesc, + const sp<IEffectClient>& client, + int32_t priority, + int output, + int sessionId, + status_t *status, + int *id, + int *enabled) = 0; }; diff --git a/include/media/IAudioTrack.h b/include/media/IAudioTrack.h index de6426a..47d530b 100644 --- a/include/media/IAudioTrack.h +++ b/include/media/IAudioTrack.h @@ -62,6 +62,11 @@ public: */ virtual void pause() = 0; + /* Attach track auxiliary output to specified effect. Use effectId = 0 + * to detach track from effect. + */ + virtual status_t attachAuxEffect(int effectId) = 0; + /* get this tracks control block */ virtual sp<IMemory> getCblk() const = 0; }; diff --git a/include/private/media/AudioEffectShared.h b/include/private/media/AudioEffectShared.h new file mode 100644 index 0000000..a3a99a4 --- /dev/null +++ b/include/private/media/AudioEffectShared.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_EFFECTCBASESHARED_H +#define ANDROID_EFFECTCBASESHARED_H + +#include <stdint.h> +#include <sys/types.h> + +#include <utils/threads.h> + +namespace android { + +// ---------------------------------------------------------------------------- + +// Size of buffer used to exchange parameters between application and mediaserver processes. +#define EFFECT_PARAM_BUFFER_SIZE 1024 + + +// Shared memory area used to exchange parameters between application and mediaserver +// process. +struct effect_param_cblk_t +{ + Mutex lock; + volatile uint32_t clientIndex; // Current read/write index for application + volatile uint32_t serverIndex; // Current read/write index for mediaserver + uint8_t* buffer; // start of parameter buffer + + effect_param_cblk_t() + : lock(Mutex::SHARED), clientIndex(0), serverIndex(0) {} +}; + + +// ---------------------------------------------------------------------------- + +}; // namespace android + +#endif // ANDROID_EFFECTCBASESHARED_H diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h index cd47fdf..1510f87 100644 --- a/include/private/media/AudioTrackShared.h +++ b/include/private/media/AudioTrackShared.h @@ -78,7 +78,8 @@ struct audio_track_cblk_t uint16_t bufferTimeoutMs; // Maximum cumulated timeout before restarting audioflinger uint16_t waitTimeMs; // Cumulated wait time - uint32_t reserved; + uint16_t sendLevel; + uint16_t reserved; // Cache line boundary (32 bytes) audio_track_cblk_t(); uint32_t stepUser(uint32_t frameCount); diff --git a/media/libeffects/EffectEqualizer.cpp b/media/libeffects/EffectEqualizer.cpp index c08f4f5..e39e595 100644 --- a/media/libeffects/EffectEqualizer.cpp +++ b/media/libeffects/EffectEqualizer.cpp @@ -114,7 +114,7 @@ int Equalizer_setParameter(AudioEqualizer * pEqualizer, int32_t *pParam, void *p //--- Effect Library Interface Implementation // -extern "C" int EffectQueryNumberEffects(int *pNumEffects) { +extern "C" int EffectQueryNumberEffects(uint32_t *pNumEffects) { *pNumEffects = 1; gEffectIndex = 0; return 0; diff --git a/media/libeffects/EffectReverb.c b/media/libeffects/EffectReverb.c index 3181504..202f50b 100644 --- a/media/libeffects/EffectReverb.c +++ b/media/libeffects/EffectReverb.c @@ -18,7 +18,8 @@ // #define LOG_NDEBUG 0 #include <cutils/log.h> - +#include <stdlib.h> +#include <string.h> #include <stdbool.h> #include "EffectReverb.h" #include "EffectsMath.h" @@ -86,7 +87,7 @@ static const effect_descriptor_t * const gDescriptors[] = { /*--- Effect Library Interface Implementation ---*/ -int EffectQueryNumberEffects(int *pNumEffects) { +int EffectQueryNumberEffects(uint32_t *pNumEffects) { *pNumEffects = sizeof(gDescriptors) / sizeof(const effect_descriptor_t *) - 1; gEffectIndex = 0; diff --git a/media/libeffects/EffectReverb.h b/media/libeffects/EffectReverb.h index cd14891..578e09e 100644 --- a/media/libeffects/EffectReverb.h +++ b/media/libeffects/EffectReverb.h @@ -292,7 +292,7 @@ typedef struct reverb_module_s { * Effect API *------------------------------------ */ -int EffectQueryNumberEffects(int *pNumEffects); +int EffectQueryNumberEffects(uint32_t *pNumEffects); int EffectQueryNext(effect_descriptor_t *pDescriptor); int EffectCreate(effect_uuid_t *effectUID, effect_interface_t *pInterface); int EffectRelease(effect_interface_t interface); diff --git a/media/libeffects/EffectsFactory.c b/media/libeffects/EffectsFactory.c index 35a1001..6800765 100644 --- a/media/libeffects/EffectsFactory.c +++ b/media/libeffects/EffectsFactory.c @@ -39,7 +39,7 @@ static int gInitDone; // true is global initialization has been preformed static int init(); static int loadLibrary(const char *libPath, int *handle); static int unloadLibrary(int handle); -static int numEffectModules(); +static uint32_t numEffectModules(); static int findEffect(effect_uuid_t *uuid, lib_entry_t **lib, effect_descriptor_t **desc); static void dumpEffectDescriptor(effect_descriptor_t *desc, char *str, size_t len); @@ -96,7 +96,7 @@ const struct effect_interface_s gInterface = { // Effect Factory Interface functions ///////////////////////////////////////////////// -int EffectQueryNumberEffects(int *pNumEffects) +int EffectQueryNumberEffects(uint32_t *pNumEffects) { int ret = init(); if (ret < 0) { @@ -353,8 +353,8 @@ int loadLibrary(const char *libPath, int *handle) effect_QueryNextEffect_t queryFx; effect_CreateEffect_t createFx; effect_ReleaseEffect_t releaseFx; - int numFx; - int fx; + uint32_t numFx; + uint32_t fx; int ret; list_elem_t *e, *descHead = NULL; lib_entry_t *l; @@ -525,9 +525,9 @@ int unloadLibrary(int handle) -int numEffectModules() { +uint32_t numEffectModules() { list_elem_t *e = gLibraryList; - int cnt = 0; + uint32_t cnt = 0; // Reset pointers for EffectQueryNext() gCurLib = e; diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index fd2b1ce..a2436ab 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -45,7 +45,7 @@ namespace android { // --------------------------------------------------------------------------- AudioRecord::AudioRecord() - : mStatus(NO_INIT) + : mStatus(NO_INIT), mSessionId(0) { } @@ -58,11 +58,12 @@ AudioRecord::AudioRecord( uint32_t flags, callback_t cbf, void* user, - int notificationFrames) - : mStatus(NO_INIT) + int notificationFrames, + int sessionId) + : mStatus(NO_INIT), mSessionId(0) { mStatus = set(inputSource, sampleRate, format, channels, - frameCount, flags, cbf, user, notificationFrames); + frameCount, flags, cbf, user, notificationFrames, sessionId); } AudioRecord::~AudioRecord() @@ -91,7 +92,8 @@ status_t AudioRecord::set( callback_t cbf, void* user, int notificationFrames, - bool threadCanCallJava) + bool threadCanCallJava, + int sessionId) { LOGV("set(): sampleRate %d, channels %d, frameCount %d",sampleRate, channels, frameCount); @@ -119,6 +121,7 @@ status_t AudioRecord::set( if (!AudioSystem::isInputChannel(channels)) { return BAD_VALUE; } + int channelCount = AudioSystem::popCount(channels); audio_io_handle_t input = AudioSystem::getInput(inputSource, @@ -164,6 +167,8 @@ status_t AudioRecord::set( notificationFrames = frameCount/2; } + mSessionId = sessionId; + // create the IAudioRecord status_t status = openRecord(sampleRate, format, channelCount, frameCount, flags, input); @@ -414,6 +419,7 @@ status_t AudioRecord::openRecord( channelCount, frameCount, ((uint16_t)flags) << 16, + &mSessionId, &status); if (record == 0) { LOGE("AudioFlinger could not create record track, status: %d", status); @@ -532,6 +538,11 @@ audio_io_handle_t AudioRecord::getInput() return mInput; } +int AudioRecord::getSessionId() +{ + return mSessionId; +} + // ------------------------------------------------------------------------- ssize_t AudioRecord::read(void* buffer, size_t userSize) diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 5e6ce42..c77f551 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -364,6 +364,12 @@ unsigned int AudioSystem::getInputFramesLost(audio_io_handle_t ioHandle) { return result; } +int AudioSystem::newAudioSessionId() { + const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger(); + if (af == 0) return 0; + return af->newAudioSessionId(); +} + // --------------------------------------------------------------------------- void AudioSystem::AudioFlingerClient::binderDied(const wp<IBinder>& who) { diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index c350532..4b61131 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -58,7 +58,8 @@ AudioTrack::AudioTrack( uint32_t flags, callback_t cbf, void* user, - int notificationFrames) + int notificationFrames, + int sessionId) : mStatus(NO_INIT) { mStatus = set(streamType, sampleRate, format, channels, @@ -74,7 +75,8 @@ AudioTrack::AudioTrack( uint32_t flags, callback_t cbf, void* user, - int notificationFrames) + int notificationFrames, + int sessionId) : mStatus(NO_INIT) { mStatus = set(streamType, sampleRate, format, channels, @@ -110,7 +112,8 @@ status_t AudioTrack::set( void* user, int notificationFrames, const sp<IMemory>& sharedBuffer, - bool threadCanCallJava) + bool threadCanCallJava, + int sessionId) { LOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size()); @@ -171,8 +174,11 @@ status_t AudioTrack::set( mVolume[LEFT] = 1.0f; mVolume[RIGHT] = 1.0f; + mSendLevel = 0; mFrameCount = frameCount; mNotificationFramesReq = notificationFrames; + mSessionId = sessionId; + // create the IAudioTrack status_t status = createTrack(streamType, sampleRate, format, channelCount, frameCount, flags, sharedBuffer, output, true); @@ -396,19 +402,49 @@ bool AudioTrack::muted() const return mMuted; } -void AudioTrack::setVolume(float left, float right) +status_t AudioTrack::setVolume(float left, float right) { + if (left > 1.0f || right > 1.0f) { + return BAD_VALUE; + } + mVolume[LEFT] = left; mVolume[RIGHT] = right; // write must be atomic - mCblk->volumeLR = (int32_t(int16_t(left * 0x1000)) << 16) | int16_t(right * 0x1000); + mCblk->volumeLR = (uint32_t(uint16_t(right * 0x1000)) << 16) | uint16_t(left * 0x1000); + + return NO_ERROR; } void AudioTrack::getVolume(float* left, float* right) { - *left = mVolume[LEFT]; - *right = mVolume[RIGHT]; + if (left != NULL) { + *left = mVolume[LEFT]; + } + if (right != NULL) { + *right = mVolume[RIGHT]; + } +} + +status_t AudioTrack::setSendLevel(float level) +{ + if (level > 1.0f) { + return BAD_VALUE; + } + + mSendLevel = level; + + mCblk->sendLevel = uint16_t(level * 0x1000); + + return NO_ERROR; +} + +void AudioTrack::getSendLevel(float* level) +{ + if (level != NULL) { + *level = mSendLevel; + } } status_t AudioTrack::setSampleRate(int rate) @@ -563,6 +599,16 @@ audio_io_handle_t AudioTrack::getOutput() mCblk->sampleRate, mFormat, mChannels, (AudioSystem::output_flags)mFlags); } +int AudioTrack::getSessionId() +{ + return mSessionId; +} + +status_t AudioTrack::attachAuxEffect(int effectId) +{ + return mAudioTrack->attachAuxEffect(effectId); +} + // ------------------------------------------------------------------------- status_t AudioTrack::createTrack( @@ -647,6 +693,7 @@ status_t AudioTrack::createTrack( ((uint16_t)flags) << 16, sharedBuffer, output, + &mSessionId, &status); if (track == 0) { @@ -672,7 +719,8 @@ status_t AudioTrack::createTrack( mCblk->stepUser(mCblk->frameCount); } - mCblk->volumeLR = (int32_t(int16_t(mVolume[LEFT] * 0x1000)) << 16) | int16_t(mVolume[RIGHT] * 0x1000); + mCblk->volumeLR = (uint32_t(uint16_t(mVolume[RIGHT] * 0x1000)) << 16) | uint16_t(mVolume[LEFT] * 0x1000); + mCblk->sendLevel = uint16_t(mSendLevel * 0x1000); mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS; mCblk->waitTimeMs = 0; mRemainingFrames = mNotificationFramesAct; @@ -1016,7 +1064,7 @@ audio_track_cblk_t::audio_track_cblk_t() : lock(Mutex::SHARED), cv(Condition::SHARED), user(0), server(0), userBase(0), serverBase(0), buffers(0), frameCount(0), loopStart(UINT_MAX), loopEnd(UINT_MAX), loopCount(0), volumeLR(0), - flags(0) + flags(0), sendLevel(0) { } diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp index 47bcc12..f2a8db3 100644 --- a/media/libmedia/IAudioFlinger.cpp +++ b/media/libmedia/IAudioFlinger.cpp @@ -62,7 +62,14 @@ enum { SET_STREAM_OUTPUT, SET_VOICE_VOLUME, GET_RENDER_POSITION, - GET_INPUT_FRAMES_LOST + GET_INPUT_FRAMES_LOST, + NEW_AUDIO_SESSION_ID, + LOAD_EFFECT_LIBRARY, + UNLOAD_EFFECT_LIBRARY, + QUERY_NUM_EFFECTS, + QUERY_NEXT_EFFECT, + GET_EFFECT_DESCRIPTOR, + CREATE_EFFECT }; class BpAudioFlinger : public BpInterface<IAudioFlinger> @@ -83,6 +90,7 @@ public: uint32_t flags, const sp<IMemory>& sharedBuffer, int output, + int *sessionId, status_t *status) { Parcel data, reply; @@ -97,10 +105,19 @@ public: data.writeInt32(flags); data.writeStrongBinder(sharedBuffer->asBinder()); data.writeInt32(output); + int lSessionId = 0; + if (sessionId != NULL) { + lSessionId = *sessionId; + } + data.writeInt32(lSessionId); status_t lStatus = remote()->transact(CREATE_TRACK, data, &reply); if (lStatus != NO_ERROR) { LOGE("createTrack error: %s", strerror(-lStatus)); } else { + lSessionId = reply.readInt32(); + if (sessionId != NULL) { + *sessionId = lSessionId; + } lStatus = reply.readInt32(); track = interface_cast<IAudioTrack>(reply.readStrongBinder()); } @@ -118,6 +135,7 @@ public: int channelCount, int frameCount, uint32_t flags, + int *sessionId, status_t *status) { Parcel data, reply; @@ -130,10 +148,19 @@ public: data.writeInt32(channelCount); data.writeInt32(frameCount); data.writeInt32(flags); + int lSessionId = 0; + if (sessionId != NULL) { + lSessionId = *sessionId; + } + data.writeInt32(lSessionId); status_t lStatus = remote()->transact(OPEN_RECORD, data, &reply); if (lStatus != NO_ERROR) { LOGE("openRecord error: %s", strerror(-lStatus)); } else { + lSessionId = reply.readInt32(); + if (sessionId != NULL) { + *sessionId = lSessionId; + } lStatus = reply.readInt32(); record = interface_cast<IAudioRecord>(reply.readStrongBinder()); } @@ -497,6 +524,157 @@ public: remote()->transact(GET_INPUT_FRAMES_LOST, data, &reply); return reply.readInt32(); } + + virtual int newAudioSessionId() + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + status_t status = remote()->transact(NEW_AUDIO_SESSION_ID, data, &reply); + int id = 0; + if (status == NO_ERROR) { + id = reply.readInt32(); + } + return id; + } + + virtual status_t loadEffectLibrary(const char *libPath, int *handle) + { + if (libPath == NULL || handle == NULL) { + return BAD_VALUE; + } + *handle = 0; + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.writeCString(libPath); + status_t status = remote()->transact(LOAD_EFFECT_LIBRARY, data, &reply); + if (status == NO_ERROR) { + status = reply.readInt32(); + if (status == NO_ERROR) { + *handle = reply.readInt32(); + } + } + return status; + } + + virtual status_t unloadEffectLibrary(int handle) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.writeInt32(handle); + status_t status = remote()->transact(UNLOAD_EFFECT_LIBRARY, data, &reply); + if (status == NO_ERROR) { + status = reply.readInt32(); + } + return status; + } + + virtual status_t queryNumberEffects(uint32_t *numEffects) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + status_t status = remote()->transact(QUERY_NUM_EFFECTS, data, &reply); + if (status != NO_ERROR) { + return status; + } + status = reply.readInt32(); + if (status != NO_ERROR) { + return status; + } + if (numEffects) { + *numEffects = (uint32_t)reply.readInt32(); + } + return NO_ERROR; + } + + virtual status_t queryNextEffect(effect_descriptor_t *pDescriptor) + { + if (pDescriptor == NULL) { + return BAD_VALUE; + } + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + status_t status = remote()->transact(QUERY_NEXT_EFFECT, data, &reply); + if (status != NO_ERROR) { + return status; + } + status = reply.readInt32(); + if (status != NO_ERROR) { + return status; + } + reply.read(pDescriptor, sizeof(effect_descriptor_t)); + return NO_ERROR; + } + + virtual status_t getEffectDescriptor(effect_uuid_t *pUuid, effect_descriptor_t *pDescriptor) + { + if (pUuid == NULL || pDescriptor == NULL) { + return BAD_VALUE; + } + Parcel data, reply; + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.write(pUuid, sizeof(effect_uuid_t)); + status_t status = remote()->transact(GET_EFFECT_DESCRIPTOR, data, &reply); + if (status != NO_ERROR) { + return status; + } + status = reply.readInt32(); + if (status != NO_ERROR) { + return status; + } + reply.read(pDescriptor, sizeof(effect_descriptor_t)); + return NO_ERROR; + } + + virtual sp<IEffect> createEffect(pid_t pid, + effect_descriptor_t *pDesc, + const sp<IEffectClient>& client, + int32_t priority, + int output, + int sessionId, + status_t *status, + int *id, + int *enabled) + { + Parcel data, reply; + sp<IEffect> effect; + + if (pDesc == NULL) { + return effect; + if (status) { + *status = BAD_VALUE; + } + } + + data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor()); + data.writeInt32(pid); + data.write(pDesc, sizeof(effect_descriptor_t)); + data.writeStrongBinder(client->asBinder()); + data.writeInt32(priority); + data.writeInt32(output); + data.writeInt32(sessionId); + + status_t lStatus = remote()->transact(CREATE_EFFECT, data, &reply); + if (lStatus != NO_ERROR) { + LOGE("createEffect error: %s", strerror(-lStatus)); + } else { + lStatus = reply.readInt32(); + int tmp = reply.readInt32(); + if (id) { + *id = tmp; + } + tmp = reply.readInt32(); + if (enabled) { + *enabled = tmp; + } + effect = interface_cast<IEffect>(reply.readStrongBinder()); + reply.read(pDesc, sizeof(effect_descriptor_t)); + } + if (status) { + *status = lStatus; + } + + return effect; + } }; IMPLEMENT_META_INTERFACE(AudioFlinger, "android.media.IAudioFlinger"); @@ -518,10 +696,12 @@ status_t BnAudioFlinger::onTransact( uint32_t flags = data.readInt32(); sp<IMemory> buffer = interface_cast<IMemory>(data.readStrongBinder()); int output = data.readInt32(); + int sessionId = data.readInt32(); status_t status; sp<IAudioTrack> track = createTrack(pid, streamType, sampleRate, format, - channelCount, bufferCount, flags, buffer, output, &status); + channelCount, bufferCount, flags, buffer, output, &sessionId, &status); + reply->writeInt32(sessionId); reply->writeInt32(status); reply->writeStrongBinder(track->asBinder()); return NO_ERROR; @@ -535,9 +715,11 @@ status_t BnAudioFlinger::onTransact( int channelCount = data.readInt32(); size_t bufferCount = data.readInt32(); uint32_t flags = data.readInt32(); + int sessionId = data.readInt32(); status_t status; sp<IAudioRecord> record = openRecord(pid, input, - sampleRate, format, channelCount, bufferCount, flags, &status); + sampleRate, format, channelCount, bufferCount, flags, &sessionId, &status); + reply->writeInt32(sessionId); reply->writeInt32(status); reply->writeStrongBinder(record->asBinder()); return NO_ERROR; @@ -768,7 +950,79 @@ status_t BnAudioFlinger::onTransact( reply->writeInt32(getInputFramesLost(ioHandle)); return NO_ERROR; } break; + case NEW_AUDIO_SESSION_ID: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + reply->writeInt32(newAudioSessionId()); + return NO_ERROR; + } break; + case LOAD_EFFECT_LIBRARY: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + int handle; + status_t status = loadEffectLibrary(data.readCString(), &handle); + reply->writeInt32(status); + if (status == NO_ERROR) { + reply->writeInt32(handle); + } + return NO_ERROR; + } + case UNLOAD_EFFECT_LIBRARY: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + reply->writeInt32(unloadEffectLibrary(data.readInt32())); + return NO_ERROR; + } + case QUERY_NUM_EFFECTS: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + uint32_t numEffects; + status_t status = queryNumberEffects(&numEffects); + reply->writeInt32(status); + if (status == NO_ERROR) { + reply->writeInt32((int32_t)numEffects); + } + return NO_ERROR; + } + case QUERY_NEXT_EFFECT: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + effect_descriptor_t desc; + status_t status = queryNextEffect(&desc); + reply->writeInt32(status); + if (status == NO_ERROR) { + reply->write(&desc, sizeof(effect_descriptor_t)); + } + return NO_ERROR; + } + case GET_EFFECT_DESCRIPTOR: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + effect_uuid_t uuid; + data.read(&uuid, sizeof(effect_uuid_t)); + effect_descriptor_t desc; + status_t status = getEffectDescriptor(&uuid, &desc); + reply->writeInt32(status); + if (status == NO_ERROR) { + reply->write(&desc, sizeof(effect_descriptor_t)); + } + return NO_ERROR; + } + case CREATE_EFFECT: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + pid_t pid = data.readInt32(); + effect_descriptor_t desc; + data.read(&desc, sizeof(effect_descriptor_t)); + sp<IEffectClient> client = interface_cast<IEffectClient>(data.readStrongBinder()); + int32_t priority = data.readInt32(); + int output = data.readInt32(); + int sessionId = data.readInt32(); + status_t status; + int id; + int enabled; + sp<IEffect> effect = createEffect(pid, &desc, client, priority, output, sessionId, &status, &id, &enabled); + reply->writeInt32(status); + reply->writeInt32(id); + reply->writeInt32(enabled); + reply->writeStrongBinder(effect->asBinder()); + reply->write(&desc, sizeof(effect_descriptor_t)); + return NO_ERROR; + } break; default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/media/libmedia/IAudioTrack.cpp b/media/libmedia/IAudioTrack.cpp index 01ffd75..bc8ff34 100644 --- a/media/libmedia/IAudioTrack.cpp +++ b/media/libmedia/IAudioTrack.cpp @@ -34,7 +34,8 @@ enum { STOP, FLUSH, MUTE, - PAUSE + PAUSE, + ATTACH_AUX_EFFECT }; class BpAudioTrack : public BpInterface<IAudioTrack> @@ -97,7 +98,21 @@ public: cblk = interface_cast<IMemory>(reply.readStrongBinder()); } return cblk; - } + } + + virtual status_t attachAuxEffect(int effectId) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); + data.writeInt32(effectId); + status_t status = remote()->transact(ATTACH_AUX_EFFECT, data, &reply); + if (status == NO_ERROR) { + status = reply.readInt32(); + } else { + LOGW("attachAuxEffect() error: %s", strerror(-status)); + } + return status; + } }; IMPLEMENT_META_INTERFACE(AudioTrack, "android.media.IAudioTrack"); @@ -138,6 +153,11 @@ status_t BnAudioTrack::onTransact( pause(); return NO_ERROR; } + case ATTACH_AUX_EFFECT: { + CHECK_INTERFACE(IAudioTrack, data, reply); + reply->writeInt32(attachAuxEffect(data.readInt32())); + return NO_ERROR; + } break; default: return BBinder::onTransact(code, data, reply, flags); } |