use of androidx.annotation.Nullable in project ExoPlayer by google.
the class BaseMediaSource method prepareSource.
@Override
public final void prepareSource(MediaSourceCaller caller, @Nullable TransferListener mediaTransferListener, PlayerId playerId) {
Looper looper = Looper.myLooper();
Assertions.checkArgument(this.looper == null || this.looper == looper);
this.playerId = playerId;
@Nullable Timeline timeline = this.timeline;
mediaSourceCallers.add(caller);
if (this.looper == null) {
this.looper = looper;
enabledMediaSourceCallers.add(caller);
prepareSourceInternal(mediaTransferListener);
} else if (timeline != null) {
enable(caller);
caller.onSourceInfoRefreshed(/* source= */
this, timeline);
}
}
use of androidx.annotation.Nullable in project ExoPlayer by google.
the class MediaCodecRenderer method drmNeedsCodecReinitialization.
/**
* Returns whether it's necessary to re-initialize the codec to handle a DRM change. If {@code
* false} is returned then either {@code oldSession == newSession} (i.e., there was no change), or
* it's possible to update the existing codec using MediaCrypto.setMediaDrmSession.
*/
private boolean drmNeedsCodecReinitialization(MediaCodecInfo codecInfo, Format newFormat, @Nullable DrmSession oldSession, @Nullable DrmSession newSession) throws ExoPlaybackException {
if (oldSession == newSession) {
// No need to re-initialize if the old and new sessions are the same.
return false;
}
if (newSession == null || oldSession == null) {
// Changing from DRM to no DRM and vice-versa always requires re-initialization.
return true;
}
if (Util.SDK_INT < 23) {
// required to switch to newSession on older API levels.
return true;
}
if (C.PLAYREADY_UUID.equals(oldSession.getSchemeUuid()) || C.PLAYREADY_UUID.equals(newSession.getSchemeUuid())) {
// TODO: Add an API check once [Internal ref: b/128835874] is fixed.
return true;
}
@Nullable FrameworkCryptoConfig newCryptoConfig = getFrameworkCryptoConfig(newSession);
if (newCryptoConfig == null) {
// the case is to occur, so we re-initialize in this case.
return true;
}
boolean requiresSecureDecoder;
if (newCryptoConfig.forceAllowInsecureDecoderComponents) {
requiresSecureDecoder = false;
} else {
requiresSecureDecoder = newSession.requiresSecureDecoder(newFormat.sampleMimeType);
}
if (!codecInfo.secure && requiresSecureDecoder) {
// output path.
return true;
}
return false;
}
use of androidx.annotation.Nullable in project ExoPlayer by google.
the class MediaCodecUtil method getAv1ProfileAndLevel.
@Nullable
private static Pair<Integer, Integer> getAv1ProfileAndLevel(String codec, String[] parts, @Nullable ColorInfo colorInfo) {
if (parts.length < 4) {
Log.w(TAG, "Ignoring malformed AV1 codec string: " + codec);
return null;
}
int profileInteger;
int levelInteger;
int bitDepthInteger;
try {
profileInteger = Integer.parseInt(parts[1]);
levelInteger = Integer.parseInt(parts[2].substring(0, 2));
bitDepthInteger = Integer.parseInt(parts[3]);
} catch (NumberFormatException e) {
Log.w(TAG, "Ignoring malformed AV1 codec string: " + codec);
return null;
}
if (profileInteger != 0) {
Log.w(TAG, "Unknown AV1 profile: " + profileInteger);
return null;
}
if (bitDepthInteger != 8 && bitDepthInteger != 10) {
Log.w(TAG, "Unknown AV1 bit depth: " + bitDepthInteger);
return null;
}
int profile;
if (bitDepthInteger == 8) {
profile = CodecProfileLevel.AV1ProfileMain8;
} else if (colorInfo != null && (colorInfo.hdrStaticInfo != null || colorInfo.colorTransfer == C.COLOR_TRANSFER_HLG || colorInfo.colorTransfer == C.COLOR_TRANSFER_ST2084)) {
profile = CodecProfileLevel.AV1ProfileMain10HDR10;
} else {
profile = CodecProfileLevel.AV1ProfileMain10;
}
int level = av1LevelNumberToConst(levelInteger);
if (level == -1) {
Log.w(TAG, "Unknown AV1 level: " + levelInteger);
return null;
}
return new Pair<>(profile, level);
}
use of androidx.annotation.Nullable in project ExoPlayer by google.
the class MediaCodecUtil method maxH264DecodableFrameSize.
/**
* Returns the maximum frame size supported by the default H264 decoder.
*
* @return The maximum frame size for an H264 stream that can be decoded on the device.
*/
public static int maxH264DecodableFrameSize() throws DecoderQueryException {
if (maxH264DecodableFrameSize == -1) {
int result = 0;
@Nullable MediaCodecInfo decoderInfo = getDecoderInfo(MimeTypes.VIDEO_H264, /* secure= */
false, /* tunneling= */
false);
if (decoderInfo != null) {
for (CodecProfileLevel profileLevel : decoderInfo.getProfileLevels()) {
result = max(avcLevelToMaxFrameSize(profileLevel.level), result);
}
// We assume support for at least 480p (SDK_INT >= 21) or 360p (SDK_INT < 21), which are
// the levels mandated by the Android CDD.
result = max(result, Util.SDK_INT >= 21 ? (720 * 480) : (480 * 360));
}
maxH264DecodableFrameSize = result;
}
return maxH264DecodableFrameSize;
}
use of androidx.annotation.Nullable in project ExoPlayer by google.
the class MediaCodecUtil method getDecoderInfosInternal.
// Internal methods.
/**
* Returns {@link MediaCodecInfo}s for the given codec {@link CodecKey} in the order given by
* {@code mediaCodecList}.
*
* @param key The codec key.
* @param mediaCodecList The codec list.
* @return The codec information for usable codecs matching the specified key.
* @throws DecoderQueryException If there was an error querying the available decoders.
*/
private static ArrayList<MediaCodecInfo> getDecoderInfosInternal(CodecKey key, MediaCodecListCompat mediaCodecList) throws DecoderQueryException {
try {
ArrayList<MediaCodecInfo> decoderInfos = new ArrayList<>();
String mimeType = key.mimeType;
int numberOfCodecs = mediaCodecList.getCodecCount();
boolean secureDecodersExplicit = mediaCodecList.secureDecodersExplicit();
// Note: MediaCodecList is sorted by the framework such that the best decoders come first.
for (int i = 0; i < numberOfCodecs; i++) {
android.media.MediaCodecInfo codecInfo = mediaCodecList.getCodecInfoAt(i);
if (isAlias(codecInfo)) {
// names.
continue;
}
String name = codecInfo.getName();
if (!isCodecUsableDecoder(codecInfo, name, secureDecodersExplicit, mimeType)) {
continue;
}
@Nullable String codecMimeType = getCodecMimeType(codecInfo, name, mimeType);
if (codecMimeType == null) {
continue;
}
try {
CodecCapabilities capabilities = codecInfo.getCapabilitiesForType(codecMimeType);
boolean tunnelingSupported = mediaCodecList.isFeatureSupported(CodecCapabilities.FEATURE_TunneledPlayback, codecMimeType, capabilities);
boolean tunnelingRequired = mediaCodecList.isFeatureRequired(CodecCapabilities.FEATURE_TunneledPlayback, codecMimeType, capabilities);
if ((!key.tunneling && tunnelingRequired) || (key.tunneling && !tunnelingSupported)) {
continue;
}
boolean secureSupported = mediaCodecList.isFeatureSupported(CodecCapabilities.FEATURE_SecurePlayback, codecMimeType, capabilities);
boolean secureRequired = mediaCodecList.isFeatureRequired(CodecCapabilities.FEATURE_SecurePlayback, codecMimeType, capabilities);
if ((!key.secure && secureRequired) || (key.secure && !secureSupported)) {
continue;
}
boolean hardwareAccelerated = isHardwareAccelerated(codecInfo, mimeType);
boolean softwareOnly = isSoftwareOnly(codecInfo, mimeType);
boolean vendor = isVendor(codecInfo);
if ((secureDecodersExplicit && key.secure == secureSupported) || (!secureDecodersExplicit && !key.secure)) {
decoderInfos.add(MediaCodecInfo.newInstance(name, mimeType, codecMimeType, capabilities, hardwareAccelerated, softwareOnly, vendor, /* forceDisableAdaptive= */
false, /* forceSecure= */
false));
} else if (!secureDecodersExplicit && secureSupported) {
decoderInfos.add(MediaCodecInfo.newInstance(name + ".secure", mimeType, codecMimeType, capabilities, hardwareAccelerated, softwareOnly, vendor, /* forceDisableAdaptive= */
false, /* forceSecure= */
true));
// It only makes sense to have one synthesized secure decoder, return immediately.
return decoderInfos;
}
} catch (Exception e) {
if (Util.SDK_INT <= 23 && !decoderInfos.isEmpty()) {
// Suppress error querying secondary codec capabilities up to API level 23.
Log.e(TAG, "Skipping codec " + name + " (failed to query capabilities)");
} else {
// Rethrow error querying primary codec capabilities, or secondary codec
// capabilities if API level is greater than 23.
Log.e(TAG, "Failed to query codec " + name + " (" + codecMimeType + ")");
throw e;
}
}
}
return decoderInfos;
} catch (Exception e) {
// or an IllegalArgumentException here.
throw new DecoderQueryException(e);
}
}
Aggregations