mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
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:
parent
4c163553e7
commit
92a06606b4
@ -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 =
|
||||||
|
@ -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,16 +801,14 @@ 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)) {
|
throw new IllegalStateException("Missed shutdown timeout.");
|
||||||
throw new IllegalStateException("Missed shutdown timeout.");
|
|
||||||
}
|
|
||||||
} catch (InterruptedException unexpected) {
|
|
||||||
Thread.currentThread().interrupt();
|
|
||||||
throw new IllegalStateException(unexpected);
|
|
||||||
}
|
}
|
||||||
|
} catch (InterruptedException unexpected) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
throw new IllegalStateException(unexpected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user