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 ed79f4696f026872f2840c53f9526980f4c966d4)
This commit is contained in:
parent
ab37184917
commit
dd425613b7
@ -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 @@
|
|||||||
*/
|
*/
|
||||||
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;
|
|||||||
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;
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
// 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 {
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
* @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 {
|
|||||||
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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user