mirror of
https://github.com/moonlight-stream/moonlight-android.git
synced 2025-07-20 11:33:06 +00:00
Throw a special RendererException when we have a MediaCodec crash so we have much more info for debugging
This commit is contained in:
parent
ae298fbc51
commit
b5e585834d
@ -33,6 +33,11 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
|
||||
private long decoderTimeMs;
|
||||
private int totalFrames;
|
||||
|
||||
private String decoderName;
|
||||
private int numSpsIn;
|
||||
private int numPpsIn;
|
||||
private int numIframeIn;
|
||||
|
||||
private final static byte[] BITSTREAM_RESTRICTIONS = new byte[] {(byte) 0xF1, (byte) 0x83, 0x2A, 0x00};
|
||||
|
||||
public static final List<String> blacklistedDecoderPrefixes;
|
||||
@ -186,10 +191,12 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
|
||||
return false;
|
||||
}
|
||||
|
||||
decoderName = decoder.getName();
|
||||
|
||||
// Codecs have been known to throw all sorts of crazy runtime exceptions
|
||||
// due to implementation problems
|
||||
try {
|
||||
videoDecoder = MediaCodec.createByCodecName(decoder.getName());
|
||||
videoDecoder = MediaCodec.createByCodecName(decoderName);
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
@ -233,7 +240,9 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
int outIndex = videoDecoder.dequeueOutputBuffer(info, 0);
|
||||
|
||||
if (outIndex >= 0) {
|
||||
long presentationTimeUs = info.presentationTimeUs;
|
||||
int lastIndex = outIndex;
|
||||
@ -270,6 +279,9 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RendererException(MediaCodecDecoderRenderer.this, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -318,7 +330,11 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
inputIndex = videoDecoder.dequeueInputBuffer(100000);
|
||||
} catch (Exception e) {
|
||||
throw new RendererException(this, e);
|
||||
}
|
||||
} while (inputIndex < 0);
|
||||
|
||||
ByteBuffer buf = videoDecoderInputBuffers[inputIndex];
|
||||
@ -340,12 +356,15 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
|
||||
}
|
||||
if ((decodeUnitFlags & DecodeUnit.DU_FLAG_SYNC_FRAME) != 0) {
|
||||
codecFlags |= MediaCodec.BUFFER_FLAG_SYNC_FRAME;
|
||||
numIframeIn++;
|
||||
}
|
||||
|
||||
if ((decodeUnitFlags & DecodeUnit.DU_FLAG_CODEC_CONFIG) != 0 &&
|
||||
(needsSpsBitstreamFixup || needsSpsNumRefFixup)) {
|
||||
if ((decodeUnitFlags & DecodeUnit.DU_FLAG_CODEC_CONFIG) != 0) {
|
||||
ByteBufferDescriptor header = decodeUnit.getBufferList().get(0);
|
||||
if (header.data[header.offset+4] == 0x67) {
|
||||
numSpsIn++;
|
||||
|
||||
if ((needsSpsBitstreamFixup || needsSpsNumRefFixup)) {
|
||||
byte last = header.data[header.length+header.offset-1];
|
||||
|
||||
// TI OMAP4 requires a reference frame count of 1 to decode successfully
|
||||
@ -393,18 +412,24 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
|
||||
buf.put(header.data, header.offset, header.length);
|
||||
spsLength = header.length;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
buf.put(header.data, header.offset, header.length);
|
||||
spsLength = header.length;
|
||||
}
|
||||
|
||||
try {
|
||||
videoDecoder.queueInputBuffer(inputIndex,
|
||||
0, spsLength,
|
||||
currentTime * 1000, codecFlags);
|
||||
} catch (Exception e) {
|
||||
throw new RendererException(this, e, buf, codecFlags);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} else if (header.data[header.offset+4] == 0x68) {
|
||||
numPpsIn++;
|
||||
}
|
||||
}
|
||||
|
||||
// Copy data from our buffer list into the input buffer
|
||||
@ -413,9 +438,13 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
|
||||
buf.put(desc.data, desc.offset, desc.length);
|
||||
}
|
||||
|
||||
try {
|
||||
videoDecoder.queueInputBuffer(inputIndex,
|
||||
0, decodeUnit.getDataLength(),
|
||||
currentTime * 1000, codecFlags);
|
||||
} catch (Exception e) {
|
||||
throw new RendererException(this, e, buf, codecFlags);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -519,4 +548,47 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer {
|
||||
}
|
||||
return (int)(totalTimeMs / totalFrames);
|
||||
}
|
||||
|
||||
public class RendererException extends RuntimeException {
|
||||
private static final long serialVersionUID = 8985937536997012406L;
|
||||
|
||||
private Exception originalException;
|
||||
private MediaCodecDecoderRenderer renderer;
|
||||
private ByteBuffer currentBuffer;
|
||||
private int currentCodecFlags;
|
||||
|
||||
public RendererException(MediaCodecDecoderRenderer renderer, Exception e) {
|
||||
this.renderer = renderer;
|
||||
this.originalException = e;
|
||||
}
|
||||
|
||||
public RendererException(MediaCodecDecoderRenderer renderer, Exception e, ByteBuffer currentBuffer, int currentCodecFlags) {
|
||||
this.renderer = renderer;
|
||||
this.originalException = e;
|
||||
this.currentBuffer = currentBuffer;
|
||||
this.currentCodecFlags = currentCodecFlags;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String str = "";
|
||||
|
||||
str += "Decoder: "+renderer.decoderName+"\n";
|
||||
str += "In stats: "+renderer.numSpsIn+", "+renderer.numPpsIn+", "+renderer.numIframeIn+"\n";
|
||||
str += "Total frames: "+renderer.totalFrames+"\n";
|
||||
|
||||
if (currentBuffer != null) {
|
||||
str += "Current buffer: ";
|
||||
currentBuffer.flip();
|
||||
while (currentBuffer.hasRemaining() && currentBuffer.position() < 10) {
|
||||
str += String.format("%02x ", currentBuffer.get());
|
||||
}
|
||||
str += "\n";
|
||||
str += "Buffer codec flags: "+currentCodecFlags+"\n";
|
||||
}
|
||||
|
||||
str += originalException.toString();
|
||||
|
||||
return str;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user