mirror of
https://github.com/androidx/media.git
synced 2025-05-04 06:00:37 +08:00
Fix MediaCodecUtil nullability annotations
PiperOrigin-RevId: 277462799
This commit is contained in:
parent
d3933e5cac
commit
aeefb79a86
@ -350,7 +350,12 @@ 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 {
|
||||||
if (allowPassthrough(format.channelCount, format.sampleMimeType)) {
|
@Nullable String mimeType = format.sampleMimeType;
|
||||||
|
if (mimeType == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
if (allowPassthrough(format.channelCount, mimeType)) {
|
||||||
|
@Nullable
|
||||||
MediaCodecInfo passthroughDecoderInfo = mediaCodecSelector.getPassthroughDecoderInfo();
|
MediaCodecInfo passthroughDecoderInfo = mediaCodecSelector.getPassthroughDecoderInfo();
|
||||||
if (passthroughDecoderInfo != null) {
|
if (passthroughDecoderInfo != null) {
|
||||||
return Collections.singletonList(passthroughDecoderInfo);
|
return Collections.singletonList(passthroughDecoderInfo);
|
||||||
@ -358,9 +363,9 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
|||||||
}
|
}
|
||||||
List<MediaCodecInfo> decoderInfos =
|
List<MediaCodecInfo> decoderInfos =
|
||||||
mediaCodecSelector.getDecoderInfos(
|
mediaCodecSelector.getDecoderInfos(
|
||||||
format.sampleMimeType, requiresSecureDecoder, /* requiresTunnelingDecoder= */ false);
|
mimeType, requiresSecureDecoder, /* requiresTunnelingDecoder= */ false);
|
||||||
decoderInfos = MediaCodecUtil.getDecoderInfosSortedByFormatSupport(decoderInfos, format);
|
decoderInfos = MediaCodecUtil.getDecoderInfosSortedByFormatSupport(decoderInfos, format);
|
||||||
if (MimeTypes.AUDIO_E_AC3_JOC.equals(format.sampleMimeType)) {
|
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);
|
||||||
decoderInfosWithEac3.addAll(
|
decoderInfosWithEac3.addAll(
|
||||||
|
@ -38,6 +38,7 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
import org.checkerframework.checker.nullness.qual.EnsuresNonNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A utility class for querying the available codecs.
|
* A utility class for querying the available codecs.
|
||||||
@ -122,6 +123,7 @@ public final class MediaCodecUtil {
|
|||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public static MediaCodecInfo getPassthroughDecoderInfo() throws DecoderQueryException {
|
public static MediaCodecInfo getPassthroughDecoderInfo() throws DecoderQueryException {
|
||||||
|
@Nullable
|
||||||
MediaCodecInfo decoderInfo =
|
MediaCodecInfo decoderInfo =
|
||||||
getDecoderInfo(MimeTypes.AUDIO_RAW, /* secure= */ false, /* tunneling= */ false);
|
getDecoderInfo(MimeTypes.AUDIO_RAW, /* secure= */ false, /* tunneling= */ false);
|
||||||
return decoderInfo == null ? null : MediaCodecInfo.newPassthroughInstance(decoderInfo.name);
|
return decoderInfo == null ? null : MediaCodecInfo.newPassthroughInstance(decoderInfo.name);
|
||||||
@ -161,7 +163,7 @@ public final class MediaCodecUtil {
|
|||||||
public static synchronized List<MediaCodecInfo> getDecoderInfos(
|
public static synchronized List<MediaCodecInfo> getDecoderInfos(
|
||||||
String mimeType, boolean secure, boolean tunneling) throws DecoderQueryException {
|
String mimeType, boolean secure, boolean tunneling) throws DecoderQueryException {
|
||||||
CodecKey key = new CodecKey(mimeType, secure, tunneling);
|
CodecKey key = new CodecKey(mimeType, secure, tunneling);
|
||||||
List<MediaCodecInfo> cachedDecoderInfos = decoderInfosCache.get(key);
|
@Nullable List<MediaCodecInfo> cachedDecoderInfos = decoderInfosCache.get(key);
|
||||||
if (cachedDecoderInfos != null) {
|
if (cachedDecoderInfos != null) {
|
||||||
return cachedDecoderInfos;
|
return cachedDecoderInfos;
|
||||||
}
|
}
|
||||||
@ -214,6 +216,7 @@ public final class MediaCodecUtil {
|
|||||||
public static int maxH264DecodableFrameSize() throws DecoderQueryException {
|
public static int maxH264DecodableFrameSize() throws DecoderQueryException {
|
||||||
if (maxH264DecodableFrameSize == -1) {
|
if (maxH264DecodableFrameSize == -1) {
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
@Nullable
|
||||||
MediaCodecInfo decoderInfo =
|
MediaCodecInfo decoderInfo =
|
||||||
getDecoderInfo(MimeTypes.VIDEO_H264, /* secure= */ false, /* tunneling= */ false);
|
getDecoderInfo(MimeTypes.VIDEO_H264, /* secure= */ false, /* tunneling= */ false);
|
||||||
if (decoderInfo != null) {
|
if (decoderInfo != null) {
|
||||||
@ -287,6 +290,7 @@ public final class MediaCodecUtil {
|
|||||||
for (int i = 0; i < numberOfCodecs; i++) {
|
for (int i = 0; i < numberOfCodecs; i++) {
|
||||||
android.media.MediaCodecInfo codecInfo = mediaCodecList.getCodecInfoAt(i);
|
android.media.MediaCodecInfo codecInfo = mediaCodecList.getCodecInfoAt(i);
|
||||||
String name = codecInfo.getName();
|
String name = codecInfo.getName();
|
||||||
|
@Nullable
|
||||||
String codecMimeType = getCodecMimeType(codecInfo, name, secureDecodersExplicit, mimeType);
|
String codecMimeType = getCodecMimeType(codecInfo, name, secureDecodersExplicit, mimeType);
|
||||||
if (codecMimeType == null) {
|
if (codecMimeType == null) {
|
||||||
continue;
|
continue;
|
||||||
@ -652,6 +656,7 @@ public final class MediaCodecUtil {
|
|||||||
&& ("OMX.Exynos.AVC.Decoder".equals(name) || "OMX.Exynos.AVC.Decoder.secure".equals(name));
|
&& ("OMX.Exynos.AVC.Decoder".equals(name) || "OMX.Exynos.AVC.Decoder.secure".equals(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
private static Pair<Integer, Integer> getDolbyVisionProfileAndLevel(
|
private static Pair<Integer, Integer> getDolbyVisionProfileAndLevel(
|
||||||
String codec, String[] parts) {
|
String codec, String[] parts) {
|
||||||
if (parts.length < 3) {
|
if (parts.length < 3) {
|
||||||
@ -665,14 +670,14 @@ public final class MediaCodecUtil {
|
|||||||
Log.w(TAG, "Ignoring malformed Dolby Vision codec string: " + codec);
|
Log.w(TAG, "Ignoring malformed Dolby Vision codec string: " + codec);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
String profileString = matcher.group(1);
|
@Nullable String profileString = matcher.group(1);
|
||||||
Integer profile = DOLBY_VISION_STRING_TO_PROFILE.get(profileString);
|
@Nullable Integer profile = DOLBY_VISION_STRING_TO_PROFILE.get(profileString);
|
||||||
if (profile == null) {
|
if (profile == null) {
|
||||||
Log.w(TAG, "Unknown Dolby Vision profile string: " + profileString);
|
Log.w(TAG, "Unknown Dolby Vision profile string: " + profileString);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
String levelString = parts[2];
|
String levelString = parts[2];
|
||||||
Integer level = DOLBY_VISION_STRING_TO_LEVEL.get(levelString);
|
@Nullable Integer level = DOLBY_VISION_STRING_TO_LEVEL.get(levelString);
|
||||||
if (level == null) {
|
if (level == null) {
|
||||||
Log.w(TAG, "Unknown Dolby Vision level string: " + levelString);
|
Log.w(TAG, "Unknown Dolby Vision level string: " + levelString);
|
||||||
return null;
|
return null;
|
||||||
@ -680,6 +685,7 @@ public final class MediaCodecUtil {
|
|||||||
return new Pair<>(profile, level);
|
return new Pair<>(profile, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
private static Pair<Integer, Integer> getHevcProfileAndLevel(String codec, String[] parts) {
|
private static Pair<Integer, Integer> getHevcProfileAndLevel(String codec, String[] parts) {
|
||||||
if (parts.length < 4) {
|
if (parts.length < 4) {
|
||||||
// The codec has fewer parts than required by the HEVC codec string format.
|
// The codec has fewer parts than required by the HEVC codec string format.
|
||||||
@ -692,7 +698,7 @@ public final class MediaCodecUtil {
|
|||||||
Log.w(TAG, "Ignoring malformed HEVC codec string: " + codec);
|
Log.w(TAG, "Ignoring malformed HEVC codec string: " + codec);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
String profileString = matcher.group(1);
|
@Nullable String profileString = matcher.group(1);
|
||||||
int profile;
|
int profile;
|
||||||
if ("1".equals(profileString)) {
|
if ("1".equals(profileString)) {
|
||||||
profile = CodecProfileLevel.HEVCProfileMain;
|
profile = CodecProfileLevel.HEVCProfileMain;
|
||||||
@ -702,8 +708,8 @@ public final class MediaCodecUtil {
|
|||||||
Log.w(TAG, "Unknown HEVC profile string: " + profileString);
|
Log.w(TAG, "Unknown HEVC profile string: " + profileString);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
String levelString = parts[3];
|
@Nullable String levelString = parts[3];
|
||||||
Integer level = HEVC_CODEC_STRING_TO_PROFILE_LEVEL.get(levelString);
|
@Nullable Integer level = HEVC_CODEC_STRING_TO_PROFILE_LEVEL.get(levelString);
|
||||||
if (level == null) {
|
if (level == null) {
|
||||||
Log.w(TAG, "Unknown HEVC level string: " + levelString);
|
Log.w(TAG, "Unknown HEVC level string: " + levelString);
|
||||||
return null;
|
return null;
|
||||||
@ -711,6 +717,7 @@ public final class MediaCodecUtil {
|
|||||||
return new Pair<>(profile, level);
|
return new Pair<>(profile, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
private static Pair<Integer, Integer> getAvcProfileAndLevel(String codec, String[] parts) {
|
private static Pair<Integer, Integer> getAvcProfileAndLevel(String codec, String[] parts) {
|
||||||
if (parts.length < 2) {
|
if (parts.length < 2) {
|
||||||
// The codec has fewer parts than required by the AVC codec string format.
|
// The codec has fewer parts than required by the AVC codec string format.
|
||||||
@ -751,6 +758,7 @@ public final class MediaCodecUtil {
|
|||||||
return new Pair<>(profile, level);
|
return new Pair<>(profile, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
private static Pair<Integer, Integer> getVp9ProfileAndLevel(String codec, String[] parts) {
|
private static Pair<Integer, Integer> getVp9ProfileAndLevel(String codec, String[] parts) {
|
||||||
if (parts.length < 3) {
|
if (parts.length < 3) {
|
||||||
Log.w(TAG, "Ignoring malformed VP9 codec string: " + codec);
|
Log.w(TAG, "Ignoring malformed VP9 codec string: " + codec);
|
||||||
@ -779,6 +787,7 @@ public final class MediaCodecUtil {
|
|||||||
return new Pair<>(profile, level);
|
return new Pair<>(profile, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
private static Pair<Integer, Integer> getAv1ProfileAndLevel(
|
private static Pair<Integer, Integer> getAv1ProfileAndLevel(
|
||||||
String codec, String[] parts, @Nullable ColorInfo colorInfo) {
|
String codec, String[] parts, @Nullable ColorInfo colorInfo) {
|
||||||
if (parts.length < 4) {
|
if (parts.length < 4) {
|
||||||
@ -874,7 +883,7 @@ public final class MediaCodecUtil {
|
|||||||
try {
|
try {
|
||||||
// Get the object type indication, which is a hexadecimal value (see RFC 6381/ISO 14496-1).
|
// Get the object type indication, which is a hexadecimal value (see RFC 6381/ISO 14496-1).
|
||||||
int objectTypeIndication = Integer.parseInt(parts[1], 16);
|
int objectTypeIndication = Integer.parseInt(parts[1], 16);
|
||||||
String mimeType = MimeTypes.getMimeTypeFromMp4ObjectType(objectTypeIndication);
|
@Nullable String mimeType = MimeTypes.getMimeTypeFromMp4ObjectType(objectTypeIndication);
|
||||||
if (MimeTypes.AUDIO_AAC.equals(mimeType)) {
|
if (MimeTypes.AUDIO_AAC.equals(mimeType)) {
|
||||||
// For MPEG-4 audio this is followed by an audio object type indication as a decimal number.
|
// For MPEG-4 audio this is followed by an audio object type indication as a decimal number.
|
||||||
int audioObjectTypeIndication = Integer.parseInt(parts[2]);
|
int audioObjectTypeIndication = Integer.parseInt(parts[2]);
|
||||||
@ -932,7 +941,7 @@ public final class MediaCodecUtil {
|
|||||||
|
|
||||||
private final int codecKind;
|
private final int codecKind;
|
||||||
|
|
||||||
private android.media.MediaCodecInfo[] mediaCodecInfos;
|
@Nullable private android.media.MediaCodecInfo[] mediaCodecInfos;
|
||||||
|
|
||||||
public MediaCodecListCompatV21(boolean includeSecure, boolean includeTunneling) {
|
public MediaCodecListCompatV21(boolean includeSecure, boolean includeTunneling) {
|
||||||
codecKind =
|
codecKind =
|
||||||
@ -970,6 +979,7 @@ public final class MediaCodecUtil {
|
|||||||
return capabilities.isFeatureRequired(feature);
|
return capabilities.isFeatureRequired(feature);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@EnsuresNonNull({"mediaCodecInfos"})
|
||||||
private void ensureMediaCodecInfosInitialized() {
|
private void ensureMediaCodecInfosInitialized() {
|
||||||
if (mediaCodecInfos == null) {
|
if (mediaCodecInfos == null) {
|
||||||
mediaCodecInfos = new MediaCodecList(codecKind).getCodecInfos();
|
mediaCodecInfos = new MediaCodecList(codecKind).getCodecInfos();
|
||||||
@ -1028,7 +1038,7 @@ public final class MediaCodecUtil {
|
|||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
final int prime = 31;
|
final int prime = 31;
|
||||||
int result = 1;
|
int result = 1;
|
||||||
result = prime * result + ((mimeType == null) ? 0 : mimeType.hashCode());
|
result = prime * result + mimeType.hashCode();
|
||||||
result = prime * result + (secure ? 1231 : 1237);
|
result = prime * result + (secure ? 1231 : 1237);
|
||||||
result = prime * result + (tunneling ? 1231 : 1237);
|
result = prime * result + (tunneling ? 1231 : 1237);
|
||||||
return result;
|
return result;
|
||||||
|
@ -389,11 +389,15 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
|||||||
boolean requiresSecureDecoder,
|
boolean requiresSecureDecoder,
|
||||||
boolean requiresTunnelingDecoder)
|
boolean requiresTunnelingDecoder)
|
||||||
throws DecoderQueryException {
|
throws DecoderQueryException {
|
||||||
|
@Nullable String mimeType = format.sampleMimeType;
|
||||||
|
if (mimeType == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
List<MediaCodecInfo> decoderInfos =
|
List<MediaCodecInfo> decoderInfos =
|
||||||
mediaCodecSelector.getDecoderInfos(
|
mediaCodecSelector.getDecoderInfos(
|
||||||
format.sampleMimeType, requiresSecureDecoder, requiresTunnelingDecoder);
|
mimeType, requiresSecureDecoder, requiresTunnelingDecoder);
|
||||||
decoderInfos = MediaCodecUtil.getDecoderInfosSortedByFormatSupport(decoderInfos, format);
|
decoderInfos = MediaCodecUtil.getDecoderInfosSortedByFormatSupport(decoderInfos, format);
|
||||||
if (MimeTypes.VIDEO_DOLBY_VISION.equals(format.sampleMimeType)) {
|
if (MimeTypes.VIDEO_DOLBY_VISION.equals(mimeType)) {
|
||||||
// Fall back to H.264/AVC or H.265/HEVC for the relevant DV profiles.
|
// Fall back to H.264/AVC or H.265/HEVC for the relevant DV profiles.
|
||||||
@Nullable
|
@Nullable
|
||||||
Pair<Integer, Integer> codecProfileAndLevel = MediaCodecUtil.getCodecProfileAndLevel(format);
|
Pair<Integer, Integer> codecProfileAndLevel = MediaCodecUtil.getCodecProfileAndLevel(format);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user