blob: d295a59f1115500ade47f258bcc1065e9d2d9d92 [file] [log] [blame]
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.mediav2.cts;
import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_Format32bitABGR2101010;
import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface;
import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible;
import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedPlanar;
import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedSemiPlanar;
import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar;
import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar;
import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUVP010;
import static android.media.MediaCodecInfo.CodecCapabilities.FEATURE_HdrEditing;
import static android.mediav2.common.cts.CodecTestBase.FIRST_SDK_IS_AT_LEAST_T;
import static android.mediav2.common.cts.CodecTestBase.IS_AT_LEAST_T;
import static android.mediav2.common.cts.CodecTestBase.IS_HDR_CAPTURE_SUPPORTED;
import static android.mediav2.common.cts.CodecTestBase.PROFILE_HDR10_MAP;
import static android.mediav2.common.cts.CodecTestBase.PROFILE_HDR10_PLUS_MAP;
import static android.mediav2.common.cts.CodecTestBase.VNDK_IS_AT_LEAST_T;
import static android.mediav2.common.cts.CodecTestBase.canDisplaySupportHDRContent;
import static android.mediav2.common.cts.CodecTestBase.isVendorCodec;
import static android.mediav2.common.cts.CodecTestBase.selectCodecs;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import android.media.MediaCodecInfo;
import android.media.MediaCodecInfo.CodecProfileLevel;
import android.media.MediaCodecList;
import android.mediav2.common.cts.CodecTestBase;
import android.os.Build;
import androidx.test.filters.SmallTest;
import com.android.compatibility.common.util.ApiTest;
import com.android.compatibility.common.util.CddTest;
import com.android.compatibility.common.util.MediaUtils;
import com.android.compatibility.common.util.NonMainlineTest;
import org.junit.Assume;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.IntStream;
/**
* Check if information advertised by components are in accordance with its peripherals. The
* scope of this test is to only check if the information advertised is ok. Their functionality
* however is not verified here.
*/
@SmallTest
@RunWith(Parameterized.class)
public class CodecInfoTest {
private static final String LOG_TAG = CodecInfoTest.class.getSimpleName();
public String mMediaType;
public String mCodecName;
public MediaCodecInfo mCodecInfo;
public CodecInfoTest(String mediaType, String codecName, MediaCodecInfo codecInfo) {
mMediaType = mediaType;
mCodecName = codecName;
mCodecInfo = codecInfo;
}
@Parameterized.Parameters(name = "{index}_{0}_{1}")
public static Collection<Object[]> input() {
final List<Object[]> argsList = new ArrayList<>();
MediaCodecList codecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
for (MediaCodecInfo codecInfo : codecList.getCodecInfos()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && codecInfo.isAlias()) {
continue;
}
if (CodecTestBase.codecPrefix != null &&
!codecInfo.getName().startsWith(CodecTestBase.codecPrefix)) {
continue;
}
String[] types = codecInfo.getSupportedTypes();
for (String type : types) {
argsList.add(new Object[]{type, codecInfo.getName(), codecInfo});
}
}
return argsList;
}
/**
* For all the available decoders on the device, the test checks if their decoding
* capabilities are in sync with the device's display capabilities. Precisely, if a video
* decoder advertises support for a HDR profile then the device should be capable of
* displaying the same with out any tone mapping. Else, the decoder should not advertise such
* support.
*/
@Test
// TODO (b/228237404) Remove the following once there is a reliable way to query HDR
// display capabilities at native level, till then limit the test to vendor codecs
@NonMainlineTest
@CddTest(requirements = "5.1.7/C-2-1")
@ApiTest(apis = "MediaCodecInfo.CodecCapabilities#profileLevels")
public void testHDRDisplayCapabilities() {
Assume.assumeTrue("Test needs Android 13", IS_AT_LEAST_T);
Assume.assumeTrue("Test needs VNDK Android 13", VNDK_IS_AT_LEAST_T);
Assume.assumeTrue("Test needs First SDK Android 13", FIRST_SDK_IS_AT_LEAST_T);
Assume.assumeTrue("Test is applicable for video codecs", mMediaType.startsWith("video/"));
// TODO (b/228237404) Remove the following once there is a reliable way to query HDR
// display capabilities at native level, till then limit the test to vendor codecs
Assume.assumeTrue("Test is restricted to vendor codecs", isVendorCodec(mCodecName));
int[] Hdr10Profiles = PROFILE_HDR10_MAP.get(mMediaType);
int[] Hdr10PlusProfiles = PROFILE_HDR10_PLUS_MAP.get(mMediaType);
Assume.assumeTrue("Test is applicable for codecs with HDR10/HDR10+ profiles",
Hdr10Profiles != null || Hdr10PlusProfiles != null);
MediaCodecInfo.CodecCapabilities caps = mCodecInfo.getCapabilitiesForType(mMediaType);
for (CodecProfileLevel pl : caps.profileLevels) {
boolean isHdr10Profile = Hdr10Profiles != null &&
IntStream.of(Hdr10Profiles).anyMatch(x -> x == pl.profile);
boolean isHdr10PlusProfile = Hdr10PlusProfiles != null &&
IntStream.of(Hdr10PlusProfiles).anyMatch(x -> x == pl.profile);
// TODO (b/228237404) Once there is a way to query support for HDR10/HDR10+ display at
// native level, separate the following to independent checks for HDR10 and HDR10+
if (isHdr10Profile || isHdr10PlusProfile) {
assertTrue(mCodecInfo.getName() + " Advertises support for HDR10/HDR10+ profile " +
pl.profile + " without any HDR display", canDisplaySupportHDRContent());
}
}
}
/**
* Checks if the video codecs available on the device advertise support for mandatory color
* formats. The test only checks if the decoder/encoder is advertising the required color
* format. It doesn't verify if it actually supports by decoding/encoding.
*/
@CddTest(requirements = {"5.1.7/C-1-2", "5.1.7/C-1-3", "5.1.7/C-4-1", "5.12/C-6-5",
"5.12/C-7-1", "5.12/C-7-3"})
@Test
public void testColorFormatSupport() {
Assume.assumeTrue("Test is applicable for video codecs", mMediaType.startsWith("video/"));
MediaCodecInfo.CodecCapabilities caps = mCodecInfo.getCapabilitiesForType(mMediaType);
assertFalse(mCodecInfo.getName() + " does not support COLOR_FormatYUV420Flexible",
IntStream.of(caps.colorFormats)
.noneMatch(x -> x == COLOR_FormatYUV420Flexible));
assertFalse(mCodecInfo.getName()
+ " does not support at least one of planar or semi planar yuv 420 888",
IntStream.of(caps.colorFormats)
.noneMatch(x -> x == COLOR_FormatYUV420PackedPlanar)
&& IntStream.of(caps.colorFormats)
.noneMatch(x -> x == COLOR_FormatYUV420Planar)
&& IntStream.of(caps.colorFormats)
.noneMatch(x -> x == COLOR_FormatYUV420PackedSemiPlanar)
&& IntStream.of(caps.colorFormats)
.noneMatch(x -> x == COLOR_FormatYUV420SemiPlanar));
boolean canHandleHdr = CodecTestBase.doesCodecSupportHDRProfile(mCodecName, mMediaType);
if (mCodecInfo.isEncoder()) {
if (IS_HDR_CAPTURE_SUPPORTED && canHandleHdr) {
assertFalse(mCodecInfo.getName()
+ " supports HDR profile but does not support COLOR_FormatYUVP010",
IntStream.of(caps.colorFormats).noneMatch(x -> x == COLOR_FormatYUVP010));
}
// Encoders that support FEATURE_HdrEditing, must support ABGR2101010 color format
// and at least one HDR profile
boolean hdrEditingSupported = caps.isFeatureSupported(FEATURE_HdrEditing);
if (hdrEditingSupported) {
boolean abgr2101010Supported = IntStream.of(caps.colorFormats)
.anyMatch(x -> x == COLOR_Format32bitABGR2101010);
assertTrue(mCodecName + " supports FEATURE_HdrEditing, but does not support"
+ " COLOR_FormatABGR2101010 color formats.", abgr2101010Supported);
assertTrue(mCodecName + " supports FEATURE_HdrEditing, but does not support"
+ " any HDR profiles.", canHandleHdr);
}
} else {
if (FIRST_SDK_IS_AT_LEAST_T && VNDK_IS_AT_LEAST_T && canDisplaySupportHDRContent()) {
if (MediaUtils.isTv()) {
// Some TV devices support HDR10 display with VO instead of GPU. In this
// case, skip checking P010 on TV devices.
Assume.assumeFalse(mCodecInfo.getName()
+ " supports HDR profile but does not support "
+ "COLOR_FormatYUVP010. Skip checking on TV device",
IntStream.of(caps.colorFormats)
.noneMatch(x -> x == COLOR_FormatYUVP010));
} else {
assertFalse(mCodecInfo.getName()
+ " supports HDR profile but does not support "
+ "COLOR_FormatYUVP010",
IntStream.of(caps.colorFormats)
.noneMatch(x -> x == COLOR_FormatYUVP010));
}
}
}
// COLOR_FormatSurface support is an existing requirement, but we did not
// test for it before T. We can not retroactively apply the higher standard to
// devices that are already certified, so only test on devices luanching with T or later.
if (FIRST_SDK_IS_AT_LEAST_T && VNDK_IS_AT_LEAST_T) {
assertFalse(mCodecInfo.getName() + " does not support COLOR_FormatSurface",
IntStream.of(caps.colorFormats)
.noneMatch(x -> x == COLOR_FormatSurface));
}
}
/**
* For all the available encoders on the device, the test checks if their encoding
* capabilities are in sync with the device's decoding capabilities.
*/
@CddTest(requirements = "5/C-0-3")
@Test
public void testDecoderAvailability() {
Assume.assumeTrue("Test is applicable only for encoders", mCodecInfo.isEncoder());
Assume.assumeTrue("Test is applicable for video/audio codecs",
mMediaType.startsWith("video/") || mMediaType.startsWith("audio/"));
if (selectCodecs(mMediaType, null, null, true).size() > 0) {
assertTrue("Device advertises support for encoding " + mMediaType +
", but not decoding it",
selectCodecs(mMediaType, null, null, false).size() > 0);
}
}
}