Commit 48555550 by kimvde Committed by Oliver Woodman

Surface MediaCodecInfo methods added in Android Q

- Surface information provided by methods isHardwareAccelerated,
  isSoftwareOnly and isVendor added in Android Q in MediaCodecInfo
  class.
- Estimate this information based on the codec name for earlier API
  levels.

Issue:#5839
PiperOrigin-RevId: 266334850
parent f5c1e8b5
...@@ -2,6 +2,9 @@ ...@@ -2,6 +2,9 @@
### dev-v2 (not yet released) ### ### dev-v2 (not yet released) ###
* Surface information provided by methods `isHardwareAccelerated`,
`isSoftwareOnly` and `isVendor` added in Android Q in `MediaCodecInfo` class
([#5839](https://github.com/google/ExoPlayer/issues/5839)).
* Update `DefaultTrackSelector` to apply a viewport constraint for the default * Update `DefaultTrackSelector` to apply a viewport constraint for the default
display by default. display by default.
* Add `PlaybackStatsListener` to collect `PlaybackStats` for playbacks analysis * Add `PlaybackStatsListener` to collect `PlaybackStats` for playbacks analysis
......
...@@ -93,6 +93,33 @@ public final class MediaCodecInfo { ...@@ -93,6 +93,33 @@ public final class MediaCodecInfo {
/** Whether this instance describes a passthrough codec. */ /** Whether this instance describes a passthrough codec. */
public final boolean passthrough; public final boolean passthrough;
/**
* Whether the codec is hardware accelerated.
*
* <p>This could be an approximation as the exact information is only provided in API levels 29+.
*
* @see android.media.MediaCodecInfo#isHardwareAccelerated()
*/
public final boolean hardwareAccelerated;
/**
* Whether the codec is software only.
*
* <p>This could be an approximation as the exact information is only provided in API levels 29+.
*
* @see android.media.MediaCodecInfo#isSoftwareOnly()
*/
public final boolean softwareOnly;
/**
* Whether the codec is from the vendor.
*
* <p>This could be an approximation as the exact information is only provided in API levels 29+.
*
* @see android.media.MediaCodecInfo#isVendor()
*/
public final boolean vendor;
private final boolean isVideo; private final boolean isVideo;
/** /**
...@@ -108,6 +135,9 @@ public final class MediaCodecInfo { ...@@ -108,6 +135,9 @@ public final class MediaCodecInfo {
/* codecMimeType= */ null, /* codecMimeType= */ null,
/* capabilities= */ null, /* capabilities= */ null,
/* passthrough= */ true, /* passthrough= */ true,
/* hardwareAccelerated= */ false,
/* softwareOnly= */ true,
/* vendor= */ false,
/* forceDisableAdaptive= */ false, /* forceDisableAdaptive= */ false,
/* forceSecure= */ false); /* forceSecure= */ false);
} }
...@@ -121,6 +151,9 @@ public final class MediaCodecInfo { ...@@ -121,6 +151,9 @@ public final class MediaCodecInfo {
* Equal to {@code mimeType} unless the codec is known to use a non-standard MIME type alias. * Equal to {@code mimeType} unless the codec is known to use a non-standard MIME type alias.
* @param capabilities The capabilities of the {@link MediaCodec} for the specified mime type, or * @param capabilities The capabilities of the {@link MediaCodec} for the specified mime type, or
* {@code null} if not known. * {@code null} if not known.
* @param hardwareAccelerated Whether the {@link MediaCodec} is hardware accelerated.
* @param softwareOnly Whether the {@link MediaCodec} is software only.
* @param vendor Whether the {@link MediaCodec} is provided by the vendor.
* @param forceDisableAdaptive Whether {@link #adaptive} should be forced to {@code false}. * @param forceDisableAdaptive Whether {@link #adaptive} should be forced to {@code false}.
* @param forceSecure Whether {@link #secure} should be forced to {@code true}. * @param forceSecure Whether {@link #secure} should be forced to {@code true}.
* @return The created instance. * @return The created instance.
...@@ -130,6 +163,9 @@ public final class MediaCodecInfo { ...@@ -130,6 +163,9 @@ public final class MediaCodecInfo {
String mimeType, String mimeType,
String codecMimeType, String codecMimeType,
@Nullable CodecCapabilities capabilities, @Nullable CodecCapabilities capabilities,
boolean hardwareAccelerated,
boolean softwareOnly,
boolean vendor,
boolean forceDisableAdaptive, boolean forceDisableAdaptive,
boolean forceSecure) { boolean forceSecure) {
return new MediaCodecInfo( return new MediaCodecInfo(
...@@ -138,6 +174,9 @@ public final class MediaCodecInfo { ...@@ -138,6 +174,9 @@ public final class MediaCodecInfo {
codecMimeType, codecMimeType,
capabilities, capabilities,
/* passthrough= */ false, /* passthrough= */ false,
hardwareAccelerated,
softwareOnly,
vendor,
forceDisableAdaptive, forceDisableAdaptive,
forceSecure); forceSecure);
} }
...@@ -148,6 +187,9 @@ public final class MediaCodecInfo { ...@@ -148,6 +187,9 @@ public final class MediaCodecInfo {
@Nullable String codecMimeType, @Nullable String codecMimeType,
@Nullable CodecCapabilities capabilities, @Nullable CodecCapabilities capabilities,
boolean passthrough, boolean passthrough,
boolean hardwareAccelerated,
boolean softwareOnly,
boolean vendor,
boolean forceDisableAdaptive, boolean forceDisableAdaptive,
boolean forceSecure) { boolean forceSecure) {
this.name = Assertions.checkNotNull(name); this.name = Assertions.checkNotNull(name);
...@@ -155,6 +197,9 @@ public final class MediaCodecInfo { ...@@ -155,6 +197,9 @@ public final class MediaCodecInfo {
this.codecMimeType = codecMimeType; this.codecMimeType = codecMimeType;
this.capabilities = capabilities; this.capabilities = capabilities;
this.passthrough = passthrough; this.passthrough = passthrough;
this.hardwareAccelerated = hardwareAccelerated;
this.softwareOnly = softwareOnly;
this.vendor = vendor;
adaptive = !forceDisableAdaptive && capabilities != null && isAdaptive(capabilities); adaptive = !forceDisableAdaptive && capabilities != null && isAdaptive(capabilities);
tunneling = capabilities != null && isTunneling(capabilities); tunneling = capabilities != null && isTunneling(capabilities);
secure = forceSecure || (capabilities != null && isSecure(capabilities)); secure = forceSecure || (capabilities != null && isSecure(capabilities));
......
...@@ -312,6 +312,9 @@ public final class MediaCodecUtil { ...@@ -312,6 +312,9 @@ public final class MediaCodecUtil {
if ((!key.secure && secureRequired) || (key.secure && !secureSupported)) { if ((!key.secure && secureRequired) || (key.secure && !secureSupported)) {
continue; continue;
} }
boolean hardwareAccelerated = isHardwareAccelerated(codecInfo);
boolean softwareOnly = isSoftwareOnly(codecInfo);
boolean vendor = isVendor(codecInfo);
boolean forceDisableAdaptive = codecNeedsDisableAdaptationWorkaround(name); boolean forceDisableAdaptive = codecNeedsDisableAdaptationWorkaround(name);
if ((secureDecodersExplicit && key.secure == secureSupported) if ((secureDecodersExplicit && key.secure == secureSupported)
|| (!secureDecodersExplicit && !key.secure)) { || (!secureDecodersExplicit && !key.secure)) {
...@@ -321,6 +324,9 @@ public final class MediaCodecUtil { ...@@ -321,6 +324,9 @@ public final class MediaCodecUtil {
mimeType, mimeType,
codecMimeType, codecMimeType,
capabilities, capabilities,
hardwareAccelerated,
softwareOnly,
vendor,
forceDisableAdaptive, forceDisableAdaptive,
/* forceSecure= */ false)); /* forceSecure= */ false));
} else if (!secureDecodersExplicit && secureSupported) { } else if (!secureDecodersExplicit && secureSupported) {
...@@ -330,6 +336,9 @@ public final class MediaCodecUtil { ...@@ -330,6 +336,9 @@ public final class MediaCodecUtil {
mimeType, mimeType,
codecMimeType, codecMimeType,
capabilities, capabilities,
hardwareAccelerated,
softwareOnly,
vendor,
forceDisableAdaptive, forceDisableAdaptive,
/* forceSecure= */ true)); /* forceSecure= */ true));
// It only makes sense to have one synthesized secure decoder, return immediately. // It only makes sense to have one synthesized secure decoder, return immediately.
...@@ -532,6 +541,9 @@ public final class MediaCodecUtil { ...@@ -532,6 +541,9 @@ public final class MediaCodecUtil {
/* mimeType= */ MimeTypes.AUDIO_RAW, /* mimeType= */ MimeTypes.AUDIO_RAW,
/* codecMimeType= */ MimeTypes.AUDIO_RAW, /* codecMimeType= */ MimeTypes.AUDIO_RAW,
/* capabilities= */ null, /* capabilities= */ null,
/* hardwareAccelerated= */ false,
/* softwareOnly= */ true,
/* vendor= */ false,
/* forceDisableAdaptive= */ false, /* forceDisableAdaptive= */ false,
/* forceSecure= */ false)); /* forceSecure= */ false));
} }
...@@ -566,6 +578,69 @@ public final class MediaCodecUtil { ...@@ -566,6 +578,69 @@ public final class MediaCodecUtil {
} }
/** /**
* The result of {@link android.media.MediaCodecInfo#isHardwareAccelerated()} for API levels 29+,
* or a best-effort approximation for lower levels.
*/
private static boolean isHardwareAccelerated(android.media.MediaCodecInfo codecInfo) {
if (Util.SDK_INT >= 29) {
return isHardwareAcceleratedV29(codecInfo);
}
// codecInfo.isHardwareAccelerated() != codecInfo.isSoftwareOnly() is not necessarily true.
// However, we assume this to be true as an approximation.
return !isSoftwareOnly(codecInfo);
}
@TargetApi(29)
private static boolean isHardwareAcceleratedV29(android.media.MediaCodecInfo codecInfo) {
return codecInfo.isHardwareAccelerated();
}
/**
* The result of {@link android.media.MediaCodecInfo#isSoftwareOnly()} for API levels 29+, or a
* best-effort approximation for lower levels.
*/
private static boolean isSoftwareOnly(android.media.MediaCodecInfo codecInfo) {
if (Util.SDK_INT >= 29) {
return isSoftwareOnlyV29(codecInfo);
}
String codecName = codecInfo.getName().toLowerCase();
if (codecName.startsWith("arc.")) { // App Runtime for Chrome (ARC) codecs
return false;
}
return codecName.startsWith("omx.google.")
|| codecName.startsWith("omx.ffmpeg.")
|| (codecName.startsWith("omx.sec.") && codecName.contains(".sw."))
|| codecName.equals("omx.qcom.video.decoder.hevcswvdec")
|| codecName.startsWith("c2.android.")
|| codecName.startsWith("c2.google.")
|| (!codecName.startsWith("omx.") && !codecName.startsWith("c2."));
}
@TargetApi(29)
private static boolean isSoftwareOnlyV29(android.media.MediaCodecInfo codecInfo) {
return codecInfo.isSoftwareOnly();
}
/**
* The result of {@link android.media.MediaCodecInfo#isVendor()} for API levels 29+, or a
* best-effort approximation for lower levels.
*/
private static boolean isVendor(android.media.MediaCodecInfo codecInfo) {
if (Util.SDK_INT >= 29) {
return isVendorV29(codecInfo);
}
String codecName = codecInfo.getName().toLowerCase();
return !codecName.startsWith("omx.google.")
&& !codecName.startsWith("c2.android.")
&& !codecName.startsWith("c2.google.");
}
@TargetApi(29)
private static boolean isVendorV29(android.media.MediaCodecInfo codecInfo) {
return codecInfo.isVendor();
}
/**
* Returns whether the decoder is known to fail when adapting, despite advertising itself as an * Returns whether the decoder is known to fail when adapting, despite advertising itself as an
* adaptive decoder. * adaptive decoder.
* *
......
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