From b1f453f7bad36f96b88a3c5bdbf9f946fc940f28 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Thu, 31 Dec 2020 16:35:29 -0600 Subject: [PATCH] Charge time spent in the decode unit queue to the decoder rather than receive time --- .../binding/video/MediaCodecDecoderRenderer.java | 10 ++++++---- .../nvstream/av/video/VideoDecoderRenderer.java | 2 +- .../java/com/limelight/nvstream/jni/MoonBridge.java | 6 +++--- app/src/main/jni/moonlight-core/callbacks.c | 7 ++++--- app/src/main/jni/moonlight-core/moonlight-common-c | 2 +- 5 files changed, 15 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/com/limelight/binding/video/MediaCodecDecoderRenderer.java b/app/src/main/java/com/limelight/binding/video/MediaCodecDecoderRenderer.java index e655774c..53a662b5 100644 --- a/app/src/main/java/com/limelight/binding/video/MediaCodecDecoderRenderer.java +++ b/app/src/main/java/com/limelight/binding/video/MediaCodecDecoderRenderer.java @@ -638,7 +638,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer { @SuppressWarnings("deprecation") @Override public int submitDecodeUnit(byte[] decodeUnitData, int decodeUnitLength, int decodeUnitType, - int frameNumber, long receiveTimeMs) { + int frameNumber, long receiveTimeMs, long enqueueTimeMs) { if (stopping) { // Don't bother if we're stopping return MoonBridge.DR_OK; @@ -699,11 +699,13 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer { int inputBufferIndex; ByteBuffer buf; - long timestampUs = System.nanoTime() / 1000; + long timestampUs = enqueueTimeMs * 1000; if (!FRAME_RENDER_TIME_ONLY) { - // Count time from first packet received to decode start - activeWindowVideoStats.totalTimeMs += (timestampUs / 1000) - receiveTimeMs; + // Count time from first packet received to enqueue time as receive time + // We will count DU queue time as part of decoding, because it is directly + // caused by a slow decoder. + activeWindowVideoStats.totalTimeMs += enqueueTimeMs - receiveTimeMs; } if (timestampUs <= lastTimestampUs) { diff --git a/app/src/main/java/com/limelight/nvstream/av/video/VideoDecoderRenderer.java b/app/src/main/java/com/limelight/nvstream/av/video/VideoDecoderRenderer.java index ff383448..b0e76b6b 100644 --- a/app/src/main/java/com/limelight/nvstream/av/video/VideoDecoderRenderer.java +++ b/app/src/main/java/com/limelight/nvstream/av/video/VideoDecoderRenderer.java @@ -10,7 +10,7 @@ public abstract class VideoDecoderRenderer { // This is called once for each frame-start NALU. This means it will be called several times // for an IDR frame which contains several parameter sets and the I-frame data. public abstract int submitDecodeUnit(byte[] decodeUnitData, int decodeUnitLength, int decodeUnitType, - int frameNumber, long receiveTimeMs); + int frameNumber, long receiveTimeMs, long enqueueTimeMs); public abstract void cleanup(); diff --git a/app/src/main/java/com/limelight/nvstream/jni/MoonBridge.java b/app/src/main/java/com/limelight/nvstream/jni/MoonBridge.java index 9b6594c2..d297b863 100644 --- a/app/src/main/java/com/limelight/nvstream/jni/MoonBridge.java +++ b/app/src/main/java/com/limelight/nvstream/jni/MoonBridge.java @@ -149,11 +149,11 @@ public class MoonBridge { } public static int bridgeDrSubmitDecodeUnit(byte[] decodeUnitData, int decodeUnitLength, - int decodeUnitType, - int frameNumber, long receiveTimeMs) { + int decodeUnitType, int frameNumber, + long receiveTimeMs, long enqueueTimeMs) { if (videoRenderer != null) { return videoRenderer.submitDecodeUnit(decodeUnitData, decodeUnitLength, - decodeUnitType, frameNumber, receiveTimeMs); + decodeUnitType, frameNumber, receiveTimeMs, enqueueTimeMs); } else { return DR_OK; diff --git a/app/src/main/jni/moonlight-core/callbacks.c b/app/src/main/jni/moonlight-core/callbacks.c index caf33bda..8e2ceaad 100644 --- a/app/src/main/jni/moonlight-core/callbacks.c +++ b/app/src/main/jni/moonlight-core/callbacks.c @@ -79,7 +79,7 @@ Java_com_limelight_nvstream_jni_MoonBridge_init(JNIEnv *env, jclass clazz) { BridgeDrStartMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeDrStart", "()V"); BridgeDrStopMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeDrStop", "()V"); BridgeDrCleanupMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeDrCleanup", "()V"); - BridgeDrSubmitDecodeUnitMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeDrSubmitDecodeUnit", "([BIIIJ)I"); + BridgeDrSubmitDecodeUnitMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeDrSubmitDecodeUnit", "([BIIIJJ)I"); BridgeArInitMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeArInit", "(III)I"); BridgeArStartMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeArStart", "()V"); BridgeArStopMethod = (*env)->GetStaticMethodID(env, clazz, "bridgeArStop", "()V"); @@ -157,7 +157,8 @@ int BridgeDrSubmitDecodeUnit(PDECODE_UNIT decodeUnit) { ret = (*env)->CallStaticIntMethod(env, GlobalBridgeClass, BridgeDrSubmitDecodeUnitMethod, DecodedFrameBuffer, currentEntry->length, currentEntry->bufferType, - decodeUnit->frameNumber, (jlong)decodeUnit->receiveTimeMs); + decodeUnit->frameNumber, (jlong)decodeUnit->receiveTimeMs, + (jlong)decodeUnit->enqueueTimeMs); if ((*env)->ExceptionCheck(env)) { // We will crash here (*JVM)->DetachCurrentThread(JVM); @@ -178,7 +179,7 @@ int BridgeDrSubmitDecodeUnit(PDECODE_UNIT decodeUnit) { ret = (*env)->CallStaticIntMethod(env, GlobalBridgeClass, BridgeDrSubmitDecodeUnitMethod, DecodedFrameBuffer, offset, BUFFER_TYPE_PICDATA, decodeUnit->frameNumber, - (jlong)decodeUnit->receiveTimeMs); + (jlong)decodeUnit->receiveTimeMs, (jlong)decodeUnit->enqueueTimeMs); if ((*env)->ExceptionCheck(env)) { // We will crash here (*JVM)->DetachCurrentThread(JVM); diff --git a/app/src/main/jni/moonlight-core/moonlight-common-c b/app/src/main/jni/moonlight-core/moonlight-common-c index 3aa24638..fd950b64 160000 --- a/app/src/main/jni/moonlight-core/moonlight-common-c +++ b/app/src/main/jni/moonlight-core/moonlight-common-c @@ -1 +1 @@ -Subproject commit 3aa246385680454c8564d28ca3a8807eb4f56195 +Subproject commit fd950b64528ce6ca6cf5d24d93418f1dda8bd0ca