Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 845f5414 authored by Eric Laurent's avatar Eric Laurent Committed by Android Git Automerger
Browse files

am 2c2ce8e5: Merge "Added support for audio sessions in MediaPlayer and...

am 2c2ce8e5: Merge "Added support for audio sessions in MediaPlayer and AudioTrack." into gingerbread

Merge commit '2c2ce8e5' into gingerbread-plus-aosp

* commit '2c2ce8e5':
  Added support for audio sessions in MediaPlayer and AudioTrack.
parents da9269af 2c2ce8e5
Loading
Loading
Loading
Loading
+29 −4
Original line number Diff line number Diff line
@@ -166,7 +166,7 @@ static void audioCallback(int event, void* user, void *info) {
static int
android_media_AudioTrack_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,
        jint streamType, jint sampleRateInHertz, jint channels,
        jint audioFormat, jint buffSizeInBytes, jint memoryMode)
        jint audioFormat, jint buffSizeInBytes, jint memoryMode, jintArray jSession)
{
    LOGV("sampleRate=%d, audioFormat(from Java)=%d, channels=%x, buffSize=%d",
        sampleRateInHertz, audioFormat, channels, buffSizeInBytes);
@@ -253,6 +253,20 @@ android_media_AudioTrack_native_setup(JNIEnv *env, jobject thiz, jobject weak_th
    
    lpJniStorage->mStreamType = atStreamType;
    
    jint* nSession = NULL;
    if (jSession) {
        nSession = (jint *) env->GetPrimitiveArrayCritical(jSession, NULL);
        if (nSession == NULL) {
            LOGE("Error creating AudioTrack: Error retrieving session id pointer");
            delete lpJniStorage;
            return AUDIOTRACK_ERROR;
        }
    } else {
        LOGE("Error creating AudioTrack: invalid session ID pointer");
        delete lpJniStorage;
        return AUDIOTRACK_ERROR;
    }

    // create the native AudioTrack object
    AudioTrack* lpTrack = new AudioTrack();
    if (lpTrack == NULL) {
@@ -273,7 +287,8 @@ android_media_AudioTrack_native_setup(JNIEnv *env, jobject thiz, jobject weak_th
            audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user)
            0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack
            0,// shared mem
            true);// thread can call Java
            true,// thread can call Java
            nSession[0]);// audio session ID
            
    } else if (memoryMode == javaAudioTrackFields.MODE_STATIC) {
        // AudioTrack is using shared memory
@@ -293,7 +308,8 @@ android_media_AudioTrack_native_setup(JNIEnv *env, jobject thiz, jobject weak_th
            audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user));
            0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack 
            lpJniStorage->mMemBase,// shared mem
            true);// thread can call Java 
            true,// thread can call Java
            nSession[0]);// audio session ID
    }

    if (lpTrack->initCheck() != NO_ERROR) {
@@ -301,6 +317,12 @@ android_media_AudioTrack_native_setup(JNIEnv *env, jobject thiz, jobject weak_th
        goto native_init_failure;
    }

    // read the audio session ID back from AudioTrack in case we create a new session
    nSession[0] = lpTrack->getSessionId();

    env->ReleasePrimitiveArrayCritical(jSession, nSession, 0);
    nSession = NULL;

    // save our newly created C++ AudioTrack in the "nativeTrackInJavaObj" field 
    // of the Java object (in mNativeTrackInJavaObj)
    env->SetIntField(thiz, javaAudioTrackFields.nativeTrackInJavaObj, (int)lpTrack);
@@ -317,6 +339,9 @@ native_init_failure:
    env->SetIntField(thiz, javaAudioTrackFields.nativeTrackInJavaObj, 0);
    
native_track_failure:
    if (nSession != NULL) {
        env->ReleasePrimitiveArrayCritical(jSession, nSession, 0);
    }
    env->DeleteGlobalRef(lpJniStorage->mCallbackData.audioTrack_class);
    env->DeleteGlobalRef(lpJniStorage->mCallbackData.audioTrack_ref);
    delete lpJniStorage;
@@ -785,7 +810,7 @@ static JNINativeMethod gMethods[] = {
    {"native_stop",          "()V",      (void *)android_media_AudioTrack_stop},
    {"native_pause",         "()V",      (void *)android_media_AudioTrack_pause},
    {"native_flush",         "()V",      (void *)android_media_AudioTrack_flush},
    {"native_setup",         "(Ljava/lang/Object;IIIIII)I", 
    {"native_setup",         "(Ljava/lang/Object;IIIIII[I)I",
                                         (void *)android_media_AudioTrack_native_setup},
    {"native_finalize",      "()V",      (void *)android_media_AudioTrack_native_finalize},
    {"native_release",       "()V",      (void *)android_media_AudioTrack_native_release},
+5 −2
Original line number Diff line number Diff line
@@ -40,8 +40,11 @@ public:

    virtual sp<IMediaRecorder>  createMediaRecorder(pid_t pid) = 0;
    virtual sp<IMediaMetadataRetriever> createMetadataRetriever(pid_t pid) = 0;
    virtual sp<IMediaPlayer>    create(pid_t pid, const sp<IMediaPlayerClient>& client, const char* url, const KeyedVector<String8, String8> *headers = NULL) = 0;
    virtual sp<IMediaPlayer>    create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd, int64_t offset, int64_t length) = 0;
    virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client,
            const char* url, const KeyedVector<String8, String8> *headers = NULL,
            int audioSessionId = 0) = 0;
    virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client,
            int fd, int64_t offset, int64_t length, int audioSessionId) = 0;
    virtual sp<IMemory>         decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0;
    virtual sp<IMemory>         decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0;
    virtual sp<IOMX>            getOMX() = 0;
+3 −0
Original line number Diff line number Diff line
@@ -172,6 +172,8 @@ public:
            status_t        getMetadata(bool update_only, bool apply_filter, Parcel *metadata);
            status_t        suspend();
            status_t        resume();
            status_t        setAudioSessionId(int sessionId);
            int             getAudioSessionId();
private:
            void            clear_l();
            status_t        seekTo_l(int msec);
@@ -198,6 +200,7 @@ private:
    float                       mRightVolume;
    int                         mVideoWidth;
    int                         mVideoHeight;
    int                         mAudioSessionId;
};

}; // namespace android
+68 −2
Original line number Diff line number Diff line
@@ -210,6 +210,10 @@ public class AudioTrack
     * @see AudioFormat#ENCODING_PCM_16BIT
     */
    private int mAudioFormat = AudioFormat.ENCODING_PCM_16BIT;
    /**
     * Audio session ID
     */
    private int mSessionId = 0;


    //--------------------------------
@@ -257,6 +261,48 @@ public class AudioTrack
     */
    public AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat,
            int bufferSizeInBytes, int mode)
    throws IllegalArgumentException {
        this(streamType, sampleRateInHz, channelConfig, audioFormat,
                bufferSizeInBytes, mode, 0);
    }

    /**
     * Class constructor with audio session. Use this constructor when the AudioTrack must be
     * attached to a particular audio session. The primary use of the audio session ID is to
     * associate audio effects to a particular instance of AudioTrack: if an audio session ID
     * is provided when creating an AudioEffect, this effect will be applied only to audio tracks
     * and media players in the same session and not to the output mix.
     * When an AudioTrack is created without specifying a session, it will create its own session
     * which can be retreived by calling the {@link #getAudioSessionId()} method.
     * If a session ID is provided, this AudioTrack will share effects attached to this session
     * with all other media players or audio tracks in the same session.
     * @param streamType the type of the audio stream. See
     *   {@link AudioManager#STREAM_VOICE_CALL}, {@link AudioManager#STREAM_SYSTEM},
     *   {@link AudioManager#STREAM_RING}, {@link AudioManager#STREAM_MUSIC} and
     *   {@link AudioManager#STREAM_ALARM}
     * @param sampleRateInHz the sample rate expressed in Hertz. Examples of rates are (but
     *   not limited to) 44100, 22050 and 11025.
     * @param channelConfig describes the configuration of the audio channels.
     *   See {@link AudioFormat#CHANNEL_OUT_MONO} and
     *   {@link AudioFormat#CHANNEL_OUT_STEREO}
     * @param audioFormat the format in which the audio data is represented.
     *   See {@link AudioFormat#ENCODING_PCM_16BIT} and
     *   {@link AudioFormat#ENCODING_PCM_8BIT}
     * @param bufferSizeInBytes the total size (in bytes) of the buffer where audio data is read
     *   from for playback. If using the AudioTrack in streaming mode, you can write data into
     *   this buffer in smaller chunks than this size. If using the AudioTrack in static mode,
     *   this is the maximum size of the sound that will be played for this instance.
     *   See {@link #getMinBufferSize(int, int, int)} to determine the minimum required buffer size
     *   for the successful creation of an AudioTrack instance in streaming mode. Using values
     *   smaller than getMinBufferSize() will result in an initialization failure.
     * @param mode streaming or static buffer. See {@link #MODE_STATIC} and {@link #MODE_STREAM}
     * @param sessionId Id of audio session the AudioTrack must be attached to
     * @throws java.lang.IllegalArgumentException
     // FIXME: unhide.
     * @hide
     */
    public AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat,
            int bufferSizeInBytes, int mode, int sessionId)
    throws IllegalArgumentException {
        mState = STATE_UNINITIALIZED;
        
@@ -269,15 +315,23 @@ public class AudioTrack

        audioBuffSizeCheck(bufferSizeInBytes);

        if (sessionId < 0) {
            throw (new IllegalArgumentException("Invalid audio session ID: "+sessionId));
        }

        int[] session = new int[1];
        session[0] = sessionId;
        // native initialization
        int initResult = native_setup(new WeakReference<AudioTrack>(this),
                mStreamType, mSampleRate, mChannels, mAudioFormat,
                mNativeBufferSizeInBytes, mDataLoadMode);
                mNativeBufferSizeInBytes, mDataLoadMode, session);
        if (initResult != SUCCESS) {
            loge("Error code "+initResult+" when initializing AudioTrack.");
            return; // with mState == STATE_UNINITIALIZED
        }

        mSessionId = session[0];

        if (mDataLoadMode == MODE_STATIC) {
            mState = STATE_NO_STATIC_DATA;
        } else {
@@ -590,6 +644,17 @@ public class AudioTrack
        }
    }

    /**
     * Returns the audio session ID.
     *
     * @return the ID of the audio session this AudioTrack belongs to.
     // FIXME: unhide.
     // FIXME: link to AudioEffect class when public.
     * @hide
     */
    public int getAudioSessionId() {
        return mSessionId;
    }

    //--------------------------------------------------------------------------
    // Initialization / configuration
@@ -1012,7 +1077,7 @@ public class AudioTrack

    private native final int native_setup(Object audiotrack_this,
            int streamType, int sampleRate, int nbChannels, int audioFormat,
            int buffSizeInBytes, int mode);
            int buffSizeInBytes, int mode, int[] sessionId);

    private native final void native_finalize();

@@ -1056,6 +1121,7 @@ public class AudioTrack
    static private native final int native_get_min_buff_size(
            int sampleRateInHz, int channelConfig, int audioFormat);

    private native final int native_get_session_id();

    //---------------------------------------------------------
    // Utility methods
+44 −0
Original line number Diff line number Diff line
@@ -423,6 +423,18 @@ import java.lang.ref.WeakReference;
 *     <td>Successful invoke of this method in a valid state transfers the
 *         object to the <em>Stopped</em> state. Calling this method in an
 *         invalid state transfers the object to the <em>Error</em> state.</p></td></tr>
  * <tr><td>setAudioSessionId </p></td>
 *     <td>{Idle} </p></td>
 *     <td>{Initialized, Prepared, Started, Paused, Stopped, PlaybackCompleted,
 *          Error} </p></td>
 *     <td>This method must be called in idle state as the audio session ID must be known before
 *         calling setDataSource. Calling it does not change the object state. </p></td></tr>
 * <tr><td>getAudioSessionId </p></td>
 *     <td>any </p></td>
 *     <td>{} </p></td>
 *     <td>This method can be called in any state and calling it does not change
 *         the object state. </p></td></tr>
 *
 * </table>
 *
 * <a name="Permissions"></a>
@@ -1158,6 +1170,38 @@ public class MediaPlayer
     */
    public native Bitmap getFrameAt(int msec) throws IllegalStateException;

    /**
     * Sets the audio session ID.
     *
     * @param sessionId: the audio session ID.
     * The audio session ID is a system wide unique identifier for the audio stream played by
     * this MediaPlayer instance.
     * The primary use of the audio session ID  is to associate audio effects to a particular
     * instance of MediaPlayer: if an audio session ID is provided when creating an audio effect,
     * this effect will be applied only to the audio content of media players within the same
     * audio session and not to the output mix.
     * When created, a MediaPlayer instance automatically generates its own audio session ID.
     * However, it is possible to force this player to be part of an already existing audio session
     * by calling this method.
     * This method must be called before one of the overloaded <code> setDataSource </code> methods.
     * @throws IllegalStateException if it is called in an invalid state
     *
     // FIXME: unhide.
     // FIXME: link to AudioEffect class when public.
     * @hide
     */
    public native void setAudioSessionId(int sessionId)  throws IllegalArgumentException, IllegalStateException;

    /**
     * Returns the audio session ID.
     *
     * @return the audio session ID. {@see #setAudioSessionId(int)}.
     * Note that the audio session ID is 0 only if a problem occured when the MediaPlayer was contructed.
     // FIXME: unhide.
     * @hide
     */
    public native int getAudioSessionId();

    /**
     * @param request Parcel destinated to the media player. The
     *                Interface token must be set to the IMediaPlayer
Loading