Add function to clear the cached list of encoders

EncoderUtil using a static list to cache encoders means it's not possible to
use a different set of encoders for different tests when running all
robolectric tests together.

PiperOrigin-RevId: 491959350
This commit is contained in:
claincly 2022-11-30 18:38:45 +00:00 committed by Ian Baker
parent eecf7caed0
commit 7dee3aec51
5 changed files with 52 additions and 15 deletions

View File

@ -16,7 +16,6 @@
package androidx.media3.transformer; package androidx.media3.transformer;
import static androidx.media3.common.util.Assertions.checkNotNull;
import static java.lang.Math.max; import static java.lang.Math.max;
import static java.lang.Math.round; import static java.lang.Math.round;
@ -29,8 +28,10 @@ import android.util.Pair;
import android.util.Range; import android.util.Range;
import android.util.Size; import android.util.Size;
import androidx.annotation.DoNotInline; import androidx.annotation.DoNotInline;
import androidx.annotation.GuardedBy;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi; import androidx.annotation.RequiresApi;
import androidx.annotation.VisibleForTesting;
import androidx.media3.common.C; import androidx.media3.common.C;
import androidx.media3.common.C.ColorTransfer; import androidx.media3.common.C.ColorTransfer;
import androidx.media3.common.ColorInfo; import androidx.media3.common.ColorInfo;
@ -40,10 +41,8 @@ import androidx.media3.common.util.MediaFormatUtil;
import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.UnstableApi;
import androidx.media3.common.util.Util; import androidx.media3.common.util.Util;
import com.google.common.base.Ascii; import com.google.common.base.Ascii;
import com.google.common.base.Supplier; import com.google.common.collect.ArrayListMultimap;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.primitives.Ints; import com.google.common.primitives.Ints;
@ -54,20 +53,29 @@ public final class EncoderUtil {
/** A value to indicate the encoding level is not set. */ /** A value to indicate the encoding level is not set. */
public static final int LEVEL_UNSET = Format.NO_VALUE; public static final int LEVEL_UNSET = Format.NO_VALUE;
private static final Supplier<ImmutableListMultimap<String, MediaCodecInfo>> @GuardedBy("EncoderUtil.class")
MIME_TYPE_TO_ENCODERS = Suppliers.memoize(EncoderUtil::populateEncoderInfos); private static final ArrayListMultimap<String, MediaCodecInfo> mimeTypeToEncoders =
ArrayListMultimap.create();
/** /**
* Returns a list of {@linkplain MediaCodecInfo encoders} that support the given {@code mimeType}, * Returns a list of {@linkplain MediaCodecInfo encoders} that support the given {@code mimeType},
* or an empty list if there is none. * or an empty list if there is none.
*/ */
public static ImmutableList<MediaCodecInfo> getSupportedEncoders(String mimeType) { public static synchronized ImmutableList<MediaCodecInfo> getSupportedEncoders(String mimeType) {
return checkNotNull(MIME_TYPE_TO_ENCODERS.get()).get(Ascii.toLowerCase(mimeType)); maybePopulateEncoderInfo();
return ImmutableList.copyOf(mimeTypeToEncoders.get(Ascii.toLowerCase(mimeType)));
} }
/** Returns a list of video {@linkplain MimeTypes MIME types} that can be encoded. */ /** Returns a list of video {@linkplain MimeTypes MIME types} that can be encoded. */
public static ImmutableSet<String> getSupportedVideoMimeTypes() { public static synchronized ImmutableSet<String> getSupportedVideoMimeTypes() {
return checkNotNull(MIME_TYPE_TO_ENCODERS.get()).keySet(); maybePopulateEncoderInfo();
return ImmutableSet.copyOf(mimeTypeToEncoders.keySet());
}
/** Clears the cached list of encoders. */
@VisibleForTesting
public static synchronized void clearCachedEncoders() {
mimeTypeToEncoders.clear();
} }
/** /**
@ -433,9 +441,10 @@ public final class EncoderUtil {
: alignment * Math.round((float) size / alignment); : alignment * Math.round((float) size / alignment);
} }
private static ImmutableListMultimap<String, MediaCodecInfo> populateEncoderInfos() { private static synchronized void maybePopulateEncoderInfo() {
ImmutableListMultimap.Builder<String, MediaCodecInfo> encoderInfosBuilder = if (!mimeTypeToEncoders.isEmpty()) {
new ImmutableListMultimap.Builder<>(); return;
}
MediaCodecList mediaCodecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS); MediaCodecList mediaCodecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
MediaCodecInfo[] allCodecInfos = mediaCodecList.getCodecInfos(); MediaCodecInfo[] allCodecInfos = mediaCodecList.getCodecInfos();
@ -446,10 +455,9 @@ public final class EncoderUtil {
} }
String[] supportedMimeTypes = mediaCodecInfo.getSupportedTypes(); String[] supportedMimeTypes = mediaCodecInfo.getSupportedTypes();
for (String mimeType : supportedMimeTypes) { for (String mimeType : supportedMimeTypes) {
encoderInfosBuilder.put(Ascii.toLowerCase(mimeType), mediaCodecInfo); mimeTypeToEncoders.put(Ascii.toLowerCase(mimeType), mediaCodecInfo);
} }
} }
return encoderInfosBuilder.build();
} }
@RequiresApi(29) @RequiresApi(29)

View File

@ -28,11 +28,13 @@ import androidx.media3.common.Format;
import androidx.media3.common.MimeTypes; import androidx.media3.common.MimeTypes;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
import org.robolectric.shadows.MediaCodecInfoBuilder; import org.robolectric.shadows.MediaCodecInfoBuilder;
import org.robolectric.shadows.ShadowMediaCodec;
import org.robolectric.shadows.ShadowMediaCodecList; import org.robolectric.shadows.ShadowMediaCodecList;
/** Unit test for {@link DefaultEncoderFactory}. */ /** Unit test for {@link DefaultEncoderFactory}. */
@ -45,6 +47,13 @@ public class DefaultEncoderFactoryTest {
createShadowH264Encoder(); createShadowH264Encoder();
} }
@After
public void tearDown() {
ShadowMediaCodec.clearCodecs();
ShadowMediaCodecList.reset();
EncoderUtil.clearCachedEncoders();
}
private static void createShadowH264Encoder() { private static void createShadowH264Encoder() {
MediaFormat avcFormat = new MediaFormat(); MediaFormat avcFormat = new MediaFormat();
avcFormat.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_VIDEO_AVC); avcFormat.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_VIDEO_AVC);

View File

@ -27,11 +27,13 @@ import androidx.media3.common.ColorInfo;
import androidx.media3.common.MimeTypes; import androidx.media3.common.MimeTypes;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
import org.robolectric.shadows.MediaCodecInfoBuilder; import org.robolectric.shadows.MediaCodecInfoBuilder;
import org.robolectric.shadows.ShadowMediaCodec;
import org.robolectric.shadows.ShadowMediaCodecList; import org.robolectric.shadows.ShadowMediaCodecList;
/** Unit test for {@link EncoderUtil}. */ /** Unit test for {@link EncoderUtil}. */
@ -64,6 +66,13 @@ public class EncoderUtilTest {
.build()); .build());
} }
@After
public void tearDown() {
ShadowMediaCodecList.reset();
ShadowMediaCodec.clearCodecs();
EncoderUtil.clearCachedEncoders();
}
@Test @Test
public void getSupportedResolution_withSupportedResolution_succeeds() { public void getSupportedResolution_withSupportedResolution_succeeds() {
ImmutableList<MediaCodecInfo> supportedEncoders = EncoderUtil.getSupportedEncoders(MIME_TYPE); ImmutableList<MediaCodecInfo> supportedEncoders = EncoderUtil.getSupportedEncoders(MIME_TYPE);

View File

@ -898,6 +898,8 @@ public final class TransformerEndToEndTest {
private static void removeEncodersAndDecoders() { private static void removeEncodersAndDecoders() {
ShadowMediaCodec.clearCodecs(); ShadowMediaCodec.clearCodecs();
ShadowMediaCodecList.reset();
EncoderUtil.clearCachedEncoders();
} }
private static String getDumpFileName(String originalFileName) { private static String getDumpFileName(String originalFileName) {

View File

@ -32,10 +32,12 @@ import androidx.media3.common.util.Clock;
import androidx.media3.common.util.ListenerSet; import androidx.media3.common.util.ListenerSet;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.robolectric.shadows.MediaCodecInfoBuilder; import org.robolectric.shadows.MediaCodecInfoBuilder;
import org.robolectric.shadows.ShadowMediaCodec;
import org.robolectric.shadows.ShadowMediaCodecList; import org.robolectric.shadows.ShadowMediaCodecList;
/** Unit tests for {@link VideoTranscodingSamplePipeline.EncoderWrapper}. */ /** Unit tests for {@link VideoTranscodingSamplePipeline.EncoderWrapper}. */
@ -63,6 +65,13 @@ public final class VideoEncoderWrapperTest {
createShadowH264Encoder(); createShadowH264Encoder();
} }
@After
public void tearDown() {
ShadowMediaCodec.clearCodecs();
ShadowMediaCodecList.reset();
EncoderUtil.clearCachedEncoders();
}
@Test @Test
public void getSurfaceInfo_landscape_leavesOrientationUnchanged() throws Exception { public void getSurfaceInfo_landscape_leavesOrientationUnchanged() throws Exception {
int inputWidth = 200; int inputWidth = 200;