diff --git a/libs/limelight-common.jar b/libs/limelight-common.jar index e62ea43c..e7b1b446 100644 Binary files a/libs/limelight-common.jar and b/libs/limelight-common.jar differ diff --git a/src/com/limelight/binding/audio/AndroidAudioRenderer.java b/src/com/limelight/binding/audio/AndroidAudioRenderer.java index 0c2f5da4..28578e98 100644 --- a/src/com/limelight/binding/audio/AndroidAudioRenderer.java +++ b/src/com/limelight/binding/audio/AndroidAudioRenderer.java @@ -14,7 +14,7 @@ public class AndroidAudioRenderer implements AudioRenderer { private AudioTrack track; @Override - public void streamInitialized(int channelCount, int sampleRate) { + public boolean streamInitialized(int channelCount, int sampleRate) { int channelConfig; int bufferSize; @@ -27,7 +27,8 @@ public class AndroidAudioRenderer implements AudioRenderer { channelConfig = AudioFormat.CHANNEL_OUT_STEREO; break; default: - throw new IllegalArgumentException("Decoder returned unhandled channel count"); + LimeLog.severe("Decoder returned unhandled channel count"); + return false; } bufferSize = Math.max(AudioTrack.getMinBufferSize(sampleRate, @@ -47,6 +48,7 @@ public class AndroidAudioRenderer implements AudioRenderer { AudioTrack.MODE_STREAM); track.play(); + return true; } @Override diff --git a/src/com/limelight/binding/video/AndroidCpuDecoderRenderer.java b/src/com/limelight/binding/video/AndroidCpuDecoderRenderer.java index 7fbafb1a..aa54f5d5 100644 --- a/src/com/limelight/binding/video/AndroidCpuDecoderRenderer.java +++ b/src/com/limelight/binding/video/AndroidCpuDecoderRenderer.java @@ -81,7 +81,7 @@ public class AndroidCpuDecoderRenderer implements VideoDecoderRenderer { } @Override - public void setup(int width, int height, int redrawRate, Object renderTarget, int drFlags) { + public boolean setup(int width, int height, int redrawRate, Object renderTarget, int drFlags) { this.targetFps = redrawRate; int perfLevel = findOptimalPerformanceLevel(); @@ -139,10 +139,12 @@ public class AndroidCpuDecoderRenderer implements VideoDecoderRenderer { decoderBuffer = ByteBuffer.allocate(DECODER_BUFFER_SIZE + AvcDecoder.getInputPaddingSize()); LimeLog.info("Using software decoding (performance level: "+perfLevel+")"); + + return true; } @Override - public void start(final VideoDepacketizer depacketizer) { + public boolean start(final VideoDepacketizer depacketizer) { rendererThread = new Thread() { @Override public void run() { @@ -169,6 +171,7 @@ public class AndroidCpuDecoderRenderer implements VideoDecoderRenderer { rendererThread.setName("Video - Renderer (CPU)"); rendererThread.setPriority(Thread.MAX_PRIORITY); rendererThread.start(); + return true; } private long computePresentationTimeMs(int frameRate) { diff --git a/src/com/limelight/binding/video/ConfigurableDecoderRenderer.java b/src/com/limelight/binding/video/ConfigurableDecoderRenderer.java index 40baf794..6cca9c9a 100644 --- a/src/com/limelight/binding/video/ConfigurableDecoderRenderer.java +++ b/src/com/limelight/binding/video/ConfigurableDecoderRenderer.java @@ -13,7 +13,7 @@ public class ConfigurableDecoderRenderer implements VideoDecoderRenderer { } @Override - public void setup(int width, int height, int redrawRate, Object renderTarget, int drFlags) { + public boolean setup(int width, int height, int redrawRate, Object renderTarget, int drFlags) { if ((drFlags & VideoDecoderRenderer.FLAG_FORCE_HARDWARE_DECODING) != 0 || ((drFlags & VideoDecoderRenderer.FLAG_FORCE_SOFTWARE_DECODING) == 0 && MediaCodecDecoderRenderer.findSafeDecoder() != null)) { @@ -22,12 +22,12 @@ public class ConfigurableDecoderRenderer implements VideoDecoderRenderer { else { decoderRenderer = new AndroidCpuDecoderRenderer(); } - decoderRenderer.setup(width, height, redrawRate, renderTarget, drFlags); + return decoderRenderer.setup(width, height, redrawRate, renderTarget, drFlags); } @Override - public void start(VideoDepacketizer depacketizer) { - decoderRenderer.start(depacketizer); + public boolean start(VideoDepacketizer depacketizer) { + return decoderRenderer.start(depacketizer); } @Override diff --git a/src/com/limelight/binding/video/MediaCodecDecoderRenderer.java b/src/com/limelight/binding/video/MediaCodecDecoderRenderer.java index 9e4c1770..a852a18e 100644 --- a/src/com/limelight/binding/video/MediaCodecDecoderRenderer.java +++ b/src/com/limelight/binding/video/MediaCodecDecoderRenderer.java @@ -119,25 +119,32 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer { } @Override - public void setup(int width, int height, int redrawRate, Object renderTarget, int drFlags) { + public boolean setup(int width, int height, int redrawRate, Object renderTarget, int drFlags) { //dumpDecoders(); - MediaCodecInfo safeDecoder = findSafeDecoder(); - if (safeDecoder != null) { - videoDecoder = MediaCodec.createByCodecName(safeDecoder.getName()); - needsSpsBitstreamFixup = isDecoderInList(spsFixupBitsreamFixupDecoderPrefixes, safeDecoder.getName()); - needsSpsNumRefFixup = isDecoderInList(spsFixupNumRefFixupDecoderPrefixes, safeDecoder.getName()); - if (needsSpsBitstreamFixup) { - LimeLog.info("Decoder "+safeDecoder.getName()+" needs SPS bitstream restrictions fixup"); + // It's nasty to put all this in a try-catch block, + // but codecs have been known to throw all sorts of crazy runtime exceptions + // due to implementation problems + try { + MediaCodecInfo safeDecoder = findSafeDecoder(); + if (safeDecoder != null) { + videoDecoder = MediaCodec.createByCodecName(safeDecoder.getName()); + needsSpsBitstreamFixup = isDecoderInList(spsFixupBitsreamFixupDecoderPrefixes, safeDecoder.getName()); + needsSpsNumRefFixup = isDecoderInList(spsFixupNumRefFixupDecoderPrefixes, safeDecoder.getName()); + if (needsSpsBitstreamFixup) { + LimeLog.info("Decoder "+safeDecoder.getName()+" needs SPS bitstream restrictions fixup"); + } + if (needsSpsNumRefFixup) { + LimeLog.info("Decoder "+safeDecoder.getName()+" needs SPS ref num fixup"); + } } - if (needsSpsNumRefFixup) { - LimeLog.info("Decoder "+safeDecoder.getName()+" needs SPS ref num fixup"); + else { + videoDecoder = MediaCodec.createDecoderByType("video/avc"); + needsSpsBitstreamFixup = false; + needsSpsNumRefFixup = false; } - } - else { - videoDecoder = MediaCodec.createDecoderByType("video/avc"); - needsSpsBitstreamFixup = false; - needsSpsNumRefFixup = false; + } catch (Exception e) { + return false; } MediaFormat videoFormat = MediaFormat.createVideoFormat("video/avc", width, height); @@ -148,6 +155,8 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer { videoDecoderInputBuffers = videoDecoder.getInputBuffers(); LimeLog.info("Using hardware decoding"); + + return true; } private void startRendererThread() @@ -198,9 +207,10 @@ public class MediaCodecDecoderRenderer implements VideoDecoderRenderer { } @Override - public void start(VideoDepacketizer depacketizer) { + public boolean start(VideoDepacketizer depacketizer) { this.depacketizer = depacketizer; startRendererThread(); + return true; } @Override