Commit dd425613 by michaelkatz Committed by microkatz

Try alternative decoder for Dolby Vision if display does not support

If the sample type is dolby vision and the following conditions match
a)There is a supported alternative codec mimetype
b)Display does not support Dolby Vision
Then getDecoderInfos will return the alternative types.

Issue: google/ExoPlayer#9794
PiperOrigin-RevId: 476356223
(cherry picked from commit ed79f469)
parent ab371849
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
* Discard back buffer before playback gets stuck due to insufficient * Discard back buffer before playback gets stuck due to insufficient
available memory. available memory.
* Close the Tracing "doSomeWork" block when offload is enabled. * Close the Tracing "doSomeWork" block when offload is enabled.
* Try alternative decoder for Dolby Vision if display does not support it.
([#9794](https://github.com/google/ExoPlayer/issues/9794)).
* Downloads: * Downloads:
* Fix potential infinite loop in `ProgressiveDownloader` caused by * Fix potential infinite loop in `ProgressiveDownloader` caused by
simultaneous download and playback with the same `PriorityTaskManager` simultaneous download and playback with the same `PriorityTaskManager`
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
*/ */
package androidx.media3.exoplayer.video; package androidx.media3.exoplayer.video;
import static android.view.Display.DEFAULT_DISPLAY;
import static androidx.media3.exoplayer.DecoderReuseEvaluation.DISCARD_REASON_MAX_INPUT_SIZE_EXCEEDED; import static androidx.media3.exoplayer.DecoderReuseEvaluation.DISCARD_REASON_MAX_INPUT_SIZE_EXCEEDED;
import static androidx.media3.exoplayer.DecoderReuseEvaluation.DISCARD_REASON_VIDEO_MAX_RESOLUTION_EXCEEDED; import static androidx.media3.exoplayer.DecoderReuseEvaluation.DISCARD_REASON_VIDEO_MAX_RESOLUTION_EXCEEDED;
import static androidx.media3.exoplayer.DecoderReuseEvaluation.REUSE_RESULT_NO; import static androidx.media3.exoplayer.DecoderReuseEvaluation.REUSE_RESULT_NO;
...@@ -25,6 +26,7 @@ import android.annotation.SuppressLint; ...@@ -25,6 +26,7 @@ import android.annotation.SuppressLint;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.content.Context; import android.content.Context;
import android.graphics.Point; import android.graphics.Point;
import android.hardware.display.DisplayManager;
import android.media.MediaCodec; import android.media.MediaCodec;
import android.media.MediaCodecInfo.CodecCapabilities; import android.media.MediaCodecInfo.CodecCapabilities;
import android.media.MediaCodecInfo.CodecProfileLevel; import android.media.MediaCodecInfo.CodecProfileLevel;
...@@ -35,6 +37,7 @@ import android.os.Handler; ...@@ -35,6 +37,7 @@ import android.os.Handler;
import android.os.Message; import android.os.Message;
import android.os.SystemClock; import android.os.SystemClock;
import android.util.Pair; import android.util.Pair;
import android.view.Display;
import android.view.Surface; import android.view.Surface;
import androidx.annotation.CallSuper; import androidx.annotation.CallSuper;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
...@@ -356,6 +359,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -356,6 +359,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
boolean requiresSecureDecryption = drmInitData != null; boolean requiresSecureDecryption = drmInitData != null;
List<MediaCodecInfo> decoderInfos = List<MediaCodecInfo> decoderInfos =
getDecoderInfos( getDecoderInfos(
context,
mediaCodecSelector, mediaCodecSelector,
format, format,
requiresSecureDecryption, requiresSecureDecryption,
...@@ -364,6 +368,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -364,6 +368,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
// No secure decoders are available. Fall back to non-secure decoders. // No secure decoders are available. Fall back to non-secure decoders.
decoderInfos = decoderInfos =
getDecoderInfos( getDecoderInfos(
context,
mediaCodecSelector, mediaCodecSelector,
format, format,
/* requiresSecureDecoder= */ false, /* requiresSecureDecoder= */ false,
...@@ -411,6 +416,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -411,6 +416,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
if (isFormatSupported) { if (isFormatSupported) {
List<MediaCodecInfo> tunnelingDecoderInfos = List<MediaCodecInfo> tunnelingDecoderInfos =
getDecoderInfos( getDecoderInfos(
context,
mediaCodecSelector, mediaCodecSelector,
format, format,
requiresSecureDecryption, requiresSecureDecryption,
...@@ -439,7 +445,8 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -439,7 +445,8 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
MediaCodecSelector mediaCodecSelector, Format format, boolean requiresSecureDecoder) MediaCodecSelector mediaCodecSelector, Format format, boolean requiresSecureDecoder)
throws DecoderQueryException { throws DecoderQueryException {
return MediaCodecUtil.getDecoderInfosSortedByFormatSupport( return MediaCodecUtil.getDecoderInfosSortedByFormatSupport(
getDecoderInfos(mediaCodecSelector, format, requiresSecureDecoder, tunneling), format); getDecoderInfos(context, mediaCodecSelector, format, requiresSecureDecoder, tunneling),
format);
} }
/** /**
...@@ -459,6 +466,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -459,6 +466,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
* @throws DecoderQueryException Thrown if there was an error querying decoders. * @throws DecoderQueryException Thrown if there was an error querying decoders.
*/ */
private static List<MediaCodecInfo> getDecoderInfos( private static List<MediaCodecInfo> getDecoderInfos(
Context context,
MediaCodecSelector mediaCodecSelector, MediaCodecSelector mediaCodecSelector,
Format format, Format format,
boolean requiresSecureDecoder, boolean requiresSecureDecoder,
...@@ -478,6 +486,28 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -478,6 +486,28 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
List<MediaCodecInfo> alternativeDecoderInfos = List<MediaCodecInfo> alternativeDecoderInfos =
mediaCodecSelector.getDecoderInfos( mediaCodecSelector.getDecoderInfos(
alternativeMimeType, requiresSecureDecoder, requiresTunnelingDecoder); alternativeMimeType, requiresSecureDecoder, requiresTunnelingDecoder);
if (Util.SDK_INT >= 26
&& MimeTypes.VIDEO_DOLBY_VISION.equals(format.sampleMimeType)
&& !alternativeDecoderInfos.isEmpty()) {
// If sample type is Dolby Vision, check if Display supports Dolby Vision
boolean supportsDolbyVision = false;
DisplayManager displayManager =
(DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
Display display =
(displayManager != null) ? displayManager.getDisplay(DEFAULT_DISPLAY) : null;
if (display != null && display.isHdr()) {
int[] supportedHdrTypes = display.getHdrCapabilities().getSupportedHdrTypes();
for (int hdrType : supportedHdrTypes) {
if (hdrType == Display.HdrCapabilities.HDR_TYPE_DOLBY_VISION) {
supportsDolbyVision = true;
break;
}
}
}
if (!supportsDolbyVision) {
return ImmutableList.copyOf(alternativeDecoderInfos);
}
}
return ImmutableList.<MediaCodecInfo>builder() return ImmutableList.<MediaCodecInfo>builder()
.addAll(decoderInfos) .addAll(decoderInfos)
.addAll(alternativeDecoderInfos) .addAll(alternativeDecoderInfos)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment