Loading api/current.txt +10 −2 Original line number Diff line number Diff line Loading @@ -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(); Loading Loading @@ -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); Loading @@ -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 } Loading Loading @@ -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 { api/system-current.txt +10 −2 Original line number Diff line number Diff line Loading @@ -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(); Loading Loading @@ -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); Loading @@ -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 } Loading Loading @@ -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 { media/java/android/media/MediaPlayer.java +67 −23 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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 Loading Loading @@ -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 Loading @@ -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. Loading @@ -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. Loading Loading @@ -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 { Loading media/java/android/media/MediaSync.java +118 −67 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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. * Loading @@ -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) { Loading @@ -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; } Loading @@ -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. Loading media/jni/android_media_MediaPlayer.cpp +55 −4 Original line number Diff line number Diff line Loading @@ -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> Loading @@ -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" Loading Loading @@ -66,6 +68,8 @@ struct fields_t { }; static fields_t fields; static PlaybackSettings::fields_t gPlaybackSettingsFields; static Mutex sLock; // ---------------------------------------------------------------------------- Loading Loading @@ -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 Loading Loading @@ -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; Loading @@ -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 Loading Loading @@ -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 Loading
api/current.txt +10 −2 Original line number Diff line number Diff line Loading @@ -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(); Loading Loading @@ -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); Loading @@ -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 } Loading Loading @@ -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 {
api/system-current.txt +10 −2 Original line number Diff line number Diff line Loading @@ -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(); Loading Loading @@ -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); Loading @@ -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 } Loading Loading @@ -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 {
media/java/android/media/MediaPlayer.java +67 −23 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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 Loading Loading @@ -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 Loading @@ -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. Loading @@ -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. Loading Loading @@ -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 { Loading
media/java/android/media/MediaSync.java +118 −67 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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. * Loading @@ -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) { Loading @@ -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; } Loading @@ -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. Loading
media/jni/android_media_MediaPlayer.cpp +55 −4 Original line number Diff line number Diff line Loading @@ -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> Loading @@ -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" Loading Loading @@ -66,6 +68,8 @@ struct fields_t { }; static fields_t fields; static PlaybackSettings::fields_t gPlaybackSettingsFields; static Mutex sLock; // ---------------------------------------------------------------------------- Loading Loading @@ -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 Loading Loading @@ -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; Loading @@ -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 Loading Loading @@ -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