mirror of
https://github.com/moonlight-stream/moonlight-android.git
synced 2025-07-20 03:23:07 +00:00
Remove AvcDecoder.SLICE_THREADING flag which was making performance worse. Scale the thread count higher on low performing devices. Use a constant 30 fps target since rendering tends to have very little effect on decoding speed. Only wait when the wait time will exceed 8 ms in order to reduce the likelyhood that the wait causes us to render late.
This commit is contained in:
parent
55d534c8cf
commit
8e22a125e2
@ -15,12 +15,17 @@ public class CpuDecoderRenderer implements DecoderRenderer {
|
|||||||
private Surface renderTarget;
|
private Surface renderTarget;
|
||||||
private ByteBuffer decoderBuffer;
|
private ByteBuffer decoderBuffer;
|
||||||
private Thread rendererThread;
|
private Thread rendererThread;
|
||||||
private int perfLevel;
|
private int targetFps;
|
||||||
|
|
||||||
|
// Only sleep if the difference is above this value
|
||||||
|
private static final int WAIT_CEILING_MS = 8;
|
||||||
|
|
||||||
private static final int LOW_PERF = 1;
|
private static final int LOW_PERF = 1;
|
||||||
private static final int MED_PERF = 2;
|
private static final int MED_PERF = 2;
|
||||||
private static final int HIGH_PERF = 3;
|
private static final int HIGH_PERF = 3;
|
||||||
|
|
||||||
|
private int cpuCount = Runtime.getRuntime().availableProcessors();
|
||||||
|
|
||||||
private int findOptimalPerformanceLevel() {
|
private int findOptimalPerformanceLevel() {
|
||||||
StringBuilder cpuInfo = new StringBuilder();
|
StringBuilder cpuInfo = new StringBuilder();
|
||||||
BufferedReader br = null;
|
BufferedReader br = null;
|
||||||
@ -71,27 +76,40 @@ public class CpuDecoderRenderer implements DecoderRenderer {
|
|||||||
@Override
|
@Override
|
||||||
public void setup(int width, int height, Surface renderTarget) {
|
public void setup(int width, int height, Surface renderTarget) {
|
||||||
this.renderTarget = renderTarget;
|
this.renderTarget = renderTarget;
|
||||||
this.perfLevel = findOptimalPerformanceLevel();
|
this.targetFps = 30;
|
||||||
|
|
||||||
|
int perfLevel = findOptimalPerformanceLevel();
|
||||||
|
int threadCount;
|
||||||
|
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
switch (perfLevel) {
|
switch (perfLevel) {
|
||||||
|
case HIGH_PERF:
|
||||||
|
// Single threaded low latency decode is ideal but hard to acheive
|
||||||
|
flags = AvcDecoder.LOW_LATENCY_DECODE;
|
||||||
|
threadCount = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
case LOW_PERF:
|
case LOW_PERF:
|
||||||
|
// Disable the loop filter for performance reasons
|
||||||
flags = AvcDecoder.DISABLE_LOOP_FILTER |
|
flags = AvcDecoder.DISABLE_LOOP_FILTER |
|
||||||
AvcDecoder.FAST_BILINEAR_FILTERING |
|
AvcDecoder.FAST_BILINEAR_FILTERING |
|
||||||
AvcDecoder.FAST_DECODE |
|
AvcDecoder.FAST_DECODE;
|
||||||
AvcDecoder.SLICE_THREADING;
|
|
||||||
|
// Use plenty of threads to try to utilize the CPU as best we can
|
||||||
|
threadCount = cpuCount - 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
case MED_PERF:
|
case MED_PERF:
|
||||||
flags = AvcDecoder.BILINEAR_FILTERING |
|
flags = AvcDecoder.BILINEAR_FILTERING |
|
||||||
AvcDecoder.FAST_DECODE |
|
AvcDecoder.FAST_DECODE;
|
||||||
AvcDecoder.SLICE_THREADING;
|
|
||||||
break;
|
// Only use 2 threads to minimize frame processing latency
|
||||||
case HIGH_PERF:
|
threadCount = 2;
|
||||||
flags = AvcDecoder.LOW_LATENCY_DECODE;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
int err = AvcDecoder.init(width, height, flags, 2);
|
int err = AvcDecoder.init(width, height, flags, threadCount);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
throw new IllegalStateException("AVC decoder initialization failure: "+err);
|
throw new IllegalStateException("AVC decoder initialization failure: "+err);
|
||||||
}
|
}
|
||||||
@ -106,28 +124,13 @@ public class CpuDecoderRenderer implements DecoderRenderer {
|
|||||||
rendererThread = new Thread() {
|
rendererThread = new Thread() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
int frameRateTarget;
|
|
||||||
long nextFrameTime = System.currentTimeMillis();
|
long nextFrameTime = System.currentTimeMillis();
|
||||||
|
|
||||||
switch (perfLevel) {
|
|
||||||
case HIGH_PERF:
|
|
||||||
frameRateTarget = 45;
|
|
||||||
break;
|
|
||||||
case MED_PERF:
|
|
||||||
frameRateTarget = 30;
|
|
||||||
break;
|
|
||||||
case LOW_PERF:
|
|
||||||
default:
|
|
||||||
frameRateTarget = 15;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!isInterrupted())
|
while (!isInterrupted())
|
||||||
{
|
{
|
||||||
long diff = nextFrameTime - System.currentTimeMillis();
|
long diff = nextFrameTime - System.currentTimeMillis();
|
||||||
|
|
||||||
if (diff > 0) {
|
if (diff > WAIT_CEILING_MS) {
|
||||||
// Sleep until the frame should be rendered
|
|
||||||
try {
|
try {
|
||||||
Thread.sleep(diff);
|
Thread.sleep(diff);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
@ -135,9 +138,8 @@ public class CpuDecoderRenderer implements DecoderRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nextFrameTime = computePresentationTimeMs(frameRateTarget);
|
nextFrameTime = computePresentationTimeMs(targetFps);
|
||||||
AvcDecoder.redraw(renderTarget);
|
AvcDecoder.redraw(renderTarget);
|
||||||
System.gc();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user