Skip to content

Commit

Permalink
Enable adaptive playback on non-Intel devices
Browse files Browse the repository at this point in the history
  • Loading branch information
cgutman committed Nov 19, 2017
1 parent f55d630 commit 4deb881
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer {

private byte[] vpsBuffer;
private byte[] spsBuffer;
private byte[] ppsBuffer;
private boolean submittedCsd;
private boolean submitCsdNextCall;

private MediaCodec videoDecoder;
private Thread rendererThread;
Expand Down Expand Up @@ -151,7 +154,7 @@ public MediaCodecDecoderRenderer(PreferenceConfiguration prefs,
// shared between AVC and HEVC decoders on the same device.
if (avcDecoder != null) {
directSubmit = MediaCodecHelper.decoderCanDirectSubmit(avcDecoder.getName());
adaptivePlayback = MediaCodecHelper.decoderSupportsAdaptivePlayback(avcDecoder.getName());
adaptivePlayback = MediaCodecHelper.decoderSupportsAdaptivePlayback(avcDecoder);
refFrameInvalidationAvc = MediaCodecHelper.decoderSupportsRefFrameInvalidationAvc(avcDecoder.getName());
refFrameInvalidationHevc = MediaCodecHelper.decoderSupportsRefFrameInvalidationHevc(avcDecoder.getName());

Expand Down Expand Up @@ -743,29 +746,44 @@ else if (decodeUnitType == MoonBridge.BUFFER_TYPE_SPS) {
else if (decodeUnitType == MoonBridge.BUFFER_TYPE_PPS) {
numPpsIn++;

inputBufferIndex = dequeueInputBuffer();
if (inputBufferIndex < 0) {
// We're being torn down now
return MoonBridge.DR_NEED_IDR;
}
// If this is the first CSD blob or we aren't supporting
// adaptive playback, we will submit the CSD blob in a
// separate input buffer.
if (!submittedCsd || !adaptivePlayback) {
inputBufferIndex = dequeueInputBuffer();
if (inputBufferIndex < 0) {
// We're being torn down now
return MoonBridge.DR_NEED_IDR;
}

buf = getEmptyInputBuffer(inputBufferIndex);
if (buf == null) {
// We're being torn down now
return MoonBridge.DR_NEED_IDR;
}
buf = getEmptyInputBuffer(inputBufferIndex);
if (buf == null) {
// We're being torn down now
return MoonBridge.DR_NEED_IDR;
}

// When we get the PPS, submit the VPS and SPS together with
// the PPS, as required by AOSP docs on use of MediaCodec.
if (vpsBuffer != null) {
buf.put(vpsBuffer);
}
if (spsBuffer != null) {
buf.put(spsBuffer);
// When we get the PPS, submit the VPS and SPS together with
// the PPS, as required by AOSP docs on use of MediaCodec.
if (vpsBuffer != null) {
buf.put(vpsBuffer);
}
if (spsBuffer != null) {
buf.put(spsBuffer);
}

// This is the CSD blob
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;

// This is the CSD blob
codecFlags |= MediaCodec.BUFFER_FLAG_CODEC_CONFIG;
return MoonBridge.DR_OK;
}
}
else {
inputBufferIndex = dequeueInputBuffer();
Expand All @@ -779,6 +797,20 @@ else if (decodeUnitType == MoonBridge.BUFFER_TYPE_PPS) {
// We're being torn down now
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
Expand All @@ -790,14 +822,18 @@ else if (decodeUnitType == MoonBridge.BUFFER_TYPE_PPS) {
return MoonBridge.DR_NEED_IDR;
}

if (needsBaselineSpsHack) {
needsBaselineSpsHack = false;
if ((codecFlags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
submittedCsd = true;

if (!replaySps()) {
return MoonBridge.DR_NEED_IDR;
}
if (needsBaselineSpsHack) {
needsBaselineSpsHack = false;

LimeLog.info("SPS replay complete");
if (!replaySps()) {
return MoonBridge.DR_NEED_IDR;
}

LimeLog.info("SPS replay complete");
}
}

return MoonBridge.DR_OK;
Expand Down
30 changes: 12 additions & 18 deletions app/src/main/java/com/limelight/binding/video/MediaCodecHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public class MediaCodecHelper {

private static final List<String> blacklistedDecoderPrefixes;
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> baselineProfileHackPrefixes;
private static final List<String> directSubmitPrefixes;
Expand Down Expand Up @@ -93,11 +93,10 @@ public class MediaCodecHelper {
baselineProfileHackPrefixes = new LinkedList<>();
baselineProfileHackPrefixes.add("omx.intel");

whitelistedAdaptiveResolutionPrefixes = new LinkedList<>();
whitelistedAdaptiveResolutionPrefixes.add("omx.nvidia");
whitelistedAdaptiveResolutionPrefixes.add("omx.qcom");
whitelistedAdaptiveResolutionPrefixes.add("omx.sec");
whitelistedAdaptiveResolutionPrefixes.add("omx.TI");
// The Intel decoder on Lollipop on Nexus Player would increase latency badly
// if adaptive playback was enabled so let's avoid it to be safe.
blacklistedAdaptivePlaybackPrefixes = new LinkedList<>();
blacklistedAdaptivePlaybackPrefixes.add("omx.intel");

constrainedHighProfilePrefixes = new LinkedList<>();
constrainedHighProfilePrefixes.add("omx.intel");
Expand Down Expand Up @@ -208,19 +207,14 @@ public static long getMonotonicMillis() {
return System.nanoTime() / 1000000L;
}

@TargetApi(Build.VERSION_CODES.KITKAT)
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;
}
public static boolean decoderSupportsAdaptivePlayback(MediaCodecInfo decoderInfo) {
// Possibly enable adaptive playback on KitKat and above
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (isDecoderInList(blacklistedAdaptivePlaybackPrefixes, decoderInfo.getName())) {
LimeLog.info("Decoder blacklisted for adaptive playback");
return false;
}

try {
if (decoderInfo.getCapabilitiesForType("video/avc").
isFeatureSupported(CodecCapabilities.FEATURE_AdaptivePlayback))
Expand All @@ -232,7 +226,7 @@ public static boolean decoderSupportsAdaptivePlayback(String decoderName) {
} catch (Exception e) {
// Tolerate buggy codecs
}
}*/
}

return false;
}
Expand Down

0 comments on commit 4deb881

Please sign in to comment.