OSDN Git Service

Bug 5080320 MediaPlayer volume
authorGlenn Kasten <gkasten@google.com>
Thu, 28 Jul 2011 15:45:22 +0000 (08:45 -0700)
committerGlenn Kasten <gkasten@google.com>
Mon, 1 Aug 2011 15:21:35 +0000 (08:21 -0700)
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

wilhelm/src/android/AudioPlayer_to_android.cpp
wilhelm/src/android/MediaPlayer_to_android.cpp
wilhelm/src/android/MediaPlayer_to_android.h
wilhelm/src/android/android_GenericMediaPlayer.cpp
wilhelm/src/android/android_GenericPlayer.h
wilhelm/src/classes.h
wilhelm/src/handler_bodies.c
wilhelm/src/itf/IEngine.c

index ff3b0cf..729a5ff 100644 (file)
@@ -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 ; i<AUX_MAX ; i++) {
+            if (ap->mEffectSend.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 ; i<AUX_MAX ; i++) {
-            if (ap->mEffectSend.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
index bbc60a6..e31fa7c 100644 (file)
@@ -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<android::GenericPlayer> &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);
+    }
 }
 
 //-----------------------------------------------------------------------------
index 6c6bef1..dca77fd 100644 (file)
@@ -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<android::GenericPlayer> &gp, IVolume *pVolItf);
+extern void android_Player_volumeUpdate(CMediaPlayer *mp);
 
 /**************************************************************************************************
  * Playback control and events
index 1049937..56a24d0 100644 (file)
@@ -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
index f0549ea..34795a0 100644 (file)
@@ -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__ */
index f0fbe71..7f0179f 100644 (file)
@@ -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
     /**
     /** 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<android::GenericPlayer> mAVPlayer;
     enum AndroidObjectType mAndroidObjType;
index 9e435b8..d39867b 100644 (file)
@@ -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;
 }
 
index 16f121f..71fddba 100644 (file)
@@ -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