use of androidx.media3.exoplayer.mediacodec.MediaCodecInfo in project media by androidx.
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.media3.exoplayer.mediacodec.MediaCodecInfo in project media by androidx.
the class DashStreamingTest method decoderInfoH264.
// Decoder info.
@Test
public void decoderInfoH264() throws Exception {
MediaCodecInfo decoderInfo = MediaCodecUtil.getDecoderInfo(MimeTypes.VIDEO_H264, /* secure= */
false, /* tunneling= */
false);
assertThat(decoderInfo).isNotNull();
assertThat(Util.SDK_INT < 21 || decoderInfo.adaptive).isTrue();
}
use of androidx.media3.exoplayer.mediacodec.MediaCodecInfo in project media by androidx.
the class EnumerateDecodersTest method logDecoderInfos.
private void logDecoderInfos(String mimeType, boolean secure, boolean tunneling) throws DecoderQueryException {
List<MediaCodecInfo> mediaCodecInfos = MediaCodecUtil.getDecoderInfos(mimeType, secure, tunneling);
for (MediaCodecInfo mediaCodecInfo : mediaCodecInfos) {
CodecCapabilities capabilities = mediaCodecInfo.capabilities;
metricsLogger.logMetric("capabilities_" + mediaCodecInfo.name, codecCapabilitiesToString(mimeType, capabilities));
}
}
use of androidx.media3.exoplayer.mediacodec.MediaCodecInfo in project media by androidx.
the class DefaultCodecFactory method getVideoEncoderSupportedFormat.
@RequiresNonNull("#1.sampleMimeType")
private static Format getVideoEncoderSupportedFormat(Format requestedFormat, List<String> allowedMimeTypes) throws TransformationException {
String mimeType = requestedFormat.sampleMimeType;
Format.Builder formatBuilder = requestedFormat.buildUpon();
// TODO(b/210591626) Implement encoder filtering.
if (!allowedMimeTypes.contains(mimeType) || EncoderUtil.getSupportedEncoders(mimeType).isEmpty()) {
mimeType = allowedMimeTypes.contains(DEFAULT_FALLBACK_MIME_TYPE) ? DEFAULT_FALLBACK_MIME_TYPE : allowedMimeTypes.get(0);
if (EncoderUtil.getSupportedEncoders(mimeType).isEmpty()) {
throw createTransformationException(new IllegalArgumentException("No encoder is found for requested MIME type " + requestedFormat.sampleMimeType), requestedFormat, /* isVideo= */
true, /* isDecoder= */
false, /* mediaCodecName= */
null);
}
}
formatBuilder.setSampleMimeType(mimeType);
MediaCodecInfo encoderInfo = EncoderUtil.getSupportedEncoders(mimeType).get(0);
int width = requestedFormat.width;
int height = requestedFormat.height;
@Nullable Pair<Integer, Integer> encoderSupportedResolution = EncoderUtil.getClosestSupportedResolution(encoderInfo, mimeType, width, height);
if (encoderSupportedResolution == null) {
throw createTransformationException(new IllegalArgumentException("Cannot find fallback resolution for resolution " + width + " x " + height), requestedFormat, /* isVideo= */
true, /* isDecoder= */
false, /* mediaCodecName= */
null);
}
width = encoderSupportedResolution.first;
height = encoderSupportedResolution.second;
formatBuilder.setWidth(width).setHeight(height);
// The frameRate does not affect the resulting frame rate. It affects the encoder's rate control
// algorithm. Setting it too high may lead to video quality degradation.
float frameRate = requestedFormat.frameRate != Format.NO_VALUE ? requestedFormat.frameRate : DEFAULT_FRAME_RATE;
int bitrate = EncoderUtil.getClosestSupportedBitrate(encoderInfo, mimeType, /* bitrate= */
requestedFormat.averageBitrate != Format.NO_VALUE ? requestedFormat.averageBitrate : getSuggestedBitrate(width, height, frameRate));
formatBuilder.setFrameRate(frameRate).setAverageBitrate(bitrate);
@Nullable Pair<Integer, Integer> profileLevel = MediaCodecUtil.getCodecProfileAndLevel(requestedFormat);
if (profileLevel == null || // Transcoding to another MIME type.
!requestedFormat.sampleMimeType.equals(mimeType) || !EncoderUtil.isProfileLevelSupported(encoderInfo, mimeType, /* profile= */
profileLevel.first, /* level= */
profileLevel.second)) {
formatBuilder.setCodecs(null);
}
return formatBuilder.build();
}
use of androidx.media3.exoplayer.mediacodec.MediaCodecInfo in project media by androidx.
the class MediaCodecAudioRenderer method canReuseCodec.
@Override
protected DecoderReuseEvaluation canReuseCodec(MediaCodecInfo codecInfo, Format oldFormat, Format newFormat) {
DecoderReuseEvaluation evaluation = codecInfo.canReuseCodec(oldFormat, newFormat);
@DecoderDiscardReasons int discardReasons = evaluation.discardReasons;
if (getCodecMaxInputSize(codecInfo, newFormat) > codecMaxInputSize) {
discardReasons |= DISCARD_REASON_MAX_INPUT_SIZE_EXCEEDED;
}
return new DecoderReuseEvaluation(codecInfo.name, oldFormat, newFormat, discardReasons != 0 ? REUSE_RESULT_NO : evaluation.result, discardReasons);
}
Aggregations