Remove ability to run the DefaultVideoCompositor on its own GL thread.

- It's never used and handling multi-threading is costly.
- If the VideoCompositor and the VideoFrameProcessors use separate
threads and the same GlObjectsProvider, the GlObjectsProvider is
accessed from multiple threads. This class doesn't seem designed for
multi-threading.

PiperOrigin-RevId: 723448013
This commit is contained in:
kimvde 2025-02-05 03:52:50 -08:00 committed by Copybara-Service
parent 4c163553e7
commit 92a06606b4
2 changed files with 34 additions and 84 deletions

View File

@ -44,7 +44,6 @@ import androidx.media3.common.util.Log;
import androidx.media3.common.util.LongArrayQueue; import androidx.media3.common.util.LongArrayQueue;
import androidx.media3.common.util.Size; import androidx.media3.common.util.Size;
import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.UnstableApi;
import androidx.media3.common.util.Util;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import java.io.IOException; import java.io.IOException;
@ -78,8 +77,6 @@ public final class DefaultVideoCompositor implements VideoCompositor {
// * Use a lock to synchronize inputFrameInfos more narrowly, to reduce blocking. // * Use a lock to synchronize inputFrameInfos more narrowly, to reduce blocking.
// * Add support for mixing SDR streams with different ColorInfo. // * Add support for mixing SDR streams with different ColorInfo.
// * Add support for HDR input. // * Add support for HDR input.
private static final String THREAD_NAME = "Effect:DefaultVideoCompositor:GlThread";
private static final String TAG = "DefaultVideoCompositor"; private static final String TAG = "DefaultVideoCompositor";
private final VideoCompositor.Listener listener; private final VideoCompositor.Listener listener;
@ -101,8 +98,6 @@ public final class DefaultVideoCompositor implements VideoCompositor {
private @MonotonicNonNull ColorInfo configuredColorInfo; private @MonotonicNonNull ColorInfo configuredColorInfo;
// Only used on the GL Thread.
private @MonotonicNonNull EGLContext eglContext;
private @MonotonicNonNull EGLDisplay eglDisplay; private @MonotonicNonNull EGLDisplay eglDisplay;
private @MonotonicNonNull EGLSurface placeholderEglSurface; private @MonotonicNonNull EGLSurface placeholderEglSurface;
private int primaryInputIndex; private int primaryInputIndex;
@ -110,14 +105,14 @@ public final class DefaultVideoCompositor implements VideoCompositor {
/** /**
* Creates an instance. * Creates an instance.
* *
* <p>If a non-null {@code executorService} is set, the {@link ExecutorService} must be * <p>The {@link ExecutorService} must be {@linkplain ExecutorService#shutdown shut down} by the
* {@linkplain ExecutorService#shutdown shut down} by the caller. * caller.
*/ */
public DefaultVideoCompositor( public DefaultVideoCompositor(
Context context, Context context,
GlObjectsProvider glObjectsProvider, GlObjectsProvider glObjectsProvider,
VideoCompositorSettings settings, VideoCompositorSettings settings,
@Nullable ExecutorService executorService, ExecutorService executorService,
VideoCompositor.Listener listener, VideoCompositor.Listener listener,
GlTextureProducer.Listener textureOutputListener, GlTextureProducer.Listener textureOutputListener,
@IntRange(from = 1) int textureOutputCapacity) { @IntRange(from = 1) int textureOutputCapacity) {
@ -134,14 +129,9 @@ public final class DefaultVideoCompositor implements VideoCompositor {
outputTextureTimestamps = new LongArrayQueue(textureOutputCapacity); outputTextureTimestamps = new LongArrayQueue(textureOutputCapacity);
syncObjects = new LongArrayQueue(textureOutputCapacity); syncObjects = new LongArrayQueue(textureOutputCapacity);
boolean ownsExecutor = executorService == null;
ExecutorService instanceExecutorService =
ownsExecutor ? Util.newSingleThreadExecutor(THREAD_NAME) : checkNotNull(executorService);
videoFrameProcessingTaskExecutor = videoFrameProcessingTaskExecutor =
new VideoFrameProcessingTaskExecutor( new VideoFrameProcessingTaskExecutor(
instanceExecutorService, executorService, /* shouldShutdownExecutorService= */ false, listener::onError);
/* shouldShutdownExecutorService= */ ownsExecutor,
listener::onError);
videoFrameProcessingTaskExecutor.submit(this::setupGlObjects); videoFrameProcessingTaskExecutor.submit(this::setupGlObjects);
} }
@ -293,7 +283,7 @@ public final class DefaultVideoCompositor implements VideoCompositor {
// Below methods must be called on the GL thread. // Below methods must be called on the GL thread.
private void setupGlObjects() throws GlUtil.GlException { private void setupGlObjects() throws GlUtil.GlException {
eglDisplay = GlUtil.getDefaultEglDisplay(); eglDisplay = GlUtil.getDefaultEglDisplay();
eglContext = EGLContext eglContext =
glObjectsProvider.createEglContext( glObjectsProvider.createEglContext(
eglDisplay, /* openGlVersion= */ 2, GlUtil.EGL_CONFIG_ATTRIBUTES_RGBA_8888); eglDisplay, /* openGlVersion= */ 2, GlUtil.EGL_CONFIG_ATTRIBUTES_RGBA_8888);
placeholderEglSurface = placeholderEglSurface =

View File

@ -31,7 +31,6 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Typeface; import android.graphics.Typeface;
import android.opengl.EGLContext;
import android.text.Spannable; import android.text.Spannable;
import android.text.SpannableString; import android.text.SpannableString;
import android.text.style.AbsoluteSizeSpan; import android.text.style.AbsoluteSizeSpan;
@ -65,6 +64,7 @@ import androidx.media3.effect.VideoCompositor;
import androidx.media3.test.utils.BitmapPixelTestUtil; import androidx.media3.test.utils.BitmapPixelTestUtil;
import androidx.media3.test.utils.TextureBitmapReader; import androidx.media3.test.utils.TextureBitmapReader;
import androidx.media3.test.utils.VideoFrameProcessorTestRunner; import androidx.media3.test.utils.VideoFrameProcessorTestRunner;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import java.io.IOException; import java.io.IOException;
@ -82,22 +82,16 @@ import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.TestName; import org.junit.rules.TestName;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
/** Pixel test for {@link DefaultVideoCompositor} compositing 2 input frames into 1 output frame. */ /** Pixel test for {@link DefaultVideoCompositor} compositing 2 input frames into 1 output frame. */
@RunWith(Parameterized.class) @RunWith(AndroidJUnit4.class)
public final class DefaultVideoCompositorPixelTest { public final class DefaultVideoCompositorPixelTest {
@Parameterized.Parameters(name = "useSharedExecutor={0}")
public static ImmutableList<Boolean> useSharedExecutor() {
return ImmutableList.of(true, false);
}
// Golden images were generated on an API 33 emulator. API 26 emulators have a different text // Golden images were generated on an API 33 emulator. API 26 emulators have a different text
// rendering implementation that leads to a larger pixel difference. // rendering implementation that leads to a larger pixel difference.
public static final float MAXIMUM_AVERAGE_PIXEL_ABSOLUTE_DIFFERENCE_WITH_TEXT_OVERLAY = public static final float MAXIMUM_AVERAGE_PIXEL_ABSOLUTE_DIFFERENCE_WITH_TEXT_OVERLAY =
isRunningOnEmulator() && SDK_INT <= 26 ? 2.5f : MAXIMUM_AVERAGE_PIXEL_ABSOLUTE_DIFFERENCE; isRunningOnEmulator() && SDK_INT <= 26 ? 2.5f : MAXIMUM_AVERAGE_PIXEL_ABSOLUTE_DIFFERENCE;
@Parameterized.Parameter public boolean useSharedExecutor;
@Rule public final TestName testName = new TestName(); @Rule public final TestName testName = new TestName();
private static final String ORIGINAL_PNG_ASSET_PATH = "media/png/media3test_srgb.png"; private static final String ORIGINAL_PNG_ASSET_PATH = "media/png/media3test_srgb.png";
@ -128,8 +122,7 @@ public final class DefaultVideoCompositorPixelTest {
@Test @Test
public void compositeTwoInputs_withOneFrameFromEach_differentTimestamp_matchesExpectedBitmap() public void compositeTwoInputs_withOneFrameFromEach_differentTimestamp_matchesExpectedBitmap()
throws Exception { throws Exception {
compositorTestRunner = compositorTestRunner = new VideoCompositorTestRunner(testId, TWO_INPUT_COMPOSITOR_EFFECT_LISTS);
new VideoCompositorTestRunner(testId, useSharedExecutor, TWO_INPUT_COMPOSITOR_EFFECT_LISTS);
compositorTestRunner.queueBitmapToInput( compositorTestRunner.queueBitmapToInput(
/* inputId= */ 0, /* timestamps= */ ImmutableList.of(0L)); /* inputId= */ 0, /* timestamps= */ ImmutableList.of(0L));
@ -158,8 +151,7 @@ public final class DefaultVideoCompositorPixelTest {
ImmutableList.of(new AlphaScale(0f)), ImmutableList.of(new AlphaScale(0f)),
ImmutableList.of( ImmutableList.of(
new ScaleAndRotateTransformation.Builder().setRotationDegrees(180).build())); new ScaleAndRotateTransformation.Builder().setRotationDegrees(180).build()));
compositorTestRunner = compositorTestRunner = new VideoCompositorTestRunner(testId, inputEffectLists);
new VideoCompositorTestRunner(testId, useSharedExecutor, inputEffectLists);
compositorTestRunner.queueBitmapToInput( compositorTestRunner.queueBitmapToInput(
/* inputId= */ 0, /* timestamps= */ ImmutableList.of(0L)); /* inputId= */ 0, /* timestamps= */ ImmutableList.of(0L));
@ -189,8 +181,7 @@ public final class DefaultVideoCompositorPixelTest {
ImmutableList.of(RgbFilter.createGrayscaleFilter(), new AlphaScale(100f)), ImmutableList.of(RgbFilter.createGrayscaleFilter(), new AlphaScale(100f)),
ImmutableList.of( ImmutableList.of(
new ScaleAndRotateTransformation.Builder().setRotationDegrees(180).build())); new ScaleAndRotateTransformation.Builder().setRotationDegrees(180).build()));
compositorTestRunner = compositorTestRunner = new VideoCompositorTestRunner(testId, inputEffectLists);
new VideoCompositorTestRunner(testId, useSharedExecutor, inputEffectLists);
compositorTestRunner.queueBitmapToInput( compositorTestRunner.queueBitmapToInput(
/* inputId= */ 0, /* timestamps= */ ImmutableList.of(0L)); /* inputId= */ 0, /* timestamps= */ ImmutableList.of(0L));
@ -219,8 +210,7 @@ public final class DefaultVideoCompositorPixelTest {
ImmutableList.of( ImmutableList.of(
ImmutableList.of(RgbFilter.createGrayscaleFilter(), new AlphaScale(0.7f)), ImmutableList.of(RgbFilter.createGrayscaleFilter(), new AlphaScale(0.7f)),
ImmutableList.of(new AlphaScale(0f))); ImmutableList.of(new AlphaScale(0f)));
compositorTestRunner = compositorTestRunner = new VideoCompositorTestRunner(testId, inputEffectLists);
new VideoCompositorTestRunner(testId, useSharedExecutor, inputEffectLists);
compositorTestRunner.queueBitmapToInput( compositorTestRunner.queueBitmapToInput(
/* inputId= */ 0, /* timestamps= */ ImmutableList.of(0L)); /* inputId= */ 0, /* timestamps= */ ImmutableList.of(0L));
@ -247,8 +237,7 @@ public final class DefaultVideoCompositorPixelTest {
@Test @Test
public void compositeTwoInputs_withFiveFramesFromEach_matchesExpectedTimestamps() public void compositeTwoInputs_withFiveFramesFromEach_matchesExpectedTimestamps()
throws Exception { throws Exception {
compositorTestRunner = compositorTestRunner = new VideoCompositorTestRunner(testId, TWO_INPUT_COMPOSITOR_EFFECT_LISTS);
new VideoCompositorTestRunner(testId, useSharedExecutor, TWO_INPUT_COMPOSITOR_EFFECT_LISTS);
ImmutableList<Long> expectedTimestamps = ImmutableList<Long> expectedTimestamps =
ImmutableList.of(0L, 1_000_000L, 2_000_000L, 3_000_000L, 4_000_000L); ImmutableList.of(0L, 1_000_000L, 2_000_000L, 3_000_000L, 4_000_000L);
@ -271,8 +260,7 @@ public final class DefaultVideoCompositorPixelTest {
@Test @Test
public void composite_onePrimaryAndFiveSecondaryFrames_matchesExpectedTimestamps() public void composite_onePrimaryAndFiveSecondaryFrames_matchesExpectedTimestamps()
throws Exception { throws Exception {
compositorTestRunner = compositorTestRunner = new VideoCompositorTestRunner(testId, TWO_INPUT_COMPOSITOR_EFFECT_LISTS);
new VideoCompositorTestRunner(testId, useSharedExecutor, TWO_INPUT_COMPOSITOR_EFFECT_LISTS);
ImmutableList<Long> primaryTimestamps = ImmutableList.of(0L); ImmutableList<Long> primaryTimestamps = ImmutableList.of(0L);
ImmutableList<Long> secondaryTimestamps = ImmutableList<Long> secondaryTimestamps =
ImmutableList.of(0L, 1_000_000L, 2_000_000L, 3_000_000L, 4_000_000L); ImmutableList.of(0L, 1_000_000L, 2_000_000L, 3_000_000L, 4_000_000L);
@ -296,8 +284,7 @@ public final class DefaultVideoCompositorPixelTest {
@Test @Test
public void composite_fivePrimaryAndOneSecondaryFrames_matchesExpectedTimestamps() public void composite_fivePrimaryAndOneSecondaryFrames_matchesExpectedTimestamps()
throws Exception { throws Exception {
compositorTestRunner = compositorTestRunner = new VideoCompositorTestRunner(testId, TWO_INPUT_COMPOSITOR_EFFECT_LISTS);
new VideoCompositorTestRunner(testId, useSharedExecutor, TWO_INPUT_COMPOSITOR_EFFECT_LISTS);
ImmutableList<Long> primaryTimestamps = ImmutableList<Long> primaryTimestamps =
ImmutableList.of(0L, 1_000_000L, 2_000_000L, 3_000_000L, 4_000_000L); ImmutableList.of(0L, 1_000_000L, 2_000_000L, 3_000_000L, 4_000_000L);
ImmutableList<Long> secondaryTimestamps = ImmutableList.of(0L); ImmutableList<Long> secondaryTimestamps = ImmutableList.of(0L);
@ -322,8 +309,7 @@ public final class DefaultVideoCompositorPixelTest {
@Test @Test
public void composite_primaryDoubleSecondaryFrameRate_matchesExpectedTimestamps() public void composite_primaryDoubleSecondaryFrameRate_matchesExpectedTimestamps()
throws Exception { throws Exception {
compositorTestRunner = compositorTestRunner = new VideoCompositorTestRunner(testId, TWO_INPUT_COMPOSITOR_EFFECT_LISTS);
new VideoCompositorTestRunner(testId, useSharedExecutor, TWO_INPUT_COMPOSITOR_EFFECT_LISTS);
ImmutableList<Long> primaryTimestamps = ImmutableList<Long> primaryTimestamps =
ImmutableList.of(0L, 1_000_000L, 2_000_000L, 3_000_000L); ImmutableList.of(0L, 1_000_000L, 2_000_000L, 3_000_000L);
ImmutableList<Long> secondaryTimestamps = ImmutableList.of(0L, 2_000_000L); ImmutableList<Long> secondaryTimestamps = ImmutableList.of(0L, 2_000_000L);
@ -347,8 +333,7 @@ public final class DefaultVideoCompositorPixelTest {
@Test @Test
public void composite_primaryHalfSecondaryFrameRate_matchesExpectedTimestamps() throws Exception { public void composite_primaryHalfSecondaryFrameRate_matchesExpectedTimestamps() throws Exception {
compositorTestRunner = compositorTestRunner = new VideoCompositorTestRunner(testId, TWO_INPUT_COMPOSITOR_EFFECT_LISTS);
new VideoCompositorTestRunner(testId, useSharedExecutor, TWO_INPUT_COMPOSITOR_EFFECT_LISTS);
ImmutableList<Long> primaryTimestamps = ImmutableList.of(0L, 2_000_000L); ImmutableList<Long> primaryTimestamps = ImmutableList.of(0L, 2_000_000L);
ImmutableList<Long> secondaryTimestamps = ImmutableList<Long> secondaryTimestamps =
ImmutableList.of(0L, 1_000_000L, 2_000_000L, 3_000_000L); ImmutableList.of(0L, 1_000_000L, 2_000_000L, 3_000_000L);
@ -373,8 +358,7 @@ public final class DefaultVideoCompositorPixelTest {
@Test @Test
public void composite_primaryVariableFrameRateWithOffset_matchesExpectedTimestampsAndBitmaps() public void composite_primaryVariableFrameRateWithOffset_matchesExpectedTimestampsAndBitmaps()
throws Exception { throws Exception {
compositorTestRunner = compositorTestRunner = new VideoCompositorTestRunner(testId, TWO_INPUT_COMPOSITOR_EFFECT_LISTS);
new VideoCompositorTestRunner(testId, useSharedExecutor, TWO_INPUT_COMPOSITOR_EFFECT_LISTS);
ImmutableList<Long> primaryTimestamps = ImmutableList.of(1_000_000L, 3_000_000L, 4_000_000L); ImmutableList<Long> primaryTimestamps = ImmutableList.of(1_000_000L, 3_000_000L, 4_000_000L);
ImmutableList<Long> secondaryTimestamps = ImmutableList<Long> secondaryTimestamps =
ImmutableList.of(0L, 1_000_000L, 2_000_000L, 3_000_000L, 4_000_000L); ImmutableList.of(0L, 1_000_000L, 2_000_000L, 3_000_000L, 4_000_000L);
@ -399,8 +383,7 @@ public final class DefaultVideoCompositorPixelTest {
@Test @Test
public void composite_secondaryVariableFrameRateWithOffset_matchesExpectedTimestampsAndBitmaps() public void composite_secondaryVariableFrameRateWithOffset_matchesExpectedTimestampsAndBitmaps()
throws Exception { throws Exception {
compositorTestRunner = compositorTestRunner = new VideoCompositorTestRunner(testId, TWO_INPUT_COMPOSITOR_EFFECT_LISTS);
new VideoCompositorTestRunner(testId, useSharedExecutor, TWO_INPUT_COMPOSITOR_EFFECT_LISTS);
ImmutableList<Long> primaryTimestamps = ImmutableList<Long> primaryTimestamps =
ImmutableList.of(0L, 1_000_000L, 2_000_000L, 3_000_000L, 4_000_000L); ImmutableList.of(0L, 1_000_000L, 2_000_000L, 3_000_000L, 4_000_000L);
ImmutableList<Long> secondaryTimestamps = ImmutableList.of(1_000_000L, 3_000_000L, 4_000_000L); ImmutableList<Long> secondaryTimestamps = ImmutableList.of(1_000_000L, 3_000_000L, 4_000_000L);
@ -427,8 +410,7 @@ public final class DefaultVideoCompositorPixelTest {
@Test @Test
public void compositeTwoInputs_withTenFramesFromEach_matchesExpectedFrameCount() public void compositeTwoInputs_withTenFramesFromEach_matchesExpectedFrameCount()
throws Exception { throws Exception {
compositorTestRunner = compositorTestRunner = new VideoCompositorTestRunner(testId, TWO_INPUT_COMPOSITOR_EFFECT_LISTS);
new VideoCompositorTestRunner(testId, useSharedExecutor, TWO_INPUT_COMPOSITOR_EFFECT_LISTS);
int numberOfFramesToQueue = 10; int numberOfFramesToQueue = 10;
compositorTestRunner.queueBitmapToAllInputs(/* durationSec= */ numberOfFramesToQueue); compositorTestRunner.queueBitmapToAllInputs(/* durationSec= */ numberOfFramesToQueue);
@ -447,7 +429,6 @@ public final class DefaultVideoCompositorPixelTest {
compositorTestRunner = compositorTestRunner =
new VideoCompositorTestRunner( new VideoCompositorTestRunner(
testId, testId,
useSharedExecutor,
/* inputEffectLists= */ ImmutableList.of( /* inputEffectLists= */ ImmutableList.of(
ImmutableList.of(), ImmutableList.of(),
ImmutableList.of(), ImmutableList.of(),
@ -469,7 +450,6 @@ public final class DefaultVideoCompositorPixelTest {
compositorTestRunner = compositorTestRunner =
new VideoCompositorTestRunner( new VideoCompositorTestRunner(
testId, testId,
useSharedExecutor,
ImmutableList.of( ImmutableList.of(
ImmutableList.of(RgbFilter.createGrayscaleFilter(), new AlphaScale(100f)))); ImmutableList.of(RgbFilter.createGrayscaleFilter(), new AlphaScale(100f))));
@ -489,7 +469,6 @@ public final class DefaultVideoCompositorPixelTest {
compositorTestRunner = compositorTestRunner =
new VideoCompositorTestRunner( new VideoCompositorTestRunner(
testId, testId,
useSharedExecutor,
ImmutableList.of( ImmutableList.of(
ImmutableList.of(RgbFilter.createInvertedFilter(), new AlphaScale(0.4f)), ImmutableList.of(RgbFilter.createInvertedFilter(), new AlphaScale(0.4f)),
ImmutableList.of(RgbFilter.createGrayscaleFilter(), new AlphaScale(0.7f)), ImmutableList.of(RgbFilter.createGrayscaleFilter(), new AlphaScale(0.7f)),
@ -551,7 +530,7 @@ public final class DefaultVideoCompositorPixelTest {
}; };
compositorTestRunner = compositorTestRunner =
new VideoCompositorTestRunner( new VideoCompositorTestRunner(
testId, useSharedExecutor, inputEffectLists, pictureInPictureVideoCompositorSettings); testId, inputEffectLists, pictureInPictureVideoCompositorSettings);
compositorTestRunner.queueBitmapToAllInputs(1); compositorTestRunner.queueBitmapToAllInputs(1);
compositorTestRunner.endCompositing(); compositorTestRunner.endCompositing();
@ -581,10 +560,7 @@ public final class DefaultVideoCompositorPixelTest {
}; };
compositorTestRunner = compositorTestRunner =
new VideoCompositorTestRunner( new VideoCompositorTestRunner(
testId, testId, inputEffectLists, secondStreamAsOutputSizeVideoCompositorSettings);
useSharedExecutor,
inputEffectLists,
secondStreamAsOutputSizeVideoCompositorSettings);
compositorTestRunner.queueBitmapToAllInputs(1); compositorTestRunner.queueBitmapToAllInputs(1);
compositorTestRunner.endCompositing(); compositorTestRunner.endCompositing();
@ -626,7 +602,7 @@ public final class DefaultVideoCompositorPixelTest {
}; };
compositorTestRunner = compositorTestRunner =
new VideoCompositorTestRunner( new VideoCompositorTestRunner(
testId, useSharedExecutor, inputEffectLists, stackedFrameVideoCompositorSettings); testId, inputEffectLists, stackedFrameVideoCompositorSettings);
compositorTestRunner.queueBitmapToAllInputs(1); compositorTestRunner.queueBitmapToAllInputs(1);
compositorTestRunner.endCompositing(); compositorTestRunner.endCompositing();
@ -646,7 +622,7 @@ public final class DefaultVideoCompositorPixelTest {
private final LinkedHashMap<Long, Bitmap> outputTimestampsToBitmaps; private final LinkedHashMap<Long, Bitmap> outputTimestampsToBitmaps;
private final List<VideoFrameProcessorTestRunner> inputVideoFrameProcessorTestRunners; private final List<VideoFrameProcessorTestRunner> inputVideoFrameProcessorTestRunners;
private final VideoCompositor videoCompositor; private final VideoCompositor videoCompositor;
@Nullable private final ExecutorService sharedExecutorService; private final ExecutorService sharedExecutorService;
private final AtomicReference<VideoFrameProcessingException> compositionException; private final AtomicReference<VideoFrameProcessingException> compositionException;
private final CountDownLatch compositorEnded; private final CountDownLatch compositorEnded;
private final String testId; private final String testId;
@ -655,27 +631,21 @@ public final class DefaultVideoCompositorPixelTest {
* Creates an instance using {@link VideoCompositorSettings}. * Creates an instance using {@link VideoCompositorSettings}.
* *
* @param testId The {@link String} identifier for the test, used to name output files. * @param testId The {@link String} identifier for the test, used to name output files.
* @param useSharedExecutor Whether to use a shared executor for {@link
* VideoFrameProcessorTestRunner} and {@link VideoCompositor} instances.
* @param inputEffectLists {@link Effect}s to apply for {@link VideoCompositor} input sources. * @param inputEffectLists {@link Effect}s to apply for {@link VideoCompositor} input sources.
* The size of this outer {@link List} is the amount of inputs. One inner list of {@link * The size of this outer {@link List} is the amount of inputs. One inner list of {@link
* Effect}s is used for each input. For each input, the frame timestamp and {@code inputId} * Effect}s is used for each input. For each input, the frame timestamp and {@code inputId}
* are overlaid via {@link TextOverlay} prior to its effects being applied. * are overlaid via {@link TextOverlay} prior to its effects being applied.
*/ */
public VideoCompositorTestRunner( public VideoCompositorTestRunner(
String testId, String testId, ImmutableList<ImmutableList<Effect>> inputEffectLists)
boolean useSharedExecutor,
ImmutableList<ImmutableList<Effect>> inputEffectLists)
throws GlUtil.GlException, VideoFrameProcessingException { throws GlUtil.GlException, VideoFrameProcessingException {
this(testId, useSharedExecutor, inputEffectLists, VideoCompositorSettings.DEFAULT); this(testId, inputEffectLists, VideoCompositorSettings.DEFAULT);
} }
/** /**
* Creates an instance. * Creates an instance.
* *
* @param testId The {@link String} identifier for the test, used to name output files. * @param testId The {@link String} identifier for the test, used to name output files.
* @param useSharedExecutor Whether to use a shared executor for {@link
* VideoFrameProcessorTestRunner} and {@link VideoCompositor} instances.
* @param inputEffectLists {@link Effect}s to apply for {@link VideoCompositor} input sources. * @param inputEffectLists {@link Effect}s to apply for {@link VideoCompositor} input sources.
* The size of this outer {@link List} is the amount of inputs. One inner list of {@link * The size of this outer {@link List} is the amount of inputs. One inner list of {@link
* Effect}s is used for each input. For each input, the frame timestamp and {@code inputId} * Effect}s is used for each input. For each input, the frame timestamp and {@code inputId}
@ -684,18 +654,13 @@ public final class DefaultVideoCompositorPixelTest {
*/ */
public VideoCompositorTestRunner( public VideoCompositorTestRunner(
String testId, String testId,
boolean useSharedExecutor,
ImmutableList<ImmutableList<Effect>> inputEffectLists, ImmutableList<ImmutableList<Effect>> inputEffectLists,
VideoCompositorSettings videoCompositorSettings) VideoCompositorSettings videoCompositorSettings)
throws GlUtil.GlException, VideoFrameProcessingException { throws GlUtil.GlException, VideoFrameProcessingException {
this.testId = testId; this.testId = testId;
timeoutMs = inputEffectLists.size() * VIDEO_FRAME_PROCESSING_WAIT_MS; timeoutMs = inputEffectLists.size() * VIDEO_FRAME_PROCESSING_WAIT_MS;
sharedExecutorService = sharedExecutorService = Util.newSingleThreadExecutor("Effect:Shared:GlThread");
useSharedExecutor ? Util.newSingleThreadExecutor("Effect:Shared:GlThread") : null; GlObjectsProvider glObjectsProvider = new DefaultGlObjectsProvider();
EGLContext sharedEglContext = AndroidTestUtil.createOpenGlObjects();
GlObjectsProvider glObjectsProvider =
new DefaultGlObjectsProvider(
/* sharedEglContext= */ useSharedExecutor ? null : sharedEglContext);
compositionException = new AtomicReference<>(); compositionException = new AtomicReference<>();
outputTimestampsToBitmaps = new LinkedHashMap<>(); outputTimestampsToBitmaps = new LinkedHashMap<>();
@ -722,9 +687,6 @@ public final class DefaultVideoCompositorPixelTest {
outputTexture, outputTexture,
presentationTimeUs, presentationTimeUs,
syncObject) -> { syncObject) -> {
if (!useSharedExecutor) {
GlUtil.awaitSyncObject(syncObject);
}
outputTimestampsToBitmaps.put( outputTimestampsToBitmaps.put(
presentationTimeUs, presentationTimeUs,
BitmapPixelTestUtil.createUnpremultipliedArgb8888BitmapFromFocusedGlFramebuffer( BitmapPixelTestUtil.createUnpremultipliedArgb8888BitmapFromFocusedGlFramebuffer(
@ -839,7 +801,6 @@ public final class DefaultVideoCompositorPixelTest {
} }
videoCompositor.release(); videoCompositor.release();
if (sharedExecutorService != null) {
try { try {
sharedExecutorService.shutdown(); sharedExecutorService.shutdown();
if (!sharedExecutorService.awaitTermination(timeoutMs, MILLISECONDS)) { if (!sharedExecutorService.awaitTermination(timeoutMs, MILLISECONDS)) {
@ -850,7 +811,6 @@ public final class DefaultVideoCompositorPixelTest {
throw new IllegalStateException(unexpected); throw new IllegalStateException(unexpected);
} }
} }
}
private static VideoFrameProcessorTestRunner.Builder createVideoFrameProcessorTestRunnerBuilder( private static VideoFrameProcessorTestRunner.Builder createVideoFrameProcessorTestRunnerBuilder(
String testId, String testId,