From: Glenn Kasten Date: Thu, 28 Jul 2011 15:45:22 +0000 (-0700) Subject: Bug 5080320 MediaPlayer volume X-Git-Tag: android-x86-7.1-r1~847^2 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=0afa0fdcde5876941eaefaacc778984ec4efefa0;p=android-x86%2Fsystem-media.git Bug 5080320 MediaPlayer volume Details: - re-factor volume-related code yet again - remove dead variables mAmplFromVolLevel, mAmplFromStereoPos, mDirectLevel - add placeholders for kEventPrefetchFillLevelUpdate and kEventPrefetchStatusChange Known issues: - MPEG-2 TS doesn't yet implement the ability to query channel count, so default to stereo Change-Id: Ic0f2297b267dc3d380755e8d314e1d5f0f659d7c --- diff --git a/wilhelm/src/android/AudioPlayer_to_android.cpp b/wilhelm/src/android/AudioPlayer_to_android.cpp index ff3b0cf2..729a5ffc 100644 --- a/wilhelm/src/android/AudioPlayer_to_android.cpp +++ b/wilhelm/src/android/AudioPlayer_to_android.cpp @@ -186,7 +186,7 @@ void android_audioPlayer_volumeUpdate(CAudioPlayer* ap) assert(ap != NULL); // the source's channel count, where zero means unknown - int channelCount = ap->mNumChannels; + SLuint8 channelCount = ap->mNumChannels; // whether each channel is audible bool leftAudibilityFactor, rightAudibilityFactor; @@ -239,41 +239,98 @@ void android_audioPlayer_volumeUpdate(CAudioPlayer* ap) rightAudibilityFactor = true; } + // compute volumes without setting + const bool audibilityFactors[2] = {leftAudibilityFactor, rightAudibilityFactor}; + float volumes[2]; + android_player_volumeUpdate(volumes, &ap->mVolume, channelCount, ap->mAmplFromDirectLevel, + audibilityFactors); + float leftVol = volumes[0], rightVol = volumes[1]; + + // set volume on the underlying media player or audio track + if (ap->mAPlayer != 0) { + ap->mAPlayer->setVolume(leftVol, rightVol); + } else if (ap->mAudioTrack != 0) { + ap->mAudioTrack->setVolume(leftVol, rightVol); + } + + // changes in the AudioPlayer volume must be reflected in the send level: + // in SLEffectSendItf or in SLAndroidEffectSendItf? + // FIXME replace interface test by an internal API once we have one. + if (NULL != ap->mEffectSend.mItf) { + for (unsigned int i=0 ; imEffectSend.mEnableLevels[i].mEnable) { + android_fxSend_setSendLevel(ap, + ap->mEffectSend.mEnableLevels[i].mSendLevel + ap->mVolume.mLevel); + // there's a single aux bus on Android, so we can stop looking once the first + // aux effect is found. + break; + } + } + } else if (NULL != ap->mAndroidEffectSend.mItf) { + android_fxSend_setSendLevel(ap, ap->mAndroidEffectSend.mSendLevel + ap->mVolume.mLevel); + } +} + +// Called by android_audioPlayer_volumeUpdate and android_mediaPlayer_volumeUpdate to compute +// volumes, but setting volumes is handled by the caller. + +void android_player_volumeUpdate(float *pVolumes /*[2]*/, const IVolume *volumeItf, unsigned +channelCount, float amplFromDirectLevel, const bool *audibilityFactors /*[2]*/) +{ + assert(pVolumes != NULL); + assert(volumeItf != NULL); + // OK for audibilityFactors to be NULL + + bool leftAudibilityFactor, rightAudibilityFactor; + // apply player mute factor // note that AudioTrack has mute() but not MediaPlayer, so it's easier to use volume - if (ap->mVolume.mMute) { + // to mute for both rather than calling mute() for AudioTrack + + // player is muted + if (volumeItf->mMute) { leftAudibilityFactor = false; rightAudibilityFactor = false; + // player isn't muted, and channel mute/solo audibility factors are available (AudioPlayer) + } else if (audibilityFactors != NULL) { + leftAudibilityFactor = audibilityFactors[0]; + rightAudibilityFactor = audibilityFactors[1]; + // player isn't muted, and channel mute/solo audibility factors aren't available (MediaPlayer) + } else { + leftAudibilityFactor = true; + rightAudibilityFactor = true; } // compute amplification as the combination of volume level and stereo position - // amplification from volume level - ap->mAmplFromVolLevel = sles_to_android_amplification(ap->mVolume.mLevel); + // amplification (or attenuation) from volume level + float amplFromVolLevel = sles_to_android_amplification(volumeItf->mLevel); // amplification from direct level (changed in SLEffectSendtItf and SLAndroidEffectSendItf) - float leftVol = ap->mAmplFromVolLevel * ap->mAmplFromDirectLevel; - float rightVol = ap->mAmplFromVolLevel * ap->mAmplFromDirectLevel; + float leftVol = amplFromVolLevel * amplFromDirectLevel; + float rightVol = leftVol; // amplification from stereo position - if (ap->mVolume.mEnableStereoPosition) { - // panning law depends on number of channels of content: stereo panning vs 2ch. balance - if(1 == channelCount) { - // stereo panning - double theta = (1000+ap->mVolume.mStereoPosition)*M_PI_4/1000.0f; // 0 <= theta <= Pi/2 - ap->mAmplFromStereoPos[0] = cos(theta); - ap->mAmplFromStereoPos[1] = sin(theta); + if (volumeItf->mEnableStereoPosition) { + // Left/right amplification (can be attenuations) factors derived for the StereoPosition + float amplFromStereoPos[STEREO_CHANNELS]; + // panning law depends on content channel count: mono to stereo panning vs stereo balance + if (1 == channelCount) { + // mono to stereo panning + double theta = (1000+volumeItf->mStereoPosition)*M_PI_4/1000.0f; // 0 <= theta <= Pi/2 + amplFromStereoPos[0] = cos(theta); + amplFromStereoPos[1] = sin(theta); // channel count is 0 (unknown), 2 (stereo), or > 2 (multi-channel) } else { // stereo balance - if (ap->mVolume.mStereoPosition > 0) { - ap->mAmplFromStereoPos[0] = (1000-ap->mVolume.mStereoPosition)/1000.0f; - ap->mAmplFromStereoPos[1] = 1.0f; + if (volumeItf->mStereoPosition > 0) { + amplFromStereoPos[0] = (1000-volumeItf->mStereoPosition)/1000.0f; + amplFromStereoPos[1] = 1.0f; } else { - ap->mAmplFromStereoPos[0] = 1.0f; - ap->mAmplFromStereoPos[1] = (1000+ap->mVolume.mStereoPosition)/1000.0f; + amplFromStereoPos[0] = 1.0f; + amplFromStereoPos[1] = (1000+volumeItf->mStereoPosition)/1000.0f; } } - leftVol *= ap->mAmplFromStereoPos[0]; - rightVol *= ap->mAmplFromStereoPos[1]; + leftVol *= amplFromStereoPos[0]; + rightVol *= amplFromStereoPos[1]; } // apply audibility factors @@ -284,29 +341,9 @@ void android_audioPlayer_volumeUpdate(CAudioPlayer* ap) rightVol = 0.0; } - // set volume on the underlying media player or audio track - if (ap->mAPlayer != 0) { - ap->mAPlayer->setVolume(leftVol, rightVol); - } else if (ap->mAudioTrack != 0) { - ap->mAudioTrack->setVolume(leftVol, rightVol); - } - - // changes in the AudioPlayer volume must be reflected in the send level: - // in SLEffectSendItf or in SLAndroidEffectSendItf? - // FIXME replace interface test by an internal API once we have one. - if (NULL != ap->mEffectSend.mItf) { - for (unsigned int i=0 ; imEffectSend.mEnableLevels[i].mEnable) { - android_fxSend_setSendLevel(ap, - ap->mEffectSend.mEnableLevels[i].mSendLevel + ap->mVolume.mLevel); - // there's a single aux bus on Android, so we can stop looking once the first - // aux effect is found. - break; - } - } - } else if (NULL != ap->mAndroidEffectSend.mItf) { - android_fxSend_setSendLevel(ap, ap->mAndroidEffectSend.mSendLevel + ap->mVolume.mLevel); - } + // return the computed volumes + pVolumes[0] = leftVol; + pVolumes[1] = rightVol; } //----------------------------------------------------------------------------- @@ -1224,9 +1261,6 @@ SLresult android_audioPlayer_create(CAudioPlayer *pAudioPlayer) { // mAuxEffect pAudioPlayer->mAuxSendLevel = 0; - pAudioPlayer->mAmplFromVolLevel = 1.0f; - pAudioPlayer->mAmplFromStereoPos[0] = 1.0f; - pAudioPlayer->mAmplFromStereoPos[1] = 1.0f; pAudioPlayer->mAmplFromDirectLevel = 1.0f; // matches initial mDirectLevel value pAudioPlayer->mDeferredStart = false; // Already initialized in IEngine_CreateAudioPlayer, to be consolidated diff --git a/wilhelm/src/android/MediaPlayer_to_android.cpp b/wilhelm/src/android/MediaPlayer_to_android.cpp index bbc60a6a..e31fa7c8 100644 --- a/wilhelm/src/android/MediaPlayer_to_android.cpp +++ b/wilhelm/src/android/MediaPlayer_to_android.cpp @@ -123,6 +123,28 @@ static void player_handleMediaPlayerEventNotifications(int event, int data1, int break; } + case android::GenericPlayer::kEventChannelCount: { + SL_LOGV("kEventChannelCount channels = %d", data1); + object_lock_exclusive(&mp->mObject); + if (UNKNOWN_NUMCHANNELS == mp->mNumChannels && UNKNOWN_NUMCHANNELS != data1) { + mp->mNumChannels = data1; + android_Player_volumeUpdate(mp); + } + object_unlock_exclusive(&mp->mObject); + } + break; + + case android::GenericPlayer::kEventPrefetchFillLevelUpdate: { + SL_LOGV("kEventPrefetchFillLevelUpdate"); + } + break; + + case android::GenericPlayer::kEventPrefetchStatusChange: { + SL_LOGV("kEventPrefetchStatusChange"); + } + break; + + default: { SL_LOGE("Received unknown event %d, data %d from AVPlayer", event, data1); } @@ -224,8 +246,6 @@ XAresult android_Player_create(CMediaPlayer *mp) { mp->mStreamType = ANDROID_DEFAULT_OUTPUT_STREAM_TYPE; mp->mSessionId = android::AudioSystem::newAudioSessionId(); - mp->mDirectLevel = 0; // no attenuation - return result; } @@ -387,20 +407,18 @@ XAresult android_Player_getPosition(IPlay *pPlayItf, XAmillisecond *pPosMsec) { //----------------------------------------------------------------------------- /** - * pre-condition: avp != 0, pVolItf != NULL + * pre-condition: mp != NULL */ -XAresult android_Player_volumeUpdate(const android::sp &gp, - IVolume *pVolItf) +void android_Player_volumeUpdate(CMediaPlayer* mp) { - XAresult result = XA_RESULT_SUCCESS; - - // FIXME broken -#if 0 - gp->setVolume((bool)pVolItf->mMute, (bool)pVolItf->mEnableStereoPosition, - pVolItf->mStereoPosition, pVolItf->mLevel); -#endif - - return result; + android::GenericPlayer* avp = mp->mAVPlayer.get(); + if (avp != NULL) { + float volumes[2]; + // MediaPlayer does not currently support EffectSend or MuteSolo + android_player_volumeUpdate(volumes, &mp->mVolume, mp->mNumChannels, 1.0f, NULL); + float leftVol = volumes[0], rightVol = volumes[1]; + avp->setVolume(leftVol, rightVol); + } } //----------------------------------------------------------------------------- diff --git a/wilhelm/src/android/MediaPlayer_to_android.h b/wilhelm/src/android/MediaPlayer_to_android.h index 6c6bef14..dca77fdf 100644 --- a/wilhelm/src/android/MediaPlayer_to_android.h +++ b/wilhelm/src/android/MediaPlayer_to_android.h @@ -57,10 +57,9 @@ extern XAresult android_Player_getDuration(IPlay *pPlayItf, SLmillisecond *pDurM extern XAresult android_Player_getPosition(IPlay *pPlayItf, SLmillisecond *pPosMsec); /** - * pre-condition: gp != 0, pVolItf != NULL + * pre-condition: mp != NULL */ -extern XAresult android_Player_volumeUpdate( - const android::sp &gp, IVolume *pVolItf); +extern void android_Player_volumeUpdate(CMediaPlayer *mp); /************************************************************************************************** * Playback control and events diff --git a/wilhelm/src/android/android_GenericMediaPlayer.cpp b/wilhelm/src/android/android_GenericMediaPlayer.cpp index 1049937d..56a24d0f 100644 --- a/wilhelm/src/android/android_GenericMediaPlayer.cpp +++ b/wilhelm/src/android/android_GenericMediaPlayer.cpp @@ -443,12 +443,15 @@ void GenericMediaPlayer::onAfterMediaPlayerPrepared() { status_t status = mPlayer->getParameter(KEY_PARAMETER_AUDIO_CHANNEL_COUNT, reply); if (status == NO_ERROR) { mChannelCount = reply->readInt32(); - if (UNKNOWN_NUMCHANNELS != mChannelCount) { - // now that we know the channel count, re-calculate the volumes - notify(PLAYEREVENT_CHANNEL_COUNT, mChannelCount, true /*async*/); - } else { - LOGW("channel count is still unknown after prepare"); - } + } else { + // FIXME MPEG-2 TS doesn't yet implement this key, so default to stereo + mChannelCount = 2; + } + if (UNKNOWN_NUMCHANNELS != mChannelCount) { + // now that we know the channel count, re-calculate the volumes + notify(PLAYEREVENT_CHANNEL_COUNT, mChannelCount, true /*async*/); + } else { + LOGW("channel count is still unknown after prepare"); } delete reply; // retrieve duration diff --git a/wilhelm/src/android/android_GenericPlayer.h b/wilhelm/src/android/android_GenericPlayer.h index f0549eae..34795a08 100644 --- a/wilhelm/src/android/android_GenericPlayer.h +++ b/wilhelm/src/android/android_GenericPlayer.h @@ -171,4 +171,7 @@ private: } // namespace android +extern void android_player_volumeUpdate(float *pVolumes /*[2]*/, const IVolume *volumeItf, + unsigned channelCount, float amplFromDirectLevel, const bool *audibilityFactors /*[2]*/); + #endif /* __ANDROID_GENERICPLAYER_H__ */ diff --git a/wilhelm/src/classes.h b/wilhelm/src/classes.h index f0fbe71e..7f0179f1 100644 --- a/wilhelm/src/classes.h +++ b/wilhelm/src/classes.h @@ -73,6 +73,7 @@ SLuint8 mSoloMask; // Mask for which channels are soloed: bit 0=left, 1=right SLuint8 mNumChannels; // initially UNKNOWN_NUMCHANNELS, then const once it is known, // range 1 <= x <= 8 + // End of former IMuteSolo fields SLuint32 mSampleRateMilliHz;// initially UNKNOWN_SAMPLERATE, then const once it is known // Formerly at IEffectSend /** @@ -108,14 +109,6 @@ /** send level to aux effect, there's a single aux bus, so there's a single level */ SLmillibel mAuxSendLevel; /** - * Amplification (can be attenuation) factor derived for the VolumeLevel - */ - float mAmplFromVolLevel; - /** - * Left/right amplification (can be attenuations) factors derived for the StereoPosition - */ - float mAmplFromStereoPos[STEREO_CHANNELS]; - /** * Attenuation factor derived from direct level */ float mAmplFromDirectLevel; @@ -337,10 +330,8 @@ typedef struct CMediaPlayer_struct { DataLocatorFormat mImageVideoSink; DataLocatorFormat mVibraSink; DataLocatorFormat mLEDArraySink; - /** - * Dry volume modified by effect send interfaces: SLEffectSendItf and SLAndroidEffectSendItf - */ - SLmillibel mDirectLevel; + SLuint8 mNumChannels; // initially UNKNOWN_NUMCHANNELS, then const once it is known, + // range 1 <= x <= 8 #ifdef ANDROID android::sp mAVPlayer; enum AndroidObjectType mAndroidObjType; diff --git a/wilhelm/src/handler_bodies.c b/wilhelm/src/handler_bodies.c index 9e435b8d..d39867bc 100644 --- a/wilhelm/src/handler_bodies.c +++ b/wilhelm/src/handler_bodies.c @@ -51,10 +51,7 @@ unsigned handler_MidiPlayer_gain(IObject *thiz) unsigned handler_MediaPlayer_gain(IObject *thiz) { CMediaPlayer *mp = (CMediaPlayer *) thiz; - android::GenericPlayer* avp = mp->mAVPlayer.get(); - if (avp != NULL) { - android_Player_volumeUpdate(avp, &mp->mVolume); - } + android_Player_volumeUpdate(mp); return ATTR_GAIN; } diff --git a/wilhelm/src/itf/IEngine.c b/wilhelm/src/itf/IEngine.c index 16f121f6..71fddba9 100644 --- a/wilhelm/src/itf/IEngine.c +++ b/wilhelm/src/itf/IEngine.c @@ -1068,7 +1068,7 @@ static XAresult IEngine_CreateMediaPlayer(XAEngineItf self, XAObjectItf *pPlayer thiz->mImageVideoSink.mFormat.mFormatType = XA_DATAFORMAT_NULL; // More default values, in case destructor needs to be called early - thiz->mDirectLevel = 0; + thiz->mNumChannels = UNKNOWN_NUMCHANNELS; // (assume calloc or memset 0 during allocation) // placement new