From 3f4648538289905168ceecdc06c5b7af72a64130 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sat, 12 Dec 2015 21:11:08 -0800 Subject: [PATCH] Add support for streaming H.265 from Maxwell 2 cards --- app/libs/limelight-common.jar | Bin 1017826 -> 1020207 bytes app/src/main/java/com/limelight/Game.java | 20 +- .../video/AndroidCpuDecoderRenderer.java | 11 +- .../video/ConfigurableDecoderRenderer.java | 18 +- .../video/EnhancedDecoderRenderer.java | 2 +- .../video/MediaCodecDecoderRenderer.java | 183 +++++++++++++----- .../binding/video/MediaCodecHelper.java | 60 +++--- .../preferences/PreferenceConfiguration.java | 28 ++- app/src/main/res/values/arrays.xml | 11 ++ app/src/main/res/values/strings.xml | 3 + app/src/main/res/xml/preferences.xml | 7 + 11 files changed, 258 insertions(+), 85 deletions(-) diff --git a/app/libs/limelight-common.jar b/app/libs/limelight-common.jar index e7d0030c0de233ae107e74f99f56e978afa00c5c..6f656bf4082935ef92bc1d5c5f7fb49e90a7d43b 100644 GIT binary patch delta 39101 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 ZIQ>97zX)GALpZ}kc?O1#LVgAY1^{Kn#v%X! delta 36867 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 ThcSdP$jUP?tk2+QU|;|M0Hbx5 diff --git a/app/src/main/java/com/limelight/Game.java b/app/src/main/java/com/limelight/Game.java index 759a5be6..50a10a1e 100644 --- a/app/src/main/java/com/limelight/Game.java +++ b/app/src/main/java/com/limelight/Game.java @@ -208,7 +208,12 @@ public class Game extends Activity implements SurfaceHolder.Callback, } decoderRenderer = new ConfigurableDecoderRenderer(); - decoderRenderer.initializeWithFlags(drFlags); + decoderRenderer.initializeWithFlags(drFlags, prefConfig.videoFormat); + + // Display a message to the user if H.265 was forced on but we still didn't find a decoder + if (prefConfig.videoFormat == PreferenceConfiguration.FORCE_H265_ON && !decoderRenderer.isHevcSupported()) { + Toast.makeText(this, "No H.265 decoder found. Falling back to H.264", Toast.LENGTH_LONG).show(); + } StreamConfiguration config = new StreamConfiguration.Builder() .setResolution(prefConfig.width, prefConfig.height) @@ -221,6 +226,7 @@ public class Game extends Activity implements SurfaceHolder.Callback, .enableLocalAudioPlayback(prefConfig.playHostAudio) .setMaxPacketSize(remote ? 1024 : 1292) .setRemote(remote) + .setHevcSupported(decoderRenderer.isHevcSupported()) .setAudioConfiguration(prefConfig.enable51Surround ? StreamConfiguration.AUDIO_CONFIGURATION_5_1 : StreamConfiguration.AUDIO_CONFIGURATION_STEREO) @@ -352,6 +358,8 @@ public class Game extends Activity implements SurfaceHolder.Callback, unbindService(usbDriverServiceConnection); } + VideoDecoderRenderer.VideoFormat videoFormat = conn.getActiveVideoFormat(); + displayedFailureDialog = true; stopConnection(); @@ -368,6 +376,16 @@ public class Game extends Activity implements SurfaceHolder.Callback, message = getResources().getString(R.string.conn_hardware_latency)+" "+averageDecoderLat+" ms"; } + // Add the video codec to the post-stream toast + if (message != null && videoFormat != VideoDecoderRenderer.VideoFormat.Unknown) { + if (videoFormat == VideoDecoderRenderer.VideoFormat.H265) { + message += " [H.265]"; + } + else { + message += " [H.264]"; + } + } + if (message != null) { Toast.makeText(this, message, Toast.LENGTH_LONG).show(); } diff --git a/app/src/main/java/com/limelight/binding/video/AndroidCpuDecoderRenderer.java b/app/src/main/java/com/limelight/binding/video/AndroidCpuDecoderRenderer.java index b682e233..258003b2 100644 --- a/app/src/main/java/com/limelight/binding/video/AndroidCpuDecoderRenderer.java +++ b/app/src/main/java/com/limelight/binding/video/AndroidCpuDecoderRenderer.java @@ -91,9 +91,14 @@ public class AndroidCpuDecoderRenderer extends EnhancedDecoderRenderer { } @Override - public boolean setup(int width, int height, int redrawRate, Object renderTarget, int drFlags) { + public boolean setup(VideoFormat format, int width, int height, int redrawRate, Object renderTarget, int drFlags) { this.targetFps = redrawRate; + // We should never make it here with H265 + if (format != VideoFormat.H264) { + return false; + } + int perfLevel = LOW_PERF; //findOptimalPerformanceLevel(); int threadCount; @@ -283,7 +288,7 @@ public class AndroidCpuDecoderRenderer extends EnhancedDecoderRenderer { } @Override - public String getDecoderName() { - return "CPU decoding"; + public boolean isHevcSupported() { + return false; } } diff --git a/app/src/main/java/com/limelight/binding/video/ConfigurableDecoderRenderer.java b/app/src/main/java/com/limelight/binding/video/ConfigurableDecoderRenderer.java index f65830ed..526ec1d8 100644 --- a/app/src/main/java/com/limelight/binding/video/ConfigurableDecoderRenderer.java +++ b/app/src/main/java/com/limelight/binding/video/ConfigurableDecoderRenderer.java @@ -1,5 +1,7 @@ package com.limelight.binding.video; +import android.media.MediaCodecInfo; + import com.limelight.nvstream.av.DecodeUnit; import com.limelight.nvstream.av.video.VideoDecoderRenderer; import com.limelight.nvstream.av.video.VideoDepacketizer; @@ -16,18 +18,18 @@ public class ConfigurableDecoderRenderer extends EnhancedDecoderRenderer { } @Override - public boolean setup(int width, int height, int redrawRate, Object renderTarget, int drFlags) { + public boolean setup(VideoFormat format, int width, int height, int redrawRate, Object renderTarget, int drFlags) { if (decoderRenderer == null) { throw new IllegalStateException("ConfigurableDecoderRenderer not initialized"); } - return decoderRenderer.setup(width, height, redrawRate, renderTarget, drFlags); + return decoderRenderer.setup(format, width, height, redrawRate, renderTarget, drFlags); } - public void initializeWithFlags(int drFlags) { + public void initializeWithFlags(int drFlags, int videoFormat) { if ((drFlags & VideoDecoderRenderer.FLAG_FORCE_HARDWARE_DECODING) != 0 || ((drFlags & VideoDecoderRenderer.FLAG_FORCE_SOFTWARE_DECODING) == 0 && - MediaCodecHelper.findProbableSafeDecoder() != null)) { - decoderRenderer = new MediaCodecDecoderRenderer(); + MediaCodecHelper.findProbableSafeDecoder("video/avc", MediaCodecInfo.CodecProfileLevel.AVCProfileHigh) != null)) { + decoderRenderer = new MediaCodecDecoderRenderer(videoFormat); } else { decoderRenderer = new AndroidCpuDecoderRenderer(); @@ -82,12 +84,12 @@ public class ConfigurableDecoderRenderer extends EnhancedDecoderRenderer { } @Override - public String getDecoderName() { + public boolean isHevcSupported() { if (decoderRenderer != null) { - return decoderRenderer.getDecoderName(); + return decoderRenderer.isHevcSupported(); } else { - return null; + return false; } } } diff --git a/app/src/main/java/com/limelight/binding/video/EnhancedDecoderRenderer.java b/app/src/main/java/com/limelight/binding/video/EnhancedDecoderRenderer.java index 5343c381..98e77d29 100644 --- a/app/src/main/java/com/limelight/binding/video/EnhancedDecoderRenderer.java +++ b/app/src/main/java/com/limelight/binding/video/EnhancedDecoderRenderer.java @@ -3,5 +3,5 @@ package com.limelight.binding.video; import com.limelight.nvstream.av.video.VideoDecoderRenderer; public abstract class EnhancedDecoderRenderer extends VideoDecoderRenderer { - public abstract String getDecoderName(); + public abstract boolean isHevcSupported(); } diff --git a/app/src/main/java/com/limelight/binding/video/MediaCodecDecoderRenderer.java b/app/src/main/java/com/limelight/binding/video/MediaCodecDecoderRenderer.java index 008493d0..65abadc6 100644 --- a/app/src/main/java/com/limelight/binding/video/MediaCodecDecoderRenderer.java +++ b/app/src/main/java/com/limelight/binding/video/MediaCodecDecoderRenderer.java @@ -13,6 +13,7 @@ import com.limelight.nvstream.av.ByteBufferDescriptor; import com.limelight.nvstream.av.DecodeUnit; import com.limelight.nvstream.av.video.VideoDecoderRenderer; import com.limelight.nvstream.av.video.VideoDepacketizer; +import com.limelight.preferences.PreferenceConfiguration; import android.media.MediaCodec; import android.media.MediaCodecInfo; @@ -27,13 +28,17 @@ public class MediaCodecDecoderRenderer extends EnhancedDecoderRenderer { // Used on versions < 5.0 private ByteBuffer[] legacyInputBuffers; + private String avcDecoderName; + private String hevcDecoderName; + private MediaCodec videoDecoder; private Thread rendererThread; - private final boolean needsSpsBitstreamFixup, isExynos4; + private boolean needsSpsBitstreamFixup, isExynos4; private VideoDepacketizer depacketizer; - private final boolean adaptivePlayback, directSubmit; - private final boolean constrainedHighProfile; + private boolean adaptivePlayback, directSubmit; + private boolean constrainedHighProfile; private int initialWidth, initialHeight; + private VideoFormat videoFormat; private boolean needsBaselineSpsHack; private SeqParameterSet savedSps; @@ -43,71 +48,141 @@ public class MediaCodecDecoderRenderer extends EnhancedDecoderRenderer { private long decoderTimeMs; private int totalFrames; - private String decoderName; private int numSpsIn; private int numPpsIn; + private int numVpsIn; private int numIframeIn; - public MediaCodecDecoderRenderer() { + private MediaCodecInfo findAvcDecoder() { + MediaCodecInfo decoder = MediaCodecHelper.findProbableSafeDecoder("video/avc", MediaCodecInfo.CodecProfileLevel.AVCProfileHigh); + if (decoder == null) { + decoder = MediaCodecHelper.findFirstDecoder("video/avc"); + } + return decoder; + } + + private MediaCodecInfo findHevcDecoder(int videoFormat) { + // Don't return anything if H.265 is forced off + if (videoFormat == PreferenceConfiguration.FORCE_H265_OFF) { + return null; + } + + // We don't try the first HEVC decoder. We'd rather fall back to hardware accelerated AVC instead + // + // We need HEVC Main profile, so we could pass that constant to findProbableSafeDecoder, however + // some decoders (at least Qualcomm's Snapdragon 805) don't properly report support + // for even required levels of HEVC. + MediaCodecInfo decoderInfo = MediaCodecHelper.findProbableSafeDecoder("video/hevc", -1); + if (decoderInfo != null) { + if (!MediaCodecHelper.decoderIsWhitelistedForHevc(decoderInfo.getName())) { + LimeLog.info("Found HEVC decoder, but it's not whitelisted - "+decoderInfo.getName()); + + if (videoFormat == PreferenceConfiguration.FORCE_H265_ON) { + LimeLog.info("Forcing H265 enabled despite non-whitelisted decoder"); + } + else { + return null; + } + } + } + + return decoderInfo; + } + + public MediaCodecDecoderRenderer(int videoFormat) { //dumpDecoders(); - MediaCodecInfo decoder = MediaCodecHelper.findProbableSafeDecoder(); - if (decoder == null) { - decoder = MediaCodecHelper.findFirstDecoder(); + MediaCodecInfo avcDecoder = findAvcDecoder(); + if (avcDecoder != null) { + avcDecoderName = avcDecoder.getName(); + LimeLog.info("Selected AVC decoder: "+avcDecoderName); } - if (decoder == null) { - // This case is handled later in setup() - needsSpsBitstreamFixup = isExynos4 = - adaptivePlayback = directSubmit = - constrainedHighProfile = false; - return; + else { + LimeLog.warning("No AVC decoder found"); } - decoderName = decoder.getName(); - - // Set decoder-specific attributes - directSubmit = MediaCodecHelper.decoderCanDirectSubmit(decoderName, decoder); - adaptivePlayback = MediaCodecHelper.decoderSupportsAdaptivePlayback(decoderName, decoder); - needsSpsBitstreamFixup = MediaCodecHelper.decoderNeedsSpsBitstreamRestrictions(decoderName, decoder); - needsBaselineSpsHack = MediaCodecHelper.decoderNeedsBaselineSpsHack(decoderName, decoder); - constrainedHighProfile = MediaCodecHelper.decoderNeedsConstrainedHighProfile(decoderName, decoder); - isExynos4 = MediaCodecHelper.isExynos4Device(); - if (needsSpsBitstreamFixup) { - LimeLog.info("Decoder "+decoderName+" needs SPS bitstream restrictions fixup"); + MediaCodecInfo hevcDecoder = findHevcDecoder(videoFormat); + if (hevcDecoder != null) { + hevcDecoderName = hevcDecoder.getName(); + LimeLog.info("Selected HEVC decoder: "+hevcDecoderName); } - if (needsBaselineSpsHack) { - LimeLog.info("Decoder "+decoderName+" needs baseline SPS hack"); - } - if (constrainedHighProfile) { - LimeLog.info("Decoder "+decoderName+" needs constrained high profile"); - } - if (isExynos4) { - LimeLog.info("Decoder "+decoderName+" is on Exynos 4"); - } - if (directSubmit) { - LimeLog.info("Decoder "+decoderName+" will use direct submit"); + else { + LimeLog.info("No HEVC decoder found"); } } @Override - public boolean setup(int width, int height, int redrawRate, Object renderTarget, int drFlags) { + public boolean isHevcSupported() { + return hevcDecoderName != null; + } + + @Override + public boolean setup(VideoDecoderRenderer.VideoFormat format, int width, int height, int redrawRate, Object renderTarget, int drFlags) { this.initialWidth = width; this.initialHeight = height; + this.videoFormat = format; - if (decoderName == null) { - LimeLog.severe("No available hardware decoder!"); + String mimeType; + String selectedDecoderName; + + if (videoFormat == VideoFormat.H264) { + mimeType = "video/avc"; + selectedDecoderName = avcDecoderName; + + if (avcDecoderName == null) { + LimeLog.severe("No available AVC decoder!"); + return false; + } + + // These fixups only apply to H264 decoders + needsSpsBitstreamFixup = MediaCodecHelper.decoderNeedsSpsBitstreamRestrictions(selectedDecoderName); + needsBaselineSpsHack = MediaCodecHelper.decoderNeedsBaselineSpsHack(selectedDecoderName); + constrainedHighProfile = MediaCodecHelper.decoderNeedsConstrainedHighProfile(selectedDecoderName); + isExynos4 = MediaCodecHelper.isExynos4Device(); + if (needsSpsBitstreamFixup) { + LimeLog.info("Decoder "+selectedDecoderName+" needs SPS bitstream restrictions fixup"); + } + if (needsBaselineSpsHack) { + LimeLog.info("Decoder "+selectedDecoderName+" needs baseline SPS hack"); + } + if (constrainedHighProfile) { + LimeLog.info("Decoder "+selectedDecoderName+" needs constrained high profile"); + } + if (isExynos4) { + LimeLog.info("Decoder "+selectedDecoderName+" is on Exynos 4"); + } + } + else if (videoFormat == VideoFormat.H265) { + mimeType = "video/hevc"; + selectedDecoderName = hevcDecoderName; + + if (hevcDecoderName == null) { + LimeLog.severe("No available HEVC decoder!"); + return false; + } + } + else { + // Unknown format return false; } + // Set decoder-specific attributes + directSubmit = MediaCodecHelper.decoderCanDirectSubmit(selectedDecoderName); + adaptivePlayback = MediaCodecHelper.decoderSupportsAdaptivePlayback(selectedDecoderName); + + if (directSubmit) { + LimeLog.info("Decoder "+selectedDecoderName+" will use direct submit"); + } + // Codecs have been known to throw all sorts of crazy runtime exceptions // due to implementation problems try { - videoDecoder = MediaCodec.createByCodecName(decoderName); + videoDecoder = MediaCodec.createByCodecName(selectedDecoderName); } catch (Exception e) { return false; } - MediaFormat videoFormat = MediaFormat.createVideoFormat("video/avc", width, height); + MediaFormat videoFormat = MediaFormat.createVideoFormat(mimeType, width, height); // Adaptive playback can also be enabled by the whitelist on pre-KitKat devices // so we don't fill these pre-KitKat @@ -119,7 +194,7 @@ public class MediaCodecDecoderRenderer extends EnhancedDecoderRenderer { videoDecoder.configure(videoFormat, ((SurfaceHolder)renderTarget).getSurface(), null, 0); videoDecoder.setVideoScalingMode(MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT); - LimeLog.info("Using hardware decoding"); + LimeLog.info("Using codec "+selectedDecoderName+" for hardware decoding "+mimeType); return true; } @@ -483,6 +558,8 @@ public class MediaCodecDecoderRenderer extends EnhancedDecoderRenderer { if ((decodeUnitFlags & DecodeUnit.DU_FLAG_CODEC_CONFIG) != 0) { ByteBufferDescriptor header = decodeUnit.getBufferHead(); + + // H264 SPS if (header.data[header.offset+4] == 0x67) { numSpsIn++; @@ -585,6 +662,8 @@ public class MediaCodecDecoderRenderer extends EnhancedDecoderRenderer { depacketizer.freeDecodeUnit(decodeUnit); return; + + // H264 PPS } else if (header.data[header.offset+4] == 0x68) { numPpsIn++; @@ -596,6 +675,15 @@ public class MediaCodecDecoderRenderer extends EnhancedDecoderRenderer { needsSpsReplay = true; } } + else if (header.data[header.offset+4] == 0x40) { + numVpsIn++; + } + else if (header.data[header.offset+4] == 0x42) { + numSpsIn++; + } + else if (header.data[header.offset+4] == 0x44) { + numPpsIn++; + } } // Copy data from our buffer list into the input buffer @@ -674,11 +762,6 @@ public class MediaCodecDecoderRenderer extends EnhancedDecoderRenderer { return (int)(totalTimeMs / totalFrames); } - @Override - public String getDecoderName() { - return decoderName; - } - private void notifyDuReceived(DecodeUnit du) { long currentTime = MediaCodecHelper.getMonotonicMillis(); long delta = currentTime-du.getReceiveTimestamp(); @@ -731,9 +814,11 @@ public class MediaCodecDecoderRenderer extends EnhancedDecoderRenderer { public String toString() { String str = ""; - str += "Decoder: "+renderer.decoderName+"\n"; + str += "Format: "+renderer.videoFormat+"\n"; + str += "AVC Decoder: "+renderer.avcDecoderName+"\n"; + str += "HEVC Decoder: "+renderer.hevcDecoderName+"\n"; str += "Initial video dimensions: "+renderer.initialWidth+"x"+renderer.initialHeight+"\n"; - str += "In stats: "+renderer.numSpsIn+", "+renderer.numPpsIn+", "+renderer.numIframeIn+"\n"; + str += "In stats: "+renderer.numVpsIn+", "+renderer.numSpsIn+", "+renderer.numPpsIn+", "+renderer.numIframeIn+"\n"; str += "Total frames: "+renderer.totalFrames+"\n"; str += "Average end-to-end client latency: "+getAverageEndToEndLatency()+"ms\n"; str += "Average hardware decoder latency: "+getAverageDecoderLatency()+"ms\n"; diff --git a/app/src/main/java/com/limelight/binding/video/MediaCodecHelper.java b/app/src/main/java/com/limelight/binding/video/MediaCodecHelper.java index 6a9c444c..6617d230 100644 --- a/app/src/main/java/com/limelight/binding/video/MediaCodecHelper.java +++ b/app/src/main/java/com/limelight/binding/video/MediaCodecHelper.java @@ -28,6 +28,7 @@ public class MediaCodecHelper { private static final List baselineProfileHackPrefixes; private static final List directSubmitPrefixes; private static final List constrainedHighProfilePrefixes; + private static final List whitelistedHevcDecoders; static { directSubmitPrefixes = new LinkedList(); @@ -72,6 +73,12 @@ public class MediaCodecHelper { constrainedHighProfilePrefixes = new LinkedList(); constrainedHighProfilePrefixes.add("omx.intel"); + + whitelistedHevcDecoders = new LinkedList<>(); + whitelistedHevcDecoders.add("omx.exynos"); + whitelistedHevcDecoders.add("omx.qcom"); + whitelistedHevcDecoders.add("omx.nvidia"); + whitelistedHevcDecoders.add("omx.mtk"); } private static boolean isDecoderInList(List decoderList, String decoderName) { @@ -92,7 +99,7 @@ public class MediaCodecHelper { } @TargetApi(Build.VERSION_CODES.KITKAT) - public static boolean decoderSupportsAdaptivePlayback(String decoderName, MediaCodecInfo decoderInfo) { + public static boolean decoderSupportsAdaptivePlayback(String decoderName) { /* FIXME: Intel's decoder on Nexus Player forces the high latency path if adaptive playback is enabled so we'll keep it off for now, since we don't know whether other devices also do the same @@ -120,21 +127,25 @@ public class MediaCodecHelper { return false; } - public static boolean decoderNeedsConstrainedHighProfile(String decoderName, MediaCodecInfo decoderInfo) { + public static boolean decoderNeedsConstrainedHighProfile(String decoderName) { return isDecoderInList(constrainedHighProfilePrefixes, decoderName); } - public static boolean decoderCanDirectSubmit(String decoderName, MediaCodecInfo decoderInfo) { + public static boolean decoderCanDirectSubmit(String decoderName) { return isDecoderInList(directSubmitPrefixes, decoderName) && !isExynos4Device(); } - public static boolean decoderNeedsSpsBitstreamRestrictions(String decoderName, MediaCodecInfo decoderInfo) { + public static boolean decoderNeedsSpsBitstreamRestrictions(String decoderName) { return isDecoderInList(spsFixupBitstreamFixupDecoderPrefixes, decoderName); } - public static boolean decoderNeedsBaselineSpsHack(String decoderName, MediaCodecInfo decoderInfo) { + public static boolean decoderNeedsBaselineSpsHack(String decoderName) { return isDecoderInList(baselineProfileHackPrefixes, decoderName); } + + public static boolean decoderIsWhitelistedForHevc(String decoderName) { + return isDecoderInList(whitelistedHevcDecoders, decoderName); + } @SuppressWarnings("deprecation") @SuppressLint("NewApi") @@ -199,7 +210,7 @@ public class MediaCodecHelper { return null; } - public static MediaCodecInfo findFirstDecoder() { + public static MediaCodecInfo findFirstDecoder(String mimeType) { for (MediaCodecInfo codecInfo : getMediaCodecList()) { // Skip encoders if (codecInfo.isEncoder()) { @@ -212,9 +223,9 @@ public class MediaCodecHelper { continue; } - // Find a decoder that supports H.264 + // Find a decoder that supports the specified video format for (String mime : codecInfo.getSupportedTypes()) { - if (mime.equalsIgnoreCase("video/avc")) { + if (mime.equalsIgnoreCase(mimeType)) { LimeLog.info("First decoder choice is "+codecInfo.getName()); return codecInfo; } @@ -224,7 +235,7 @@ public class MediaCodecHelper { return null; } - public static MediaCodecInfo findProbableSafeDecoder() { + public static MediaCodecInfo findProbableSafeDecoder(String mimeType, int requiredProfile) { // First look for a preferred decoder by name MediaCodecInfo info = findPreferredDecoder(); if (info != null) { @@ -234,12 +245,12 @@ public class MediaCodecHelper { // Now look for decoders we know are safe try { // If this function completes, it will determine if the decoder is safe - return findKnownSafeDecoder(); + return findKnownSafeDecoder(mimeType, requiredProfile); } catch (Exception e) { // Some buggy devices seem to throw exceptions // from getCapabilitiesForType() so we'll just assume // they're okay and go with the first one we find - return findFirstDecoder(); + return findFirstDecoder(mimeType); } } @@ -247,7 +258,7 @@ public class MediaCodecHelper { // since some bad decoders can throw IllegalArgumentExceptions unexpectedly // and we want to be sure all callers are handling this possibility @SuppressWarnings("RedundantThrows") - private static MediaCodecInfo findKnownSafeDecoder() throws Exception { + private static MediaCodecInfo findKnownSafeDecoder(String mimeType, int requiredProfile) throws Exception { for (MediaCodecInfo codecInfo : getMediaCodecList()) { // Skip encoders if (codecInfo.isEncoder()) { @@ -260,21 +271,26 @@ public class MediaCodecHelper { continue; } - // Find a decoder that supports H.264 high profile + // Find a decoder that supports the requested video format for (String mime : codecInfo.getSupportedTypes()) { - if (mime.equalsIgnoreCase("video/avc")) { + if (mime.equalsIgnoreCase(mimeType)) { LimeLog.info("Examining decoder capabilities of "+codecInfo.getName()); - + CodecCapabilities caps = codecInfo.getCapabilitiesForType(mime); - for (CodecProfileLevel profile : caps.profileLevels) { - if (profile.profile == CodecProfileLevel.AVCProfileHigh) { - LimeLog.info("Decoder "+codecInfo.getName()+" supports high profile"); - LimeLog.info("Selected decoder: "+codecInfo.getName()); - return codecInfo; + + if (requiredProfile != -1) { + for (CodecProfileLevel profile : caps.profileLevels) { + if (profile.profile == requiredProfile) { + LimeLog.info("Decoder " + codecInfo.getName() + " supports required profile"); + return codecInfo; + } } + + LimeLog.info("Decoder " + codecInfo.getName() + " does NOT support required profile"); + } + else { + return codecInfo; } - - LimeLog.info("Decoder "+codecInfo.getName()+" does NOT support high profile"); } } } diff --git a/app/src/main/java/com/limelight/preferences/PreferenceConfiguration.java b/app/src/main/java/com/limelight/preferences/PreferenceConfiguration.java index f1d9091e..9972d69c 100644 --- a/app/src/main/java/com/limelight/preferences/PreferenceConfiguration.java +++ b/app/src/main/java/com/limelight/preferences/PreferenceConfiguration.java @@ -21,6 +21,7 @@ public class PreferenceConfiguration { private static final String MULTI_CONTROLLER_PREF_STRING = "checkbox_multi_controller"; private static final String ENABLE_51_SURROUND_PREF_STRING = "checkbox_51_surround"; private static final String USB_DRIVER_PREF_SRING = "checkbox_usb_driver"; + private static final String VIDEO_FORMAT_PREF_STRING = "video_format"; private static final int BITRATE_DEFAULT_720_30 = 5; private static final int BITRATE_DEFAULT_720_60 = 10; @@ -42,14 +43,19 @@ public class PreferenceConfiguration { private static final boolean DEFAULT_MULTI_CONTROLLER = true; private static final boolean DEFAULT_ENABLE_51_SURROUND = false; private static final boolean DEFAULT_USB_DRIVER = true; + private static final String DEFAULT_VIDEO_FORMAT = "auto"; public static final int FORCE_HARDWARE_DECODER = -1; public static final int AUTOSELECT_DECODER = 0; public static final int FORCE_SOFTWARE_DECODER = 1; + public static final int FORCE_H265_ON = -1; + public static final int AUTOSELECT_H265 = 0; + public static final int FORCE_H265_OFF = 1; + public int width, height, fps; public int bitrate; - public int decoder; + public int decoder, videoFormat; public int deadzonePercentage; public boolean stretchVideo, enableSops, playHostAudio, disableWarnings; public String language; @@ -124,6 +130,25 @@ public class PreferenceConfiguration { } } + private static int getVideoFormatValue(Context context) { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + + String str = prefs.getString(VIDEO_FORMAT_PREF_STRING, DEFAULT_VIDEO_FORMAT); + if (str.equals("auto")) { + return AUTOSELECT_H265; + } + else if (str.equals("forceh265")) { + return FORCE_H265_ON; + } + else if (str.equals("neverh265")) { + return FORCE_H265_OFF; + } + else { + // Should never get here + return AUTOSELECT_H265; + } + } + public static PreferenceConfiguration readPreferences(Context context) { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); PreferenceConfiguration config = new PreferenceConfiguration(); @@ -168,6 +193,7 @@ public class PreferenceConfiguration { } config.decoder = getDecoderValue(context); + config.videoFormat = getVideoFormatValue(context); config.deadzonePercentage = prefs.getInt(DEADZONE_PREF_STRING, DEFAULT_DEADZONE); diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index ec7c150c..d4191bdb 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -38,4 +38,15 @@ software hardware + + + Use H.265 only if safe + Always use H.265 if available + Never use H.265 + + + auto + forceh265 + neverh265 + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d633c26a..3e28bd23 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -123,4 +123,7 @@ Advanced Settings Change decoder Software decoding may improve video latency at lower streaming settings + Change H.265 settings + H.265 lowers video bandwidth requirements but requires a very recent device. + diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 7b9a3b3d..c78cdd8b 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -89,6 +89,13 @@ android:entryValues="@array/decoder_values" android:summary="@string/summary_decoder_list" android:defaultValue="auto" /> +