Added support for auxiliary audio effects to AudioTrack and MediaPlayer.
Added methods to AudioTrack and MediaPlayer java classes to enable use of
auxiliary audio effects. The effect can be attached and detached by specifying its
ID and the send level controlled.
Change-Id: Ie74ff54a453096a742688476f612ce355543b6f3
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index ef537f4..4475d4a 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -261,8 +261,8 @@
/* 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);
+ status_t setAuxEffectSendLevel(float level);
+ void getAuxEffectSendLevel(float* level);
/* set sample rate for this track, mostly used for games' sound effects
*/
@@ -479,6 +479,7 @@
uint32_t mUpdatePeriod;
uint32_t mFlags;
int mSessionId;
+ int mAuxEffectId;
};
diff --git a/include/media/IMediaPlayer.h b/include/media/IMediaPlayer.h
index 2619691..af9a7ed 100644
--- a/include/media/IMediaPlayer.h
+++ b/include/media/IMediaPlayer.h
@@ -48,6 +48,8 @@
virtual status_t setVolume(float leftVolume, float rightVolume) = 0;
virtual status_t suspend() = 0;
virtual status_t resume() = 0;
+ virtual status_t setAuxEffectSendLevel(float level) = 0;
+ virtual status_t attachAuxEffect(int effectId) = 0;
// Invoke a generic method on the player by using opaque parcels
// for the request and reply.
diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h
index 4963f73..207191d 100644
--- a/include/media/mediaplayer.h
+++ b/include/media/mediaplayer.h
@@ -173,6 +173,8 @@
status_t resume();
status_t setAudioSessionId(int sessionId);
int getAudioSessionId();
+ status_t setAuxEffectSendLevel(float level);
+ status_t attachAuxEffect(int effectId);
private:
void clear_l();
status_t seekTo_l(int msec);
@@ -200,6 +202,7 @@
int mVideoWidth;
int mVideoHeight;
int mAudioSessionId;
+ float mSendLevel;
};
}; // namespace android
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 0f2093a..890786e 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -209,6 +209,7 @@
mFrameCount = frameCount;
mNotificationFramesReq = notificationFrames;
mSessionId = sessionId;
+ mAuxEffectId = 0;
// create the IAudioTrack
status_t status = createTrack(streamType, sampleRate, format, channelCount,
@@ -458,8 +459,9 @@
}
}
-status_t AudioTrack::setSendLevel(float level)
+status_t AudioTrack::setAuxEffectSendLevel(float level)
{
+ LOGV("setAuxEffectSendLevel(%f)", level);
if (level > 1.0f) {
return BAD_VALUE;
}
@@ -471,7 +473,7 @@
return NO_ERROR;
}
-void AudioTrack::getSendLevel(float* level)
+void AudioTrack::getAuxEffectSendLevel(float* level)
{
if (level != NULL) {
*level = mSendLevel;
@@ -637,7 +639,12 @@
status_t AudioTrack::attachAuxEffect(int effectId)
{
- return mAudioTrack->attachAuxEffect(effectId);
+ LOGV("attachAuxEffect(%d)", effectId);
+ status_t status = mAudioTrack->attachAuxEffect(effectId);
+ if (status == NO_ERROR) {
+ mAuxEffectId = effectId;
+ }
+ return status;
}
// -------------------------------------------------------------------------
@@ -752,6 +759,7 @@
mCblk->volumeLR = (uint32_t(uint16_t(mVolume[RIGHT] * 0x1000)) << 16) | uint16_t(mVolume[LEFT] * 0x1000);
mCblk->sendLevel = uint16_t(mSendLevel * 0x1000);
+ mAudioTrack->attachAuxEffect(mAuxEffectId);
mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
mCblk->waitTimeMs = 0;
mRemainingFrames = mNotificationFramesAct;
diff --git a/media/libmedia/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp
index ed792b3..0f55b19 100644
--- a/media/libmedia/IMediaPlayer.cpp
+++ b/media/libmedia/IMediaPlayer.cpp
@@ -45,6 +45,8 @@
GET_METADATA,
SUSPEND,
RESUME,
+ SET_AUX_EFFECT_SEND_LEVEL,
+ ATTACH_AUX_EFFECT
};
class BpMediaPlayer: public BpInterface<IMediaPlayer>
@@ -221,6 +223,24 @@
return reply.readInt32();
}
+
+ status_t setAuxEffectSendLevel(float level)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+ data.writeFloat(level);
+ remote()->transact(SET_AUX_EFFECT_SEND_LEVEL, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t attachAuxEffect(int effectId)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+ data.writeInt32(effectId);
+ remote()->transact(ATTACH_AUX_EFFECT, data, &reply);
+ return reply.readInt32();
+ }
};
IMPLEMENT_META_INTERFACE(MediaPlayer, "android.media.IMediaPlayer");
@@ -339,6 +359,16 @@
reply->setDataPosition(0);
return NO_ERROR;
} break;
+ case SET_AUX_EFFECT_SEND_LEVEL: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ reply->writeInt32(setAuxEffectSendLevel(data.readFloat()));
+ return NO_ERROR;
+ } break;
+ case ATTACH_AUX_EFFECT: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ reply->writeInt32(attachAuxEffect(data.readInt32()));
+ return NO_ERROR;
+ } break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index b43f75f..1c99ae5 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -270,6 +270,7 @@
MEDIA_PLAYER_PLAYBACK_COMPLETE | MEDIA_PLAYER_PAUSED ) ) ) {
mPlayer->setLooping(mLoop);
mPlayer->setVolume(mLeftVolume, mRightVolume);
+ mPlayer->setAuxEffectSendLevel(mSendLevel);
mCurrentState = MEDIA_PLAYER_STARTED;
status_t ret = mPlayer->start();
if (ret != NO_ERROR) {
@@ -523,6 +524,31 @@
return mAudioSessionId;
}
+status_t MediaPlayer::setAuxEffectSendLevel(float level)
+{
+ LOGV("MediaPlayer::setAuxEffectSendLevel(%f)", level);
+ Mutex::Autolock _l(mLock);
+ mSendLevel = level;
+ if (mPlayer != 0) {
+ return mPlayer->setAuxEffectSendLevel(level);
+ }
+ return OK;
+}
+
+status_t MediaPlayer::attachAuxEffect(int effectId)
+{
+ LOGV("MediaPlayer::attachAuxEffect(%d)", effectId);
+ Mutex::Autolock _l(mLock);
+ if (mPlayer == 0 ||
+ (mCurrentState & MEDIA_PLAYER_IDLE) ||
+ (mCurrentState == MEDIA_PLAYER_STATE_ERROR )) {
+ LOGE("attachAuxEffect called in state %d", mCurrentState);
+ return INVALID_OPERATION;
+ }
+
+ return mPlayer->attachAuxEffect(effectId);
+}
+
void MediaPlayer::notify(int msg, int ext1, int ext2)
{
LOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2);
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 5401ec0..b5972e7 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -329,6 +329,10 @@
snprintf(buffer, 255, " msec per frame(%f), latency (%d)\n",
mMsecsPerFrame, mLatency);
result.append(buffer);
+ snprintf(buffer, 255, " aux effect id(%d), send level (%f)\n",
+ mAuxEffectId, mSendLevel);
+ result.append(buffer);
+
::write(fd, result.string(), result.size());
if (mTrack != 0) {
mTrack->dump(fd, args);
@@ -1093,6 +1097,21 @@
return NO_ERROR;
}
+status_t MediaPlayerService::Client::setAuxEffectSendLevel(float level)
+{
+ LOGV("[%d] setAuxEffectSendLevel(%f)", mConnId, level);
+ Mutex::Autolock l(mLock);
+ if (mAudioOutput != 0) return mAudioOutput->setAuxEffectSendLevel(level);
+ return NO_ERROR;
+}
+
+status_t MediaPlayerService::Client::attachAuxEffect(int effectId)
+{
+ LOGV("[%d] attachAuxEffect(%d)", mConnId, effectId);
+ Mutex::Autolock l(mLock);
+ if (mAudioOutput != 0) return mAudioOutput->attachAuxEffect(effectId);
+ return NO_ERROR;
+}
void MediaPlayerService::Client::notify(void* cookie, int msg, int ext1, int ext2)
{
@@ -1285,6 +1304,8 @@
mRightVolume = 1.0;
mLatency = 0;
mMsecsPerFrame = 0;
+ mAuxEffectId = 0;
+ mSendLevel = 0.0;
setMinBufferCount();
}
@@ -1417,10 +1438,13 @@
LOGV("setVolume");
t->setVolume(mLeftVolume, mRightVolume);
+
mMsecsPerFrame = 1.e3 / (float) sampleRate;
mLatency = t->latency();
mTrack = t;
- return NO_ERROR;
+
+ t->setAuxEffectSendLevel(mSendLevel);
+ return t->attachAuxEffect(mAuxEffectId);;
}
void MediaPlayerService::AudioOutput::start()
@@ -1428,6 +1452,7 @@
LOGV("start");
if (mTrack) {
mTrack->setVolume(mLeftVolume, mRightVolume);
+ mTrack->setAuxEffectSendLevel(mSendLevel);
mTrack->start();
}
}
@@ -1481,6 +1506,26 @@
}
}
+status_t MediaPlayerService::AudioOutput::setAuxEffectSendLevel(float level)
+{
+ LOGV("setAuxEffectSendLevel(%f)", level);
+ mSendLevel = level;
+ if (mTrack) {
+ return mTrack->setAuxEffectSendLevel(level);
+ }
+ return NO_ERROR;
+}
+
+status_t MediaPlayerService::AudioOutput::attachAuxEffect(int effectId)
+{
+ LOGV("attachAuxEffect(%d)", effectId);
+ mAuxEffectId = effectId;
+ if (mTrack) {
+ return mTrack->attachAuxEffect(effectId);
+ }
+ return NO_ERROR;
+}
+
// static
void MediaPlayerService::AudioOutput::CallbackWrapper(
int event, void *cookie, void *info) {
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index 39f525e..a967ee2 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -91,6 +91,8 @@
virtual void close();
void setAudioStreamType(int streamType) { mStreamType = streamType; }
void setVolume(float left, float right);
+ status_t setAuxEffectSendLevel(float level);
+ status_t attachAuxEffect(int effectId);
virtual status_t dump(int fd, const Vector<String16>& args) const;
static bool isOnEmulator();
@@ -109,7 +111,8 @@
float mMsecsPerFrame;
uint32_t mLatency;
int mSessionId;
-
+ float mSendLevel;
+ int mAuxEffectId;
static bool mIsOnEmulator;
static int mMinBufferCount; // 12 for emulator; otherwise 4
@@ -221,6 +224,8 @@
Parcel *reply);
virtual status_t suspend();
virtual status_t resume();
+ virtual status_t setAuxEffectSendLevel(float level);
+ virtual status_t attachAuxEffect(int effectId);
sp<MediaPlayerBase> createPlayer(player_type playerType);