Skip to content

Commit 5968fe7

Browse files
committed
Fix DV Profile 7 fallback to HEVC to preserve HDR10+ metadata
On devices that don't support Dolby Vision output, Profile 7 (DvheDtb) remux files fell back to plain HDR10 because the HEVC base-layer fallback path was blocked and HDR10+ metadata was never forwarded to HEVC decoders. - Allow DolbyVisionProfileDvheDtb to fall back to HEVC in getAlternativeCodecMimeType, since its base layer is always backward-compatible HEVC Main 10. - Extend isHdr10PlusOutOfBandMetadataSupported to recognize HEVC decoders advertising HEVCProfileMain10HDR10Plus (API 33+), so dynamic HDR10+ metadata is forwarded via PARAMETER_KEY_HDR10_PLUS_INFO.
1 parent e0dd3fd commit 5968fe7

3 files changed

Lines changed: 27 additions & 8 deletions

File tree

libraries/exoplayer/src/main/java/androidx/media3/exoplayer/mediacodec/MediaCodecInfo.java

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -410,10 +410,19 @@ private boolean isCompressedAudioBitDepthSupported(Format format) {
410410

411411
/** Whether the codec handles HDR10+ out-of-band metadata. */
412412
public boolean isHdr10PlusOutOfBandMetadataSupported() {
413-
if (SDK_INT >= 29 && MimeTypes.VIDEO_VP9.equals(mimeType)) {
414-
for (CodecProfileLevel capabilities : getProfileLevels()) {
415-
if (capabilities.profile == CodecProfileLevel.VP9Profile2HDR10Plus) {
416-
return true;
413+
if (SDK_INT >= 29) {
414+
if (MimeTypes.VIDEO_VP9.equals(mimeType)) {
415+
for (CodecProfileLevel capabilities : getProfileLevels()) {
416+
if (capabilities.profile == CodecProfileLevel.VP9Profile2HDR10Plus) {
417+
return true;
418+
}
419+
}
420+
}
421+
if (SDK_INT >= 33 && MimeTypes.VIDEO_H265.equals(mimeType)) {
422+
for (CodecProfileLevel capabilities : getProfileLevels()) {
423+
if (capabilities.profile == CodecProfileLevel.HEVCProfileMain10HDR10Plus) {
424+
return true;
425+
}
417426
}
418427
}
419428
}

libraries/exoplayer/src/main/java/androidx/media3/exoplayer/mediacodec/MediaCodecUtil.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -382,16 +382,17 @@ public static String getAlternativeCodecMimeType(Format format) {
382382
}
383383
if (MimeTypes.VIDEO_DOLBY_VISION.equals(format.sampleMimeType)) {
384384
// H.264/AVC, H.265/HEVC or AV1 decoders can decode the base layer of some DV profiles.
385-
// This can't be done for profile CodecProfileLevel.DolbyVisionProfileDvheStn and profile
386-
// CodecProfileLevel.DolbyVisionProfileDvheDtb because the first one is not backward
387-
// compatible and the second one is deprecated and is not always backward compatible.
385+
// This can't be done for profile CodecProfileLevel.DolbyVisionProfileDvheStn because it is
386+
// not backward compatible. Profile DolbyVisionProfileDvheDtb (profile 7) is deprecated but
387+
// its base layer is always backward-compatible HEVC Main 10, so HEVC fallback is safe.
388388
@Nullable
389389
MediaCodecProfileAndLevel codecProfileAndLevel =
390390
CodecSpecificDataUtil.getMediaCodecProfileAndLevel(format);
391391
if (codecProfileAndLevel != null && codecProfileAndLevel.isSupportableByMediaCodec()) {
392392
int profile = codecProfileAndLevel.getProfile();
393393
if (profile == CodecProfileLevel.DolbyVisionProfileDvheDtr
394-
|| profile == CodecProfileLevel.DolbyVisionProfileDvheSt) {
394+
|| profile == CodecProfileLevel.DolbyVisionProfileDvheSt
395+
|| profile == CodecProfileLevel.DolbyVisionProfileDvheDtb) {
395396
return MimeTypes.VIDEO_H265;
396397
} else if (profile == CodecProfileLevel.DolbyVisionProfileDvavSe) {
397398
return MimeTypes.VIDEO_H264;

libraries/exoplayer/src/test/java/androidx/media3/exoplayer/video/MediaCodecVideoRendererTest.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4445,6 +4445,11 @@ public void supportsFormat_withDolbyVisionMedia_returnsTrueWhenFallbackToAv1H265
44454445
.setSampleMimeType(MimeTypes.VIDEO_DOLBY_VISION)
44464446
.setCodecs("dvhe.04.01")
44474447
.build();
4448+
Format formatDvheDtbFallbackToH265 =
4449+
new Format.Builder()
4450+
.setSampleMimeType(MimeTypes.VIDEO_DOLBY_VISION)
4451+
.setCodecs("dvhe.07.01")
4452+
.build();
44484453
Format formatDvheStFallbackToH265 =
44494454
new Format.Builder()
44504455
.setSampleMimeType(MimeTypes.VIDEO_DOLBY_VISION)
@@ -4556,6 +4561,8 @@ public void supportsFormat_withDolbyVisionMedia_returnsTrueWhenFallbackToAv1H265
45564561
@Capabilities
45574562
int capabilitiesDvheDtrFallbackToH265 = renderer.supportsFormat(formatDvheDtrFallbackToH265);
45584563
@Capabilities
4564+
int capabilitiesDvheDtbFallbackToH265 = renderer.supportsFormat(formatDvheDtbFallbackToH265);
4565+
@Capabilities
45594566
int capabilitiesDvheStFallbackToH265 = renderer.supportsFormat(formatDvheStFallbackToH265);
45604567
@Capabilities
45614568
int capabilitiesDvavSeFallbackToH264 = renderer.supportsFormat(formatDvavSeFallbackToH264);
@@ -4568,6 +4575,8 @@ public void supportsFormat_withDolbyVisionMedia_returnsTrueWhenFallbackToAv1H265
45684575

45694576
assertThat(RendererCapabilities.getFormatSupport(capabilitiesDvheDtrFallbackToH265))
45704577
.isEqualTo(C.FORMAT_HANDLED);
4578+
assertThat(RendererCapabilities.getFormatSupport(capabilitiesDvheDtbFallbackToH265))
4579+
.isEqualTo(C.FORMAT_HANDLED);
45714580
assertThat(RendererCapabilities.getFormatSupport(capabilitiesDvheStFallbackToH265))
45724581
.isEqualTo(C.FORMAT_HANDLED);
45734582
assertThat(RendererCapabilities.getFormatSupport(capabilitiesDvavSeFallbackToH264))

0 commit comments

Comments
 (0)