use of android.media.MediaCodecInfo.CodecCapabilities in project ExoPlayer by google.
the class MediaCodecVideoRendererTest method supportsFormat_withDolbyVisionMedia_returnsTrueWhenFallbackToH265orH264Allowed.
@Test
public void supportsFormat_withDolbyVisionMedia_returnsTrueWhenFallbackToH265orH264Allowed() throws Exception {
// Create Dolby media formats that could fall back to H265 or H264.
Format formatDvheDtrFallbackToH265 = new Format.Builder().setSampleMimeType(MimeTypes.VIDEO_DOLBY_VISION).setCodecs("dvhe.04.01").build();
Format formatDvheStFallbackToH265 = new Format.Builder().setSampleMimeType(MimeTypes.VIDEO_DOLBY_VISION).setCodecs("dvhe.08.01").build();
Format formatDvavSeFallbackToH264 = new Format.Builder().setSampleMimeType(MimeTypes.VIDEO_DOLBY_VISION).setCodecs("dvav.09.01").build();
Format formatNoFallbackPossible = new Format.Builder().setSampleMimeType(MimeTypes.VIDEO_DOLBY_VISION).setCodecs("dvav.01.01").build();
// Only provide H264 and H265 decoders with codec profiles needed for fallback.
MediaCodecSelector mediaCodecSelector = (mimeType, requiresSecureDecoder, requiresTunnelingDecoder) -> {
switch(mimeType) {
case MimeTypes.VIDEO_H264:
CodecCapabilities capabilitiesH264 = new CodecCapabilities();
capabilitiesH264.profileLevels = new CodecProfileLevel[] { new CodecProfileLevel(), new CodecProfileLevel() };
capabilitiesH264.profileLevels[0].profile = CodecProfileLevel.AVCProfileBaseline;
capabilitiesH264.profileLevels[0].level = CodecProfileLevel.AVCLevel42;
capabilitiesH264.profileLevels[1].profile = CodecProfileLevel.AVCProfileHigh;
capabilitiesH264.profileLevels[1].level = CodecProfileLevel.AVCLevel42;
return ImmutableList.of(MediaCodecInfo.newInstance(/* name= */
"h264-codec", /* mimeType= */
mimeType, /* codecMimeType= */
mimeType, /* capabilities= */
capabilitiesH264, /* hardwareAccelerated= */
false, /* softwareOnly= */
true, /* vendor= */
false, /* forceDisableAdaptive= */
false, /* forceSecure= */
false));
case MimeTypes.VIDEO_H265:
CodecCapabilities capabilitiesH265 = new CodecCapabilities();
capabilitiesH265.profileLevels = new CodecProfileLevel[] { new CodecProfileLevel(), new CodecProfileLevel() };
capabilitiesH265.profileLevels[0].profile = CodecProfileLevel.HEVCProfileMain;
capabilitiesH265.profileLevels[0].level = CodecProfileLevel.HEVCMainTierLevel41;
capabilitiesH265.profileLevels[1].profile = CodecProfileLevel.HEVCProfileMain10;
capabilitiesH265.profileLevels[1].level = CodecProfileLevel.HEVCHighTierLevel51;
return ImmutableList.of(MediaCodecInfo.newInstance(/* name= */
"h265-codec", /* mimeType= */
mimeType, /* codecMimeType= */
mimeType, /* capabilities= */
capabilitiesH265, /* hardwareAccelerated= */
false, /* softwareOnly= */
true, /* vendor= */
false, /* forceDisableAdaptive= */
false, /* forceSecure= */
false));
default:
return ImmutableList.of();
}
};
MediaCodecVideoRenderer renderer = new MediaCodecVideoRenderer(ApplicationProvider.getApplicationContext(), mediaCodecSelector, /* allowedJoiningTimeMs= */
0, /* eventHandler= */
new Handler(testMainLooper), /* eventListener= */
eventListener, /* maxDroppedFramesToNotify= */
1);
renderer.init(/* index= */
0, PlayerId.UNSET);
@Capabilities int capabilitiesDvheDtrFallbackToH265 = renderer.supportsFormat(formatDvheDtrFallbackToH265);
@Capabilities int capabilitiesDvheStFallbackToH265 = renderer.supportsFormat(formatDvheStFallbackToH265);
@Capabilities int capabilitiesDvavSeFallbackToH264 = renderer.supportsFormat(formatDvavSeFallbackToH264);
@Capabilities int capabilitiesNoFallbackPossible = renderer.supportsFormat(formatNoFallbackPossible);
assertThat(RendererCapabilities.getFormatSupport(capabilitiesDvheDtrFallbackToH265)).isEqualTo(C.FORMAT_HANDLED);
assertThat(RendererCapabilities.getFormatSupport(capabilitiesDvheStFallbackToH265)).isEqualTo(C.FORMAT_HANDLED);
assertThat(RendererCapabilities.getFormatSupport(capabilitiesDvavSeFallbackToH264)).isEqualTo(C.FORMAT_HANDLED);
assertThat(RendererCapabilities.getFormatSupport(capabilitiesNoFallbackPossible)).isEqualTo(C.FORMAT_UNSUPPORTED_SUBTYPE);
}
use of android.media.MediaCodecInfo.CodecCapabilities in project robolectric by robolectric.
the class ShadowMediaCodecListTest method codecCapabilities_createFromProfileLevel.
@Test
public void codecCapabilities_createFromProfileLevel() {
CodecCapabilities codecCapabilities = CodecCapabilities.createFromProfileLevel(MediaFormat.MIMETYPE_VIDEO_AVC, CodecProfileLevel.AVCProfileBaseline, CodecProfileLevel.AVCLevel2);
CodecProfileLevel expected = new CodecProfileLevel();
expected.profile = CodecProfileLevel.AVCProfileBaseline;
expected.level = CodecProfileLevel.AVCLevel2;
assertThat(codecCapabilities.getMimeType()).isEqualTo(MediaFormat.MIMETYPE_VIDEO_AVC);
assertThat(codecCapabilities.profileLevels).hasLength(1);
assertThat(codecCapabilities.profileLevels[0]).isEqualTo(expected);
}
use of android.media.MediaCodecInfo.CodecCapabilities in project media by androidx.
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