diff options
author | Lajos Molnar <lajos@google.com> | 2015-06-10 01:04:45 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2015-06-10 01:04:50 +0000 |
commit | 53858ced4cfe4717d90b298e7fb4ffa18effcfcf (patch) | |
tree | 25b0e5fa5c5ea3cd6e6ea070ff1216a66144e416 | |
parent | dbcf0a9e7d36545b73225ba2c164beb4b0ad9a06 (diff) | |
parent | d8578577b02cf6360402eb8726e964d18b46434d (diff) | |
download | frameworks_base-53858ced4cfe4717d90b298e7fb4ffa18effcfcf.zip frameworks_base-53858ced4cfe4717d90b298e7fb4ffa18effcfcf.tar.gz frameworks_base-53858ced4cfe4717d90b298e7fb4ffa18effcfcf.tar.bz2 |
Merge "media: hook up OnFrameRenderedListener events to framework events" into mnc-dev
-rw-r--r-- | media/java/android/media/MediaCodec.java | 47 | ||||
-rw-r--r-- | media/jni/android_media_MediaCodec.cpp | 58 | ||||
-rw-r--r-- | media/jni/android_media_MediaCodec.h | 7 |
3 files changed, 76 insertions, 36 deletions
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java index eec4960..a79dd04 100644 --- a/media/java/android/media/MediaCodec.java +++ b/media/java/android/media/MediaCodec.java @@ -1455,15 +1455,6 @@ final public class MediaCodec { @Retention(RetentionPolicy.SOURCE) public @interface BufferFlag {} - private static class FrameRenderedInfo { - public long mPresentationTimeUs; - public long mNanoTime; - public FrameRenderedInfo(long presentationTimeUs, long nanoTime) { - mPresentationTimeUs = presentationTimeUs; - mNanoTime = nanoTime; - } - } - private EventHandler mEventHandler; private EventHandler mOnFrameRenderedHandler; private EventHandler mCallbackHandler; @@ -1503,10 +1494,16 @@ final public class MediaCodec { } case EVENT_FRAME_RENDERED: synchronized (mListenerLock) { - FrameRenderedInfo info = (FrameRenderedInfo)msg.obj; - if (mOnFrameRenderedListener != null) { + Map<String, Object> map = (Map<String, Object>)msg.obj; + for (int i = 0; ; ++i) { + Object mediaTimeUs = map.get(i + "-media-time-us"); + Object systemNano = map.get(i + "-system-nano"); + if (mediaTimeUs == null || systemNano == null + || mOnFrameRenderedListener == null) { + break; + } mOnFrameRenderedListener.onFrameRendered( - mCodec, info.mPresentationTimeUs, info.mNanoTime); + mCodec, (long)mediaTimeUs, (long)systemNano); } break; } @@ -2362,26 +2359,9 @@ final public class MediaCodec { info = mDequeuedOutputInfos.remove(index); } } - // TODO - // until codec and libgui supports callback, assume frame is rendered within 50 ms - postRenderedCallback(render, info, 50 /* delayMs */); releaseOutputBuffer(index, render, false /* updatePTS */, 0 /* dummy */); } - private void postRenderedCallback(boolean render, @Nullable BufferInfo info, long delayMs) { - if (render && info != null) { - synchronized (mListenerLock) { - if (mOnFrameRenderedListener != null) { - FrameRenderedInfo obj = new FrameRenderedInfo( - info.presentationTimeUs, System.nanoTime() + delayMs * 1000000); - Message msg = mOnFrameRenderedHandler.obtainMessage( - EVENT_FRAME_RENDERED, obj); - mOnFrameRenderedHandler.sendMessageDelayed(msg, delayMs); - } - } - } - } - /** * If you are done with a buffer, use this call to update its surface timestamp * and return it to the codec to render it on the output surface. If you @@ -2440,12 +2420,6 @@ final public class MediaCodec { info = mDequeuedOutputInfos.remove(index); } } - // TODO - // until codec and libgui supports callback, assume frame is rendered at the - // render time or 16 ms from now, whichever is later. - postRenderedCallback( - true /* render */, info, - Math.max(renderTimestampNs - System.nanoTime(), 16666666) / 1000000); releaseOutputBuffer( index, true /* render */, true /* updatePTS */, renderTimestampNs); } @@ -3049,9 +3023,12 @@ final public class MediaCodec { } else if (mOnFrameRenderedHandler != null) { mOnFrameRenderedHandler.removeMessages(EVENT_FRAME_RENDERED); } + native_enableOnFrameRenderedListener(listener != null); } } + private native void native_enableOnFrameRenderedListener(boolean enable); + private EventHandler getEventHandlerOn( @Nullable Handler handler, @NonNull EventHandler lastHandler) { if (handler == null) { diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp index 93b8ec7..ce7f7e5 100644 --- a/media/jni/android_media_MediaCodec.cpp +++ b/media/jni/android_media_MediaCodec.cpp @@ -56,6 +56,7 @@ enum { enum { EVENT_CALLBACK = 1, EVENT_SET_CALLBACK = 2, + EVENT_FRAME_RENDERED = 3, }; static struct CryptoErrorCodes { @@ -226,6 +227,18 @@ void JMediaCodec::deleteJavaObjects(JNIEnv *env) { mByteBufferLimitMethodID = NULL; } +status_t JMediaCodec::enableOnFrameRenderedListener(jboolean enable) { + if (enable) { + if (mOnFrameRenderedNotification == NULL) { + mOnFrameRenderedNotification = new AMessage(kWhatFrameRendered, this); + } + } else { + mOnFrameRenderedNotification.clear(); + } + + return mCodec->setOnFrameRenderedNotification(mOnFrameRenderedNotification); +} + status_t JMediaCodec::setCallback(jobject cb) { if (cb != NULL) { if (mCallbackNotification == NULL) { @@ -728,6 +741,27 @@ void JMediaCodec::handleCallback(const sp<AMessage> &msg) { env->DeleteLocalRef(obj); } +void JMediaCodec::handleFrameRenderedNotification(const sp<AMessage> &msg) { + int32_t arg1 = 0, arg2 = 0; + jobject obj = NULL; + JNIEnv *env = AndroidRuntime::getJNIEnv(); + + sp<AMessage> data; + CHECK(msg->findMessage("data", &data)); + + status_t err = ConvertMessageToMap(env, data, &obj); + if (err != OK) { + jniThrowException(env, "java/lang/IllegalStateException", NULL); + return; + } + + env->CallVoidMethod( + mObject, gFields.postEventFromNativeID, + EVENT_FRAME_RENDERED, arg1, arg2, obj); + + env->DeleteLocalRef(obj); +} + void JMediaCodec::onMessageReceived(const sp<AMessage> &msg) { switch (msg->what()) { case kWhatCallbackNotify: @@ -735,6 +769,11 @@ void JMediaCodec::onMessageReceived(const sp<AMessage> &msg) { handleCallback(msg); break; } + case kWhatFrameRendered: + { + handleFrameRenderedNotification(msg); + break; + } default: TRESPASS(); } @@ -848,6 +887,22 @@ static jint throwExceptionAsNecessary( } } +static void android_media_MediaCodec_native_enableOnFrameRenderedListener( + JNIEnv *env, + jobject thiz, + jboolean enabled) { + sp<JMediaCodec> codec = getMediaCodec(env, thiz); + + if (codec == NULL) { + throwExceptionAsNecessary(env, INVALID_OPERATION); + return; + } + + status_t err = codec->enableOnFrameRenderedListener(enabled); + + throwExceptionAsNecessary(env, err); +} + static void android_media_MediaCodec_native_setCallback( JNIEnv *env, jobject thiz, @@ -1744,6 +1799,9 @@ static JNINativeMethod gMethods[] = { { "native_setInputSurface", "(Landroid/view/Surface;)V", (void *)android_media_MediaCodec_setInputSurface }, + { "native_enableOnFrameRenderedListener", "(Z)V", + (void *)android_media_MediaCodec_native_enableOnFrameRenderedListener }, + { "native_setCallback", "(Landroid/media/MediaCodec$Callback;)V", (void *)android_media_MediaCodec_native_setCallback }, diff --git a/media/jni/android_media_MediaCodec.h b/media/jni/android_media_MediaCodec.h index a4ed67b..6650cf9 100644 --- a/media/jni/android_media_MediaCodec.h +++ b/media/jni/android_media_MediaCodec.h @@ -46,6 +46,8 @@ struct JMediaCodec : public AHandler { void registerSelf(); void release(); + status_t enableOnFrameRenderedListener(jboolean enable); + status_t setCallback(jobject cb); status_t configure( @@ -116,11 +118,11 @@ protected: virtual ~JMediaCodec(); virtual void onMessageReceived(const sp<AMessage> &msg); - void handleCallback(const sp<AMessage> &msg); private: enum { kWhatCallbackNotify, + kWhatFrameRendered, }; jclass mClass; @@ -139,6 +141,7 @@ private: sp<MediaCodec> mCodec; sp<AMessage> mCallbackNotification; + sp<AMessage> mOnFrameRenderedNotification; status_t mInitStatus; @@ -148,6 +151,8 @@ private: void cacheJavaObjects(JNIEnv *env); void deleteJavaObjects(JNIEnv *env); + void handleCallback(const sp<AMessage> &msg); + void handleFrameRenderedNotification(const sp<AMessage> &msg); DISALLOW_EVIL_CONSTRUCTORS(JMediaCodec); }; |