Rollback of de83033ffc
*** Original commit ***
Rollback of d7867800dc
*** Original commit ***
Don't sort decoders by format support in supportsFormat
This is a no-op change that updates supportsFormat to use the
decoder list before it's reordered by format support. Instead,
supportsFormat iterates through the decoders listed in their
original priority order as specified by the MediaCodecSelector.
The end result is identical.
This is n...
***
PiperOrigin-RevId: 416269130
This commit is contained in:
parent
de83033ffc
commit
38a0f60b8e
@ -307,16 +307,28 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
|||||||
return RendererCapabilities.create(C.FORMAT_UNSUPPORTED_SUBTYPE);
|
return RendererCapabilities.create(C.FORMAT_UNSUPPORTED_SUBTYPE);
|
||||||
}
|
}
|
||||||
List<MediaCodecInfo> decoderInfos =
|
List<MediaCodecInfo> decoderInfos =
|
||||||
getDecoderInfos(mediaCodecSelector, format, /* requiresSecureDecoder= */ false);
|
getDecoderInfos(mediaCodecSelector, format, /* requiresSecureDecoder= */ false, audioSink);
|
||||||
if (decoderInfos.isEmpty()) {
|
if (decoderInfos.isEmpty()) {
|
||||||
return RendererCapabilities.create(C.FORMAT_UNSUPPORTED_SUBTYPE);
|
return RendererCapabilities.create(C.FORMAT_UNSUPPORTED_SUBTYPE);
|
||||||
}
|
}
|
||||||
if (!supportsFormatDrm) {
|
if (!supportsFormatDrm) {
|
||||||
return RendererCapabilities.create(C.FORMAT_UNSUPPORTED_DRM);
|
return RendererCapabilities.create(C.FORMAT_UNSUPPORTED_DRM);
|
||||||
}
|
}
|
||||||
// Check capabilities for the first decoder in the list, which takes priority.
|
// Check whether the first decoder supports the format. This is the preferred decoder for the
|
||||||
|
// format's MIME type, according to the MediaCodecSelector.
|
||||||
MediaCodecInfo decoderInfo = decoderInfos.get(0);
|
MediaCodecInfo decoderInfo = decoderInfos.get(0);
|
||||||
boolean isFormatSupported = decoderInfo.isFormatSupported(format);
|
boolean isFormatSupported = decoderInfo.isFormatSupported(format);
|
||||||
|
if (!isFormatSupported) {
|
||||||
|
// Check whether any of the other decoders support the format.
|
||||||
|
for (int i = 1; i < decoderInfos.size(); i++) {
|
||||||
|
MediaCodecInfo otherDecoderInfo = decoderInfos.get(i);
|
||||||
|
if (otherDecoderInfo.isFormatSupported(format)) {
|
||||||
|
decoderInfo = otherDecoderInfo;
|
||||||
|
isFormatSupported = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@AdaptiveSupport
|
@AdaptiveSupport
|
||||||
int adaptiveSupport =
|
int adaptiveSupport =
|
||||||
isFormatSupported && decoderInfo.isSeamlessAdaptationSupported(format)
|
isFormatSupported && decoderInfo.isSeamlessAdaptationSupported(format)
|
||||||
@ -331,6 +343,32 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
|||||||
protected List<MediaCodecInfo> getDecoderInfos(
|
protected List<MediaCodecInfo> getDecoderInfos(
|
||||||
MediaCodecSelector mediaCodecSelector, Format format, boolean requiresSecureDecoder)
|
MediaCodecSelector mediaCodecSelector, Format format, boolean requiresSecureDecoder)
|
||||||
throws DecoderQueryException {
|
throws DecoderQueryException {
|
||||||
|
return MediaCodecUtil.getDecoderInfosSortedByFormatSupport(
|
||||||
|
getDecoderInfos(mediaCodecSelector, format, requiresSecureDecoder, audioSink), format);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of decoders that can decode media in the specified format, in the priority order
|
||||||
|
* specified by the {@link MediaCodecSelector}. Note that since the {@link MediaCodecSelector}
|
||||||
|
* only has access to {@link Format#sampleMimeType}, the list is not ordered to account for
|
||||||
|
* whether each decoder supports the details of the format (e.g., taking into account the format's
|
||||||
|
* profile, level, channel count and so on). {@link
|
||||||
|
* MediaCodecUtil#getDecoderInfosSortedByFormatSupport} can be used to further sort the list into
|
||||||
|
* an order where decoders that fully support the format come first.
|
||||||
|
*
|
||||||
|
* @param mediaCodecSelector The decoder selector.
|
||||||
|
* @param format The {@link Format} for which a decoder is required.
|
||||||
|
* @param requiresSecureDecoder Whether a secure decoder is required.
|
||||||
|
* @param audioSink The {@link AudioSink} to which audio will be output.
|
||||||
|
* @return A list of {@link MediaCodecInfo}s corresponding to decoders. May be empty.
|
||||||
|
* @throws DecoderQueryException Thrown if there was an error querying decoders.
|
||||||
|
*/
|
||||||
|
private static List<MediaCodecInfo> getDecoderInfos(
|
||||||
|
MediaCodecSelector mediaCodecSelector,
|
||||||
|
Format format,
|
||||||
|
boolean requiresSecureDecoder,
|
||||||
|
AudioSink audioSink)
|
||||||
|
throws DecoderQueryException {
|
||||||
@Nullable String mimeType = format.sampleMimeType;
|
@Nullable String mimeType = format.sampleMimeType;
|
||||||
if (mimeType == null) {
|
if (mimeType == null) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
@ -345,7 +383,6 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
|||||||
List<MediaCodecInfo> decoderInfos =
|
List<MediaCodecInfo> decoderInfos =
|
||||||
mediaCodecSelector.getDecoderInfos(
|
mediaCodecSelector.getDecoderInfos(
|
||||||
mimeType, requiresSecureDecoder, /* requiresTunnelingDecoder= */ false);
|
mimeType, requiresSecureDecoder, /* requiresTunnelingDecoder= */ false);
|
||||||
decoderInfos = MediaCodecUtil.getDecoderInfosSortedByFormatSupport(decoderInfos, format);
|
|
||||||
if (MimeTypes.AUDIO_E_AC3_JOC.equals(mimeType)) {
|
if (MimeTypes.AUDIO_E_AC3_JOC.equals(mimeType)) {
|
||||||
// E-AC3 decoders can decode JOC streams, but in 2-D rather than 3-D.
|
// E-AC3 decoders can decode JOC streams, but in 2-D rather than 3-D.
|
||||||
List<MediaCodecInfo> decoderInfosWithEac3 = new ArrayList<>(decoderInfos);
|
List<MediaCodecInfo> decoderInfosWithEac3 = new ArrayList<>(decoderInfos);
|
||||||
|
@ -67,6 +67,7 @@ import androidx.media3.exoplayer.mediacodec.MediaCodecSelector;
|
|||||||
import androidx.media3.exoplayer.mediacodec.MediaCodecUtil;
|
import androidx.media3.exoplayer.mediacodec.MediaCodecUtil;
|
||||||
import androidx.media3.exoplayer.mediacodec.MediaCodecUtil.DecoderQueryException;
|
import androidx.media3.exoplayer.mediacodec.MediaCodecUtil.DecoderQueryException;
|
||||||
import androidx.media3.exoplayer.video.VideoRendererEventListener.EventDispatcher;
|
import androidx.media3.exoplayer.video.VideoRendererEventListener.EventDispatcher;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -373,9 +374,21 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
|||||||
if (!supportsFormatDrm(format)) {
|
if (!supportsFormatDrm(format)) {
|
||||||
return RendererCapabilities.create(C.FORMAT_UNSUPPORTED_DRM);
|
return RendererCapabilities.create(C.FORMAT_UNSUPPORTED_DRM);
|
||||||
}
|
}
|
||||||
// Check capabilities for the first decoder in the list, which takes priority.
|
// Check whether the first decoder supports the format. This is the preferred decoder for the
|
||||||
|
// format's MIME type, according to the MediaCodecSelector.
|
||||||
MediaCodecInfo decoderInfo = decoderInfos.get(0);
|
MediaCodecInfo decoderInfo = decoderInfos.get(0);
|
||||||
boolean isFormatSupported = decoderInfo.isFormatSupported(format);
|
boolean isFormatSupported = decoderInfo.isFormatSupported(format);
|
||||||
|
if (!isFormatSupported) {
|
||||||
|
// Check whether any of the other decoders support the format.
|
||||||
|
for (int i = 1; i < decoderInfos.size(); i++) {
|
||||||
|
MediaCodecInfo otherDecoderInfo = decoderInfos.get(i);
|
||||||
|
if (otherDecoderInfo.isFormatSupported(format)) {
|
||||||
|
decoderInfo = otherDecoderInfo;
|
||||||
|
isFormatSupported = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@AdaptiveSupport
|
@AdaptiveSupport
|
||||||
int adaptiveSupport =
|
int adaptiveSupport =
|
||||||
decoderInfo.isSeamlessAdaptationSupported(format)
|
decoderInfo.isSeamlessAdaptationSupported(format)
|
||||||
@ -390,7 +403,9 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
|||||||
requiresSecureDecryption,
|
requiresSecureDecryption,
|
||||||
/* requiresTunnelingDecoder= */ true);
|
/* requiresTunnelingDecoder= */ true);
|
||||||
if (!tunnelingDecoderInfos.isEmpty()) {
|
if (!tunnelingDecoderInfos.isEmpty()) {
|
||||||
MediaCodecInfo tunnelingDecoderInfo = tunnelingDecoderInfos.get(0);
|
MediaCodecInfo tunnelingDecoderInfo =
|
||||||
|
MediaCodecUtil.getDecoderInfosSortedByFormatSupport(tunnelingDecoderInfos, format)
|
||||||
|
.get(0);
|
||||||
if (tunnelingDecoderInfo.isFormatSupported(format)
|
if (tunnelingDecoderInfo.isFormatSupported(format)
|
||||||
&& tunnelingDecoderInfo.isSeamlessAdaptationSupported(format)) {
|
&& tunnelingDecoderInfo.isSeamlessAdaptationSupported(format)) {
|
||||||
tunnelingSupport = TUNNELING_SUPPORTED;
|
tunnelingSupport = TUNNELING_SUPPORTED;
|
||||||
@ -406,9 +421,26 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
|||||||
protected List<MediaCodecInfo> getDecoderInfos(
|
protected List<MediaCodecInfo> getDecoderInfos(
|
||||||
MediaCodecSelector mediaCodecSelector, Format format, boolean requiresSecureDecoder)
|
MediaCodecSelector mediaCodecSelector, Format format, boolean requiresSecureDecoder)
|
||||||
throws DecoderQueryException {
|
throws DecoderQueryException {
|
||||||
return getDecoderInfos(mediaCodecSelector, format, requiresSecureDecoder, tunneling);
|
return MediaCodecUtil.getDecoderInfosSortedByFormatSupport(
|
||||||
|
getDecoderInfos(mediaCodecSelector, format, requiresSecureDecoder, tunneling), format);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of decoders that can decode media in the specified format, in the priority order
|
||||||
|
* specified by the {@link MediaCodecSelector}. Note that since the {@link MediaCodecSelector}
|
||||||
|
* only has access to {@link Format#sampleMimeType}, the list is not ordered to account for
|
||||||
|
* whether each decoder supports the details of the format (e.g., taking into account the format's
|
||||||
|
* profile, level, resolution and so on). {@link
|
||||||
|
* MediaCodecUtil#getDecoderInfosSortedByFormatSupport} can be used to further sort the list into
|
||||||
|
* an order where decoders that fully support the format come first.
|
||||||
|
*
|
||||||
|
* @param mediaCodecSelector The decoder selector.
|
||||||
|
* @param format The {@link Format} for which a decoder is required.
|
||||||
|
* @param requiresSecureDecoder Whether a secure decoder is required.
|
||||||
|
* @param requiresTunnelingDecoder Whether a tunneling decoder is required.
|
||||||
|
* @return A list of {@link MediaCodecInfo}s corresponding to decoders. May be empty.
|
||||||
|
* @throws DecoderQueryException Thrown if there was an error querying decoders.
|
||||||
|
*/
|
||||||
private static List<MediaCodecInfo> getDecoderInfos(
|
private static List<MediaCodecInfo> getDecoderInfos(
|
||||||
MediaCodecSelector mediaCodecSelector,
|
MediaCodecSelector mediaCodecSelector,
|
||||||
Format format,
|
Format format,
|
||||||
@ -422,7 +454,6 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
|||||||
List<MediaCodecInfo> decoderInfos =
|
List<MediaCodecInfo> decoderInfos =
|
||||||
mediaCodecSelector.getDecoderInfos(
|
mediaCodecSelector.getDecoderInfos(
|
||||||
mimeType, requiresSecureDecoder, requiresTunnelingDecoder);
|
mimeType, requiresSecureDecoder, requiresTunnelingDecoder);
|
||||||
decoderInfos = MediaCodecUtil.getDecoderInfosSortedByFormatSupport(decoderInfos, format);
|
|
||||||
if (MimeTypes.VIDEO_DOLBY_VISION.equals(mimeType)) {
|
if (MimeTypes.VIDEO_DOLBY_VISION.equals(mimeType)) {
|
||||||
// Fall back to H.264/AVC or H.265/HEVC for the relevant DV profiles. This can't be done for
|
// Fall back to H.264/AVC or H.265/HEVC for the relevant DV profiles. This can't be done for
|
||||||
// profile CodecProfileLevel.DolbyVisionProfileDvheStn and profile
|
// profile CodecProfileLevel.DolbyVisionProfileDvheStn and profile
|
||||||
@ -431,17 +462,25 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
|||||||
@Nullable
|
@Nullable
|
||||||
Pair<Integer, Integer> codecProfileAndLevel = MediaCodecUtil.getCodecProfileAndLevel(format);
|
Pair<Integer, Integer> codecProfileAndLevel = MediaCodecUtil.getCodecProfileAndLevel(format);
|
||||||
if (codecProfileAndLevel != null) {
|
if (codecProfileAndLevel != null) {
|
||||||
|
List<MediaCodecInfo> fallbackDecoderInfos;
|
||||||
int profile = codecProfileAndLevel.first;
|
int profile = codecProfileAndLevel.first;
|
||||||
if (profile == CodecProfileLevel.DolbyVisionProfileDvheDtr
|
if (profile == CodecProfileLevel.DolbyVisionProfileDvheDtr
|
||||||
|| profile == CodecProfileLevel.DolbyVisionProfileDvheSt) {
|
|| profile == CodecProfileLevel.DolbyVisionProfileDvheSt) {
|
||||||
decoderInfos.addAll(
|
fallbackDecoderInfos =
|
||||||
mediaCodecSelector.getDecoderInfos(
|
mediaCodecSelector.getDecoderInfos(
|
||||||
MimeTypes.VIDEO_H265, requiresSecureDecoder, requiresTunnelingDecoder));
|
MimeTypes.VIDEO_H265, requiresSecureDecoder, requiresTunnelingDecoder);
|
||||||
} else if (profile == CodecProfileLevel.DolbyVisionProfileDvavSe) {
|
} else if (profile == CodecProfileLevel.DolbyVisionProfileDvavSe) {
|
||||||
decoderInfos.addAll(
|
fallbackDecoderInfos =
|
||||||
mediaCodecSelector.getDecoderInfos(
|
mediaCodecSelector.getDecoderInfos(
|
||||||
MimeTypes.VIDEO_H264, requiresSecureDecoder, requiresTunnelingDecoder));
|
MimeTypes.VIDEO_H264, requiresSecureDecoder, requiresTunnelingDecoder);
|
||||||
|
} else {
|
||||||
|
fallbackDecoderInfos = ImmutableList.of();
|
||||||
}
|
}
|
||||||
|
decoderInfos =
|
||||||
|
ImmutableList.<MediaCodecInfo>builder()
|
||||||
|
.addAll(decoderInfos)
|
||||||
|
.addAll(fallbackDecoderInfos)
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Collections.unmodifiableList(decoderInfos);
|
return Collections.unmodifiableList(decoderInfos);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user