• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.mediav2.cts;
18 
19 import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible;
20 import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUVP010;
21 import static android.mediav2.common.cts.CodecTestBase.SupportClass.CODEC_ANY;
22 import static android.mediav2.common.cts.CodecTestBase.SupportClass.CODEC_HW;
23 import static android.mediav2.common.cts.CodecTestBase.SupportClass.CODEC_HW_RECOMMENDED;
24 import static android.mediav2.common.cts.CodecTestBase.SupportClass.CODEC_OPTIONAL;
25 import static android.mediav2.common.cts.CodecTestBase.SupportClass.CODEC_SHOULD;
26 
27 import static org.junit.Assert.assertNotNull;
28 
29 import android.media.MediaFormat;
30 import android.mediav2.common.cts.CodecEncoderTestBase;
31 import android.mediav2.common.cts.CodecTestBase;
32 import android.mediav2.common.cts.EncoderConfigParams;
33 import android.mediav2.common.cts.RawResource;
34 
35 import androidx.test.filters.LargeTest;
36 
37 import com.android.compatibility.common.util.ApiTest;
38 import com.android.compatibility.common.util.CddTest;
39 
40 import org.junit.Assume;
41 import org.junit.Test;
42 import org.junit.runner.RunWith;
43 import org.junit.runners.Parameterized;
44 
45 import java.io.IOException;
46 import java.util.ArrayList;
47 import java.util.Arrays;
48 import java.util.Collection;
49 import java.util.List;
50 import java.util.Objects;
51 
52 /**
53  * The test verifies encoders present in media codec list in bytebuffer mode. The test feeds raw
54  * input data to the component and receives compressed bitstream from the component. This is
55  * written to an output file using muxer.
56  * <p>
57  * At the end of encoding process, the test enforces following checks :-
58  * <ul>
59  *     <li>The minimum PSNR of encoded output is at least the tolerance value.</li>
60  * </ul>
61  */
62 @RunWith(Parameterized.class)
63 public class VideoEncoderTest extends CodecEncoderTestBase {
64     private final SupportClass mSupportRequirements;
65     private final int mFrameLimit;
66 
VideoEncoderTest(String encoder, String mediaType, EncoderConfigParams encCfgParams, SupportClass supportRequirements, @SuppressWarnings("unused") String testLabel, String allTestParams)67     public VideoEncoderTest(String encoder, String mediaType, EncoderConfigParams encCfgParams,
68             SupportClass supportRequirements, @SuppressWarnings("unused") String testLabel,
69             String allTestParams) {
70         super(encoder, mediaType, new EncoderConfigParams[]{encCfgParams}, allTestParams);
71         mSupportRequirements = supportRequirements;
72         mFrameLimit = Math.max(encCfgParams.mFrameRate, 30);
73     }
74 
getVideoEncoderCfgParams(String mediaType, int bitRate, int width, int height, int frameRate, int colorFormat, int maxBFrames)75     private static EncoderConfigParams getVideoEncoderCfgParams(String mediaType, int bitRate,
76             int width, int height, int frameRate, int colorFormat, int maxBFrames) {
77         EncoderConfigParams.Builder foreman =
78                 new EncoderConfigParams.Builder(mediaType)
79                         .setBitRate(bitRate)
80                         .setWidth(width)
81                         .setHeight(height)
82                         .setFrameRate(frameRate)
83                         .setColorFormat(colorFormat)
84                         .setMaxBFrames(maxBFrames);
85         if (colorFormat == COLOR_FormatYUVP010) {
86             foreman.setProfile(Objects.requireNonNull(PROFILE_HLG_MAP.get(mediaType))[0]);
87         }
88         return foreman.build();
89     }
90 
prepareTestArgs(List<Object[]> args)91     private static List<Object[]> prepareTestArgs(List<Object[]> args) {
92         List<Object[]> argsList = new ArrayList<>();
93         for (Object[] arg : args) {
94             String mediaType = (String) arg[0];
95             int bitRate = (int) arg[1];
96             int width = (int) arg[2];
97             int height = (int) arg[3];
98             int frameRate = (int) arg[4];
99             int colorFormat = (int) arg[5];
100             int[] maxBFrames = {0, 2};
101             for (int maxBframe : maxBFrames) {
102                 Object[] testArgs = new Object[4];
103                 if (maxBframe != 0) {
104                     if (!mediaType.equals(MediaFormat.MIMETYPE_VIDEO_AVC)
105                             && !mediaType.equals(MediaFormat.MIMETYPE_VIDEO_HEVC)) {
106                         continue;
107                     }
108                 }
109                 testArgs[0] = arg[0];
110                 testArgs[1] = getVideoEncoderCfgParams(mediaType, bitRate, width, height, frameRate,
111                         colorFormat, maxBframe);
112                 testArgs[2] = arg[6];
113                 testArgs[3] = String.format("%dkbps_%dx%d_%s_%d-bframes", bitRate / 1000, width,
114                         height, colorFormatToString(colorFormat, -1), maxBframe);
115                 argsList.add(testArgs);
116             }
117         }
118         return argsList;
119     }
120 
getSupportRequirementsDynamic(String mediaType, int width, int height)121     private static SupportClass getSupportRequirementsDynamic(String mediaType, int width,
122             int height) {
123         ArrayList<MediaFormat> formats = new ArrayList<>();
124         formats.add(MediaFormat.createVideoFormat(mediaType, width, height));
125         return selectCodecs(mediaType, formats, null, true).size() != 0 ? CODEC_ANY : CODEC_SHOULD;
126     }
127 
128     @Parameterized.Parameters(name = "{index}_{0}_{1}_{4}")
input()129     public static Collection<Object[]> input() {
130         final boolean isEncoder = true;
131         final boolean needAudio = false;
132         final boolean needVideo = true;
133         List<Object[]> defArgsList = new ArrayList<>(Arrays.asList(new Object[][]{
134                 // mediaType, width, height, bit-rate, frame-rate, color format, support class
135                 {MediaFormat.MIMETYPE_VIDEO_H263, 64000, 128, 96, 15, COLOR_FormatYUV420Flexible,
136                         CODEC_OPTIONAL},
137                 {MediaFormat.MIMETYPE_VIDEO_H263, 64000, 176, 144, 15, COLOR_FormatYUV420Flexible,
138                         CODEC_ANY},
139                 {MediaFormat.MIMETYPE_VIDEO_H263, 128000, 128, 96, 15, COLOR_FormatYUV420Flexible,
140                         CODEC_OPTIONAL},
141                 {MediaFormat.MIMETYPE_VIDEO_H263, 128000, 176, 144, 15, COLOR_FormatYUV420Flexible,
142                         CODEC_ANY},
143 
144                 {MediaFormat.MIMETYPE_VIDEO_MPEG4, 64000, 128, 96, 15, COLOR_FormatYUV420Flexible,
145                         CODEC_OPTIONAL},
146                 {MediaFormat.MIMETYPE_VIDEO_MPEG4, 64000, 176, 144, 15, COLOR_FormatYUV420Flexible,
147                         CODEC_OPTIONAL},
148 
149                 {MediaFormat.MIMETYPE_VIDEO_AVC, 384000, 320, 240, 20, COLOR_FormatYUV420Flexible,
150                         CODEC_ANY},
151                 {MediaFormat.MIMETYPE_VIDEO_AVC, 2000000, 720, 480, 30, COLOR_FormatYUV420Flexible,
152                         CODEC_ANY},
153                 {MediaFormat.MIMETYPE_VIDEO_AVC, 3000000, 1280, 720, 30,
154                         COLOR_FormatYUV420Flexible, getSupportRequirementsDynamic(
155                         MediaFormat.MIMETYPE_VIDEO_AVC, 1280, 720)},
156                 {MediaFormat.MIMETYPE_VIDEO_AVC, 10000000, 1920, 1080, 30,
157                         COLOR_FormatYUV420Flexible, getSupportRequirementsDynamic(
158                         MediaFormat.MIMETYPE_VIDEO_AVC, 1920, 1080)},
159 
160                 {MediaFormat.MIMETYPE_VIDEO_VP8, 800000, 320, 180, 30, COLOR_FormatYUV420Flexible,
161                         CODEC_ANY},
162                 {MediaFormat.MIMETYPE_VIDEO_VP8, 2000000, 640, 360, 30, COLOR_FormatYUV420Flexible,
163                         CODEC_ANY},
164                 {MediaFormat.MIMETYPE_VIDEO_VP8, 4000000, 1280, 720, 30,
165                         COLOR_FormatYUV420Flexible, getSupportRequirementsDynamic(
166                         MediaFormat.MIMETYPE_VIDEO_VP8, 1280, 720)},
167                 {MediaFormat.MIMETYPE_VIDEO_VP8, 10000000, 1920, 1080, 30,
168                         COLOR_FormatYUV420Flexible, getSupportRequirementsDynamic(
169                         MediaFormat.MIMETYPE_VIDEO_VP8, 1920, 1080)},
170 
171                 {MediaFormat.MIMETYPE_VIDEO_VP9, 1600000, 720, 480, 30, COLOR_FormatYUV420Flexible,
172                         CODEC_ANY},
173                 {MediaFormat.MIMETYPE_VIDEO_VP9, 4000000, 1280, 720, 30, COLOR_FormatYUV420Flexible,
174                         CODEC_HW_RECOMMENDED},
175                 {MediaFormat.MIMETYPE_VIDEO_VP9, 5000000, 1920, 1080, 30,
176                         COLOR_FormatYUV420Flexible, CODEC_HW_RECOMMENDED},
177                 {MediaFormat.MIMETYPE_VIDEO_VP9, 20000000, 3840, 2160, 30,
178                         COLOR_FormatYUV420Flexible, CODEC_HW_RECOMMENDED},
179 
180                 {MediaFormat.MIMETYPE_VIDEO_HEVC, 1000000, 512, 512, 30,
181                         COLOR_FormatYUV420Flexible, CODEC_ANY},
182                 {MediaFormat.MIMETYPE_VIDEO_HEVC, 1600000, 720, 480, 30,
183                         COLOR_FormatYUV420Flexible, CODEC_HW_RECOMMENDED},
184                 {MediaFormat.MIMETYPE_VIDEO_HEVC, 4000000, 1280, 720, 30,
185                         COLOR_FormatYUV420Flexible, CODEC_HW_RECOMMENDED},
186                 {MediaFormat.MIMETYPE_VIDEO_HEVC, 5000000, 1920, 1080, 30,
187                         COLOR_FormatYUV420Flexible, CODEC_HW_RECOMMENDED},
188                 {MediaFormat.MIMETYPE_VIDEO_HEVC, 20000000, 3840, 2160, 30,
189                         COLOR_FormatYUV420Flexible, CODEC_HW_RECOMMENDED},
190 
191                 {MediaFormat.MIMETYPE_VIDEO_AV1, 5000000, 720, 480, 30,
192                         COLOR_FormatYUV420Flexible, CODEC_HW},
193                 {MediaFormat.MIMETYPE_VIDEO_AV1, 8000000, 1280, 720, 30,
194                         COLOR_FormatYUV420Flexible, CODEC_HW},
195                 {MediaFormat.MIMETYPE_VIDEO_AV1, 16000000, 1920, 1080, 30,
196                         COLOR_FormatYUV420Flexible, CODEC_HW},
197                 {MediaFormat.MIMETYPE_VIDEO_AV1, 50000000, 3840, 2160, 30,
198                         COLOR_FormatYUV420Flexible, CODEC_SHOULD},
199         }));
200         // P010 support was added in Android T, hence limit the following tests to Android T and
201         // above
202         if (IS_AT_LEAST_T) {
203             defArgsList.addAll(Arrays.asList(new Object[][]{
204                     {MediaFormat.MIMETYPE_VIDEO_AVC, 384000, 320, 240, 20, COLOR_FormatYUVP010,
205                             CODEC_OPTIONAL},
206                     {MediaFormat.MIMETYPE_VIDEO_AVC, 2000000, 720, 480, 30, COLOR_FormatYUVP010,
207                             CODEC_OPTIONAL},
208                     {MediaFormat.MIMETYPE_VIDEO_AVC, 3000000, 1280, 720, 30, COLOR_FormatYUVP010,
209                             CODEC_OPTIONAL},
210                     {MediaFormat.MIMETYPE_VIDEO_AVC, 10000000, 1920, 1080, 30,
211                             COLOR_FormatYUVP010, CODEC_OPTIONAL},
212 
213                     {MediaFormat.MIMETYPE_VIDEO_VP9, 1600000, 720, 480, 30, COLOR_FormatYUVP010,
214                             CODEC_OPTIONAL},
215                     {MediaFormat.MIMETYPE_VIDEO_VP9, 4000000, 1280, 720, 30, COLOR_FormatYUVP010,
216                             CODEC_OPTIONAL},
217                     {MediaFormat.MIMETYPE_VIDEO_VP9, 5000000, 1920, 1080, 30, COLOR_FormatYUVP010,
218                             CODEC_OPTIONAL},
219                     {MediaFormat.MIMETYPE_VIDEO_VP9, 20000000, 3840, 2160, 30,
220                             COLOR_FormatYUVP010, CODEC_OPTIONAL},
221 
222                     {MediaFormat.MIMETYPE_VIDEO_HEVC, 1600000, 720, 480, 30, COLOR_FormatYUVP010,
223                             CODEC_OPTIONAL},
224                     {MediaFormat.MIMETYPE_VIDEO_HEVC, 4000000, 1280, 720, 30, COLOR_FormatYUVP010,
225                             CODEC_OPTIONAL},
226                     {MediaFormat.MIMETYPE_VIDEO_HEVC, 5000000, 1920, 1080, 30,
227                             COLOR_FormatYUVP010, CODEC_OPTIONAL},
228                     {MediaFormat.MIMETYPE_VIDEO_HEVC, 20000000, 3840, 2160, 30,
229                             COLOR_FormatYUVP010, CODEC_OPTIONAL},
230 
231                     {MediaFormat.MIMETYPE_VIDEO_AV1, 5000000, 720, 480, 30, COLOR_FormatYUVP010,
232                             CODEC_HW},
233                     {MediaFormat.MIMETYPE_VIDEO_AV1, 8000000, 1280, 720, 30, COLOR_FormatYUVP010,
234                             CODEC_HW},
235                     {MediaFormat.MIMETYPE_VIDEO_AV1, 16000000, 1920, 1080, 30,
236                             COLOR_FormatYUVP010, CODEC_HW},
237                     {MediaFormat.MIMETYPE_VIDEO_AV1, 50000000, 3840, 2160, 30,
238                             COLOR_FormatYUVP010, CODEC_SHOULD},
239             }));
240         }
241         List<Object[]> argsList = prepareTestArgs(defArgsList);
242         return prepareParamList(argsList, isEncoder, needAudio, needVideo, false);
243     }
244 
245     /**
246      * Check description of class {@link VideoEncoderTest}
247      */
248     @CddTest(requirements = {"5.2.1/C-1-1", "5.2.2/C-1-2", "5.2.2/C-2-1", "5.2.3/C-1-1",
249             "5.2.3/C-1-2", "5.2.3/C-2-1", "5.2.4/C-1-1", "5.2.6/C-2-1"})
250     @ApiTest(apis = {"MediaCodecInfo.CodecCapabilities#COLOR_FormatYUV420Flexible",
251             "MediaCodecInfo.CodecCapabilities#COLOR_FormatYUVP010"})
252     @LargeTest
253     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
testEncodeAndValidate()254     public void testEncodeAndValidate() throws IOException, InterruptedException {
255         // pre run checks
256         if (mEncCfgParams[0].mInputBitDepth > 8) {
257             Assume.assumeTrue("Codec doesn't support high bit depth profile encoding",
258                     doesCodecSupportHDRProfile(mCodecName, mMediaType));
259             Assume.assumeTrue(mCodecName + " doesn't support " + colorFormatToString(
260                             mEncCfgParams[0].mColorFormat, mEncCfgParams[0].mInputBitDepth),
261                     hasSupportForColorFormat(mCodecName, mMediaType,
262                             mEncCfgParams[0].mColorFormat));
263         }
264         ArrayList<MediaFormat> formats = new ArrayList<>();
265         formats.add(mEncCfgParams[0].getFormat());
266         checkFormatSupport(mCodecName, mMediaType, true, formats, null, mSupportRequirements);
267 
268         // encode
269         RawResource res = EncoderInput.getRawResource(mEncCfgParams[0]);
270         assertNotNull("no raw resource found for testing config : " + mActiveEncCfg + mTestConfig
271                 + mTestEnv, res);
272 
273         boolean muxOutput = true;
274         if (mMediaType.equals(MediaFormat.MIMETYPE_VIDEO_AV1) && CodecTestBase.IS_BEFORE_U) {
275             muxOutput = false;
276         }
277         encodeToMemory(mCodecName, mEncCfgParams[0], res, mFrameLimit, false, muxOutput);
278 
279         // validate output
280         if (muxOutput) {
281             validateEncodedPSNR(res, mMediaType, mMuxedOutputFile, true, mIsLoopBack,
282                     ACCEPTABLE_WIRELESS_TX_QUALITY);
283         }
284     }
285 }
286