From 1b3838cb0e1202d5d9df6dd8f8155ee0203f31cd Mon Sep 17 00:00:00 2001 From: claincly Date: Wed, 16 Mar 2022 11:10:06 +0000 Subject: [PATCH] Add test for DefaultEncoderFactory. PiperOrigin-RevId: 435009545 --- .../DefaultEncoderFactoryTest.java | 149 ++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 libraries/transformer/src/test/java/androidx/media3/transformer/DefaultEncoderFactoryTest.java diff --git a/libraries/transformer/src/test/java/androidx/media3/transformer/DefaultEncoderFactoryTest.java b/libraries/transformer/src/test/java/androidx/media3/transformer/DefaultEncoderFactoryTest.java new file mode 100644 index 0000000000..0051978bdc --- /dev/null +++ b/libraries/transformer/src/test/java/androidx/media3/transformer/DefaultEncoderFactoryTest.java @@ -0,0 +1,149 @@ +/* + * Copyright 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 androidx.media3.transformer; + +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertThrows; + +import android.media.MediaCodecInfo; +import android.media.MediaFormat; +import androidx.media3.common.Format; +import androidx.media3.common.MimeTypes; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.google.common.collect.ImmutableList; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.shadows.MediaCodecInfoBuilder; +import org.robolectric.shadows.ShadowMediaCodecList; + +/** Unit test for {@link DefaultEncoderFactory}. */ +@RunWith(AndroidJUnit4.class) +public class DefaultEncoderFactoryTest { + + @Before + public void setUp() { + MediaFormat avcFormat = new MediaFormat(); + avcFormat.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_VIDEO_AVC); + MediaCodecInfo.CodecProfileLevel profileLevel = new MediaCodecInfo.CodecProfileLevel(); + profileLevel.profile = MediaCodecInfo.CodecProfileLevel.AVCProfileHigh; + // Using Level4 gives us 8192 16x16 blocks. If using width 1920 uses 120 blocks, 8192 / 120 = 68 + // blocks will be left for encoding height 1088. + profileLevel.level = MediaCodecInfo.CodecProfileLevel.AVCLevel4; + + ShadowMediaCodecList.addCodec( + MediaCodecInfoBuilder.newBuilder() + .setName("test.transformer.avc.encoder") + .setIsEncoder(true) + .setCapabilities( + MediaCodecInfoBuilder.CodecCapabilitiesBuilder.newBuilder() + .setMediaFormat(avcFormat) + .setIsEncoder(true) + .setColorFormats( + new int[] {MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible}) + .setProfileLevels(new MediaCodecInfo.CodecProfileLevel[] {profileLevel}) + .build()) + .build()); + } + + @Test + public void createForVideoEncoding_withFallbackOnAndSupportedInputFormat_configuresEncoder() + throws Exception { + Format requestedVideoFormat = createVideoFormat(MimeTypes.VIDEO_H264, 1920, 1080, 30); + Format actualVideoFormat = + new DefaultEncoderFactory() + .createForVideoEncoding( + requestedVideoFormat, + /* allowedMimeTypes= */ ImmutableList.of(MimeTypes.VIDEO_H264)) + .getConfigurationFormat(); + + assertThat(actualVideoFormat.sampleMimeType).isEqualTo(MimeTypes.VIDEO_H264); + assertThat(actualVideoFormat.width).isEqualTo(1920); + assertThat(actualVideoFormat.height).isEqualTo(1080); + // 1920 * 1080 * 30 * 0.1 + assertThat(actualVideoFormat.averageBitrate).isEqualTo(6_220_800); + } + + @Test + public void createForVideoEncoding_withFallbackOnAndUnsupportedMimeType_configuresEncoder() + throws Exception { + Format requestedVideoFormat = createVideoFormat(MimeTypes.VIDEO_H265, 1920, 1080, 30); + Format actualVideoFormat = + new DefaultEncoderFactory() + .createForVideoEncoding( + requestedVideoFormat, + /* allowedMimeTypes= */ ImmutableList.of(MimeTypes.VIDEO_H264)) + .getConfigurationFormat(); + + assertThat(actualVideoFormat.sampleMimeType).isEqualTo(MimeTypes.VIDEO_H264); + assertThat(actualVideoFormat.width).isEqualTo(1920); + assertThat(actualVideoFormat.height).isEqualTo(1080); + // 1920 * 1080 * 30 * 0.1 + assertThat(actualVideoFormat.averageBitrate).isEqualTo(6_220_800); + } + + @Test + public void createForVideoEncoding_withFallbackOnAndUnsupportedResolution_configuresEncoder() + throws Exception { + Format requestedVideoFormat = createVideoFormat(MimeTypes.VIDEO_H264, 3840, 2160, 60); + Format actualVideoFormat = + new DefaultEncoderFactory() + .createForVideoEncoding( + requestedVideoFormat, + /* allowedMimeTypes= */ ImmutableList.of(MimeTypes.VIDEO_H264)) + .getConfigurationFormat(); + + assertThat(actualVideoFormat.width).isEqualTo(1920); + assertThat(actualVideoFormat.height).isEqualTo(1080); + } + + @Test + public void createForVideoEncoding_withNoSupportedEncoder_throws() { + Format requestedVideoFormat = createVideoFormat(MimeTypes.VIDEO_H264, 1920, 1080, 30); + assertThrows( + TransformationException.class, + () -> + new DefaultEncoderFactory() + .createForVideoEncoding( + requestedVideoFormat, + /* allowedMimeTypes= */ ImmutableList.of(MimeTypes.VIDEO_H265))); + } + + @Test + public void createForVideoEncoding_withNoAvailableEncoderFromEncoderSelector_throws() { + Format requestedVideoFormat = createVideoFormat(MimeTypes.VIDEO_H264, 1920, 1080, 30); + assertThrows( + TransformationException.class, + () -> + new DefaultEncoderFactory( + /* videoEncoderSelector= */ mimeType -> ImmutableList.of(), + /* enableFallback= */ true) + .createForVideoEncoding( + requestedVideoFormat, + /* allowedMimeTypes= */ ImmutableList.of(MimeTypes.VIDEO_H264))); + } + + private static Format createVideoFormat(String mimeType, int width, int height, int frameRate) { + return new Format.Builder() + .setWidth(width) + .setHeight(height) + .setFrameRate(frameRate) + .setRotationDegrees(0) + .setSampleMimeType(mimeType) + .build(); + } +}