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

View File

@ -28,11 +28,13 @@ 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.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.MediaCodecInfoBuilder;
import org.robolectric.shadows.ShadowMediaCodec;
import org.robolectric.shadows.ShadowMediaCodecList;
/** Unit test for {@link DefaultEncoderFactory}. */
@ -45,6 +47,13 @@ public class DefaultEncoderFactoryTest {
createShadowH264Encoder();
}
@After
public void tearDown() {
ShadowMediaCodec.clearCodecs();
ShadowMediaCodecList.reset();
EncoderUtil.clearCachedEncoders();
}
private static void createShadowH264Encoder() {
MediaFormat avcFormat = new MediaFormat();
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.test.ext.junit.runners.AndroidJUnit4;
import com.google.common.collect.ImmutableList;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.MediaCodecInfoBuilder;
import org.robolectric.shadows.ShadowMediaCodec;
import org.robolectric.shadows.ShadowMediaCodecList;
/** Unit test for {@link EncoderUtil}. */
@ -64,6 +66,13 @@ public class EncoderUtilTest {
.build());
}
@After
public void tearDown() {
ShadowMediaCodecList.reset();
ShadowMediaCodec.clearCodecs();
EncoderUtil.clearCachedEncoders();
}
@Test
public void getSupportedResolution_withSupportedResolution_succeeds() {
ImmutableList<MediaCodecInfo> supportedEncoders = EncoderUtil.getSupportedEncoders(MIME_TYPE);

View File

@ -898,6 +898,8 @@ public final class TransformerEndToEndTest {
private static void removeEncodersAndDecoders() {
ShadowMediaCodec.clearCodecs();
ShadowMediaCodecList.reset();
EncoderUtil.clearCachedEncoders();
}
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.test.ext.junit.runners.AndroidJUnit4;
import com.google.common.collect.ImmutableList;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.shadows.MediaCodecInfoBuilder;
import org.robolectric.shadows.ShadowMediaCodec;
import org.robolectric.shadows.ShadowMediaCodecList;
/** Unit tests for {@link VideoTranscodingSamplePipeline.EncoderWrapper}. */
@ -63,6 +65,13 @@ public final class VideoEncoderWrapperTest {
createShadowH264Encoder();
}
@After
public void tearDown() {
ShadowMediaCodec.clearCodecs();
ShadowMediaCodecList.reset();
EncoderUtil.clearCachedEncoders();
}
@Test
public void getSurfaceInfo_landscape_leavesOrientationUnchanged() throws Exception {
int inputWidth = 200;