Loading media/java/android/media/MediaSync.java +18 −42 Original line number Original line Diff line number Diff line Loading @@ -199,6 +199,7 @@ final public class MediaSync { private final Object mAudioLock = new Object(); private final Object mAudioLock = new Object(); private AudioTrack mAudioTrack = null; private AudioTrack mAudioTrack = null; private List<AudioBuffer> mAudioBuffers = new LinkedList<AudioBuffer>(); 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 float mPlaybackRate = 0.0f; private long mNativeContext; private long mNativeContext; Loading Loading @@ -459,37 +460,12 @@ final public class MediaSync { * @throws IllegalArgumentException if the settings are not supported. * @throws IllegalArgumentException if the settings are not supported. */ */ public void setPlaybackSettings(@NonNull PlaybackSettings settings) { 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) { synchronized(mAudioLock) { mPlaybackRate = rate; mPlaybackRate = native_setPlaybackSettings(settings);; } } if (mPlaybackRate != 0.0 && mAudioThread != null) { if (mPlaybackRate != 0.0 && mAudioThread != null) { postRenderAudio(0); postRenderAudio(0); } } native_setPlaybackRate(mPlaybackRate); } catch (IllegalStateException e) { // rate is not specified; still, propagate settings to audio track if (mAudioTrack != null) { mAudioTrack.setPlaybackSettings(settings); } } } } /** /** Loading @@ -501,18 +477,9 @@ final public class MediaSync { * been initialized. * been initialized. */ */ @NonNull @NonNull public PlaybackSettings getPlaybackSettings() { public native 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); private native float native_setPlaybackSettings(@NonNull PlaybackSettings settings); /** /** * Sets A/V sync mode. * Sets A/V sync mode. Loading @@ -523,7 +490,16 @@ final public class MediaSync { * initialized. * initialized. * @throws IllegalArgumentException if settings are not supported. * @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. * Gets the A/V sync mode. Loading media/jni/android_media_MediaPlayer.cpp +77 −28 Original line number Original line Diff line number Diff line Loading @@ -174,6 +174,8 @@ static void process_media_player_call(JNIEnv *env, jobject thiz, status_t opStat } else { // Throw exception! } else { // Throw exception! if ( opStatus == (status_t) INVALID_OPERATION ) { if ( opStatus == (status_t) INVALID_OPERATION ) { jniThrowException(env, "java/lang/IllegalStateException", NULL); 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 ) { } else if ( opStatus == (status_t) PERMISSION_DENIED ) { jniThrowException(env, "java/lang/SecurityException", NULL); jniThrowException(env, "java/lang/SecurityException", NULL); } else if ( opStatus != (status_t) OK ) { } else if ( opStatus != (status_t) OK ) { Loading Loading @@ -442,8 +444,33 @@ android_media_MediaPlayer_setPlaybackSettings(JNIEnv *env, jobject thiz, jobject pbs.audioFallbackModeSet, pbs.audioRate.mFallbackMode, pbs.audioFallbackModeSet, pbs.audioRate.mFallbackMode, pbs.audioStretchModeSet, pbs.audioRate.mStretchMode); pbs.audioStretchModeSet, pbs.audioRate.mStretchMode); // TODO: pass playback settings to mediaplayer when audiotrack supports it AudioPlaybackRate rate; process_media_player_call(env, thiz, mp->setPlaybackRate(pbs.audioRate.mSpeed), NULL, NULL); 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 static jobject Loading @@ -457,15 +484,9 @@ android_media_MediaPlayer_getPlaybackSettings(JNIEnv *env, jobject thiz) PlaybackSettings pbs; PlaybackSettings pbs; AudioPlaybackRate &audioRate = pbs.audioRate; AudioPlaybackRate &audioRate = pbs.audioRate; process_media_player_call( audioRate.mSpeed = 1.0f; env, thiz, mp->getPlaybackSettings(&audioRate), audioRate.mPitch = 1.0f; "java/lang/IllegalStateException", "unexpected error"); 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", ALOGV("getPlaybackSettings: %f %f %d %d", audioRate.mSpeed, audioRate.mPitch, audioRate.mFallbackMode, audioRate.mStretchMode); audioRate.mSpeed, audioRate.mPitch, audioRate.mFallbackMode, audioRate.mStretchMode); Loading @@ -489,13 +510,35 @@ android_media_MediaPlayer_setSyncSettings(JNIEnv *env, jobject thiz, jobject set SyncSettings scs; SyncSettings scs; scs.fillFromJobject(env, gSyncSettingsFields, settings); scs.fillFromJobject(env, gSyncSettingsFields, settings); ALOGV("setSyncSettings: %d:%d %d:%d %d:%f %d:%f", ALOGV("setSyncSettings: %d:%d %d:%d %d:%f %d:%f", scs.syncSourceSet, scs.syncSource, scs.syncSourceSet, scs.sync.mSource, scs.audioAdjustModeSet, scs.audioAdjustMode, scs.audioAdjustModeSet, scs.sync.mAudioAdjustMode, scs.toleranceSet, scs.tolerance, scs.toleranceSet, scs.sync.mTolerance, scs.frameRateSet, scs.frameRate); scs.frameRateSet, scs.frameRate); // TODO: pass sync settings to mediaplayer when it supports it AVSyncSettings avsync; // process_media_player_call(env, thiz, mp->setSyncSettings(scs), NULL, NULL); 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 static jobject Loading @@ -508,21 +551,27 @@ android_media_MediaPlayer_getSyncSettings(JNIEnv *env, jobject thiz) } } SyncSettings scs; SyncSettings scs; scs.syncSource = 0; // SYNC_SOURCE_DEFAULT scs.frameRate = -1.f; scs.audioAdjustMode = 0; // AUDIO_ADJUST_MODE_DEFAULT process_media_player_call( scs.tolerance = 0.f; env, thiz, mp->getSyncSettings(&scs.sync, &scs.frameRate), scs.frameRate = 0.f; "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", 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.syncSourceSet = true; scs.audioAdjustModeSet = true; scs.audioAdjustModeSet = true; scs.toleranceSet = true; scs.toleranceSet = true; scs.frameRateSet = false; scs.frameRateSet = scs.frameRate >= 0.f; return scs.asJobject(env, gSyncSettingsFields); return scs.asJobject(env, gSyncSettingsFields); } } Loading media/jni/android_media_MediaSync.cpp +169 −49 Original line number Original line Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include "android_media_MediaSync.h" #include "android_media_MediaSync.h" #include "android_media_AudioTrack.h" #include "android_media_AudioTrack.h" #include "android_media_PlaybackSettings.h" #include "android_media_SyncSettings.h" #include "android_media_SyncSettings.h" #include "android_runtime/AndroidRuntime.h" #include "android_runtime/AndroidRuntime.h" #include "android_runtime/android_view_Surface.h" #include "android_runtime/android_view_Surface.h" Loading @@ -29,6 +30,7 @@ #include <gui/Surface.h> #include <gui/Surface.h> #include <media/AudioResamplerPublic.h> #include <media/AudioTrack.h> #include <media/AudioTrack.h> #include <media/stagefright/MediaClock.h> #include <media/stagefright/MediaClock.h> #include <media/stagefright/MediaSync.h> #include <media/stagefright/MediaSync.h> Loading @@ -47,6 +49,7 @@ struct fields_t { }; }; static fields_t gFields; static fields_t gFields; static PlaybackSettings::fields_t gPlaybackSettingsFields; static SyncSettings::fields_t gSyncSettingsFields; static SyncSettings::fields_t gSyncSettingsFields; //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// Loading @@ -62,10 +65,8 @@ status_t JMediaSync::configureSurface(const sp<IGraphicBufferProducer> &bufferPr return mSync->configureSurface(bufferProducer); return mSync->configureSurface(bufferProducer); } } status_t JMediaSync::configureAudioTrack( status_t JMediaSync::configureAudioTrack(const sp<AudioTrack> &audioTrack) { const sp<AudioTrack> &audioTrack, return mSync->configureAudioTrack(audioTrack); int32_t nativeSampleRateInHz) { return mSync->configureAudioTrack(audioTrack, nativeSampleRateInHz); } } status_t JMediaSync::createInputSurface( status_t JMediaSync::createInputSurface( Loading @@ -73,14 +74,34 @@ status_t JMediaSync::createInputSurface( return mSync->createInputSurface(bufferProducer); return mSync->createInputSurface(bufferProducer); } } status_t JMediaSync::setPlaybackRate(float rate) { return mSync->setPlaybackRate(rate); } sp<const MediaClock> JMediaSync::getMediaClock() { sp<const MediaClock> JMediaSync::getMediaClock() { return mSync->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( status_t JMediaSync::updateQueuedAudioData( int sizeInBytes, int64_t presentationTimeUs) { int sizeInBytes, int64_t presentationTimeUs) { return mSync->updateQueuedAudioData(sizeInBytes, presentationTimeUs); return mSync->updateQueuedAudioData(sizeInBytes, presentationTimeUs); Loading Loading @@ -176,7 +197,7 @@ static void android_media_MediaSync_native_configureSurface( } } static void android_media_MediaSync_native_configureAudioTrack( 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"); ALOGV("android_media_MediaSync_configureAudioTrack"); sp<JMediaSync> sync = getMediaSync(env, thiz); sp<JMediaSync> sync = getMediaSync(env, thiz); Loading @@ -194,7 +215,7 @@ static void android_media_MediaSync_native_configureAudioTrack( } } } } status_t err = sync->configureAudioTrack(audioTrack, nativeSampleRateInHz); status_t err = sync->configureAudioTrack(audioTrack); if (err == INVALID_OPERATION) { if (err == INVALID_OPERATION) { throwExceptionAsNecessary( throwExceptionAsNecessary( Loading Loading @@ -287,29 +308,132 @@ static jlong android_media_MediaSync_native_getPlayTimeForPendingAudioFrames( return (jlong)playTimeUs; return (jlong)playTimeUs; } } static void static jfloat android_media_MediaSync_setPlaybackSettings( android_media_MediaSync_setSyncSettings(JNIEnv *env, jobject thiz, jobject settings) JNIEnv *env, jobject thiz, jobject settings) { { sp<JMediaSync> sync = getMediaSync(env, thiz); sp<JMediaSync> sync = getMediaSync(env, thiz); if (sync == NULL) { if (sync == NULL) { throwExceptionAsNecessary(env, INVALID_OPERATION); 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; SyncSettings scs; scs.fillFromJobject(env, gSyncSettingsFields, settings); scs.fillFromJobject(env, gSyncSettingsFields, settings); ALOGV("setSyncSettings: %d:%d %d:%d %d:%f %d:%f", ALOGV("setSyncSettings: %d:%d %d:%d %d:%f %d:%f", scs.syncSourceSet, scs.syncSource, scs.syncSourceSet, scs.sync.mSource, scs.audioAdjustModeSet, scs.audioAdjustMode, scs.audioAdjustModeSet, scs.sync.mAudioAdjustMode, scs.toleranceSet, scs.tolerance, scs.toleranceSet, scs.sync.mTolerance, scs.frameRateSet, scs.frameRate); 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; } } static jobject sp<const MediaClock> mediaClock = sync->getMediaClock(); android_media_MediaSync_getSyncSettings(JNIEnv *env, jobject thiz) if (mediaClock == NULL) { { return (jfloat)0.f; } return (jfloat)mediaClock->getPlaybackRate(); } static jobject android_media_MediaSync_getSyncSettings(JNIEnv *env, jobject thiz) { sp<JMediaSync> sync = getMediaSync(env, thiz); sp<JMediaSync> sync = getMediaSync(env, thiz); if (sync == NULL) { if (sync == NULL) { throwExceptionAsNecessary(env, INVALID_OPERATION); throwExceptionAsNecessary(env, INVALID_OPERATION); Loading @@ -317,21 +441,25 @@ android_media_MediaSync_getSyncSettings(JNIEnv *env, jobject thiz) } } SyncSettings scs; SyncSettings scs; scs.syncSource = 0; // SYNC_SOURCE_DEFAULT sync->getSyncSettings(&scs.sync); scs.audioAdjustMode = 0; // AUDIO_ADJUST_MODE_DEFAULT scs.frameRate = sync->getVideoFrameRate(); scs.tolerance = 0.f; scs.frameRate = 0.f; // 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", 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.syncSourceSet = true; scs.audioAdjustModeSet = true; scs.audioAdjustModeSet = true; scs.toleranceSet = true; scs.toleranceSet = true; scs.frameRateSet = false; scs.frameRateSet = scs.frameRate >= 0.f; return scs.asJobject(env, gSyncSettingsFields); return scs.asJobject(env, gSyncSettingsFields); } } Loading Loading @@ -359,6 +487,7 @@ static void android_media_MediaSync_native_init(JNIEnv *env) { CHECK(gFields.mediaTimestampClockRateID != NULL); CHECK(gFields.mediaTimestampClockRateID != NULL); gSyncSettingsFields.init(env); gSyncSettingsFields.init(env); gPlaybackSettingsFields.init(env); } } static void android_media_MediaSync_native_setup(JNIEnv *env, jobject thiz) { static void android_media_MediaSync_native_setup(JNIEnv *env, jobject thiz) { Loading @@ -367,21 +496,6 @@ static void android_media_MediaSync_native_setup(JNIEnv *env, jobject thiz) { setMediaSync(env, thiz, sync); 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) { static void android_media_MediaSync_native_finalize(JNIEnv *env, jobject thiz) { android_media_MediaSync_release(env, thiz); android_media_MediaSync_release(env, thiz); } } Loading Loading @@ -416,11 +530,17 @@ static JNINativeMethod gMethods[] = { { "native_release", "()V", (void *)android_media_MediaSync_release }, { "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 }, { "getPlaybackSettings", "()Landroid/media/PlaybackSettings;", (void *)android_media_MediaSync_getPlaybackSettings }, { "setSyncSettings", "(Landroid/media/SyncSettings;)V", (void *)android_media_MediaSync_setSyncSettings}, { "native_setSyncSettings", "(Landroid/media/SyncSettings;)F", (void *)android_media_MediaSync_setSyncSettings }, { "getSyncSettings", "()Landroid/media/SyncSettings;", (void *)android_media_MediaSync_getSyncSettings}, { "getSyncSettings", "()Landroid/media/SyncSettings;", (void *)android_media_MediaSync_getSyncSettings }, { "native_finalize", "()V", (void *)android_media_MediaSync_native_finalize }, { "native_finalize", "()V", (void *)android_media_MediaSync_native_finalize }, }; }; Loading media/jni/android_media_MediaSync.h +10 −4 Original line number Original line Diff line number Diff line Loading @@ -18,11 +18,13 @@ #define _ANDROID_MEDIA_MEDIASYNC_H_ #define _ANDROID_MEDIA_MEDIASYNC_H_ #include <media/stagefright/foundation/ABase.h> #include <media/stagefright/foundation/ABase.h> #include <media/stagefright/MediaSync.h> #include <utils/Errors.h> #include <utils/Errors.h> #include <utils/RefBase.h> #include <utils/RefBase.h> namespace android { namespace android { struct AudioPlaybackRate; class AudioTrack; class AudioTrack; struct IGraphicBufferProducer; struct IGraphicBufferProducer; struct MediaClock; struct MediaClock; Loading @@ -32,17 +34,21 @@ struct JMediaSync : public RefBase { JMediaSync(); JMediaSync(); status_t configureSurface(const sp<IGraphicBufferProducer> &bufferProducer); status_t configureSurface(const sp<IGraphicBufferProducer> &bufferProducer); status_t configureAudioTrack( status_t configureAudioTrack(const sp<AudioTrack> &audioTrack); const sp<AudioTrack> &audioTrack, int32_t nativeSampleRateInHz); status_t createInputSurface(sp<IGraphicBufferProducer>* bufferProducer); status_t createInputSurface(sp<IGraphicBufferProducer>* bufferProducer); status_t updateQueuedAudioData(int sizeInBytes, int64_t presentationTimeUs); status_t updateQueuedAudioData(int sizeInBytes, int64_t presentationTimeUs); status_t setPlaybackRate(float rate); status_t getPlayTimeForPendingAudioFrames(int64_t *outTimeUs); 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(); sp<const MediaClock> getMediaClock(); protected: protected: Loading media/jni/android_media_SyncSettings.cpp +6 −6 Original line number Original line Diff line number Diff line Loading @@ -57,9 +57,9 @@ void SyncSettings::fields_t::exit(JNIEnv *env) { } } void SyncSettings::fillFromJobject(JNIEnv *env, const fields_t& fields, jobject settings) { void SyncSettings::fillFromJobject(JNIEnv *env, const fields_t& fields, jobject settings) { syncSource = env->GetIntField(settings, fields.sync_source); sync.mSource = (AVSyncSource)env->GetIntField(settings, fields.sync_source); audioAdjustMode = env->GetIntField(settings, fields.audio_adjust_mode); sync.mAudioAdjustMode = (AVSyncAudioAdjustMode)env->GetIntField(settings, fields.audio_adjust_mode); tolerance = env->GetFloatField(settings, fields.tolerance); sync.mTolerance = env->GetFloatField(settings, fields.tolerance); frameRate = env->GetFloatField(settings, fields.frame_rate); frameRate = env->GetFloatField(settings, fields.frame_rate); int set = env->GetIntField(settings, fields.set); int set = env->GetIntField(settings, fields.set); Loading @@ -74,9 +74,9 @@ jobject SyncSettings::asJobject(JNIEnv *env, const fields_t& fields) { if (settings == NULL) { if (settings == NULL) { return NULL; return NULL; } } env->SetIntField(settings, fields.sync_source, (jint)syncSource); env->SetIntField(settings, fields.sync_source, (jint)sync.mSource); env->SetIntField(settings, fields.audio_adjust_mode, (jint)audioAdjustMode); env->SetIntField(settings, fields.audio_adjust_mode, (jint)sync.mAudioAdjustMode); env->SetFloatField(settings, fields.tolerance, (jfloat)tolerance); env->SetFloatField(settings, fields.tolerance, (jfloat)sync.mTolerance); env->SetFloatField(settings, fields.frame_rate, (jfloat)frameRate); env->SetFloatField(settings, fields.frame_rate, (jfloat)frameRate); env->SetIntField( env->SetIntField( settings, fields.set, settings, fields.set, Loading Loading
media/java/android/media/MediaSync.java +18 −42 Original line number Original line Diff line number Diff line Loading @@ -199,6 +199,7 @@ final public class MediaSync { private final Object mAudioLock = new Object(); private final Object mAudioLock = new Object(); private AudioTrack mAudioTrack = null; private AudioTrack mAudioTrack = null; private List<AudioBuffer> mAudioBuffers = new LinkedList<AudioBuffer>(); 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 float mPlaybackRate = 0.0f; private long mNativeContext; private long mNativeContext; Loading Loading @@ -459,37 +460,12 @@ final public class MediaSync { * @throws IllegalArgumentException if the settings are not supported. * @throws IllegalArgumentException if the settings are not supported. */ */ public void setPlaybackSettings(@NonNull PlaybackSettings settings) { 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) { synchronized(mAudioLock) { mPlaybackRate = rate; mPlaybackRate = native_setPlaybackSettings(settings);; } } if (mPlaybackRate != 0.0 && mAudioThread != null) { if (mPlaybackRate != 0.0 && mAudioThread != null) { postRenderAudio(0); postRenderAudio(0); } } native_setPlaybackRate(mPlaybackRate); } catch (IllegalStateException e) { // rate is not specified; still, propagate settings to audio track if (mAudioTrack != null) { mAudioTrack.setPlaybackSettings(settings); } } } } /** /** Loading @@ -501,18 +477,9 @@ final public class MediaSync { * been initialized. * been initialized. */ */ @NonNull @NonNull public PlaybackSettings getPlaybackSettings() { public native 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); private native float native_setPlaybackSettings(@NonNull PlaybackSettings settings); /** /** * Sets A/V sync mode. * Sets A/V sync mode. Loading @@ -523,7 +490,16 @@ final public class MediaSync { * initialized. * initialized. * @throws IllegalArgumentException if settings are not supported. * @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. * Gets the A/V sync mode. Loading
media/jni/android_media_MediaPlayer.cpp +77 −28 Original line number Original line Diff line number Diff line Loading @@ -174,6 +174,8 @@ static void process_media_player_call(JNIEnv *env, jobject thiz, status_t opStat } else { // Throw exception! } else { // Throw exception! if ( opStatus == (status_t) INVALID_OPERATION ) { if ( opStatus == (status_t) INVALID_OPERATION ) { jniThrowException(env, "java/lang/IllegalStateException", NULL); 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 ) { } else if ( opStatus == (status_t) PERMISSION_DENIED ) { jniThrowException(env, "java/lang/SecurityException", NULL); jniThrowException(env, "java/lang/SecurityException", NULL); } else if ( opStatus != (status_t) OK ) { } else if ( opStatus != (status_t) OK ) { Loading Loading @@ -442,8 +444,33 @@ android_media_MediaPlayer_setPlaybackSettings(JNIEnv *env, jobject thiz, jobject pbs.audioFallbackModeSet, pbs.audioRate.mFallbackMode, pbs.audioFallbackModeSet, pbs.audioRate.mFallbackMode, pbs.audioStretchModeSet, pbs.audioRate.mStretchMode); pbs.audioStretchModeSet, pbs.audioRate.mStretchMode); // TODO: pass playback settings to mediaplayer when audiotrack supports it AudioPlaybackRate rate; process_media_player_call(env, thiz, mp->setPlaybackRate(pbs.audioRate.mSpeed), NULL, NULL); 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 static jobject Loading @@ -457,15 +484,9 @@ android_media_MediaPlayer_getPlaybackSettings(JNIEnv *env, jobject thiz) PlaybackSettings pbs; PlaybackSettings pbs; AudioPlaybackRate &audioRate = pbs.audioRate; AudioPlaybackRate &audioRate = pbs.audioRate; process_media_player_call( audioRate.mSpeed = 1.0f; env, thiz, mp->getPlaybackSettings(&audioRate), audioRate.mPitch = 1.0f; "java/lang/IllegalStateException", "unexpected error"); 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", ALOGV("getPlaybackSettings: %f %f %d %d", audioRate.mSpeed, audioRate.mPitch, audioRate.mFallbackMode, audioRate.mStretchMode); audioRate.mSpeed, audioRate.mPitch, audioRate.mFallbackMode, audioRate.mStretchMode); Loading @@ -489,13 +510,35 @@ android_media_MediaPlayer_setSyncSettings(JNIEnv *env, jobject thiz, jobject set SyncSettings scs; SyncSettings scs; scs.fillFromJobject(env, gSyncSettingsFields, settings); scs.fillFromJobject(env, gSyncSettingsFields, settings); ALOGV("setSyncSettings: %d:%d %d:%d %d:%f %d:%f", ALOGV("setSyncSettings: %d:%d %d:%d %d:%f %d:%f", scs.syncSourceSet, scs.syncSource, scs.syncSourceSet, scs.sync.mSource, scs.audioAdjustModeSet, scs.audioAdjustMode, scs.audioAdjustModeSet, scs.sync.mAudioAdjustMode, scs.toleranceSet, scs.tolerance, scs.toleranceSet, scs.sync.mTolerance, scs.frameRateSet, scs.frameRate); scs.frameRateSet, scs.frameRate); // TODO: pass sync settings to mediaplayer when it supports it AVSyncSettings avsync; // process_media_player_call(env, thiz, mp->setSyncSettings(scs), NULL, NULL); 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 static jobject Loading @@ -508,21 +551,27 @@ android_media_MediaPlayer_getSyncSettings(JNIEnv *env, jobject thiz) } } SyncSettings scs; SyncSettings scs; scs.syncSource = 0; // SYNC_SOURCE_DEFAULT scs.frameRate = -1.f; scs.audioAdjustMode = 0; // AUDIO_ADJUST_MODE_DEFAULT process_media_player_call( scs.tolerance = 0.f; env, thiz, mp->getSyncSettings(&scs.sync, &scs.frameRate), scs.frameRate = 0.f; "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", 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.syncSourceSet = true; scs.audioAdjustModeSet = true; scs.audioAdjustModeSet = true; scs.toleranceSet = true; scs.toleranceSet = true; scs.frameRateSet = false; scs.frameRateSet = scs.frameRate >= 0.f; return scs.asJobject(env, gSyncSettingsFields); return scs.asJobject(env, gSyncSettingsFields); } } Loading
media/jni/android_media_MediaSync.cpp +169 −49 Original line number Original line Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include "android_media_MediaSync.h" #include "android_media_MediaSync.h" #include "android_media_AudioTrack.h" #include "android_media_AudioTrack.h" #include "android_media_PlaybackSettings.h" #include "android_media_SyncSettings.h" #include "android_media_SyncSettings.h" #include "android_runtime/AndroidRuntime.h" #include "android_runtime/AndroidRuntime.h" #include "android_runtime/android_view_Surface.h" #include "android_runtime/android_view_Surface.h" Loading @@ -29,6 +30,7 @@ #include <gui/Surface.h> #include <gui/Surface.h> #include <media/AudioResamplerPublic.h> #include <media/AudioTrack.h> #include <media/AudioTrack.h> #include <media/stagefright/MediaClock.h> #include <media/stagefright/MediaClock.h> #include <media/stagefright/MediaSync.h> #include <media/stagefright/MediaSync.h> Loading @@ -47,6 +49,7 @@ struct fields_t { }; }; static fields_t gFields; static fields_t gFields; static PlaybackSettings::fields_t gPlaybackSettingsFields; static SyncSettings::fields_t gSyncSettingsFields; static SyncSettings::fields_t gSyncSettingsFields; //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// Loading @@ -62,10 +65,8 @@ status_t JMediaSync::configureSurface(const sp<IGraphicBufferProducer> &bufferPr return mSync->configureSurface(bufferProducer); return mSync->configureSurface(bufferProducer); } } status_t JMediaSync::configureAudioTrack( status_t JMediaSync::configureAudioTrack(const sp<AudioTrack> &audioTrack) { const sp<AudioTrack> &audioTrack, return mSync->configureAudioTrack(audioTrack); int32_t nativeSampleRateInHz) { return mSync->configureAudioTrack(audioTrack, nativeSampleRateInHz); } } status_t JMediaSync::createInputSurface( status_t JMediaSync::createInputSurface( Loading @@ -73,14 +74,34 @@ status_t JMediaSync::createInputSurface( return mSync->createInputSurface(bufferProducer); return mSync->createInputSurface(bufferProducer); } } status_t JMediaSync::setPlaybackRate(float rate) { return mSync->setPlaybackRate(rate); } sp<const MediaClock> JMediaSync::getMediaClock() { sp<const MediaClock> JMediaSync::getMediaClock() { return mSync->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( status_t JMediaSync::updateQueuedAudioData( int sizeInBytes, int64_t presentationTimeUs) { int sizeInBytes, int64_t presentationTimeUs) { return mSync->updateQueuedAudioData(sizeInBytes, presentationTimeUs); return mSync->updateQueuedAudioData(sizeInBytes, presentationTimeUs); Loading Loading @@ -176,7 +197,7 @@ static void android_media_MediaSync_native_configureSurface( } } static void android_media_MediaSync_native_configureAudioTrack( 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"); ALOGV("android_media_MediaSync_configureAudioTrack"); sp<JMediaSync> sync = getMediaSync(env, thiz); sp<JMediaSync> sync = getMediaSync(env, thiz); Loading @@ -194,7 +215,7 @@ static void android_media_MediaSync_native_configureAudioTrack( } } } } status_t err = sync->configureAudioTrack(audioTrack, nativeSampleRateInHz); status_t err = sync->configureAudioTrack(audioTrack); if (err == INVALID_OPERATION) { if (err == INVALID_OPERATION) { throwExceptionAsNecessary( throwExceptionAsNecessary( Loading Loading @@ -287,29 +308,132 @@ static jlong android_media_MediaSync_native_getPlayTimeForPendingAudioFrames( return (jlong)playTimeUs; return (jlong)playTimeUs; } } static void static jfloat android_media_MediaSync_setPlaybackSettings( android_media_MediaSync_setSyncSettings(JNIEnv *env, jobject thiz, jobject settings) JNIEnv *env, jobject thiz, jobject settings) { { sp<JMediaSync> sync = getMediaSync(env, thiz); sp<JMediaSync> sync = getMediaSync(env, thiz); if (sync == NULL) { if (sync == NULL) { throwExceptionAsNecessary(env, INVALID_OPERATION); 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; SyncSettings scs; scs.fillFromJobject(env, gSyncSettingsFields, settings); scs.fillFromJobject(env, gSyncSettingsFields, settings); ALOGV("setSyncSettings: %d:%d %d:%d %d:%f %d:%f", ALOGV("setSyncSettings: %d:%d %d:%d %d:%f %d:%f", scs.syncSourceSet, scs.syncSource, scs.syncSourceSet, scs.sync.mSource, scs.audioAdjustModeSet, scs.audioAdjustMode, scs.audioAdjustModeSet, scs.sync.mAudioAdjustMode, scs.toleranceSet, scs.tolerance, scs.toleranceSet, scs.sync.mTolerance, scs.frameRateSet, scs.frameRate); 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; } } static jobject sp<const MediaClock> mediaClock = sync->getMediaClock(); android_media_MediaSync_getSyncSettings(JNIEnv *env, jobject thiz) if (mediaClock == NULL) { { return (jfloat)0.f; } return (jfloat)mediaClock->getPlaybackRate(); } static jobject android_media_MediaSync_getSyncSettings(JNIEnv *env, jobject thiz) { sp<JMediaSync> sync = getMediaSync(env, thiz); sp<JMediaSync> sync = getMediaSync(env, thiz); if (sync == NULL) { if (sync == NULL) { throwExceptionAsNecessary(env, INVALID_OPERATION); throwExceptionAsNecessary(env, INVALID_OPERATION); Loading @@ -317,21 +441,25 @@ android_media_MediaSync_getSyncSettings(JNIEnv *env, jobject thiz) } } SyncSettings scs; SyncSettings scs; scs.syncSource = 0; // SYNC_SOURCE_DEFAULT sync->getSyncSettings(&scs.sync); scs.audioAdjustMode = 0; // AUDIO_ADJUST_MODE_DEFAULT scs.frameRate = sync->getVideoFrameRate(); scs.tolerance = 0.f; scs.frameRate = 0.f; // 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", 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.syncSourceSet = true; scs.audioAdjustModeSet = true; scs.audioAdjustModeSet = true; scs.toleranceSet = true; scs.toleranceSet = true; scs.frameRateSet = false; scs.frameRateSet = scs.frameRate >= 0.f; return scs.asJobject(env, gSyncSettingsFields); return scs.asJobject(env, gSyncSettingsFields); } } Loading Loading @@ -359,6 +487,7 @@ static void android_media_MediaSync_native_init(JNIEnv *env) { CHECK(gFields.mediaTimestampClockRateID != NULL); CHECK(gFields.mediaTimestampClockRateID != NULL); gSyncSettingsFields.init(env); gSyncSettingsFields.init(env); gPlaybackSettingsFields.init(env); } } static void android_media_MediaSync_native_setup(JNIEnv *env, jobject thiz) { static void android_media_MediaSync_native_setup(JNIEnv *env, jobject thiz) { Loading @@ -367,21 +496,6 @@ static void android_media_MediaSync_native_setup(JNIEnv *env, jobject thiz) { setMediaSync(env, thiz, sync); 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) { static void android_media_MediaSync_native_finalize(JNIEnv *env, jobject thiz) { android_media_MediaSync_release(env, thiz); android_media_MediaSync_release(env, thiz); } } Loading Loading @@ -416,11 +530,17 @@ static JNINativeMethod gMethods[] = { { "native_release", "()V", (void *)android_media_MediaSync_release }, { "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 }, { "getPlaybackSettings", "()Landroid/media/PlaybackSettings;", (void *)android_media_MediaSync_getPlaybackSettings }, { "setSyncSettings", "(Landroid/media/SyncSettings;)V", (void *)android_media_MediaSync_setSyncSettings}, { "native_setSyncSettings", "(Landroid/media/SyncSettings;)F", (void *)android_media_MediaSync_setSyncSettings }, { "getSyncSettings", "()Landroid/media/SyncSettings;", (void *)android_media_MediaSync_getSyncSettings}, { "getSyncSettings", "()Landroid/media/SyncSettings;", (void *)android_media_MediaSync_getSyncSettings }, { "native_finalize", "()V", (void *)android_media_MediaSync_native_finalize }, { "native_finalize", "()V", (void *)android_media_MediaSync_native_finalize }, }; }; Loading
media/jni/android_media_MediaSync.h +10 −4 Original line number Original line Diff line number Diff line Loading @@ -18,11 +18,13 @@ #define _ANDROID_MEDIA_MEDIASYNC_H_ #define _ANDROID_MEDIA_MEDIASYNC_H_ #include <media/stagefright/foundation/ABase.h> #include <media/stagefright/foundation/ABase.h> #include <media/stagefright/MediaSync.h> #include <utils/Errors.h> #include <utils/Errors.h> #include <utils/RefBase.h> #include <utils/RefBase.h> namespace android { namespace android { struct AudioPlaybackRate; class AudioTrack; class AudioTrack; struct IGraphicBufferProducer; struct IGraphicBufferProducer; struct MediaClock; struct MediaClock; Loading @@ -32,17 +34,21 @@ struct JMediaSync : public RefBase { JMediaSync(); JMediaSync(); status_t configureSurface(const sp<IGraphicBufferProducer> &bufferProducer); status_t configureSurface(const sp<IGraphicBufferProducer> &bufferProducer); status_t configureAudioTrack( status_t configureAudioTrack(const sp<AudioTrack> &audioTrack); const sp<AudioTrack> &audioTrack, int32_t nativeSampleRateInHz); status_t createInputSurface(sp<IGraphicBufferProducer>* bufferProducer); status_t createInputSurface(sp<IGraphicBufferProducer>* bufferProducer); status_t updateQueuedAudioData(int sizeInBytes, int64_t presentationTimeUs); status_t updateQueuedAudioData(int sizeInBytes, int64_t presentationTimeUs); status_t setPlaybackRate(float rate); status_t getPlayTimeForPendingAudioFrames(int64_t *outTimeUs); 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(); sp<const MediaClock> getMediaClock(); protected: protected: Loading
media/jni/android_media_SyncSettings.cpp +6 −6 Original line number Original line Diff line number Diff line Loading @@ -57,9 +57,9 @@ void SyncSettings::fields_t::exit(JNIEnv *env) { } } void SyncSettings::fillFromJobject(JNIEnv *env, const fields_t& fields, jobject settings) { void SyncSettings::fillFromJobject(JNIEnv *env, const fields_t& fields, jobject settings) { syncSource = env->GetIntField(settings, fields.sync_source); sync.mSource = (AVSyncSource)env->GetIntField(settings, fields.sync_source); audioAdjustMode = env->GetIntField(settings, fields.audio_adjust_mode); sync.mAudioAdjustMode = (AVSyncAudioAdjustMode)env->GetIntField(settings, fields.audio_adjust_mode); tolerance = env->GetFloatField(settings, fields.tolerance); sync.mTolerance = env->GetFloatField(settings, fields.tolerance); frameRate = env->GetFloatField(settings, fields.frame_rate); frameRate = env->GetFloatField(settings, fields.frame_rate); int set = env->GetIntField(settings, fields.set); int set = env->GetIntField(settings, fields.set); Loading @@ -74,9 +74,9 @@ jobject SyncSettings::asJobject(JNIEnv *env, const fields_t& fields) { if (settings == NULL) { if (settings == NULL) { return NULL; return NULL; } } env->SetIntField(settings, fields.sync_source, (jint)syncSource); env->SetIntField(settings, fields.sync_source, (jint)sync.mSource); env->SetIntField(settings, fields.audio_adjust_mode, (jint)audioAdjustMode); env->SetIntField(settings, fields.audio_adjust_mode, (jint)sync.mAudioAdjustMode); env->SetFloatField(settings, fields.tolerance, (jfloat)tolerance); env->SetFloatField(settings, fields.tolerance, (jfloat)sync.mTolerance); env->SetFloatField(settings, fields.frame_rate, (jfloat)frameRate); env->SetFloatField(settings, fields.frame_rate, (jfloat)frameRate); env->SetIntField( env->SetIntField( settings, fields.set, settings, fields.set, Loading