diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/RendererCapabilities.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/RendererCapabilities.java index 2f50f283e8..929c8077e7 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/RendererCapabilities.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/RendererCapabilities.java @@ -64,16 +64,16 @@ public interface RendererCapabilities { @interface AdaptiveSupport {} /** A mask to apply to {@link Capabilities} to obtain the {@link AdaptiveSupport} only. */ - int ADAPTIVE_SUPPORT_MASK = 0b11000; + int ADAPTIVE_SUPPORT_MASK = 0b11 << 3; /** The {@link Renderer} can seamlessly adapt between formats. */ - int ADAPTIVE_SEAMLESS = 0b10000; + int ADAPTIVE_SEAMLESS = 0b10 << 3; /** * The {@link Renderer} can adapt between formats, but may suffer a brief discontinuity * (~50-100ms) when adaptation occurs. */ - int ADAPTIVE_NOT_SEAMLESS = 0b01000; + int ADAPTIVE_NOT_SEAMLESS = 0b01 << 3; /** The {@link Renderer} does not support adaptation between formats. */ - int ADAPTIVE_NOT_SUPPORTED = 0b00000; + int ADAPTIVE_NOT_SUPPORTED = 0; /** * Level of renderer support for tunneling. One of {@link #TUNNELING_SUPPORTED} or {@link @@ -84,20 +84,62 @@ public interface RendererCapabilities { @IntDef({TUNNELING_SUPPORTED, TUNNELING_NOT_SUPPORTED}) @interface TunnelingSupport {} - /** A mask to apply to {@link Capabilities} to obtain the {@link TunnelingSupport} only. */ - int TUNNELING_SUPPORT_MASK = 0b100000; + /** A mask to apply to {@link Capabilities} to obtain {@link TunnelingSupport} only. */ + int TUNNELING_SUPPORT_MASK = 0b1 << 5; /** The {@link Renderer} supports tunneled output. */ - int TUNNELING_SUPPORTED = 0b100000; + int TUNNELING_SUPPORTED = 0b1 << 5; /** The {@link Renderer} does not support tunneled output. */ - int TUNNELING_NOT_SUPPORTED = 0b000000; + int TUNNELING_NOT_SUPPORTED = 0; + + /** + * Level of renderer support for hardware acceleration. One of {@link + * #HARDWARE_ACCELERATION_SUPPORTED} and {@link #HARDWARE_ACCELERATION_NOT_SUPPORTED}. + * + *
For video renderers, the level of support is indicated for non-tunneled output. + */ + @Documented + @Retention(RetentionPolicy.SOURCE) + @IntDef({ + HARDWARE_ACCELERATION_SUPPORTED, + HARDWARE_ACCELERATION_NOT_SUPPORTED, + }) + @interface HardwareAccelerationSupport {} + /** A mask to apply to {@link Capabilities} to obtain {@link HardwareAccelerationSupport} only. */ + int HARDWARE_ACCELERATION_SUPPORT_MASK = 0b1 << 6; + /** The renderer is able to use hardware acceleration. */ + int HARDWARE_ACCELERATION_SUPPORTED = 0b1 << 6; + /** The renderer is not able to use hardware acceleration. */ + int HARDWARE_ACCELERATION_NOT_SUPPORTED = 0; + + /** + * Level of decoder support. One of {@link #DECODER_SUPPORT_PRIMARY} and {@link + * #DECODER_SUPPORT_FALLBACK}. + * + *
For video renderers, the level of support is indicated for non-tunneled output. + */ + @Documented + @Retention(RetentionPolicy.SOURCE) + @IntDef({ + DECODER_SUPPORT_PRIMARY, + DECODER_SUPPORT_FALLBACK, + }) + @interface DecoderSupport {} + /** A mask to apply to {@link Capabilities} to obtain {@link DecoderSupport} only. */ + int MODE_SUPPORT_MASK = 0b1 << 7; + /** The renderer is able to use the primary decoder for the format's MIME type. */ + int DECODER_SUPPORT_PRIMARY = 0b1 << 7; + /** The renderer will use a fallback decoder. */ + int DECODER_SUPPORT_FALLBACK = 0; /** * Combined renderer capabilities. * - *
This is a bitwise OR of {@link C.FormatSupport}, {@link AdaptiveSupport} and {@link - * TunnelingSupport}. Use {@link #getFormatSupport(int)}, {@link #getAdaptiveSupport(int)} or - * {@link #getTunnelingSupport(int)} to obtain the individual flags. And use {@link #create(int)} - * or {@link #create(int, int, int)} to create the combined capabilities. + *
This is a bitwise OR of {@link C.FormatSupport}, {@link AdaptiveSupport}, {@link + * TunnelingSupport}, {@link HardwareAccelerationSupport} and {@link DecoderSupport}. Use {@link + * #getFormatSupport}, {@link #getAdaptiveSupport}, {@link #getTunnelingSupport}, {@link + * #getHardwareAccelerationSupport} and {@link #getDecoderSupport} to obtain individual + * components. Use {@link #create(int)}, {@link #create(int, int, int)} or {@link #create(int, + * int, int, int, int)} to create combined capabilities from individual components. * *
Possible values: * @@ -115,6 +157,11 @@ public interface RendererCapabilities { * #TUNNELING_SUPPORTED} and {@link #TUNNELING_NOT_SUPPORTED}. Only set if the level of * support for the format itself is {@link C#FORMAT_HANDLED} or {@link * C#FORMAT_EXCEEDS_CAPABILITIES}. + *
The {@link AdaptiveSupport} is set to {@link #ADAPTIVE_NOT_SUPPORTED} and {{@link - * TunnelingSupport} is set to {@link #TUNNELING_NOT_SUPPORTED}. + *
{@link AdaptiveSupport} is set to {@link #ADAPTIVE_NOT_SUPPORTED}, {@link TunnelingSupport} + * is set to {@link #TUNNELING_NOT_SUPPORTED}, {@link HardwareAccelerationSupport} is set to + * {@link #HARDWARE_ACCELERATION_NOT_SUPPORTED} and {@link DecoderSupport} is set to {@link + * #DECODER_SUPPORT_PRIMARY}. * * @param formatSupport The {@link C.FormatSupport}. * @return The combined {@link Capabilities} of the given {@link C.FormatSupport}, {@link @@ -142,19 +191,53 @@ public interface RendererCapabilities { * Returns {@link Capabilities} combining the given {@link C.FormatSupport}, {@link * AdaptiveSupport} and {@link TunnelingSupport}. * + *
{@link HardwareAccelerationSupport} is set to {@link #HARDWARE_ACCELERATION_NOT_SUPPORTED}
+ * and {@link DecoderSupport} is set to {@link #DECODER_SUPPORT_PRIMARY}.
+ *
* @param formatSupport The {@link C.FormatSupport}.
* @param adaptiveSupport The {@link AdaptiveSupport}.
* @param tunnelingSupport The {@link TunnelingSupport}.
* @return The combined {@link Capabilities}.
*/
+ @Capabilities
+ static int create(
+ @C.FormatSupport int formatSupport,
+ @AdaptiveSupport int adaptiveSupport,
+ @TunnelingSupport int tunnelingSupport) {
+ return create(
+ formatSupport,
+ adaptiveSupport,
+ tunnelingSupport,
+ HARDWARE_ACCELERATION_NOT_SUPPORTED,
+ DECODER_SUPPORT_PRIMARY);
+ }
+
+ /**
+ * Returns {@link Capabilities} combining the given {@link C.FormatSupport}, {@link
+ * AdaptiveSupport}, {@link TunnelingSupport}, {@link HardwareAccelerationSupport} and {@link
+ * DecoderSupport}.
+ *
+ * @param formatSupport The {@link C.FormatSupport}.
+ * @param adaptiveSupport The {@link AdaptiveSupport}.
+ * @param tunnelingSupport The {@link TunnelingSupport}.
+ * @param hardwareAccelerationSupport The {@link HardwareAccelerationSupport}.
+ * @param decoderSupport The {@link DecoderSupport}.
+ * @return The combined {@link Capabilities}.
+ */
// Suppression needed for IntDef casting.
@SuppressLint("WrongConstant")
@Capabilities
static int create(
@C.FormatSupport int formatSupport,
@AdaptiveSupport int adaptiveSupport,
- @TunnelingSupport int tunnelingSupport) {
- return formatSupport | adaptiveSupport | tunnelingSupport;
+ @TunnelingSupport int tunnelingSupport,
+ @HardwareAccelerationSupport int hardwareAccelerationSupport,
+ @DecoderSupport int decoderSupport) {
+ return formatSupport
+ | adaptiveSupport
+ | tunnelingSupport
+ | hardwareAccelerationSupport
+ | decoderSupport;
}
/**
@@ -196,6 +279,32 @@ public interface RendererCapabilities {
return supportFlags & TUNNELING_SUPPORT_MASK;
}
+ /**
+ * Returns the {@link HardwareAccelerationSupport} from the combined {@link Capabilities}.
+ *
+ * @param supportFlags The combined {@link Capabilities}.
+ * @return The {@link HardwareAccelerationSupport} only.
+ */
+ // Suppression needed for IntDef casting.
+ @SuppressLint("WrongConstant")
+ @HardwareAccelerationSupport
+ static int getHardwareAccelerationSupport(@Capabilities int supportFlags) {
+ return supportFlags & HARDWARE_ACCELERATION_SUPPORT_MASK;
+ }
+
+ /**
+ * Returns the {@link DecoderSupport} from the combined {@link Capabilities}.
+ *
+ * @param supportFlags The combined {@link Capabilities}.
+ * @return The {@link DecoderSupport} only.
+ */
+ // Suppression needed for IntDef casting.
+ @SuppressLint("WrongConstant")
+ @DecoderSupport
+ static int getDecoderSupport(@Capabilities int supportFlags) {
+ return supportFlags & MODE_SUPPORT_MASK;
+ }
+
/** Returns the name of the {@link Renderer}. */
String getName();
diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/MediaCodecAudioRenderer.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/MediaCodecAudioRenderer.java
index 04d098cef1..68a46728db 100644
--- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/MediaCodecAudioRenderer.java
+++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/MediaCodecAudioRenderer.java
@@ -318,6 +318,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
// format's MIME type, according to the MediaCodecSelector.
MediaCodecInfo decoderInfo = decoderInfos.get(0);
boolean isFormatSupported = decoderInfo.isFormatSupported(format);
+ boolean isPreferredDecoder = true;
if (!isFormatSupported) {
// Check whether any of the other decoders support the format.
for (int i = 1; i < decoderInfos.size(); i++) {
@@ -325,18 +326,31 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
if (otherDecoderInfo.isFormatSupported(format)) {
decoderInfo = otherDecoderInfo;
isFormatSupported = true;
+ isPreferredDecoder = false;
break;
}
}
}
+ @C.FormatSupport
+ int formatSupport = isFormatSupported ? C.FORMAT_HANDLED : C.FORMAT_EXCEEDS_CAPABILITIES;
@AdaptiveSupport
int adaptiveSupport =
isFormatSupported && decoderInfo.isSeamlessAdaptationSupported(format)
? ADAPTIVE_SEAMLESS
: ADAPTIVE_NOT_SEAMLESS;
- @C.FormatSupport
- int formatSupport = isFormatSupported ? C.FORMAT_HANDLED : C.FORMAT_EXCEEDS_CAPABILITIES;
- return RendererCapabilities.create(formatSupport, adaptiveSupport, tunnelingSupport);
+ @HardwareAccelerationSupport
+ int hardwareAccelerationSupport =
+ decoderInfo.hardwareAccelerated
+ ? HARDWARE_ACCELERATION_SUPPORTED
+ : HARDWARE_ACCELERATION_NOT_SUPPORTED;
+ @DecoderSupport
+ int decoderSupport = isPreferredDecoder ? DECODER_SUPPORT_PRIMARY : DECODER_SUPPORT_FALLBACK;
+ return RendererCapabilities.create(
+ formatSupport,
+ adaptiveSupport,
+ tunnelingSupport,
+ hardwareAccelerationSupport,
+ decoderSupport);
}
@Override
diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/trackselection/MappingTrackSelector.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/trackselection/MappingTrackSelector.java
index edb4497722..00981a4973 100644
--- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/trackselection/MappingTrackSelector.java
+++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/trackselection/MappingTrackSelector.java
@@ -219,6 +219,19 @@ public abstract class MappingTrackSelector extends TrackSelector {
return bestRendererSupport;
}
+ /**
+ * Returns the {@link Capabilities} of the renderer for an individual track.
+ *
+ * @param rendererIndex The renderer index.
+ * @param groupIndex The index of the track group to which the track belongs.
+ * @param trackIndex The index of the track within the track group.
+ * @return The {@link Capabilities}.
+ */
+ @Capabilities
+ public int getCapabilities(int rendererIndex, int groupIndex, int trackIndex) {
+ return rendererFormatSupports[rendererIndex][groupIndex][trackIndex];
+ }
+
/**
* Returns the extent to which an individual track is supported by the renderer.
*
@@ -230,7 +243,7 @@ public abstract class MappingTrackSelector extends TrackSelector {
@FormatSupport
public int getTrackSupport(int rendererIndex, int groupIndex, int trackIndex) {
return RendererCapabilities.getFormatSupport(
- rendererFormatSupports[rendererIndex][groupIndex][trackIndex]);
+ getCapabilities(rendererIndex, groupIndex, trackIndex));
}
/**
diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/util/EventLogger.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/util/EventLogger.java
index 3b3d169364..197370a1b4 100644
--- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/util/EventLogger.java
+++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/util/EventLogger.java
@@ -15,6 +15,12 @@
*/
package androidx.media3.exoplayer.util;
+import static androidx.media3.common.util.Util.getFormatSupportString;
+import static androidx.media3.exoplayer.RendererCapabilities.DECODER_SUPPORT_FALLBACK;
+import static androidx.media3.exoplayer.RendererCapabilities.HARDWARE_ACCELERATION_SUPPORTED;
+import static androidx.media3.exoplayer.RendererCapabilities.getDecoderSupport;
+import static androidx.media3.exoplayer.RendererCapabilities.getFormatSupport;
+import static androidx.media3.exoplayer.RendererCapabilities.getHardwareAccelerationSupport;
import static java.lang.Math.min;
import android.os.SystemClock;
@@ -37,11 +43,11 @@ import androidx.media3.common.TrackSelectionArray;
import androidx.media3.common.VideoSize;
import androidx.media3.common.util.Log;
import androidx.media3.common.util.UnstableApi;
-import androidx.media3.common.util.Util;
import androidx.media3.exoplayer.DecoderCounters;
import androidx.media3.exoplayer.DecoderReuseEvaluation;
import androidx.media3.exoplayer.RendererCapabilities;
import androidx.media3.exoplayer.RendererCapabilities.AdaptiveSupport;
+import androidx.media3.exoplayer.RendererCapabilities.Capabilities;
import androidx.media3.exoplayer.analytics.AnalyticsListener;
import androidx.media3.exoplayer.drm.DrmSession;
import androidx.media3.exoplayer.source.LoadEventInfo;
@@ -280,9 +286,16 @@ public class EventLogger implements AnalyticsListener {
logd(" Group:" + trackGroup.id + ", adaptive_supported=" + adaptiveSupport + " [");
for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
String status = getTrackStatusString(trackSelection, trackGroup, trackIndex);
- String formatSupport =
- Util.getFormatSupportString(
- mappedTrackInfo.getTrackSupport(rendererIndex, groupIndex, trackIndex));
+ @Capabilities
+ int capabilities =
+ mappedTrackInfo.getCapabilities(rendererIndex, groupIndex, trackIndex);
+ String formatSupport = getFormatSupportString(getFormatSupport(capabilities));
+ String hardwareAccelerationSupport =
+ getHardwareAccelerationSupport(capabilities) == HARDWARE_ACCELERATION_SUPPORTED
+ ? ", accelerated=YES"
+ : "";
+ String decoderSupport =
+ getDecoderSupport(capabilities) == DECODER_SUPPORT_FALLBACK ? ", fallback=YES" : "";
logd(
" "
+ status
@@ -291,7 +304,9 @@ public class EventLogger implements AnalyticsListener {
+ ", "
+ Format.toLogString(trackGroup.getFormat(trackIndex))
+ ", supported="
- + formatSupport);
+ + formatSupport
+ + hardwareAccelerationSupport
+ + decoderSupport);
}
logd(" ]");
}
@@ -319,7 +334,7 @@ public class EventLogger implements AnalyticsListener {
TrackGroup trackGroup = unassociatedTrackGroups.get(groupIndex);
for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
String status = getTrackStatusString(false);
- String formatSupport = Util.getFormatSupportString(C.FORMAT_UNSUPPORTED_TYPE);
+ String formatSupport = getFormatSupportString(C.FORMAT_UNSUPPORTED_TYPE);
logd(
" "
+ status
diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/MediaCodecVideoRenderer.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/MediaCodecVideoRenderer.java
index 74de91fcfa..c6aca51a92 100644
--- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/MediaCodecVideoRenderer.java
+++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/MediaCodecVideoRenderer.java
@@ -377,6 +377,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
// format's MIME type, according to the MediaCodecSelector.
MediaCodecInfo decoderInfo = decoderInfos.get(0);
boolean isFormatSupported = decoderInfo.isFormatSupported(format);
+ boolean isPreferredDecoder = true;
if (!isFormatSupported) {
// Check whether any of the other decoders support the format.
for (int i = 1; i < decoderInfos.size(); i++) {
@@ -384,15 +385,26 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
if (otherDecoderInfo.isFormatSupported(format)) {
decoderInfo = otherDecoderInfo;
isFormatSupported = true;
+ isPreferredDecoder = false;
break;
}
}
}
+ @C.FormatSupport
+ int formatSupport = isFormatSupported ? C.FORMAT_HANDLED : C.FORMAT_EXCEEDS_CAPABILITIES;
@AdaptiveSupport
int adaptiveSupport =
decoderInfo.isSeamlessAdaptationSupported(format)
? ADAPTIVE_SEAMLESS
: ADAPTIVE_NOT_SEAMLESS;
+ @HardwareAccelerationSupport
+ int hardwareAccelerationSupport =
+ decoderInfo.hardwareAccelerated
+ ? HARDWARE_ACCELERATION_SUPPORTED
+ : HARDWARE_ACCELERATION_NOT_SUPPORTED;
+ @DecoderSupport
+ int decoderSupport = isPreferredDecoder ? DECODER_SUPPORT_PRIMARY : DECODER_SUPPORT_FALLBACK;
+
@TunnelingSupport int tunnelingSupport = TUNNELING_NOT_SUPPORTED;
if (isFormatSupported) {
List