mirror of
https://github.com/moonlight-stream/moonlight-android.git
synced 2025-07-19 19:13:03 +00:00
Enable adaptive playback on non-Intel devices
This commit is contained in:
parent
f55d6308ce
commit
4deb881ec8
@ -33,6 +33,9 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer {
|
|||||||
|
|
||||||
private byte[] vpsBuffer;
|
private byte[] vpsBuffer;
|
||||||
private byte[] spsBuffer;
|
private byte[] spsBuffer;
|
||||||
|
private byte[] ppsBuffer;
|
||||||
|
private boolean submittedCsd;
|
||||||
|
private boolean submitCsdNextCall;
|
||||||
|
|
||||||
private MediaCodec videoDecoder;
|
private MediaCodec videoDecoder;
|
||||||
private Thread rendererThread;
|
private Thread rendererThread;
|
||||||
@ -151,7 +154,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer {
|
|||||||
// shared between AVC and HEVC decoders on the same device.
|
// shared between AVC and HEVC decoders on the same device.
|
||||||
if (avcDecoder != null) {
|
if (avcDecoder != null) {
|
||||||
directSubmit = MediaCodecHelper.decoderCanDirectSubmit(avcDecoder.getName());
|
directSubmit = MediaCodecHelper.decoderCanDirectSubmit(avcDecoder.getName());
|
||||||
adaptivePlayback = MediaCodecHelper.decoderSupportsAdaptivePlayback(avcDecoder.getName());
|
adaptivePlayback = MediaCodecHelper.decoderSupportsAdaptivePlayback(avcDecoder);
|
||||||
refFrameInvalidationAvc = MediaCodecHelper.decoderSupportsRefFrameInvalidationAvc(avcDecoder.getName());
|
refFrameInvalidationAvc = MediaCodecHelper.decoderSupportsRefFrameInvalidationAvc(avcDecoder.getName());
|
||||||
refFrameInvalidationHevc = MediaCodecHelper.decoderSupportsRefFrameInvalidationHevc(avcDecoder.getName());
|
refFrameInvalidationHevc = MediaCodecHelper.decoderSupportsRefFrameInvalidationHevc(avcDecoder.getName());
|
||||||
|
|
||||||
@ -743,29 +746,44 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer {
|
|||||||
else if (decodeUnitType == MoonBridge.BUFFER_TYPE_PPS) {
|
else if (decodeUnitType == MoonBridge.BUFFER_TYPE_PPS) {
|
||||||
numPpsIn++;
|
numPpsIn++;
|
||||||
|
|
||||||
inputBufferIndex = dequeueInputBuffer();
|
// If this is the first CSD blob or we aren't supporting
|
||||||
if (inputBufferIndex < 0) {
|
// adaptive playback, we will submit the CSD blob in a
|
||||||
// We're being torn down now
|
// separate input buffer.
|
||||||
return MoonBridge.DR_NEED_IDR;
|
if (!submittedCsd || !adaptivePlayback) {
|
||||||
}
|
inputBufferIndex = dequeueInputBuffer();
|
||||||
|
if (inputBufferIndex < 0) {
|
||||||
|
// We're being torn down now
|
||||||
|
return MoonBridge.DR_NEED_IDR;
|
||||||
|
}
|
||||||
|
|
||||||
buf = getEmptyInputBuffer(inputBufferIndex);
|
buf = getEmptyInputBuffer(inputBufferIndex);
|
||||||
if (buf == null) {
|
if (buf == null) {
|
||||||
// We're being torn down now
|
// We're being torn down now
|
||||||
return MoonBridge.DR_NEED_IDR;
|
return MoonBridge.DR_NEED_IDR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// When we get the PPS, submit the VPS and SPS together with
|
// When we get the PPS, submit the VPS and SPS together with
|
||||||
// the PPS, as required by AOSP docs on use of MediaCodec.
|
// the PPS, as required by AOSP docs on use of MediaCodec.
|
||||||
if (vpsBuffer != null) {
|
if (vpsBuffer != null) {
|
||||||
buf.put(vpsBuffer);
|
buf.put(vpsBuffer);
|
||||||
}
|
}
|
||||||
if (spsBuffer != null) {
|
if (spsBuffer != null) {
|
||||||
buf.put(spsBuffer);
|
buf.put(spsBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is the CSD blob
|
// This is the CSD blob
|
||||||
codecFlags |= MediaCodec.BUFFER_FLAG_CODEC_CONFIG;
|
codecFlags |= MediaCodec.BUFFER_FLAG_CODEC_CONFIG;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Batch this to submit together with the next I-frame
|
||||||
|
ppsBuffer = new byte[decodeUnitLength];
|
||||||
|
System.arraycopy(decodeUnitData, 0, ppsBuffer, 0, decodeUnitLength);
|
||||||
|
|
||||||
|
// Next call will be I-frame data
|
||||||
|
submitCsdNextCall = true;
|
||||||
|
|
||||||
|
return MoonBridge.DR_OK;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
inputBufferIndex = dequeueInputBuffer();
|
inputBufferIndex = dequeueInputBuffer();
|
||||||
@ -779,6 +797,20 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer {
|
|||||||
// We're being torn down now
|
// We're being torn down now
|
||||||
return MoonBridge.DR_NEED_IDR;
|
return MoonBridge.DR_NEED_IDR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (submitCsdNextCall) {
|
||||||
|
if (vpsBuffer != null) {
|
||||||
|
buf.put(vpsBuffer);
|
||||||
|
}
|
||||||
|
if (spsBuffer != null) {
|
||||||
|
buf.put(spsBuffer);
|
||||||
|
}
|
||||||
|
if (ppsBuffer != null) {
|
||||||
|
buf.put(ppsBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
submitCsdNextCall = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy data from our buffer list into the input buffer
|
// Copy data from our buffer list into the input buffer
|
||||||
@ -790,14 +822,18 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer {
|
|||||||
return MoonBridge.DR_NEED_IDR;
|
return MoonBridge.DR_NEED_IDR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (needsBaselineSpsHack) {
|
if ((codecFlags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
|
||||||
needsBaselineSpsHack = false;
|
submittedCsd = true;
|
||||||
|
|
||||||
if (!replaySps()) {
|
if (needsBaselineSpsHack) {
|
||||||
return MoonBridge.DR_NEED_IDR;
|
needsBaselineSpsHack = false;
|
||||||
|
|
||||||
|
if (!replaySps()) {
|
||||||
|
return MoonBridge.DR_NEED_IDR;
|
||||||
|
}
|
||||||
|
|
||||||
|
LimeLog.info("SPS replay complete");
|
||||||
}
|
}
|
||||||
|
|
||||||
LimeLog.info("SPS replay complete");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return MoonBridge.DR_OK;
|
return MoonBridge.DR_OK;
|
||||||
|
@ -27,7 +27,7 @@ public class MediaCodecHelper {
|
|||||||
|
|
||||||
private static final List<String> blacklistedDecoderPrefixes;
|
private static final List<String> blacklistedDecoderPrefixes;
|
||||||
private static final List<String> spsFixupBitstreamFixupDecoderPrefixes;
|
private static final List<String> spsFixupBitstreamFixupDecoderPrefixes;
|
||||||
private static final List<String> whitelistedAdaptiveResolutionPrefixes;
|
private static final List<String> blacklistedAdaptivePlaybackPrefixes;
|
||||||
private static final List<String> deprioritizedHevcDecoders;
|
private static final List<String> deprioritizedHevcDecoders;
|
||||||
private static final List<String> baselineProfileHackPrefixes;
|
private static final List<String> baselineProfileHackPrefixes;
|
||||||
private static final List<String> directSubmitPrefixes;
|
private static final List<String> directSubmitPrefixes;
|
||||||
@ -93,11 +93,10 @@ public class MediaCodecHelper {
|
|||||||
baselineProfileHackPrefixes = new LinkedList<>();
|
baselineProfileHackPrefixes = new LinkedList<>();
|
||||||
baselineProfileHackPrefixes.add("omx.intel");
|
baselineProfileHackPrefixes.add("omx.intel");
|
||||||
|
|
||||||
whitelistedAdaptiveResolutionPrefixes = new LinkedList<>();
|
// The Intel decoder on Lollipop on Nexus Player would increase latency badly
|
||||||
whitelistedAdaptiveResolutionPrefixes.add("omx.nvidia");
|
// if adaptive playback was enabled so let's avoid it to be safe.
|
||||||
whitelistedAdaptiveResolutionPrefixes.add("omx.qcom");
|
blacklistedAdaptivePlaybackPrefixes = new LinkedList<>();
|
||||||
whitelistedAdaptiveResolutionPrefixes.add("omx.sec");
|
blacklistedAdaptivePlaybackPrefixes.add("omx.intel");
|
||||||
whitelistedAdaptiveResolutionPrefixes.add("omx.TI");
|
|
||||||
|
|
||||||
constrainedHighProfilePrefixes = new LinkedList<>();
|
constrainedHighProfilePrefixes = new LinkedList<>();
|
||||||
constrainedHighProfilePrefixes.add("omx.intel");
|
constrainedHighProfilePrefixes.add("omx.intel");
|
||||||
@ -208,19 +207,14 @@ public class MediaCodecHelper {
|
|||||||
return System.nanoTime() / 1000000L;
|
return System.nanoTime() / 1000000L;
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.KITKAT)
|
public static boolean decoderSupportsAdaptivePlayback(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
|
|
||||||
|
|
||||||
if (isDecoderInList(whitelistedAdaptiveResolutionPrefixes, decoderName)) {
|
|
||||||
LimeLog.info("Adaptive playback supported (whitelist)");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Possibly enable adaptive playback on KitKat and above
|
// Possibly enable adaptive playback on KitKat and above
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||||
|
if (isDecoderInList(blacklistedAdaptivePlaybackPrefixes, decoderInfo.getName())) {
|
||||||
|
LimeLog.info("Decoder blacklisted for adaptive playback");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (decoderInfo.getCapabilitiesForType("video/avc").
|
if (decoderInfo.getCapabilitiesForType("video/avc").
|
||||||
isFeatureSupported(CodecCapabilities.FEATURE_AdaptivePlayback))
|
isFeatureSupported(CodecCapabilities.FEATURE_AdaptivePlayback))
|
||||||
@ -232,7 +226,7 @@ public class MediaCodecHelper {
|
|||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// Tolerate buggy codecs
|
// Tolerate buggy codecs
|
||||||
}
|
}
|
||||||
}*/
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user