mirror of
https://github.com/moonlight-stream/moonlight-android.git
synced 2025-07-20 11:33:06 +00:00
Fix a potential deadlock that could occur if the input buffers are exhausted. A couple other performance optimizations by overlapping some latency.
This commit is contained in:
parent
6efc7e254b
commit
1430801888
@ -315,12 +315,35 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
BufferInfo info = new BufferInfo();
|
BufferInfo info = new BufferInfo();
|
||||||
DecodeUnit du;
|
DecodeUnit du = null;
|
||||||
|
int inputIndex = -1;
|
||||||
while (!isInterrupted())
|
while (!isInterrupted())
|
||||||
{
|
{
|
||||||
du = depacketizer.pollNextDecodeUnit();
|
// Grab an input buffer if we don't have one already.
|
||||||
if (du != null) {
|
// This way we can have one ready hopefully by the time
|
||||||
if (!submitDecodeUnit(du)) {
|
// the depacketizer is done with this frame. It's important
|
||||||
|
// that this can timeout because it's possible that we could exhaust
|
||||||
|
// the decoder's input buffers and deadlocks because aren't pulling
|
||||||
|
// frames out of the other end.
|
||||||
|
if (inputIndex == -1) {
|
||||||
|
try {
|
||||||
|
// Wait for 3 milliseconds at maximum before continuing to
|
||||||
|
// grab a DU or render a frame
|
||||||
|
inputIndex = videoDecoder.dequeueInputBuffer(3000);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RendererException(MediaCodecDecoderRenderer.this, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Grab a decode unit if we don't have one already
|
||||||
|
if (du == null) {
|
||||||
|
du = depacketizer.pollNextDecodeUnit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we've got both a decode unit and an input buffer, we'll
|
||||||
|
// submit now. Otherwise, we wait until we have one.
|
||||||
|
if (du != null && inputIndex >= 0) {
|
||||||
|
if (!submitDecodeUnit(du, inputIndex)) {
|
||||||
// Thread was interrupted
|
// Thread was interrupted
|
||||||
depacketizer.freeDecodeUnit(du);
|
depacketizer.freeDecodeUnit(du);
|
||||||
return;
|
return;
|
||||||
@ -328,8 +351,13 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
|
|||||||
else {
|
else {
|
||||||
depacketizer.freeDecodeUnit(du);
|
depacketizer.freeDecodeUnit(du);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DU and input buffer have both been consumed
|
||||||
|
du = null;
|
||||||
|
inputIndex = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Try to output a frame
|
||||||
try {
|
try {
|
||||||
int outIndex = videoDecoder.dequeueOutputBuffer(info, 0);
|
int outIndex = videoDecoder.dequeueOutputBuffer(info, 0);
|
||||||
|
|
||||||
@ -356,7 +384,11 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
|
|||||||
} else {
|
} else {
|
||||||
switch (outIndex) {
|
switch (outIndex) {
|
||||||
case MediaCodec.INFO_TRY_AGAIN_LATER:
|
case MediaCodec.INFO_TRY_AGAIN_LATER:
|
||||||
LockSupport.parkNanos(1);
|
// Getting an input buffer may already block
|
||||||
|
// so don't park if we still need to do that
|
||||||
|
if (inputIndex >= 0) {
|
||||||
|
LockSupport.parkNanos(1);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
|
case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
|
||||||
LimeLog.info("Output buffers changed");
|
LimeLog.info("Output buffers changed");
|
||||||
@ -412,22 +444,8 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean submitDecodeUnit(DecodeUnit decodeUnit) {
|
private boolean submitDecodeUnit(DecodeUnit decodeUnit, int inputBufferIndex) {
|
||||||
int inputIndex;
|
ByteBuffer buf = videoDecoderInputBuffers[inputBufferIndex];
|
||||||
|
|
||||||
do {
|
|
||||||
if (Thread.interrupted()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
inputIndex = videoDecoder.dequeueInputBuffer(100000);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RendererException(this, e);
|
|
||||||
}
|
|
||||||
} while (inputIndex < 0);
|
|
||||||
|
|
||||||
ByteBuffer buf = videoDecoderInputBuffers[inputIndex];
|
|
||||||
|
|
||||||
long currentTime = System.currentTimeMillis();
|
long currentTime = System.currentTimeMillis();
|
||||||
long delta = currentTime-decodeUnit.getReceiveTimestamp();
|
long delta = currentTime-decodeUnit.getReceiveTimestamp();
|
||||||
@ -490,7 +508,7 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
|
|||||||
sps.write(buf);
|
sps.write(buf);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
videoDecoder.queueInputBuffer(inputIndex,
|
videoDecoder.queueInputBuffer(inputBufferIndex,
|
||||||
0, buf.position(),
|
0, buf.position(),
|
||||||
currentTime * 1000, codecFlags);
|
currentTime * 1000, codecFlags);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -510,7 +528,7 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
videoDecoder.queueInputBuffer(inputIndex,
|
videoDecoder.queueInputBuffer(inputBufferIndex,
|
||||||
0, decodeUnit.getDataLength(),
|
0, decodeUnit.getDataLength(),
|
||||||
currentTime * 1000, codecFlags);
|
currentTime * 1000, codecFlags);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user