media: Hook up MediaPlayer and MediaSync to new settings

Bug: 19666434
Change-Id: Ib815a80a991d4be9ce179514ac517c54f98234fd
diff --git a/media/java/android/media/MediaSync.java b/media/java/android/media/MediaSync.java
index dc6760d..ecc87e7 100644
--- a/media/java/android/media/MediaSync.java
+++ b/media/java/android/media/MediaSync.java
@@ -199,6 +199,7 @@
     private final Object mAudioLock = new Object();
     private AudioTrack mAudioTrack = null;
     private List<AudioBuffer> mAudioBuffers = new LinkedList<AudioBuffer>();
+    // this is only used for paused/running decisions, so it is not affected by clock drift
     private float mPlaybackRate = 0.0f;
 
     private long mNativeContext;
@@ -459,36 +460,11 @@
      * @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 {
-                        mAudioTrack.setPlaybackSettings(settings);
-                        mAudioTrack.play();
-                    }
-                } catch (IllegalStateException e) {
-                    throw e;
-                }
-            }
-
-            synchronized(mAudioLock) {
-                mPlaybackRate = rate;
-            }
-            if (mPlaybackRate != 0.0 && mAudioThread != null) {
-                postRenderAudio(0);
-            }
-            native_setPlaybackRate(mPlaybackRate);
-        } catch (IllegalStateException e) {
-            // rate is not specified; still, propagate settings to audio track
-            if (mAudioTrack != null) {
-                mAudioTrack.setPlaybackSettings(settings);
-            }
+        synchronized(mAudioLock) {
+            mPlaybackRate = native_setPlaybackSettings(settings);;
+        }
+        if (mPlaybackRate != 0.0 && mAudioThread != null) {
+            postRenderAudio(0);
         }
     }
 
@@ -501,18 +477,9 @@
      *     been initialized.
      */
     @NonNull
-    public PlaybackSettings getPlaybackSettings() {
-        if (mAudioTrack != null) {
-            return mAudioTrack.getPlaybackSettings();
-        } else {
-            PlaybackSettings settings = new PlaybackSettings();
-            settings.allowDefaults();
-            settings.setSpeed(mPlaybackRate);
-            return settings;
-        }
-    }
+    public native PlaybackSettings getPlaybackSettings();
 
-    private native final void native_setPlaybackRate(float rate);
+    private native float native_setPlaybackSettings(@NonNull PlaybackSettings settings);
 
     /**
      * Sets A/V sync mode.
@@ -523,7 +490,16 @@
      * initialized.
      * @throws IllegalArgumentException if settings are not supported.
      */
-    public native void setSyncSettings(@NonNull SyncSettings settings);
+    public void setSyncSettings(@NonNull SyncSettings settings) {
+        synchronized(mAudioLock) {
+            mPlaybackRate = native_setSyncSettings(settings);;
+        }
+        if (mPlaybackRate != 0.0 && mAudioThread != null) {
+            postRenderAudio(0);
+        }
+    }
+
+    private native float native_setSyncSettings(@NonNull SyncSettings settings);
 
     /**
      * Gets the A/V sync mode.
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 2c61779..5b55a61 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -174,6 +174,8 @@
     } else {  // Throw exception!
         if ( opStatus == (status_t) INVALID_OPERATION ) {
             jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        } else if ( opStatus == (status_t) BAD_VALUE ) {
+            jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
         } else if ( opStatus == (status_t) PERMISSION_DENIED ) {
             jniThrowException(env, "java/lang/SecurityException", NULL);
         } else if ( opStatus != (status_t) OK ) {
@@ -442,8 +444,33 @@
             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);
+    AudioPlaybackRate rate;
+    status_t err = mp->getPlaybackSettings(&rate);
+    if (err == OK) {
+        bool updatedRate = false;
+        if (pbs.speedSet) {
+            rate.mSpeed = pbs.audioRate.mSpeed;
+            updatedRate = true;
+        }
+        if (pbs.pitchSet) {
+            rate.mPitch = pbs.audioRate.mPitch;
+            updatedRate = true;
+        }
+        if (pbs.audioFallbackModeSet) {
+            rate.mFallbackMode = pbs.audioRate.mFallbackMode;
+            updatedRate = true;
+        }
+        if (pbs.audioStretchModeSet) {
+            rate.mStretchMode = pbs.audioRate.mStretchMode;
+            updatedRate = true;
+        }
+        if (updatedRate) {
+            err = mp->setPlaybackSettings(rate);
+        }
+    }
+    process_media_player_call(
+            env, thiz, err,
+            "java/lang/IllegalStateException", "unexpected error");
 }
 
 static jobject
@@ -457,15 +484,9 @@
 
     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);
+    process_media_player_call(
+            env, thiz, mp->getPlaybackSettings(&audioRate),
+            "java/lang/IllegalStateException", "unexpected error");
     ALOGV("getPlaybackSettings: %f %f %d %d",
             audioRate.mSpeed, audioRate.mPitch, audioRate.mFallbackMode, audioRate.mStretchMode);
 
@@ -489,13 +510,35 @@
     SyncSettings scs;
     scs.fillFromJobject(env, gSyncSettingsFields, settings);
     ALOGV("setSyncSettings: %d:%d %d:%d %d:%f %d:%f",
-            scs.syncSourceSet, scs.syncSource,
-            scs.audioAdjustModeSet, scs.audioAdjustMode,
-            scs.toleranceSet, scs.tolerance,
-            scs.frameRateSet, scs.frameRate);
+          scs.syncSourceSet, scs.sync.mSource,
+          scs.audioAdjustModeSet, scs.sync.mAudioAdjustMode,
+          scs.toleranceSet, scs.sync.mTolerance,
+          scs.frameRateSet, scs.frameRate);
 
-    // TODO: pass sync settings to mediaplayer when it supports it
-    // process_media_player_call(env, thiz, mp->setSyncSettings(scs), NULL, NULL);
+    AVSyncSettings avsync;
+    float videoFrameRate;
+    status_t err = mp->getSyncSettings(&avsync, &videoFrameRate);
+    if (err == OK) {
+        bool updatedSync = scs.frameRateSet;
+        if (scs.syncSourceSet) {
+            avsync.mSource = scs.sync.mSource;
+            updatedSync = true;
+        }
+        if (scs.audioAdjustModeSet) {
+            avsync.mAudioAdjustMode = scs.sync.mAudioAdjustMode;
+            updatedSync = true;
+        }
+        if (scs.toleranceSet) {
+            avsync.mTolerance = scs.sync.mTolerance;
+            updatedSync = true;
+        }
+        if (updatedSync) {
+            err = mp->setSyncSettings(avsync, scs.frameRateSet ? scs.frameRate : -1.f);
+        }
+    }
+    process_media_player_call(
+            env, thiz, err,
+            "java/lang/IllegalStateException", "unexpected error");
 }
 
 static jobject
@@ -508,21 +551,27 @@
     }
 
     SyncSettings scs;
-    scs.syncSource = 0; // SYNC_SOURCE_DEFAULT
-    scs.audioAdjustMode = 0; // AUDIO_ADJUST_MODE_DEFAULT
-    scs.tolerance = 0.f;
-    scs.frameRate = 0.f;
+    scs.frameRate = -1.f;
+    process_media_player_call(
+            env, thiz, mp->getSyncSettings(&scs.sync, &scs.frameRate),
+            "java/lang/IllegalStateException", "unexpected error");
 
-    // TODO: get this from mediaplayer when it supports it
-    // process_media_player_call(
-    //        env, thiz, mp->getSyncSettings(&scs), NULL, NULL);
     ALOGV("getSyncSettings: %d %d %f %f",
-            scs.syncSource, scs.audioAdjustMode, scs.tolerance, scs.frameRate);
+            scs.sync.mSource, scs.sync.mAudioAdjustMode, scs.sync.mTolerance, scs.frameRate);
+
+    // sanity check settings
+    if (scs.sync.mSource >= AVSYNC_SOURCE_MAX
+            || scs.sync.mAudioAdjustMode >= AVSYNC_AUDIO_ADJUST_MODE_MAX
+            || scs.sync.mTolerance < 0.f
+            || scs.sync.mTolerance >= AVSYNC_TOLERANCE_MAX) {
+        jniThrowException(env,  "java/lang/IllegalStateException", NULL);
+        return NULL;
+    }
 
     scs.syncSourceSet = true;
     scs.audioAdjustModeSet = true;
     scs.toleranceSet = true;
-    scs.frameRateSet = false;
+    scs.frameRateSet = scs.frameRate >= 0.f;
 
     return scs.asJobject(env, gSyncSettingsFields);
 }
diff --git a/media/jni/android_media_MediaSync.cpp b/media/jni/android_media_MediaSync.cpp
index f192262..8ad4b71 100644
--- a/media/jni/android_media_MediaSync.cpp
+++ b/media/jni/android_media_MediaSync.cpp
@@ -21,6 +21,7 @@
 #include "android_media_MediaSync.h"
 
 #include "android_media_AudioTrack.h"
+#include "android_media_PlaybackSettings.h"
 #include "android_media_SyncSettings.h"
 #include "android_runtime/AndroidRuntime.h"
 #include "android_runtime/android_view_Surface.h"
@@ -29,6 +30,7 @@
 
 #include <gui/Surface.h>
 
+#include <media/AudioResamplerPublic.h>
 #include <media/AudioTrack.h>
 #include <media/stagefright/MediaClock.h>
 #include <media/stagefright/MediaSync.h>
@@ -47,6 +49,7 @@
 };
 
 static fields_t gFields;
+static PlaybackSettings::fields_t gPlaybackSettingsFields;
 static SyncSettings::fields_t gSyncSettingsFields;
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -62,10 +65,8 @@
     return mSync->configureSurface(bufferProducer);
 }
 
-status_t JMediaSync::configureAudioTrack(
-        const sp<AudioTrack> &audioTrack,
-        int32_t nativeSampleRateInHz) {
-    return mSync->configureAudioTrack(audioTrack, nativeSampleRateInHz);
+status_t JMediaSync::configureAudioTrack(const sp<AudioTrack> &audioTrack) {
+    return mSync->configureAudioTrack(audioTrack);
 }
 
 status_t JMediaSync::createInputSurface(
@@ -73,14 +74,34 @@
     return mSync->createInputSurface(bufferProducer);
 }
 
-status_t JMediaSync::setPlaybackRate(float rate) {
-    return mSync->setPlaybackRate(rate);
-}
-
 sp<const MediaClock> JMediaSync::getMediaClock() {
     return mSync->getMediaClock();
 }
 
+status_t JMediaSync::setPlaybackSettings(const AudioPlaybackRate& rate) {
+    return mSync->setPlaybackSettings(rate);
+}
+
+void JMediaSync::getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */) {
+    mSync->getPlaybackSettings(rate);
+}
+
+status_t JMediaSync::setSyncSettings(const AVSyncSettings& syncSettings) {
+    return mSync->setSyncSettings(syncSettings);
+}
+
+void JMediaSync::getSyncSettings(AVSyncSettings* syncSettings /* nonnull */) {
+    mSync->getSyncSettings(syncSettings);
+}
+
+status_t JMediaSync::setVideoFrameRateHint(float rate) {
+    return mSync->setVideoFrameRateHint(rate);
+}
+
+float JMediaSync::getVideoFrameRate() {
+    return mSync->getVideoFrameRate();
+}
+
 status_t JMediaSync::updateQueuedAudioData(
         int sizeInBytes, int64_t presentationTimeUs) {
     return mSync->updateQueuedAudioData(sizeInBytes, presentationTimeUs);
@@ -176,7 +197,7 @@
 }
 
 static void android_media_MediaSync_native_configureAudioTrack(
-        JNIEnv *env, jobject thiz, jobject jaudioTrack, jint nativeSampleRateInHz) {
+        JNIEnv *env, jobject thiz, jobject jaudioTrack) {
     ALOGV("android_media_MediaSync_configureAudioTrack");
 
     sp<JMediaSync> sync = getMediaSync(env, thiz);
@@ -194,7 +215,7 @@
         }
     }
 
-    status_t err = sync->configureAudioTrack(audioTrack, nativeSampleRateInHz);
+    status_t err = sync->configureAudioTrack(audioTrack);
 
     if (err == INVALID_OPERATION) {
         throwExceptionAsNecessary(
@@ -287,29 +308,132 @@
     return (jlong)playTimeUs;
 }
 
-static void
-android_media_MediaSync_setSyncSettings(JNIEnv *env, jobject thiz, jobject settings)
-{
+static jfloat android_media_MediaSync_setPlaybackSettings(
+        JNIEnv *env, jobject thiz, jobject settings) {
     sp<JMediaSync> sync = getMediaSync(env, thiz);
     if (sync == NULL) {
         throwExceptionAsNecessary(env, INVALID_OPERATION);
-        return;
+        return (jfloat)0.f;
+    }
+
+    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);
+
+    AudioPlaybackRate rate;
+    sync->getPlaybackSettings(&rate);
+    bool updatedRate = false;
+    if (pbs.speedSet) {
+        rate.mSpeed = pbs.audioRate.mSpeed;
+        updatedRate = true;
+    }
+    if (pbs.pitchSet) {
+        rate.mPitch = pbs.audioRate.mPitch;
+        updatedRate = true;
+    }
+    if (pbs.audioFallbackModeSet) {
+        rate.mFallbackMode = pbs.audioRate.mFallbackMode;
+        updatedRate = true;
+    }
+    if (pbs.audioStretchModeSet) {
+        rate.mStretchMode = pbs.audioRate.mStretchMode;
+        updatedRate = true;
+    }
+    if (updatedRate) {
+        status_t err = sync->setPlaybackSettings(rate);
+        if (err != OK) {
+            throwExceptionAsNecessary(env, err);
+            return (jfloat)0.f;
+        }
+    }
+
+    sp<const MediaClock> mediaClock = sync->getMediaClock();
+    if (mediaClock == NULL) {
+        return (jfloat)0.f;
+    }
+
+    return (jfloat)mediaClock->getPlaybackRate();
+}
+
+static jobject android_media_MediaSync_getPlaybackSettings(
+        JNIEnv *env, jobject thiz) {
+    sp<JMediaSync> sync = getMediaSync(env, thiz);
+    if (sync == NULL) {
+        throwExceptionAsNecessary(env, INVALID_OPERATION);
+        return NULL;
+    }
+
+    PlaybackSettings pbs;
+    AudioPlaybackRate &audioRate = pbs.audioRate;
+    sync->getPlaybackSettings(&audioRate);
+    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 jfloat android_media_MediaSync_setSyncSettings(
+        JNIEnv *env, jobject thiz, jobject settings) {
+    sp<JMediaSync> sync = getMediaSync(env, thiz);
+    if (sync == NULL) {
+        throwExceptionAsNecessary(env, INVALID_OPERATION);
+        return (jfloat)0.f;
     }
 
     SyncSettings scs;
     scs.fillFromJobject(env, gSyncSettingsFields, settings);
     ALOGV("setSyncSettings: %d:%d %d:%d %d:%f %d:%f",
-            scs.syncSourceSet, scs.syncSource,
-            scs.audioAdjustModeSet, scs.audioAdjustMode,
-            scs.toleranceSet, scs.tolerance,
+            scs.syncSourceSet, scs.sync.mSource,
+            scs.audioAdjustModeSet, scs.sync.mAudioAdjustMode,
+            scs.toleranceSet, scs.sync.mTolerance,
             scs.frameRateSet, scs.frameRate);
 
-    // TODO: pass sync settings to mediasync when it supports it
+    AVSyncSettings avsync;
+    sync->getSyncSettings(&avsync);
+    bool updatedSync = false;
+    status_t err = OK;
+    if (scs.syncSourceSet) {
+        avsync.mSource = scs.sync.mSource;
+        updatedSync = true;
+    }
+    if (scs.audioAdjustModeSet) {
+        avsync.mAudioAdjustMode = scs.sync.mAudioAdjustMode;
+        updatedSync = true;
+    }
+    if (scs.toleranceSet) {
+        avsync.mTolerance = scs.sync.mTolerance;
+        updatedSync = true;
+    }
+    if (updatedSync) {
+        err = sync->setSyncSettings(avsync);
+    }
+
+    if (scs.frameRateSet && err == OK) {
+        err = sync->setVideoFrameRateHint(scs.frameRate);
+    }
+    if (err != OK) {
+        throwExceptionAsNecessary(env, err);
+        return (jfloat)0.f;
+    }
+
+    sp<const MediaClock> mediaClock = sync->getMediaClock();
+    if (mediaClock == NULL) {
+        return (jfloat)0.f;
+    }
+
+    return (jfloat)mediaClock->getPlaybackRate();
 }
 
-static jobject
-android_media_MediaSync_getSyncSettings(JNIEnv *env, jobject thiz)
-{
+static jobject android_media_MediaSync_getSyncSettings(JNIEnv *env, jobject thiz) {
     sp<JMediaSync> sync = getMediaSync(env, thiz);
     if (sync == NULL) {
         throwExceptionAsNecessary(env, INVALID_OPERATION);
@@ -317,21 +441,25 @@
     }
 
     SyncSettings scs;
-    scs.syncSource = 0; // SYNC_SOURCE_DEFAULT
-    scs.audioAdjustMode = 0; // AUDIO_ADJUST_MODE_DEFAULT
-    scs.tolerance = 0.f;
-    scs.frameRate = 0.f;
+    sync->getSyncSettings(&scs.sync);
+    scs.frameRate = sync->getVideoFrameRate();
 
-    // TODO: get this from mediaplayer when it supports it
-    // process_media_player_call(
-    //        env, thiz, mp->getSyncSettings(&scs), NULL, NULL);
     ALOGV("getSyncSettings: %d %d %f %f",
-            scs.syncSource, scs.audioAdjustMode, scs.tolerance, scs.frameRate);
+            scs.sync.mSource, scs.sync.mAudioAdjustMode, scs.sync.mTolerance, scs.frameRate);
+
+    // sanity check settings
+    if (scs.sync.mSource >= AVSYNC_SOURCE_MAX
+            || scs.sync.mAudioAdjustMode >= AVSYNC_AUDIO_ADJUST_MODE_MAX
+            || scs.sync.mTolerance < 0.f
+            || scs.sync.mTolerance >= AVSYNC_TOLERANCE_MAX) {
+        throwExceptionAsNecessary(env, INVALID_OPERATION);
+        return NULL;
+    }
 
     scs.syncSourceSet = true;
     scs.audioAdjustModeSet = true;
     scs.toleranceSet = true;
-    scs.frameRateSet = false;
+    scs.frameRateSet = scs.frameRate >= 0.f;
 
     return scs.asJobject(env, gSyncSettingsFields);
 }
@@ -359,6 +487,7 @@
     CHECK(gFields.mediaTimestampClockRateID != NULL);
 
     gSyncSettingsFields.init(env);
+    gPlaybackSettingsFields.init(env);
 }
 
 static void android_media_MediaSync_native_setup(JNIEnv *env, jobject thiz) {
@@ -367,21 +496,6 @@
     setMediaSync(env, thiz, sync);
 }
 
-static void android_media_MediaSync_native_setPlaybackRate(
-        JNIEnv *env, jobject thiz, jfloat rate) {
-    sp<JMediaSync> sync = getMediaSync(env, thiz);
-    if (sync == NULL) {
-        throwExceptionAsNecessary(env, INVALID_OPERATION);
-        return;
-    }
-
-    status_t err = sync->setPlaybackRate(rate);
-    if (err != NO_ERROR) {
-        throwExceptionAsNecessary(env, err);
-        return;
-    }
-}
-
 static void android_media_MediaSync_native_finalize(JNIEnv *env, jobject thiz) {
     android_media_MediaSync_release(env, thiz);
 }
@@ -416,11 +530,17 @@
 
     { "native_release", "()V", (void *)android_media_MediaSync_release },
 
-    { "native_setPlaybackRate", "(F)V", (void *)android_media_MediaSync_native_setPlaybackRate },
+    { "native_setPlaybackSettings", "(Landroid/media/PlaybackSettings;)F",
+      (void *)android_media_MediaSync_setPlaybackSettings },
 
-    { "setSyncSettings", "(Landroid/media/SyncSettings;)V", (void *)android_media_MediaSync_setSyncSettings},
+    { "getPlaybackSettings", "()Landroid/media/PlaybackSettings;",
+      (void *)android_media_MediaSync_getPlaybackSettings },
 
-    { "getSyncSettings", "()Landroid/media/SyncSettings;", (void *)android_media_MediaSync_getSyncSettings},
+    { "native_setSyncSettings", "(Landroid/media/SyncSettings;)F",
+      (void *)android_media_MediaSync_setSyncSettings },
+
+    { "getSyncSettings", "()Landroid/media/SyncSettings;",
+      (void *)android_media_MediaSync_getSyncSettings },
 
     { "native_finalize", "()V", (void *)android_media_MediaSync_native_finalize },
 };
diff --git a/media/jni/android_media_MediaSync.h b/media/jni/android_media_MediaSync.h
index cf81a72..80f5d63 100644
--- a/media/jni/android_media_MediaSync.h
+++ b/media/jni/android_media_MediaSync.h
@@ -18,11 +18,13 @@
 #define _ANDROID_MEDIA_MEDIASYNC_H_
 
 #include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/MediaSync.h>
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
 
 namespace android {
 
+struct AudioPlaybackRate;
 class AudioTrack;
 struct IGraphicBufferProducer;
 struct MediaClock;
@@ -32,17 +34,21 @@
     JMediaSync();
 
     status_t configureSurface(const sp<IGraphicBufferProducer> &bufferProducer);
-    status_t configureAudioTrack(
-            const sp<AudioTrack> &audioTrack, int32_t nativeSampleRateInHz);
+    status_t configureAudioTrack(const sp<AudioTrack> &audioTrack);
 
     status_t createInputSurface(sp<IGraphicBufferProducer>* bufferProducer);
 
     status_t updateQueuedAudioData(int sizeInBytes, int64_t presentationTimeUs);
 
-    status_t setPlaybackRate(float rate);
-
     status_t getPlayTimeForPendingAudioFrames(int64_t *outTimeUs);
 
+    status_t setPlaybackSettings(const AudioPlaybackRate& rate);
+    void getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */);
+    status_t setSyncSettings(const AVSyncSettings& syncSettings);
+    void getSyncSettings(AVSyncSettings* syncSettings /* nonnull */);
+    status_t setVideoFrameRateHint(float rate);
+    float getVideoFrameRate();
+
     sp<const MediaClock> getMediaClock();
 
 protected:
diff --git a/media/jni/android_media_SyncSettings.cpp b/media/jni/android_media_SyncSettings.cpp
index 2f0605e..5da35e7 100644
--- a/media/jni/android_media_SyncSettings.cpp
+++ b/media/jni/android_media_SyncSettings.cpp
@@ -57,9 +57,9 @@
 }
 
 void SyncSettings::fillFromJobject(JNIEnv *env, const fields_t& fields, jobject settings) {
-    syncSource = env->GetIntField(settings, fields.sync_source);
-    audioAdjustMode = env->GetIntField(settings, fields.audio_adjust_mode);
-    tolerance = env->GetFloatField(settings, fields.tolerance);
+    sync.mSource = (AVSyncSource)env->GetIntField(settings, fields.sync_source);
+    sync.mAudioAdjustMode = (AVSyncAudioAdjustMode)env->GetIntField(settings, fields.audio_adjust_mode);
+    sync.mTolerance = env->GetFloatField(settings, fields.tolerance);
     frameRate = env->GetFloatField(settings, fields.frame_rate);
     int set = env->GetIntField(settings, fields.set);
 
@@ -74,9 +74,9 @@
     if (settings == NULL) {
         return NULL;
     }
-    env->SetIntField(settings, fields.sync_source, (jint)syncSource);
-    env->SetIntField(settings, fields.audio_adjust_mode, (jint)audioAdjustMode);
-    env->SetFloatField(settings, fields.tolerance, (jfloat)tolerance);
+    env->SetIntField(settings, fields.sync_source, (jint)sync.mSource);
+    env->SetIntField(settings, fields.audio_adjust_mode, (jint)sync.mAudioAdjustMode);
+    env->SetFloatField(settings, fields.tolerance, (jfloat)sync.mTolerance);
     env->SetFloatField(settings, fields.frame_rate, (jfloat)frameRate);
     env->SetIntField(
             settings, fields.set,
diff --git a/media/jni/android_media_SyncSettings.h b/media/jni/android_media_SyncSettings.h
index 586533f..23530db 100644
--- a/media/jni/android_media_SyncSettings.h
+++ b/media/jni/android_media_SyncSettings.h
@@ -19,13 +19,12 @@
 
 #include "jni.h"
 
+#include <media/stagefright/MediaSync.h>
+
 namespace android {
 
 struct SyncSettings {
-    // keep this here until it is implemented
-    int syncSource;
-    int audioAdjustMode;
-    float tolerance;
+    AVSyncSettings sync;
     float frameRate;
 
     bool syncSourceSet;