summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--media/java/android/media/MediaSync.java40
-rw-r--r--media/jni/android_media_MediaSync.cpp16
-rw-r--r--media/jni/android_media_MediaSync.h2
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: