mirror of
https://github.com/moonlight-stream/moonlight-android.git
synced 2025-07-20 03:23:07 +00:00
Add a latency toast after the stream stops
This commit is contained in:
parent
b3c78ce1b1
commit
a639143e94
Binary file not shown.
@ -65,6 +65,8 @@ public class Game extends Activity implements SurfaceHolder.Callback, OnGenericM
|
||||
private boolean connecting = false;
|
||||
private boolean connected = false;
|
||||
|
||||
private ConfigurableDecoderRenderer decoderRenderer;
|
||||
|
||||
private WifiManager.WifiLock wifiLock;
|
||||
|
||||
private int drFlags = 0;
|
||||
@ -194,6 +196,7 @@ public class Game extends Activity implements SurfaceHolder.Callback, OnGenericM
|
||||
enableLargePackets ? 1460 : 1024), PlatformBinding.getCryptoProvider(this));
|
||||
keybTranslator = new KeyboardTranslator(conn);
|
||||
controllerHandler = new ControllerHandler(conn);
|
||||
decoderRenderer = new ConfigurableDecoderRenderer();
|
||||
|
||||
// The connection will be started when the surface gets created
|
||||
sh.addCallback(this);
|
||||
@ -330,6 +333,23 @@ public class Game extends Activity implements SurfaceHolder.Callback, OnGenericM
|
||||
displayedFailureDialog = true;
|
||||
conn.stop();
|
||||
|
||||
int averageEndToEndLat = decoderRenderer.getAverageEndToEndLatency();
|
||||
int averageDecoderLat = decoderRenderer.getAverageDecoderLatency();
|
||||
String message = null;
|
||||
if (averageEndToEndLat > 0) {
|
||||
message = "Average frame latency from receive to display: "+averageEndToEndLat+" ms";
|
||||
if (averageDecoderLat > 0) {
|
||||
message += " (decoder latency: "+averageDecoderLat+" ms)";
|
||||
}
|
||||
}
|
||||
else if (averageDecoderLat > 0) {
|
||||
message = "Average decoder latency: "+averageDecoderLat+" ms";
|
||||
}
|
||||
|
||||
if (message != null) {
|
||||
Toast.makeText(this, message, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
finish();
|
||||
}
|
||||
|
||||
@ -647,7 +667,7 @@ public class Game extends Activity implements SurfaceHolder.Callback, OnGenericM
|
||||
if (!connected && !connecting) {
|
||||
connecting = true;
|
||||
conn.start(PlatformBinding.getDeviceName(), holder, drFlags,
|
||||
PlatformBinding.getAudioRenderer(), new ConfigurableDecoderRenderer());
|
||||
PlatformBinding.getAudioRenderer(), decoderRenderer);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -222,4 +222,14 @@ public class AndroidCpuDecoderRenderer implements VideoDecoderRenderer {
|
||||
public int getCapabilities() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAverageDecoderLatency() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAverageEndToEndLatency() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -40,4 +40,23 @@ public class ConfigurableDecoderRenderer implements VideoDecoderRenderer {
|
||||
return decoderRenderer.getCapabilities();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAverageDecoderLatency() {
|
||||
if (decoderRenderer != null) {
|
||||
return decoderRenderer.getAverageDecoderLatency();
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAverageEndToEndLatency() {
|
||||
if (decoderRenderer != null) {
|
||||
return decoderRenderer.getAverageEndToEndLatency();
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,12 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
|
||||
private boolean needsSpsNumRefFixup;
|
||||
private VideoDepacketizer depacketizer;
|
||||
|
||||
private long totalTimeMs;
|
||||
private long decoderTimeMs;
|
||||
private int totalFrames;
|
||||
|
||||
private final static byte[] BITSTREAM_RESTRICTIONS = new byte[] {(byte) 0xF1, (byte) 0x83, 0x2A, 0x00};
|
||||
|
||||
public static final List<String> blacklistedDecoderPrefixes;
|
||||
public static final List<String> spsFixupBitsreamFixupDecoderPrefixes;
|
||||
public static final List<String> spsFixupNumRefFixupDecoderPrefixes;
|
||||
@ -177,6 +183,13 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
|
||||
if (outIndex >= 0) {
|
||||
int lastIndex = outIndex;
|
||||
|
||||
// Add delta time to the totals (excluding probable outliers)
|
||||
long delta = System.currentTimeMillis()-info.presentationTimeUs;
|
||||
if (delta > 5 && delta < 300) {
|
||||
decoderTimeMs += delta;
|
||||
totalTimeMs += delta;
|
||||
}
|
||||
|
||||
// Get the last output buffer in the queue
|
||||
while ((outIndex = videoDecoder.dequeueOutputBuffer(info, 0)) >= 0) {
|
||||
videoDecoder.releaseOutputBuffer(lastIndex, false);
|
||||
@ -216,7 +229,7 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
|
||||
@Override
|
||||
public void stop() {
|
||||
rendererThread.interrupt();
|
||||
|
||||
|
||||
try {
|
||||
rendererThread.join();
|
||||
} catch (InterruptedException e) { }
|
||||
@ -235,6 +248,13 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
|
||||
{
|
||||
ByteBuffer buf = videoDecoderInputBuffers[inputIndex];
|
||||
|
||||
long currentTime = System.currentTimeMillis();
|
||||
long delta = currentTime-decodeUnit.getReceiveTimestamp();
|
||||
if (delta >= 0 && delta < 300) {
|
||||
totalTimeMs += currentTime-decodeUnit.getReceiveTimestamp();
|
||||
totalFrames++;
|
||||
}
|
||||
|
||||
// Clear old input data
|
||||
buf.clear();
|
||||
|
||||
@ -251,6 +271,8 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
|
||||
(needsSpsBitstreamFixup || needsSpsNumRefFixup)) {
|
||||
ByteBufferDescriptor header = decodeUnit.getBufferList().get(0);
|
||||
if (header.data[header.offset+4] == 0x67) {
|
||||
byte last = header.data[header.length+header.offset-1];
|
||||
|
||||
// TI OMAP4 requires a reference frame count of 1 to decode successfully
|
||||
if (needsSpsNumRefFixup) {
|
||||
LimeLog.info("Fixing up num ref frames");
|
||||
@ -262,31 +284,41 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
|
||||
// We manually modify the SPS here to speed-up decoding if the decoder was flagged as needing it.
|
||||
int spsLength;
|
||||
if (needsSpsBitstreamFixup) {
|
||||
switch (header.length) {
|
||||
case 26:
|
||||
LimeLog.info("Adding bitstream restrictions to SPS (26)");
|
||||
buf.put(header.data, header.offset, 24);
|
||||
buf.put((byte) 0x11);
|
||||
buf.put((byte) 0xe3);
|
||||
buf.put((byte) 0x06);
|
||||
buf.put((byte) 0x50);
|
||||
spsLength = header.length + 2;
|
||||
break;
|
||||
case 27:
|
||||
LimeLog.info("Adding bitstream restrictions to SPS (27)");
|
||||
buf.put(header.data, header.offset, 25);
|
||||
buf.put((byte) 0x04);
|
||||
buf.put((byte) 0x78);
|
||||
buf.put((byte) 0xc1);
|
||||
buf.put((byte) 0x94);
|
||||
spsLength = header.length + 2;
|
||||
break;
|
||||
default:
|
||||
LimeLog.warning("Unknown SPS of length "+header.length);
|
||||
if (!needsSpsNumRefFixup) {
|
||||
switch (header.length) {
|
||||
case 26:
|
||||
LimeLog.info("Adding bitstream restrictions to SPS (26)");
|
||||
buf.put(header.data, header.offset, 24);
|
||||
buf.put((byte) 0x11);
|
||||
buf.put((byte) 0xe3);
|
||||
buf.put((byte) 0x06);
|
||||
buf.put((byte) 0x50);
|
||||
spsLength = header.length + 2;
|
||||
break;
|
||||
case 27:
|
||||
LimeLog.info("Adding bitstream restrictions to SPS (27)");
|
||||
buf.put(header.data, header.offset, 25);
|
||||
buf.put((byte) 0x04);
|
||||
buf.put((byte) 0x78);
|
||||
buf.put((byte) 0xc1);
|
||||
buf.put((byte) 0x94);
|
||||
spsLength = header.length + 2;
|
||||
break;
|
||||
default:
|
||||
LimeLog.warning("Unknown SPS of length "+header.length);
|
||||
buf.put(header.data, header.offset, header.length);
|
||||
spsLength = header.length;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Set bitstream restrictions to only buffer single frame
|
||||
// (starts 9 bits before stop bit and 6 bits earlier because of the shortening above)
|
||||
this.replace(header, header.length*8+Integer.numberOfLeadingZeros(last & - last)%8-9-6, 2, BITSTREAM_RESTRICTIONS, 3*8);
|
||||
buf.put(header.data, header.offset, header.length);
|
||||
spsLength = header.length;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
buf.put(header.data, header.offset, header.length);
|
||||
@ -295,7 +327,7 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
|
||||
|
||||
videoDecoder.queueInputBuffer(inputIndex,
|
||||
0, spsLength,
|
||||
0, codecFlags);
|
||||
currentTime, codecFlags);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -308,7 +340,7 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
|
||||
|
||||
videoDecoder.queueInputBuffer(inputIndex,
|
||||
0, decodeUnit.getDataLength(),
|
||||
0, codecFlags);
|
||||
currentTime, codecFlags);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -397,4 +429,14 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
|
||||
source.offset = offset;
|
||||
source.length = length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAverageDecoderLatency() {
|
||||
return (int)(decoderTimeMs / totalFrames);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAverageEndToEndLatency() {
|
||||
return (int)(totalTimeMs / totalFrames);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user