Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 53858ced authored by Lajos Molnar's avatar Lajos Molnar Committed by Android (Google) Code Review
Browse files

Merge "media: hook up OnFrameRenderedListener events to framework events" into mnc-dev

parents dbcf0a9e d8578577
Loading
Loading
Loading
Loading
+12 −35
Original line number Diff line number Diff line
@@ -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) {
+58 −0
Original line number Diff line number Diff line
@@ -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 },
+6 −1
Original line number Diff line number Diff line
@@ -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);
};