diff --git a/libraries/test_data/src/test/assets/media/bitmap/sample_mp4_first_frame/electrical_colors/srgb_to_electrical_media3test.png b/libraries/test_data/src/test/assets/media/bitmap/sample_mp4_first_frame/electrical_colors/srgb_to_electrical_media3test.png new file mode 100644 index 0000000000..908e00ef00 Binary files /dev/null and b/libraries/test_data/src/test/assets/media/bitmap/sample_mp4_first_frame/electrical_colors/srgb_to_electrical_media3test.png differ diff --git a/libraries/test_data/src/test/assets/media/bitmap/sample_mp4_first_frame/electrical_colors/srgb_to_electrical_original.png b/libraries/test_data/src/test/assets/media/bitmap/sample_mp4_first_frame/electrical_colors/srgb_to_electrical_original.png new file mode 100644 index 0000000000..07f121ecf2 Binary files /dev/null and b/libraries/test_data/src/test/assets/media/bitmap/sample_mp4_first_frame/electrical_colors/srgb_to_electrical_original.png differ diff --git a/libraries/test_utils/src/main/java/androidx/media3/test/utils/VideoFrameProcessorTestRunner.java b/libraries/test_utils/src/main/java/androidx/media3/test/utils/VideoFrameProcessorTestRunner.java index ed00d9c5cb..b4d0ffb632 100644 --- a/libraries/test_utils/src/main/java/androidx/media3/test/utils/VideoFrameProcessorTestRunner.java +++ b/libraries/test_utils/src/main/java/androidx/media3/test/utils/VideoFrameProcessorTestRunner.java @@ -368,10 +368,12 @@ public final class VideoFrameProcessorTestRunner { videoFrameProcessor.queueInputTexture(inputTexture.getTexId(), pts); } + /** {@link #endFrameProcessing(long)} with {@link #VIDEO_FRAME_PROCESSING_WAIT_MS} applied. */ public void endFrameProcessing() throws InterruptedException { endFrameProcessing(VIDEO_FRAME_PROCESSING_WAIT_MS); } + /** Have the {@link VideoFrameProcessor} finish processing. */ public void endFrameProcessing(long videoFrameProcessingWaitTime) throws InterruptedException { videoFrameProcessor.signalEndOfInput(); Thread.sleep(videoFrameProcessingWaitTime); diff --git a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/mh/DefaultVideoFrameProcessorMultipleTextureOutputPixelTest.java b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/mh/DefaultVideoFrameProcessorMultipleTextureOutputPixelTest.java new file mode 100644 index 0000000000..abbc3c6f07 --- /dev/null +++ b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/mh/DefaultVideoFrameProcessorMultipleTextureOutputPixelTest.java @@ -0,0 +1,148 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package androidx.media3.transformer.mh; + +import static androidx.media3.common.VideoFrameProcessor.INPUT_TYPE_BITMAP; +import static androidx.media3.common.util.Assertions.checkNotNull; +import static androidx.media3.test.utils.BitmapPixelTestUtil.MAXIMUM_AVERAGE_PIXEL_ABSOLUTE_DIFFERENCE_DIFFERENT_DEVICE; +import static androidx.media3.test.utils.BitmapPixelTestUtil.maybeSaveTestBitmap; +import static androidx.media3.test.utils.BitmapPixelTestUtil.readBitmap; +import static com.google.common.truth.Truth.assertThat; + +import android.graphics.Bitmap; +import androidx.media3.common.C; +import androidx.media3.common.ColorInfo; +import androidx.media3.common.VideoFrameProcessor; +import androidx.media3.effect.DefaultVideoFrameProcessor; +import androidx.media3.test.utils.BitmapPixelTestUtil; +import androidx.media3.test.utils.VideoFrameProcessorTestRunner; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import java.util.Set; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Tests for {@link DefaultVideoFrameProcessor} texture output. + * + *
Confirms that the output timestamps are correct for each frame, and that the output pixels are
+ * correct for the first frame of each bitmap.
+ */
+@RunWith(AndroidJUnit4.class)
+public class DefaultVideoFrameProcessorMultipleTextureOutputPixelTest {
+ private static final String ORIGINAL_PNG_ASSET_PATH =
+ "media/bitmap/sample_mp4_first_frame/electrical_colors/original.png";
+ private static final String MEDIA3_TEST_PNG_ASSET_PATH =
+ "media/bitmap/input_images/media3test.png";
+ private static final String SRGB_TO_ELECTRICAL_ORIGINAL_PNG_ASSET_PATH =
+ "media/bitmap/sample_mp4_first_frame/electrical_colors/srgb_to_electrical_original.png";
+ private static final String SRGB_TO_ELECTRICAL_MEDIA3_TEST_PNG_ASSET_PATH =
+ "media/bitmap/sample_mp4_first_frame/electrical_colors/srgb_to_electrical_media3test.png";
+
+ private @MonotonicNonNull VideoFrameProcessorTestRunner videoFrameProcessorTestRunner;
+
+ private @MonotonicNonNull TextureBitmapReader textureBitmapReader;
+
+ @After
+ public void release() {
+ checkNotNull(videoFrameProcessorTestRunner).release();
+ }
+
+ @Test
+ public void textureOutput_queueBitmap_matchesGoldenFile() throws Exception {
+ String testId = "textureOutput_queueBitmap_matchesGoldenFile";
+ videoFrameProcessorTestRunner = getFrameProcessorTestRunnerBuilder(testId).build();
+
+ long offsetUs = 1_000_000L;
+ videoFrameProcessorTestRunner.queueInputBitmap(
+ readBitmap(ORIGINAL_PNG_ASSET_PATH),
+ /* durationUs= */ 3 * C.MICROS_PER_SECOND,
+ /* offsetToAddUs= */ offsetUs,
+ /* frameRate= */ 1);
+ videoFrameProcessorTestRunner.endFrameProcessing();
+
+ Set Reads from an OpenGL texture. Only for use on physical devices.
- */
- private static final class TextureBitmapReader implements BitmapReader {
- // TODO(b/239172735): This outputs an incorrect black output image on emulators.
- private boolean useHighPrecisionColorComponents;
- private @MonotonicNonNull Bitmap outputBitmap;
-
- @Nullable
- @Override
- public Surface getSurface(int width, int height, boolean useHighPrecisionColorComponents) {
- this.useHighPrecisionColorComponents = useHighPrecisionColorComponents;
- return null;
- }
-
- @Override
- public Bitmap getBitmap() {
- return checkStateNotNull(outputBitmap);
- }
-
- public void readBitmapFromTexture(
- GlTextureInfo outputTexture,
- long presentationTimeUs,
- DefaultVideoFrameProcessor.ReleaseOutputTextureCallback releaseOutputTextureCallback)
- throws VideoFrameProcessingException {
- try {
- GlUtil.focusFramebufferUsingCurrentContext(
- outputTexture.getFboId(), outputTexture.getWidth(), outputTexture.getHeight());
- outputBitmap =
- createBitmapFromCurrentGlFrameBuffer(
- outputTexture.getWidth(),
- outputTexture.getHeight(),
- useHighPrecisionColorComponents);
- } catch (GlUtil.GlException e) {
- throw new VideoFrameProcessingException(e);
- }
- releaseOutputTextureCallback.release(presentationTimeUs);
- }
-
- private static Bitmap createBitmapFromCurrentGlFrameBuffer(
- int width, int height, boolean useHighPrecisionColorComponents) throws GlUtil.GlException {
- if (!useHighPrecisionColorComponents) {
- return BitmapPixelTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer(width, height);
- }
- checkState(Util.SDK_INT > 26, "useHighPrecisionColorComponents only supported on API 26+");
- return BitmapPixelTestUtil.createFp16BitmapFromCurrentGlFramebuffer(width, height);
- }
- }
-
private static boolean deviceSupportsHdrEditing(Format format) {
return !EncoderUtil.getSupportedEncodersForHdrEditing(
checkNotNull(checkNotNull(format).sampleMimeType), format.colorInfo)
diff --git a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/mh/TextureBitmapReader.java b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/mh/TextureBitmapReader.java
new file mode 100644
index 0000000000..a7b76f6529
--- /dev/null
+++ b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/mh/TextureBitmapReader.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package androidx.media3.transformer.mh;
+
+import static androidx.media3.common.util.Assertions.checkState;
+import static androidx.media3.common.util.Assertions.checkStateNotNull;
+
+import android.graphics.Bitmap;
+import android.view.Surface;
+import androidx.media3.common.GlTextureInfo;
+import androidx.media3.common.VideoFrameProcessingException;
+import androidx.media3.common.util.GlUtil;
+import androidx.media3.common.util.Util;
+import androidx.media3.effect.DefaultVideoFrameProcessor;
+import androidx.media3.test.utils.BitmapPixelTestUtil;
+import androidx.media3.test.utils.VideoFrameProcessorTestRunner;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+/**
+ * {@inheritDoc}
+ *
+ * Reads from an OpenGL texture. Only for use on physical devices.
+ */
+public final class TextureBitmapReader implements VideoFrameProcessorTestRunner.BitmapReader {
+ // TODO(b/239172735): This outputs an incorrect black output image on emulators.
+ private final Map