diff options
author | Lajos Molnar <lajos@google.com> | 2015-07-17 13:24:15 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2015-07-17 13:24:27 +0000 |
commit | e6b407b4be0b9c8240d34259b14e324da4d6832b (patch) | |
tree | aa4005d7bc547bd7e9ff931f81691c3b8966ac9c | |
parent | 9349093cd984523a9d4bab397cd092b33c04f27e (diff) | |
parent | d08debcf42d820fa8ef9916077a7bfc0a36f2db5 (diff) | |
download | frameworks_base-e6b407b4be0b9c8240d34259b14e324da4d6832b.zip frameworks_base-e6b407b4be0b9c8240d34259b14e324da4d6832b.tar.gz frameworks_base-e6b407b4be0b9c8240d34259b14e324da4d6832b.tar.bz2 |
Merge "MediaSync: fix flush handling and deadlock" into mnc-dev
-rw-r--r-- | media/java/android/media/MediaSync.java | 40 | ||||
-rw-r--r-- | media/jni/android_media_MediaSync.cpp | 16 | ||||
-rw-r--r-- | media/jni/android_media_MediaSync.h | 2 |
3 files changed, 51 insertions, 7 deletions
diff --git a/media/java/android/media/MediaSync.java b/media/java/android/media/MediaSync.java index b07931d..b37e02c 100644 --- a/media/java/android/media/MediaSync.java +++ b/media/java/android/media/MediaSync.java @@ -24,6 +24,7 @@ import android.media.PlaybackParams; import android.os.Handler; import android.os.Looper; import android.os.Message; +import android.util.Log; import android.view.Surface; import java.lang.annotation.Retention; @@ -82,7 +83,7 @@ import java.util.List; * codec.releaseOutputBuffer(bufferId, 1000 * info.presentationTime); * } else { * ByteBuffer audioByteBuffer = codec.getOutputBuffer(bufferId); - * sync.queueByteBuffer(audioByteBuffer, bufferId, info.size, info.presentationTime); + * sync.queueAudio(audioByteBuffer, bufferId, info.presentationTime); * } * // ... * } @@ -427,6 +428,11 @@ public final class MediaSync { /** * Flushes all buffers from the sync object. * <p> + * All pending unprocessed audio and video buffers are discarded. If an audio track was + * configured, it is flushed and stopped. If a video output surface was configured, the + * last frame queued to it is left on the frame. Queue a blank video frame to clear the + * surface, + * <p> * No callbacks are received for the flushed buffers. * * @throws IllegalStateException if the internal player engine has not been @@ -437,10 +443,19 @@ public final class MediaSync { mAudioBuffers.clear(); mCallbackHandler.removeCallbacksAndMessages(null); } - // TODO implement this for surface buffers. + if (mAudioTrack != null) { + mAudioTrack.pause(); + mAudioTrack.flush(); + // Call stop() to signal to the AudioSink to completely fill the + // internal buffer before resuming playback. + mAudioTrack.stop(); + } + native_flush(); } - /** + private native final void native_flush(); + + /** * Get current playback position. * <p> * The MediaTimestamp represents how the media time correlates to the system time in @@ -478,6 +493,7 @@ public final class MediaSync { /** * Queues the audio data asynchronously for playback (AudioTrack must be in streaming mode). + * If the audio track was flushed as a result of {@link #flush}, it will be restarted. * @param audioData the buffer that holds the data to play. This buffer will be returned * to the client via registered callback. * @param bufferId an integer used to identify audioData. It will be returned to @@ -519,6 +535,14 @@ public final class MediaSync { AudioBuffer audioBuffer = mAudioBuffers.get(0); int size = audioBuffer.mByteBuffer.remaining(); + // restart audio track after flush + if (size > 0 && mAudioTrack.getPlayState() != AudioTrack.PLAYSTATE_PLAYING) { + try { + mAudioTrack.play(); + } catch (IllegalStateException e) { + Log.w(TAG, "could not start audio track"); + } + } int sizeWritten = mAudioTrack.write( audioBuffer.mByteBuffer, size, @@ -558,17 +582,19 @@ public final class MediaSync { final MediaSync sync = this; mCallbackHandler.post(new Runnable() { public void run() { + Callback callback; synchronized(mCallbackLock) { + callback = mCallback; if (mCallbackHandler == null || mCallbackHandler.getLooper().getThread() != Thread.currentThread()) { // callback handler has been changed. return; } - if (mCallback != null) { - mCallback.onAudioBufferConsumed(sync, audioBuffer.mByteBuffer, - audioBuffer.mBufferIndex); - } + } + if (callback != null) { + callback.onAudioBufferConsumed(sync, audioBuffer.mByteBuffer, + audioBuffer.mBufferIndex); } } }); diff --git a/media/jni/android_media_MediaSync.cpp b/media/jni/android_media_MediaSync.cpp index 8e0ed64..893c414 100644 --- a/media/jni/android_media_MediaSync.cpp +++ b/media/jni/android_media_MediaSync.cpp @@ -102,6 +102,10 @@ float JMediaSync::getVideoFrameRate() { return mSync->getVideoFrameRate(); } +void JMediaSync::flush() { + mSync->flush(); +} + status_t JMediaSync::updateQueuedAudioData( int sizeInBytes, int64_t presentationTimeUs) { return mSync->updateQueuedAudioData(sizeInBytes, presentationTimeUs); @@ -464,6 +468,16 @@ static jobject android_media_MediaSync_getSyncParams(JNIEnv *env, jobject thiz) return scs.asJobject(env, gSyncParamsFields); } +static void android_media_MediaSync_native_flush(JNIEnv *env, jobject thiz) { + sp<JMediaSync> sync = getMediaSync(env, thiz); + if (sync == NULL) { + throwExceptionAsNecessary(env, INVALID_OPERATION); + return; + } + + sync->flush(); +} + static void android_media_MediaSync_native_init(JNIEnv *env) { ScopedLocalRef<jclass> clazz(env, env->FindClass("android/media/MediaSync")); CHECK(clazz.get() != NULL); @@ -524,6 +538,8 @@ static JNINativeMethod gMethods[] = { "()J", (void *)android_media_MediaSync_native_getPlayTimeForPendingAudioFrames }, + { "native_flush", "()V", (void *)android_media_MediaSync_native_flush }, + { "native_init", "()V", (void *)android_media_MediaSync_native_init }, { "native_setup", "()V", (void *)android_media_MediaSync_native_setup }, diff --git a/media/jni/android_media_MediaSync.h b/media/jni/android_media_MediaSync.h index 22c77c7..6f80885 100644 --- a/media/jni/android_media_MediaSync.h +++ b/media/jni/android_media_MediaSync.h @@ -49,6 +49,8 @@ struct JMediaSync : public RefBase { status_t setVideoFrameRateHint(float rate); float getVideoFrameRate(); + void flush(); + sp<const MediaClock> getMediaClock(); protected: |