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

Commit c1d54873 authored by Lajos Molnar's avatar Lajos Molnar Committed by Android (Google) Code Review
Browse files

Merge "media: use PlaybackSettings in MediaSync and MediaPlayer"

parents 58885cc6 b3d5fd25
Loading
Loading
Loading
Loading
+10 −2
Original line number Diff line number Diff line
@@ -15988,6 +15988,7 @@ package android.media {
    method public int getAudioSessionId();
    method public int getCurrentPosition();
    method public int getDuration();
    method public android.media.PlaybackSettings getPlaybackSettings();
    method public int getSelectedTrack(int) throws java.lang.IllegalStateException;
    method public android.media.MediaPlayer.TrackInfo[] getTrackInfo() throws java.lang.IllegalStateException;
    method public int getVideoHeight();
@@ -16024,6 +16025,7 @@ package android.media {
    method public void setOnTimedTextListener(android.media.MediaPlayer.OnTimedTextListener);
    method public void setOnVideoSizeChangedListener(android.media.MediaPlayer.OnVideoSizeChangedListener);
    method public void setPlaybackRate(float, int);
    method public void setPlaybackSettings(android.media.PlaybackSettings);
    method public void setScreenOnWhilePlaying(boolean);
    method public void setSurface(android.view.Surface);
    method public void setVideoScalingMode(int);
@@ -16049,7 +16051,9 @@ package android.media {
    field public static final int MEDIA_INFO_VIDEO_RENDERING_START = 3; // 0x3
    field public static final int MEDIA_INFO_VIDEO_TRACK_LAGGING = 700; // 0x2bc
    field public static final java.lang.String MEDIA_MIMETYPE_TEXT_SUBRIP = "application/x-subrip";
    field public static final int PLAYBACK_RATE_AUDIO_MODE_RESAMPLE = 0; // 0x0
    field public static final int PLAYBACK_RATE_AUDIO_MODE_DEFAULT = 0; // 0x0
    field public static final int PLAYBACK_RATE_AUDIO_MODE_RESAMPLE = 2; // 0x2
    field public static final int PLAYBACK_RATE_AUDIO_MODE_STRETCH = 1; // 0x1
    field public static final int VIDEO_SCALING_MODE_SCALE_TO_FIT = 1; // 0x1
    field public static final int VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING = 2; // 0x2
  }
@@ -16342,12 +16346,16 @@ package android.media {
    method public void configureAudioTrack(android.media.AudioTrack);
    method public void configureSurface(android.view.Surface);
    method public final android.view.Surface createInputSurface();
    method public android.media.PlaybackSettings getPlaybackSettings();
    method public boolean getTimestamp(android.media.MediaTimestamp);
    method public void queueAudio(java.nio.ByteBuffer, int, int, long);
    method public final void release();
    method public void setCallback(android.media.MediaSync.Callback, android.os.Handler);
    method public void setPlaybackRate(float, int);
    field public static final int PLAYBACK_RATE_AUDIO_MODE_RESAMPLE = 0; // 0x0
    method public void setPlaybackSettings(android.media.PlaybackSettings);
    field public static final int PLAYBACK_RATE_AUDIO_MODE_DEFAULT = 0; // 0x0
    field public static final int PLAYBACK_RATE_AUDIO_MODE_RESAMPLE = 2; // 0x2
    field public static final int PLAYBACK_RATE_AUDIO_MODE_STRETCH = 1; // 0x1
  }
  public static abstract class MediaSync.Callback {
+10 −2
Original line number Diff line number Diff line
@@ -17201,6 +17201,7 @@ package android.media {
    method public int getAudioSessionId();
    method public int getCurrentPosition();
    method public int getDuration();
    method public android.media.PlaybackSettings getPlaybackSettings();
    method public int getSelectedTrack(int) throws java.lang.IllegalStateException;
    method public android.media.MediaPlayer.TrackInfo[] getTrackInfo() throws java.lang.IllegalStateException;
    method public int getVideoHeight();
@@ -17237,6 +17238,7 @@ package android.media {
    method public void setOnTimedTextListener(android.media.MediaPlayer.OnTimedTextListener);
    method public void setOnVideoSizeChangedListener(android.media.MediaPlayer.OnVideoSizeChangedListener);
    method public void setPlaybackRate(float, int);
    method public void setPlaybackSettings(android.media.PlaybackSettings);
    method public void setScreenOnWhilePlaying(boolean);
    method public void setSurface(android.view.Surface);
    method public void setVideoScalingMode(int);
@@ -17262,7 +17264,9 @@ package android.media {
    field public static final int MEDIA_INFO_VIDEO_RENDERING_START = 3; // 0x3
    field public static final int MEDIA_INFO_VIDEO_TRACK_LAGGING = 700; // 0x2bc
    field public static final java.lang.String MEDIA_MIMETYPE_TEXT_SUBRIP = "application/x-subrip";
    field public static final int PLAYBACK_RATE_AUDIO_MODE_RESAMPLE = 0; // 0x0
    field public static final int PLAYBACK_RATE_AUDIO_MODE_DEFAULT = 0; // 0x0
    field public static final int PLAYBACK_RATE_AUDIO_MODE_RESAMPLE = 2; // 0x2
    field public static final int PLAYBACK_RATE_AUDIO_MODE_STRETCH = 1; // 0x1
    field public static final int VIDEO_SCALING_MODE_SCALE_TO_FIT = 1; // 0x1
    field public static final int VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING = 2; // 0x2
  }
@@ -17557,12 +17561,16 @@ package android.media {
    method public void configureAudioTrack(android.media.AudioTrack);
    method public void configureSurface(android.view.Surface);
    method public final android.view.Surface createInputSurface();
    method public android.media.PlaybackSettings getPlaybackSettings();
    method public boolean getTimestamp(android.media.MediaTimestamp);
    method public void queueAudio(java.nio.ByteBuffer, int, int, long);
    method public final void release();
    method public void setCallback(android.media.MediaSync.Callback, android.os.Handler);
    method public void setPlaybackRate(float, int);
    field public static final int PLAYBACK_RATE_AUDIO_MODE_RESAMPLE = 0; // 0x0
    method public void setPlaybackSettings(android.media.PlaybackSettings);
    field public static final int PLAYBACK_RATE_AUDIO_MODE_DEFAULT = 0; // 0x0
    field public static final int PLAYBACK_RATE_AUDIO_MODE_RESAMPLE = 2; // 0x2
    field public static final int PLAYBACK_RATE_AUDIO_MODE_STRETCH = 1; // 0x1
  }
  public static abstract class MediaSync.Callback {
+67 −23
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package android.media;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.app.ActivityThread;
import android.app.AppOpsManager;
import android.content.ContentResolver;
@@ -44,6 +45,7 @@ import android.graphics.SurfaceTexture;
import android.media.AudioManager;
import android.media.MediaFormat;
import android.media.MediaTimeProvider;
import android.media.PlaybackSettings;
import android.media.SubtitleController;
import android.media.SubtitleController.Anchor;
import android.media.SubtitleData;
@@ -471,12 +473,17 @@ import java.lang.ref.WeakReference;
 *     <td>{} </p></td>
 *     <td>This method can be called in any state and calling it does not change
 *         the object state. </p></td></tr>
 * <tr><td>setScreenOnWhilePlaying</></td>
 * <tr><td>setPlaybackRate</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>
 * <tr><td>setPlaybackRate</p></td>
 * <tr><td>setPlaybackSettings</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>
 * <tr><td>setScreenOnWhilePlaying</></td>
 *     <td>any </p></td>
 *     <td>{} </p></td>
 *     <td>This method can be called in any state and calling it does not change
@@ -1342,6 +1349,8 @@ public class MediaPlayer implements SubtitleController.Listener
    public native boolean isPlaying();

    /**
     * Change playback speed of audio by resampling the audio.
     * <p>
     * Specifies resampling as audio mode for variable rate playback, i.e.,
     * resample the waveform based on the requested playback rate to get
     * a new waveform, and play back the new waveform at the original sampling
@@ -1349,33 +1358,44 @@ public class MediaPlayer implements SubtitleController.Listener
     * When rate is larger than 1.0, pitch becomes higher.
     * When rate is smaller than 1.0, pitch becomes lower.
     */
    public static final int PLAYBACK_RATE_AUDIO_MODE_RESAMPLE = 0;
    public static final int PLAYBACK_RATE_AUDIO_MODE_RESAMPLE = 2;

    /**
     * Change playback speed of audio without changing its pitch.
     * <p>
     * Specifies time stretching as audio mode for variable rate playback.
     * Time stretching changes the duration of the audio samples without
     * affecting its pitch.
     * FIXME: implement time strectching.
     * @hide
     * <p>
     * This mode is only supported for a limited range of playback speed factors,
     * e.g. between 1/2x and 2x.
     */
    public static final int PLAYBACK_RATE_AUDIO_MODE_STRETCH = 1;

    /**
     * Change playback speed of audio without changing its pitch, and
     * possibly mute audio if time stretching is not supported for the playback
     * speed.
     * <p>
     * Try to keep audio pitch when changing the playback rate, but allow the
     * system to determine how to change audio playback if the rate is out
     * of range.
     */
    public static final int PLAYBACK_RATE_AUDIO_MODE_DEFAULT = 0;

    /** @hide */
    @IntDef(
        value = {
            PLAYBACK_RATE_AUDIO_MODE_DEFAULT,
            PLAYBACK_RATE_AUDIO_MODE_STRETCH,
            PLAYBACK_RATE_AUDIO_MODE_RESAMPLE,
            PLAYBACK_RATE_AUDIO_MODE_STRETCH })
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface PlaybackRateAudioMode {}

    /**
     * Sets playback rate and audio mode.
     *
     * <p> The supported audio modes are:
     * <ul>
     * <li> {@link #PLAYBACK_RATE_AUDIO_MODE_RESAMPLE}
     * </ul>
     *
     * @param rate the ratio between desired playback rate and normal one.
     * @param audioMode audio playback mode. Must be one of the supported
     * audio modes.
@@ -1385,14 +1405,46 @@ public class MediaPlayer implements SubtitleController.Listener
     * @throws IllegalArgumentException if audioMode is not supported.
     */
    public void setPlaybackRate(float rate, @PlaybackRateAudioMode int audioMode) {
        if (!isAudioPlaybackModeSupported(audioMode)) {
        PlaybackSettings settings = new PlaybackSettings();
        settings.allowDefaults();
        switch (audioMode) {
        case PLAYBACK_RATE_AUDIO_MODE_DEFAULT:
            settings.setSpeed(rate).setPitch(1.0f);
            break;
        case PLAYBACK_RATE_AUDIO_MODE_STRETCH:
            settings.setSpeed(rate).setPitch(1.0f)
                    .setAudioFallbackMode(settings.AUDIO_FALLBACK_MODE_FAIL);
            break;
        case PLAYBACK_RATE_AUDIO_MODE_RESAMPLE:
            settings.setSpeed(rate).setPitch(rate);
            break;
        default:
            final String msg = "Audio playback mode " + audioMode + " is not supported";
            throw new IllegalArgumentException(msg);
        }
        _setPlaybackRate(rate);
        setPlaybackSettings(settings);
    }

    private native void _setPlaybackRate(float rate) throws IllegalStateException;
    /**
     * Sets playback rate using {@link PlaybackSettings}.
     *
     * @param settings the playback settings.
     *
     * @throws IllegalStateException if the internal player engine has not been
     * initialized.
     * @throws IllegalArgumentException if settings is not supported.
     */
    public native void setPlaybackSettings(@NonNull PlaybackSettings settings);

    /**
     * Gets the playback settings, containing the current playback rate.
     *
     * @return the playback settings.
     * @throws IllegalStateException if the internal player engine has not been
     * initialized.
     */
    @NonNull
    public native PlaybackSettings getPlaybackSettings();

    /**
     * Seeks to specified time position.
@@ -3219,14 +3271,6 @@ public class MediaPlayer implements SubtitleController.Listener
                mode == VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING);
    }

    /*
     * Test whether a given audio playback mode is supported.
     * TODO query supported AudioPlaybackMode from player.
     */
    private boolean isAudioPlaybackModeSupported(int mode) {
        return (mode == PLAYBACK_RATE_AUDIO_MODE_RESAMPLE);
    }

    /** @hide */
    static class TimeProvider implements MediaPlayer.OnSeekCompleteListener,
            MediaTimeProvider {
+118 −67
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.media.AudioTrack;
import android.media.PlaybackSettings;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -282,60 +283,58 @@ final public class MediaSync {
    public native final Surface createInputSurface();

    /**
     * Specifies resampling as audio mode for variable rate playback, i.e.,
     * resample the waveform based on the requested playback rate to get
     * Resample audio data when changing playback speed.
     * <p>
     * Resample the waveform based on the requested playback rate to get
     * a new waveform, and play back the new waveform at the original sampling
     * frequency.
     * When rate is larger than 1.0, pitch becomes higher.
     * When rate is smaller than 1.0, pitch becomes lower.
     * <p><ul>
     * <li>When rate is larger than 1.0, pitch becomes higher.
     * <li>When rate is smaller than 1.0, pitch becomes lower.
     * </ul>
     */
    public static final int PLAYBACK_RATE_AUDIO_MODE_RESAMPLE = 0;
    public static final int PLAYBACK_RATE_AUDIO_MODE_RESAMPLE = 2;

    /**
     * Specifies time stretching as audio mode for variable rate playback.
     * Time stretch audio when changing playback speed.
     * <p>
     * Time stretching changes the duration of the audio samples without
     * affecting its pitch.
     * FIXME: implement time strectching.
     * @hide
     * affecting their pitch. This is only supported for a limited range
     * of playback speeds, e.g. from 1/2x to 2x. If the rate is adjusted
     * beyond this limit, the rate change will fail.
     */
    public static final int PLAYBACK_RATE_AUDIO_MODE_STRETCH = 1;

    /**
     * Time stretch audio when changing playback speed, and may mute if
     * stretching is no longer supported.
     * <p>
     * Time stretching changes the duration of the audio samples without
     * affecting their pitch. This is only supported for a limited range
     * of playback speeds, e.g. from 1/2x to 2x. When it is no longer
     * supported, the audio may be muted.  Using this mode will not fail
     * for non-negative playback rates.
     */
    public static final int PLAYBACK_RATE_AUDIO_MODE_DEFAULT = 0;

    /** @hide */
    @IntDef(
        value = {
            PLAYBACK_RATE_AUDIO_MODE_DEFAULT,
            PLAYBACK_RATE_AUDIO_MODE_STRETCH,
            PLAYBACK_RATE_AUDIO_MODE_RESAMPLE,
            PLAYBACK_RATE_AUDIO_MODE_STRETCH })
        })
    @Retention(RetentionPolicy.SOURCE)
    public @interface PlaybackRateAudioMode {}

    /**
     * Sets playback rate. It does same as {@link #setPlaybackRate(float, int)},
     * except that it always uses {@link #PLAYBACK_RATE_AUDIO_MODE_STRETCH} for audioMode.
     *
     * @param rate the ratio between desired playback rate and normal one. 1.0 means normal
     *     playback speed. 0.0 means stop or pause. Value larger than 1.0 means faster playback,
     *     while value between 0.0 and 1.0 for slower playback.
     *
     * @throws IllegalStateException if the internal sync engine or the audio track has not
     *     been initialized.
     * TODO: unhide when PLAYBACK_RATE_AUDIO_MODE_STRETCH is supported.
     * @hide
     */
    public void setPlaybackRate(float rate) {
        setPlaybackRate(rate, PLAYBACK_RATE_AUDIO_MODE_STRETCH);
    }

    /**
     * Sets playback rate and audio mode.
     *
     * <p> The supported audio modes are:
     * <ul>
     * <li> {@link #PLAYBACK_RATE_AUDIO_MODE_RESAMPLE}
     * </ul>
     *
     * @param rate the ratio between desired playback rate and normal one. 1.0 means normal
     *     playback speed. 0.0 means stop or pause. Value larger than 1.0 means faster playback,
     *     while value between 0.0 and 1.0 for slower playback.
     *     playback speed. 0.0 means pause. Value larger than 1.0 means faster playback,
     *     while value between 0.0 and 1.0 for slower playback. <b>Note:</b> the normal rate
     *     does not change as a result of this call. To restore the original rate at any time,
     *     use 1.0.
     * @param audioMode audio playback mode. Must be one of the supported
     *     audio modes.
     *
@@ -344,22 +343,60 @@ final public class MediaSync {
     * @throws IllegalArgumentException if audioMode is not supported.
     */
    public void setPlaybackRate(float rate, @PlaybackRateAudioMode int audioMode) {
        if (!isAudioPlaybackModeSupported(audioMode)) {
        PlaybackSettings rateSettings = new PlaybackSettings();
        rateSettings.allowDefaults();
        switch (audioMode) {
            case PLAYBACK_RATE_AUDIO_MODE_DEFAULT:
                rateSettings.setSpeed(rate).setPitch(1.0f);
                break;
            case PLAYBACK_RATE_AUDIO_MODE_STRETCH:
                rateSettings.setSpeed(rate).setPitch(1.0f)
                        .setAudioFallbackMode(rateSettings.AUDIO_FALLBACK_MODE_FAIL);
                break;
            case PLAYBACK_RATE_AUDIO_MODE_RESAMPLE:
                rateSettings.setSpeed(rate).setPitch(rate);
                break;
            default:
            {
                final String msg = "Audio playback mode " + audioMode + " is not supported";
                throw new IllegalArgumentException(msg);
            }
        }
        setPlaybackSettings(rateSettings);
    }

        int status = AudioTrack.SUCCESS;
        if (mAudioTrack != null) {
            int nativeSampleRateInHz = mAudioTrack.getSampleRate();
            int playbackSampleRate = (int)(rate * nativeSampleRateInHz + 0.5);
            rate = playbackSampleRate / (float)nativeSampleRateInHz;
    /**
     * Sets playback rate using {@link PlaybackSettings}.
     * <p>
     * When using MediaSync with {@link AudioTrack}, set playback settings using this
     * call instead of calling it directly on the track, so that the sync is aware of
     * the settings change.
     * <p>
     * This call also works if there is no audio track.
     *
     * @param settings the playback settings to use. {@link PlaybackSettings#getSpeed
     *     Speed} is the ratio between desired playback rate and normal one. 1.0 means
     *     normal playback speed. 0.0 means pause. Value larger than 1.0 means faster playback,
     *     while value between 0.0 and 1.0 for slower playback. <b>Note:</b> the normal rate
     *     does not change as a result of this call. To restore the original rate at any time,
     *     use speed of 1.0.
     *
     * @throws IllegalStateException if the internal sync engine or the audio track has not
     *     been initialized.
     * @throws IllegalArgumentException if the settings are not supported.
     */
    public void setPlaybackSettings(@NonNull PlaybackSettings settings) {
        float rate;
        try {
            rate = settings.getSpeed();

            // rate is specified
            if (mAudioTrack != null) {
                try {
                    if (rate == 0.0) {
                        mAudioTrack.pause();
                    } else {
                    status = mAudioTrack.setPlaybackRate(playbackSampleRate);
                        mAudioTrack.setPlaybackSettings(settings);
                        mAudioTrack.play();
                    }
                } catch (IllegalStateException e) {
@@ -367,10 +404,6 @@ final public class MediaSync {
                }
            }

        if (status != AudioTrack.SUCCESS) {
            throw new IllegalArgumentException("Fail to set playback rate in audio track");
        }

            synchronized(mAudioLock) {
                mPlaybackRate = rate;
            }
@@ -378,17 +411,35 @@ final public class MediaSync {
                postRenderAudio(0);
            }
            native_setPlaybackRate(mPlaybackRate);
        } catch (IllegalStateException e) {
            // rate is not specified; still, propagate settings to audio track
            if (mAudioTrack != null) {
                mAudioTrack.setPlaybackSettings(settings);
            }
        }
    }

    private native final void native_setPlaybackRate(float rate);

    /*
     * Test whether a given audio playback mode is supported.
     * TODO query supported AudioPlaybackMode from audio track.
    /**
     * Gets the playback rate using {@link PlaybackSettings}.
     *
     * @return the playback rate being used.
     *
     * @throws IllegalStateException if the internal sync engine or the audio track has not
     *     been initialized.
     */
    private boolean isAudioPlaybackModeSupported(int mode) {
        return (mode == PLAYBACK_RATE_AUDIO_MODE_RESAMPLE);
    @NonNull
    public PlaybackSettings getPlaybackSettings() {
        if (mAudioTrack != null) {
            return mAudioTrack.getPlaybackSettings();
        } else {
            PlaybackSettings settings = new PlaybackSettings();
            settings.allowDefaults();
            settings.setSpeed(mPlaybackRate);
            return settings;
        }
    }

    private native final void native_setPlaybackRate(float rate);

   /**
    * Get current playback position.
+55 −4
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include "utils/Log.h"

#include <media/mediaplayer.h>
#include <media/AudioResamplerPublic.h>
#include <media/IMediaHTTPService.h>
#include <media/MediaPlayerInterface.h>
#include <stdio.h>
@@ -37,6 +38,7 @@
#include "utils/KeyedVector.h"
#include "utils/String8.h"
#include "android_media_MediaDataSource.h"
#include "android_media_PlaybackSettings.h"
#include "android_media_Utils.h"

#include "android_os_Parcel.h"
@@ -66,6 +68,8 @@ struct fields_t {
};
static fields_t fields;

static PlaybackSettings::fields_t gPlaybackSettingsFields;

static Mutex sLock;

// ----------------------------------------------------------------------------
@@ -420,15 +424,55 @@ android_media_MediaPlayer_isPlaying(JNIEnv *env, jobject thiz)
}

static void
android_media_MediaPlayer_setPlaybackRate(JNIEnv *env, jobject thiz, jfloat rate)
android_media_MediaPlayer_setPlaybackSettings(JNIEnv *env, jobject thiz, jobject settings)
{
    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
    if (mp == NULL) {
        jniThrowException(env, "java/lang/IllegalStateException", NULL);
        return;
    }
    ALOGV("setPlaybackRate: %f", rate);
    process_media_player_call(env, thiz, mp->setPlaybackRate(rate), NULL, NULL);

    PlaybackSettings pbs;
    pbs.fillFromJobject(env, gPlaybackSettingsFields, settings);
    ALOGV("setPlaybackSettings: %d:%f %d:%f %d:%u %d:%u",
            pbs.speedSet, pbs.audioRate.mSpeed,
            pbs.pitchSet, pbs.audioRate.mPitch,
            pbs.audioFallbackModeSet, pbs.audioRate.mFallbackMode,
            pbs.audioStretchModeSet, pbs.audioRate.mStretchMode);

    // TODO: pass playback settings to mediaplayer when audiotrack supports it
    process_media_player_call(env, thiz, mp->setPlaybackRate(pbs.audioRate.mSpeed), NULL, NULL);
}

static jobject
android_media_MediaPlayer_getPlaybackSettings(JNIEnv *env, jobject thiz)
{
    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
    if (mp == NULL) {
        jniThrowException(env, "java/lang/IllegalStateException", NULL);
        return NULL;
    }

    PlaybackSettings pbs;
    AudioPlaybackRate &audioRate = pbs.audioRate;

    audioRate.mSpeed = 1.0f;
    audioRate.mPitch = 1.0f;
    audioRate.mFallbackMode = AUDIO_TIMESTRETCH_FALLBACK_DEFAULT;
    audioRate.mStretchMode = AUDIO_TIMESTRETCH_STRETCH_DEFAULT;

    // TODO: get this from mediaplayer when audiotrack supports it
    // process_media_player_call(
    //        env, thiz, mp->getPlaybackSettings(&audioRate), NULL, NULL);
    ALOGV("getPlaybackSettings: %f %f %d %d",
            audioRate.mSpeed, audioRate.mPitch, audioRate.mFallbackMode, audioRate.mStretchMode);

    pbs.speedSet = true;
    pbs.pitchSet = true;
    pbs.audioFallbackModeSet = true;
    pbs.audioStretchModeSet = true;

    return pbs.asJobject(env, gPlaybackSettingsFields);
}

static void
@@ -697,6 +741,8 @@ android_media_MediaPlayer_native_init(JNIEnv *env)
        return;
    }

    env->DeleteLocalRef(clazz);

    clazz = env->FindClass("android/net/ProxyInfo");
    if (clazz == NULL) {
        return;
@@ -710,6 +756,10 @@ android_media_MediaPlayer_native_init(JNIEnv *env)

    fields.proxyConfigGetExclusionList =
        env->GetMethodID(clazz, "getExclusionListAsString", "()Ljava/lang/String;");

    env->DeleteLocalRef(clazz);

    gPlaybackSettingsFields.init(env);
}

static void
@@ -898,7 +948,8 @@ static JNINativeMethod gMethods[] = {
    {"_stop",               "()V",                              (void *)android_media_MediaPlayer_stop},
    {"getVideoWidth",       "()I",                              (void *)android_media_MediaPlayer_getVideoWidth},
    {"getVideoHeight",      "()I",                              (void *)android_media_MediaPlayer_getVideoHeight},
    {"_setPlaybackRate",    "(F)V",                             (void *)android_media_MediaPlayer_setPlaybackRate},
    {"setPlaybackSettings", "(Landroid/media/PlaybackSettings;)V", (void *)android_media_MediaPlayer_setPlaybackSettings},
    {"getPlaybackSettings", "()Landroid/media/PlaybackSettings;", (void *)android_media_MediaPlayer_getPlaybackSettings},
    {"seekTo",              "(I)V",                             (void *)android_media_MediaPlayer_seekTo},
    {"_pause",              "()V",                              (void *)android_media_MediaPlayer_pause},
    {"isPlaying",           "()Z",                              (void *)android_media_MediaPlayer_isPlaying},
Loading