Compositor: Queue bitmaps by timestamp.

This allows us to manage timestamps in one list, instead of both via
offsets/framerates, and a list.

PiperOrigin-RevId: 560053888
This commit is contained in:
huangdarwin 2023-08-25 04:42:07 -07:00 committed by Copybara-Service
parent 7899241daf
commit 01689ba2ec
3 changed files with 87 additions and 148 deletions

View File

@ -17,18 +17,16 @@ package androidx.media3.effect;
import static androidx.media3.common.util.Assertions.checkNotNull; import static androidx.media3.common.util.Assertions.checkNotNull;
import static androidx.media3.test.utils.BitmapPixelTestUtil.readBitmap; import static androidx.media3.test.utils.BitmapPixelTestUtil.readBitmap;
import static androidx.media3.test.utils.VideoFrameProcessorTestRunner.createTimestampIterator;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.util.Pair; import android.util.Pair;
import androidx.media3.common.C; import androidx.media3.common.C;
import androidx.media3.common.ColorInfo; import androidx.media3.common.ColorInfo;
import androidx.media3.common.util.TimestampIterator;
import androidx.media3.test.utils.VideoFrameProcessorTestRunner; import androidx.media3.test.utils.VideoFrameProcessorTestRunner;
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 java.util.Iterator;
import java.util.List;
import java.util.Queue; import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
@ -193,29 +191,6 @@ public class DefaultVideoFrameProcessorImageFrameOutputTest {
assertThat(actualPresentationTimesUs).containsExactly(offset1, offset2, offset3).inOrder(); assertThat(actualPresentationTimesUs).containsExactly(offset1, offset2, offset3).inOrder();
} }
private static TimestampIterator createTimestampIterator(List<Long> elements) {
Iterator<Long> elementsIterator = elements.iterator();
return new TimestampIterator() {
@Override
public boolean hasNext() {
return elementsIterator.hasNext();
}
@Override
public long next() {
return elementsIterator.next();
}
@Override
public TimestampIterator copyOf() {
// Method not needed for effects tests.
throw new UnsupportedOperationException();
}
};
}
private VideoFrameProcessorTestRunner.Builder getDefaultFrameProcessorTestRunnerBuilder( private VideoFrameProcessorTestRunner.Builder getDefaultFrameProcessorTestRunnerBuilder(
String testId) { String testId) {
return new VideoFrameProcessorTestRunner.Builder() return new VideoFrameProcessorTestRunner.Builder()

View File

@ -53,6 +53,7 @@ import androidx.media3.common.util.UnstableApi;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.MoreExecutors; import com.google.common.util.concurrent.MoreExecutors;
import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
@ -524,4 +525,27 @@ public final class VideoFrameProcessorTestRunner {
return outputBitmap; return outputBitmap;
} }
} }
public static TimestampIterator createTimestampIterator(List<Long> elements) {
Iterator<Long> elementsIterator = elements.iterator();
return new TimestampIterator() {
@Override
public boolean hasNext() {
return elementsIterator.hasNext();
}
@Override
public long next() {
return elementsIterator.next();
}
@Override
public TimestampIterator copyOf() {
// Method not needed for effects tests.
throw new UnsupportedOperationException();
}
};
}
} }

View File

@ -20,6 +20,7 @@ import static androidx.media3.test.utils.BitmapPixelTestUtil.MAXIMUM_AVERAGE_PIX
import static androidx.media3.test.utils.BitmapPixelTestUtil.maybeSaveTestBitmap; import static androidx.media3.test.utils.BitmapPixelTestUtil.maybeSaveTestBitmap;
import static androidx.media3.test.utils.BitmapPixelTestUtil.readBitmapUnpremultipliedAlpha; import static androidx.media3.test.utils.BitmapPixelTestUtil.readBitmapUnpremultipliedAlpha;
import static androidx.media3.test.utils.VideoFrameProcessorTestRunner.VIDEO_FRAME_PROCESSING_WAIT_MS; import static androidx.media3.test.utils.VideoFrameProcessorTestRunner.VIDEO_FRAME_PROCESSING_WAIT_MS;
import static androidx.media3.test.utils.VideoFrameProcessorTestRunner.createTimestampIterator;
import static androidx.test.core.app.ApplicationProvider.getApplicationContext; import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage; import static com.google.common.truth.Truth.assertWithMessage;
@ -36,6 +37,7 @@ import android.text.style.BackgroundColorSpan;
import android.text.style.ForegroundColorSpan; import android.text.style.ForegroundColorSpan;
import android.text.style.StyleSpan; import android.text.style.StyleSpan;
import android.text.style.TypefaceSpan; import android.text.style.TypefaceSpan;
import android.util.Pair;
import androidx.media3.common.C; import androidx.media3.common.C;
import androidx.media3.common.ColorInfo; import androidx.media3.common.ColorInfo;
import androidx.media3.common.Effect; import androidx.media3.common.Effect;
@ -81,8 +83,6 @@ 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(Parameterized.class)
public final class DefaultVideoCompositorPixelTest { public final class DefaultVideoCompositorPixelTest {
// TODO: b/262694346 - Have CompositorTestRunner queueBitmapToInput queue bitmaps at specified
// timestamps instead of frame rates.
@Parameterized.Parameters(name = "useSharedExecutor={0}") @Parameterized.Parameters(name = "useSharedExecutor={0}")
public static ImmutableList<Boolean> useSharedExecutor() { public static ImmutableList<Boolean> useSharedExecutor() {
return ImmutableList.of(true, false); return ImmutableList.of(true, false);
@ -133,9 +133,9 @@ public final class DefaultVideoCompositorPixelTest {
new VideoCompositorTestRunner(testId, useSharedExecutor, TWO_INPUT_COMPOSITOR_EFFECT_LISTS); new VideoCompositorTestRunner(testId, useSharedExecutor, TWO_INPUT_COMPOSITOR_EFFECT_LISTS);
compositorTestRunner.queueBitmapToInput( compositorTestRunner.queueBitmapToInput(
/* inputId= */ 0, /* durationSec= */ 1, /* offsetToAddSec= */ 0, /* frameRate= */ 1); /* inputId= */ 0, /* timestamps= */ ImmutableList.of(0L));
compositorTestRunner.queueBitmapToInput( compositorTestRunner.queueBitmapToInput(
/* inputId= */ 1, /* durationSec= */ 1, /* offsetToAddSec= */ 1, /* frameRate= */ 1); /* inputId= */ 1, /* timestamps= */ ImmutableList.of(1_000_000L));
compositorTestRunner.endCompositing(); compositorTestRunner.endCompositing();
saveAndAssertBitmapMatchesExpected( saveAndAssertBitmapMatchesExpected(
@ -163,9 +163,9 @@ public final class DefaultVideoCompositorPixelTest {
compositorTestRunner = new VideoCompositorTestRunner(testId, useSharedExecutor, inputEffects); compositorTestRunner = new VideoCompositorTestRunner(testId, useSharedExecutor, inputEffects);
compositorTestRunner.queueBitmapToInput( compositorTestRunner.queueBitmapToInput(
/* inputId= */ 0, /* durationSec= */ 1, /* offsetToAddSec= */ 0, /* frameRate= */ 1); /* inputId= */ 0, /* timestamps= */ ImmutableList.of(0L));
compositorTestRunner.queueBitmapToInput( compositorTestRunner.queueBitmapToInput(
/* inputId= */ 1, /* durationSec= */ 1, /* offsetToAddSec= */ 1, /* frameRate= */ 1); /* inputId= */ 1, /* timestamps= */ ImmutableList.of(1_000_000L));
compositorTestRunner.endCompositing(); compositorTestRunner.endCompositing();
saveAndAssertBitmapMatchesExpected( saveAndAssertBitmapMatchesExpected(
@ -194,9 +194,9 @@ public final class DefaultVideoCompositorPixelTest {
compositorTestRunner = new VideoCompositorTestRunner(testId, useSharedExecutor, inputEffects); compositorTestRunner = new VideoCompositorTestRunner(testId, useSharedExecutor, inputEffects);
compositorTestRunner.queueBitmapToInput( compositorTestRunner.queueBitmapToInput(
/* inputId= */ 0, /* durationSec= */ 1, /* offsetToAddSec= */ 0, /* frameRate= */ 1); /* inputId= */ 0, /* timestamps= */ ImmutableList.of(0L));
compositorTestRunner.queueBitmapToInput( compositorTestRunner.queueBitmapToInput(
/* inputId= */ 1, /* durationSec= */ 1, /* offsetToAddSec= */ 1, /* frameRate= */ 1); /* inputId= */ 1, /* timestamps= */ ImmutableList.of(1_000_000L));
compositorTestRunner.endCompositing(); compositorTestRunner.endCompositing();
saveAndAssertBitmapMatchesExpected( saveAndAssertBitmapMatchesExpected(
@ -224,9 +224,9 @@ public final class DefaultVideoCompositorPixelTest {
compositorTestRunner = new VideoCompositorTestRunner(testId, useSharedExecutor, inputEffects); compositorTestRunner = new VideoCompositorTestRunner(testId, useSharedExecutor, inputEffects);
compositorTestRunner.queueBitmapToInput( compositorTestRunner.queueBitmapToInput(
/* inputId= */ 0, /* durationSec= */ 1, /* offsetToAddSec= */ 0, /* frameRate= */ 1); /* inputId= */ 0, /* timestamps= */ ImmutableList.of(0L));
compositorTestRunner.queueBitmapToInput( compositorTestRunner.queueBitmapToInput(
/* inputId= */ 1, /* durationSec= */ 1, /* offsetToAddSec= */ 1, /* frameRate= */ 1); /* inputId= */ 1, /* timestamps= */ ImmutableList.of(1_000_000L));
compositorTestRunner.endCompositing(); compositorTestRunner.endCompositing();
saveAndAssertBitmapMatchesExpected( saveAndAssertBitmapMatchesExpected(
@ -249,17 +249,12 @@ public final class DefaultVideoCompositorPixelTest {
throws Exception { throws Exception {
compositorTestRunner = compositorTestRunner =
new VideoCompositorTestRunner(testId, useSharedExecutor, TWO_INPUT_COMPOSITOR_EFFECT_LISTS); new VideoCompositorTestRunner(testId, useSharedExecutor, TWO_INPUT_COMPOSITOR_EFFECT_LISTS);
ImmutableList<Long> expectedTimestamps =
ImmutableList.of(0L, 1_000_000L, 2_000_000L, 3_000_000L, 4_000_000L);
compositorTestRunner.queueBitmapToAllInputs(/* durationSec= */ 5); compositorTestRunner.queueBitmapToAllInputs(/* durationSec= */ 5);
compositorTestRunner.endCompositing(); compositorTestRunner.endCompositing();
ImmutableList<Long> expectedTimestamps =
ImmutableList.of(
0 * C.MICROS_PER_SECOND,
1 * C.MICROS_PER_SECOND,
2 * C.MICROS_PER_SECOND,
3 * C.MICROS_PER_SECOND,
4 * C.MICROS_PER_SECOND);
assertThat(compositorTestRunner.inputBitmapReaders.get(0).getOutputTimestamps()) assertThat(compositorTestRunner.inputBitmapReaders.get(0).getOutputTimestamps())
.containsExactlyElementsIn(expectedTimestamps) .containsExactlyElementsIn(expectedTimestamps)
.inOrder(); .inOrder();
@ -279,21 +274,14 @@ public final class DefaultVideoCompositorPixelTest {
throws Exception { throws Exception {
compositorTestRunner = compositorTestRunner =
new VideoCompositorTestRunner(testId, useSharedExecutor, TWO_INPUT_COMPOSITOR_EFFECT_LISTS); new VideoCompositorTestRunner(testId, useSharedExecutor, TWO_INPUT_COMPOSITOR_EFFECT_LISTS);
ImmutableList<Long> primaryTimestamps = ImmutableList.of(0L);
ImmutableList<Long> secondaryTimestamps =
ImmutableList.of(0L, 1_000_000L, 2_000_000L, 3_000_000L, 4_000_000L);
compositorTestRunner.queueBitmapToInput( compositorTestRunner.queueBitmapToInput(/* inputId= */ 0, primaryTimestamps);
/* inputId= */ 0, /* durationSec= */ 5, /* offsetToAddSec= */ 0, /* frameRate= */ 0.2f); compositorTestRunner.queueBitmapToInput(/* inputId= */ 1, secondaryTimestamps);
compositorTestRunner.queueBitmapToInput(
/* inputId= */ 1, /* durationSec= */ 5, /* offsetToAddSec= */ 0, /* frameRate= */ 1f);
compositorTestRunner.endCompositing(); compositorTestRunner.endCompositing();
ImmutableList<Long> primaryTimestamps = ImmutableList.of(0 * C.MICROS_PER_SECOND);
ImmutableList<Long> secondaryTimestamps =
ImmutableList.of(
0 * C.MICROS_PER_SECOND,
1 * C.MICROS_PER_SECOND,
2 * C.MICROS_PER_SECOND,
3 * C.MICROS_PER_SECOND,
4 * C.MICROS_PER_SECOND);
assertThat(compositorTestRunner.inputBitmapReaders.get(0).getOutputTimestamps()) assertThat(compositorTestRunner.inputBitmapReaders.get(0).getOutputTimestamps())
.containsExactlyElementsIn(primaryTimestamps) .containsExactlyElementsIn(primaryTimestamps)
.inOrder(); .inOrder();
@ -312,21 +300,14 @@ public final class DefaultVideoCompositorPixelTest {
throws Exception { throws Exception {
compositorTestRunner = compositorTestRunner =
new VideoCompositorTestRunner(testId, useSharedExecutor, TWO_INPUT_COMPOSITOR_EFFECT_LISTS); new VideoCompositorTestRunner(testId, useSharedExecutor, TWO_INPUT_COMPOSITOR_EFFECT_LISTS);
ImmutableList<Long> primaryTimestamps =
ImmutableList.of(0L, 1_000_000L, 2_000_000L, 3_000_000L, 4_000_000L);
ImmutableList<Long> secondaryTimestamps = ImmutableList.of(0L);
compositorTestRunner.queueBitmapToInput( compositorTestRunner.queueBitmapToInput(/* inputId= */ 0, primaryTimestamps);
/* inputId= */ 0, /* durationSec= */ 5, /* offsetToAddSec= */ 0, /* frameRate= */ 1f); compositorTestRunner.queueBitmapToInput(/* inputId= */ 1, secondaryTimestamps);
compositorTestRunner.queueBitmapToInput(
/* inputId= */ 1, /* durationSec= */ 5, /* offsetToAddSec= */ 0, /* frameRate= */ 0.2f);
compositorTestRunner.endCompositing(); compositorTestRunner.endCompositing();
ImmutableList<Long> primaryTimestamps =
ImmutableList.of(
0 * C.MICROS_PER_SECOND,
1 * C.MICROS_PER_SECOND,
2 * C.MICROS_PER_SECOND,
3 * C.MICROS_PER_SECOND,
4 * C.MICROS_PER_SECOND);
ImmutableList<Long> secondaryTimestamps = ImmutableList.of(0 * C.MICROS_PER_SECOND);
assertThat(compositorTestRunner.inputBitmapReaders.get(0).getOutputTimestamps()) assertThat(compositorTestRunner.inputBitmapReaders.get(0).getOutputTimestamps())
.containsExactlyElementsIn(primaryTimestamps) .containsExactlyElementsIn(primaryTimestamps)
.inOrder(); .inOrder();
@ -346,21 +327,14 @@ public final class DefaultVideoCompositorPixelTest {
throws Exception { throws Exception {
compositorTestRunner = compositorTestRunner =
new VideoCompositorTestRunner(testId, useSharedExecutor, TWO_INPUT_COMPOSITOR_EFFECT_LISTS); new VideoCompositorTestRunner(testId, useSharedExecutor, TWO_INPUT_COMPOSITOR_EFFECT_LISTS);
ImmutableList<Long> primaryTimestamps =
ImmutableList.of(0L, 1_000_000L, 2_000_000L, 3_000_000L);
ImmutableList<Long> secondaryTimestamps = ImmutableList.of(0L, 2_000_000L);
compositorTestRunner.queueBitmapToInput( compositorTestRunner.queueBitmapToInput(/* inputId= */ 0, primaryTimestamps);
/* inputId= */ 0, /* durationSec= */ 4, /* offsetToAddSec= */ 0, /* frameRate= */ 1f); compositorTestRunner.queueBitmapToInput(/* inputId= */ 1, secondaryTimestamps);
compositorTestRunner.queueBitmapToInput(
/* inputId= */ 1, /* durationSec= */ 4, /* offsetToAddSec= */ 0, /* frameRate= */ 0.5f);
compositorTestRunner.endCompositing(); compositorTestRunner.endCompositing();
ImmutableList<Long> primaryTimestamps =
ImmutableList.of(
0 * C.MICROS_PER_SECOND,
1 * C.MICROS_PER_SECOND,
2 * C.MICROS_PER_SECOND,
3 * C.MICROS_PER_SECOND);
ImmutableList<Long> secondaryTimestamps =
ImmutableList.of(0 * C.MICROS_PER_SECOND, 2 * C.MICROS_PER_SECOND);
assertThat(compositorTestRunner.inputBitmapReaders.get(0).getOutputTimestamps()) assertThat(compositorTestRunner.inputBitmapReaders.get(0).getOutputTimestamps())
.containsExactlyElementsIn(primaryTimestamps) .containsExactlyElementsIn(primaryTimestamps)
.inOrder(); .inOrder();
@ -379,21 +353,14 @@ public final class DefaultVideoCompositorPixelTest {
public void composite_primaryHalfSecondaryFrameRate_matchesExpectedTimestamps() throws Exception { public void composite_primaryHalfSecondaryFrameRate_matchesExpectedTimestamps() throws Exception {
compositorTestRunner = compositorTestRunner =
new VideoCompositorTestRunner(testId, useSharedExecutor, 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> secondaryTimestamps =
ImmutableList.of(0L, 1_000_000L, 2_000_000L, 3_000_000L);
compositorTestRunner.queueBitmapToInput( compositorTestRunner.queueBitmapToInput(/* inputId= */ 0, primaryTimestamps);
/* inputId= */ 0, /* durationSec= */ 4, /* offsetToAddSec= */ 0, /* frameRate= */ 0.5f); compositorTestRunner.queueBitmapToInput(/* inputId= */ 1, secondaryTimestamps);
compositorTestRunner.queueBitmapToInput(
/* inputId= */ 1, /* durationSec= */ 4, /* offsetToAddSec= */ 0, /* frameRate= */ 1f);
compositorTestRunner.endCompositing(); compositorTestRunner.endCompositing();
ImmutableList<Long> primaryTimestamps =
ImmutableList.of(0 * C.MICROS_PER_SECOND, 2 * C.MICROS_PER_SECOND);
ImmutableList<Long> secondaryTimestamps =
ImmutableList.of(
0 * C.MICROS_PER_SECOND,
1 * C.MICROS_PER_SECOND,
2 * C.MICROS_PER_SECOND,
3 * C.MICROS_PER_SECOND);
assertThat(compositorTestRunner.inputBitmapReaders.get(0).getOutputTimestamps()) assertThat(compositorTestRunner.inputBitmapReaders.get(0).getOutputTimestamps())
.containsExactlyElementsIn(primaryTimestamps) .containsExactlyElementsIn(primaryTimestamps)
.inOrder(); .inOrder();
@ -413,24 +380,14 @@ public final class DefaultVideoCompositorPixelTest {
throws Exception { throws Exception {
compositorTestRunner = compositorTestRunner =
new VideoCompositorTestRunner(testId, useSharedExecutor, 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> secondaryTimestamps =
ImmutableList.of(0L, 1_000_000L, 2_000_000L, 3_000_000L, 4_000_000L);
compositorTestRunner.queueBitmapToInput( compositorTestRunner.queueBitmapToInput(/* inputId= */ 0, primaryTimestamps);
/* inputId= */ 0, /* durationSec= */ 2, /* offsetToAddSec= */ 1, /* frameRate= */ 0.5f); compositorTestRunner.queueBitmapToInput(/* inputId= */ 1, secondaryTimestamps);
compositorTestRunner.queueBitmapToInput(
/* inputId= */ 0, /* durationSec= */ 2, /* offsetToAddSec= */ 3, /* frameRate= */ 1f);
compositorTestRunner.queueBitmapToInput(
/* inputId= */ 1, /* durationSec= */ 5, /* offsetToAddSec= */ 0, /* frameRate= */ 1f);
compositorTestRunner.endCompositing(); compositorTestRunner.endCompositing();
ImmutableList<Long> primaryTimestamps =
ImmutableList.of(1 * C.MICROS_PER_SECOND, 3 * C.MICROS_PER_SECOND, 4 * C.MICROS_PER_SECOND);
ImmutableList<Long> secondaryTimestamps =
ImmutableList.of(
0 * C.MICROS_PER_SECOND,
1 * C.MICROS_PER_SECOND,
2 * C.MICROS_PER_SECOND,
3 * C.MICROS_PER_SECOND,
4 * C.MICROS_PER_SECOND);
assertThat(compositorTestRunner.inputBitmapReaders.get(0).getOutputTimestamps()) assertThat(compositorTestRunner.inputBitmapReaders.get(0).getOutputTimestamps())
.containsExactlyElementsIn(primaryTimestamps) .containsExactlyElementsIn(primaryTimestamps)
.inOrder(); .inOrder();
@ -450,24 +407,14 @@ public final class DefaultVideoCompositorPixelTest {
throws Exception { throws Exception {
compositorTestRunner = compositorTestRunner =
new VideoCompositorTestRunner(testId, useSharedExecutor, TWO_INPUT_COMPOSITOR_EFFECT_LISTS); new VideoCompositorTestRunner(testId, useSharedExecutor, TWO_INPUT_COMPOSITOR_EFFECT_LISTS);
ImmutableList<Long> primaryTimestamps =
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);
compositorTestRunner.queueBitmapToInput( compositorTestRunner.queueBitmapToInput(/* inputId= */ 0, primaryTimestamps);
/* inputId= */ 0, /* durationSec= */ 5, /* offsetToAddSec= */ 0, /* frameRate= */ 1f); compositorTestRunner.queueBitmapToInput(/* inputId= */ 1, secondaryTimestamps);
compositorTestRunner.queueBitmapToInput(
/* inputId= */ 1, /* durationSec= */ 2, /* offsetToAddSec= */ 1, /* frameRate= */ 0.5f);
compositorTestRunner.queueBitmapToInput(
/* inputId= */ 1, /* durationSec= */ 2, /* offsetToAddSec= */ 3, /* frameRate= */ 1f);
compositorTestRunner.endCompositing(); compositorTestRunner.endCompositing();
ImmutableList<Long> primaryTimestamps =
ImmutableList.of(
0 * C.MICROS_PER_SECOND,
1 * C.MICROS_PER_SECOND,
2 * C.MICROS_PER_SECOND,
3 * C.MICROS_PER_SECOND,
4 * C.MICROS_PER_SECOND);
ImmutableList<Long> secondaryTimestamps =
ImmutableList.of(1 * C.MICROS_PER_SECOND, 3 * C.MICROS_PER_SECOND, 4 * C.MICROS_PER_SECOND);
assertThat(compositorTestRunner.inputBitmapReaders.get(0).getOutputTimestamps()) assertThat(compositorTestRunner.inputBitmapReaders.get(0).getOutputTimestamps())
.containsExactlyElementsIn(primaryTimestamps) .containsExactlyElementsIn(primaryTimestamps)
.inOrder(); .inOrder();
@ -534,8 +481,7 @@ public final class DefaultVideoCompositorPixelTest {
compositorTestRunner.queueBitmapToAllInputs(/* durationSec= */ 3); compositorTestRunner.queueBitmapToAllInputs(/* durationSec= */ 3);
compositorTestRunner.endCompositing(); compositorTestRunner.endCompositing();
ImmutableList<Long> primaryTimestamps = ImmutableList<Long> primaryTimestamps = ImmutableList.of(0L, 1_000_000L, 2_000_000L);
ImmutableList.of(0 * C.MICROS_PER_SECOND, 1 * C.MICROS_PER_SECOND, 2 * C.MICROS_PER_SECOND);
assertThat(compositorTestRunner.inputBitmapReaders.get(0).getOutputTimestamps()) assertThat(compositorTestRunner.inputBitmapReaders.get(0).getOutputTimestamps())
.containsExactlyElementsIn(primaryTimestamps) .containsExactlyElementsIn(primaryTimestamps)
.inOrder(); .inOrder();
@ -555,20 +501,15 @@ public final class DefaultVideoCompositorPixelTest {
ImmutableList.of(RgbFilter.createGrayscaleFilter(), new AlphaScale(0.7f)), ImmutableList.of(RgbFilter.createGrayscaleFilter(), new AlphaScale(0.7f)),
ImmutableList.of( ImmutableList.of(
new ScaleAndRotateTransformation.Builder().setRotationDegrees(180).build()))); new ScaleAndRotateTransformation.Builder().setRotationDegrees(180).build())));
ImmutableList<Long> primaryTimestamps = ImmutableList.of(0L, 1_000_000L, 2_000_000L);
ImmutableList<Long> secondary1Timestamps = ImmutableList.of(1_000_000L);
ImmutableList<Long> secondary2Timestamps = ImmutableList.of(0L, 2_000_000L);
compositorTestRunner.queueBitmapToInput( compositorTestRunner.queueBitmapToInput(/* inputId= */ 0, primaryTimestamps);
/* inputId= */ 0, /* durationSec= */ 3, /* offsetToAddSec= */ 0, /* frameRate= */ 1); compositorTestRunner.queueBitmapToInput(/* inputId= */ 1, secondary1Timestamps);
compositorTestRunner.queueBitmapToInput( compositorTestRunner.queueBitmapToInput(/* inputId= */ 2, secondary2Timestamps);
/* inputId= */ 1, /* durationSec= */ 1, /* offsetToAddSec= */ 1, /* frameRate= */ 1);
compositorTestRunner.queueBitmapToInput(
/* inputId= */ 2, /* durationSec= */ 3, /* offsetToAddSec= */ 0, /* frameRate= */ 0.5f);
compositorTestRunner.endCompositing(); compositorTestRunner.endCompositing();
ImmutableList<Long> primaryTimestamps =
ImmutableList.of(0 * C.MICROS_PER_SECOND, 1 * C.MICROS_PER_SECOND, 2 * C.MICROS_PER_SECOND);
ImmutableList<Long> secondary1Timestamps = ImmutableList.of(1 * C.MICROS_PER_SECOND);
ImmutableList<Long> secondary2Timestamps =
ImmutableList.of(0 * C.MICROS_PER_SECOND, 2 * C.MICROS_PER_SECOND);
assertThat(compositorTestRunner.inputBitmapReaders.get(0).getOutputTimestamps()) assertThat(compositorTestRunner.inputBitmapReaders.get(0).getOutputTimestamps())
.containsExactlyElementsIn(primaryTimestamps) .containsExactlyElementsIn(primaryTimestamps)
.inOrder(); .inOrder();
@ -687,26 +628,25 @@ public final class DefaultVideoCompositorPixelTest {
*/ */
public void queueBitmapToAllInputs(int durationSec) throws IOException, InterruptedException { public void queueBitmapToAllInputs(int durationSec) throws IOException, InterruptedException {
for (int i = 0; i < inputVideoFrameProcessorTestRunners.size(); i++) { for (int i = 0; i < inputVideoFrameProcessorTestRunners.size(); i++) {
queueBitmapToInput(
/* inputId= */ i, durationSec, /* offsetToAddSec= */ 0L, /* frameRate= */ 1f);
}
}
/**
* Queues {@code durationSec} bitmaps, with one bitmap per second, starting from and including
* {@code 0} seconds. The primary source has a {@code frameRate} of {@code 1}, while secondary
* sources have a {@code frameRate} of {@code secondarySourceFrameRate}.
*/
public void queueBitmapToInput(
int inputId, int durationSec, long offsetToAddSec, float frameRate)
throws IOException, InterruptedException {
inputVideoFrameProcessorTestRunners inputVideoFrameProcessorTestRunners
.get(inputId) .get(i)
.queueInputBitmap( .queueInputBitmap(
readBitmapUnpremultipliedAlpha(ORIGINAL_PNG_ASSET_PATH), readBitmapUnpremultipliedAlpha(ORIGINAL_PNG_ASSET_PATH),
/* durationUs= */ durationSec * C.MICROS_PER_SECOND, /* durationUs= */ durationSec * C.MICROS_PER_SECOND,
/* offsetToAddUs= */ offsetToAddSec * C.MICROS_PER_SECOND, /* offsetToAddUs= */ 0L,
/* frameRate= */ frameRate); /* frameRate= */ 1f);
}
}
public void queueBitmapToInput(int inputId, List<Long> timestamps)
throws IOException, InterruptedException {
Bitmap bitmap = readBitmapUnpremultipliedAlpha(ORIGINAL_PNG_ASSET_PATH);
inputVideoFrameProcessorTestRunners
.get(inputId)
.queueInputBitmaps(
bitmap.getWidth(),
bitmap.getHeight(),
Pair.create(bitmap, createTimestampIterator(timestamps)));
} }
public void endCompositing() { public void endCompositing() {