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:
Cameron Gutman 2013-11-26 14:36:06 -05:00
parent 55d534c8cf
commit 8e22a125e2

View File

@ -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();
} }
} }
}; };