diff --git a/RELEASENOTES.md b/RELEASENOTES.md
index 4c9126eaa3..b8f3336e85 100644
--- a/RELEASENOTES.md
+++ b/RELEASENOTES.md
@@ -79,7 +79,7 @@
* Image:
* Add support for non-square DASH thumbnail grids
([#1300](https://github.com/androidx/media/pull/1300)).
- * Add AVIF decoding support for API 34+.
+ * Add support for AVIF for API 34+.
* DRM:
* Allow setting a `LoadErrorHandlingPolicy` on
`DefaultDrmSessionManagerProvider`
diff --git a/libraries/common/src/main/java/androidx/media3/common/FileTypes.java b/libraries/common/src/main/java/androidx/media3/common/FileTypes.java
index c31de70e68..5b43543694 100644
--- a/libraries/common/src/main/java/androidx/media3/common/FileTypes.java
+++ b/libraries/common/src/main/java/androidx/media3/common/FileTypes.java
@@ -58,6 +58,7 @@ public final class FileTypes {
*
{@link #WEBP}
* {@link #BMP}
* {@link #HEIF}
+ * {@link #AVIF}
*
*/
@Documented
@@ -65,7 +66,7 @@ public final class FileTypes {
@Target(TYPE_USE)
@IntDef({
UNKNOWN, AC3, AC4, ADTS, AMR, FLAC, FLV, MATROSKA, MP3, MP4, OGG, PS, TS, WAV, WEBVTT, JPEG,
- MIDI, AVI, PNG, WEBP, BMP, HEIF
+ MIDI, AVI, PNG, WEBP, BMP, HEIF, AVIF
})
public @interface Type {}
@@ -135,6 +136,9 @@ public final class FileTypes {
/** File type for the HEIF format. */
public static final int HEIF = 20;
+ /** File type for the AVIF format. */
+ public static final int AVIF = 21;
+
@VisibleForTesting /* package */ static final String HEADER_CONTENT_TYPE = "Content-Type";
private static final String EXTENSION_AC3 = ".ac3";
@@ -175,6 +179,7 @@ public final class FileTypes {
private static final String EXTENSION_BMP = ".bmp";
private static final String EXTENSION_DIB = ".dib";
private static final String EXTENSION_HEIC = ".heic";
+ private static final String EXTENSION_AVIF = ".avif";
private FileTypes() {}
@@ -247,7 +252,10 @@ public final class FileTypes {
case MimeTypes.IMAGE_BMP:
return FileTypes.BMP;
case MimeTypes.IMAGE_HEIF:
+ case MimeTypes.IMAGE_HEIC:
return FileTypes.HEIF;
+ case MimeTypes.IMAGE_AVIF:
+ return FileTypes.AVIF;
default:
return FileTypes.UNKNOWN;
}
@@ -323,6 +331,8 @@ public final class FileTypes {
return FileTypes.BMP;
} else if (filename.endsWith(EXTENSION_HEIC)) {
return FileTypes.HEIF;
+ } else if (filename.endsWith(EXTENSION_AVIF)) {
+ return FileTypes.AVIF;
} else {
return FileTypes.UNKNOWN;
}
diff --git a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/e2etest/ParameterizedImagePlaybackTest.java b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/e2etest/ParameterizedImagePlaybackTest.java
index 9dd6ce4119..47d3e964a0 100644
--- a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/e2etest/ParameterizedImagePlaybackTest.java
+++ b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/e2etest/ParameterizedImagePlaybackTest.java
@@ -63,7 +63,8 @@ public class ParameterizedImagePlaybackTest {
"png/media3test.png",
"bmp/non-motion-photo-shortened-cropped.bmp",
"png/non-motion-photo-shortened.png",
- "webp/ic_launcher_round.webp")),
+ "webp/ic_launcher_round.webp",
+ "avif/white-1x1.avif")),
/* predicate= */ input -> !input.isEmpty()));
}
diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/DefaultExtractorsFactory.java b/libraries/extractor/src/main/java/androidx/media3/extractor/DefaultExtractorsFactory.java
index d32a71ea6d..7a0615931d 100644
--- a/libraries/extractor/src/main/java/androidx/media3/extractor/DefaultExtractorsFactory.java
+++ b/libraries/extractor/src/main/java/androidx/media3/extractor/DefaultExtractorsFactory.java
@@ -31,6 +31,7 @@ import androidx.media3.common.util.TimestampAdjuster;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.extractor.amr.AmrExtractor;
import androidx.media3.extractor.avi.AviExtractor;
+import androidx.media3.extractor.avif.AvifExtractor;
import androidx.media3.extractor.bmp.BmpExtractor;
import androidx.media3.extractor.flac.FlacExtractor;
import androidx.media3.extractor.flv.FlvExtractor;
@@ -94,6 +95,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
* WEBP ({@link WebpExtractor})
* BMP ({@link BmpExtractor})
* HEIF ({@link HeifExtractor})
+ * AVIF ({@link AvifExtractor})
* MIDI, if available, the MIDI extension's {@code androidx.media3.decoder.midi.MidiExtractor}
* is used.
*
@@ -128,7 +130,8 @@ public final class DefaultExtractorsFactory implements ExtractorsFactory {
FileTypes.PNG,
FileTypes.WEBP,
FileTypes.BMP,
- FileTypes.HEIF
+ FileTypes.HEIF,
+ FileTypes.AVIF
};
private static final ExtensionLoader FLAC_EXTENSION_LOADER =
@@ -569,6 +572,9 @@ public final class DefaultExtractorsFactory implements ExtractorsFactory {
extractors.add(new HeifExtractor());
}
break;
+ case FileTypes.AVIF:
+ extractors.add(new AvifExtractor());
+ break;
case FileTypes.WEBVTT:
case FileTypes.UNKNOWN:
default:
diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/avif/AvifExtractor.java b/libraries/extractor/src/main/java/androidx/media3/extractor/avif/AvifExtractor.java
new file mode 100644
index 0000000000..963bb5a98d
--- /dev/null
+++ b/libraries/extractor/src/main/java/androidx/media3/extractor/avif/AvifExtractor.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2024 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
+ *
+ * http://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.extractor.avif;
+
+import androidx.media3.common.C;
+import androidx.media3.common.MimeTypes;
+import androidx.media3.common.util.ParsableByteArray;
+import androidx.media3.common.util.UnstableApi;
+import androidx.media3.extractor.Extractor;
+import androidx.media3.extractor.ExtractorInput;
+import androidx.media3.extractor.ExtractorOutput;
+import androidx.media3.extractor.PositionHolder;
+import androidx.media3.extractor.SingleSampleExtractor;
+import java.io.IOException;
+
+/** Extracts data from the AVIF (.avif) container format. */
+@UnstableApi
+public final class AvifExtractor implements Extractor {
+
+ // Specification reference: ISO/IEC 23008-12:2022
+ private static final int AVIF_FILE_SIGNATURE_PART_1 = 0x66747970;
+ private static final int AVIF_FILE_SIGNATURE_PART_2 = 0x61766966;
+ private static final int FILE_SIGNATURE_SEGMENT_LENGTH = 4;
+
+ private final ParsableByteArray scratch;
+ private final SingleSampleExtractor imageExtractor;
+
+ /** Creates an instance. */
+ public AvifExtractor() {
+ scratch = new ParsableByteArray(FILE_SIGNATURE_SEGMENT_LENGTH);
+ imageExtractor =
+ new SingleSampleExtractor(
+ /* fileSignature= */ C.INDEX_UNSET,
+ /* fileSignatureLength= */ C.LENGTH_UNSET,
+ MimeTypes.IMAGE_AVIF);
+ }
+
+ @Override
+ public boolean sniff(ExtractorInput input) throws IOException {
+ input.advancePeekPosition(4);
+ return readAndCompareFourBytes(input, AVIF_FILE_SIGNATURE_PART_1)
+ && readAndCompareFourBytes(input, AVIF_FILE_SIGNATURE_PART_2);
+ }
+
+ @Override
+ public void init(ExtractorOutput output) {
+ imageExtractor.init(output);
+ }
+
+ @Override
+ public @ReadResult int read(ExtractorInput input, PositionHolder seekPosition)
+ throws IOException {
+ return imageExtractor.read(input, seekPosition);
+ }
+
+ @Override
+ public void seek(long position, long timeUs) {
+ imageExtractor.seek(position, timeUs);
+ }
+
+ @Override
+ public void release() {
+ // Do nothing.
+ }
+
+ private boolean readAndCompareFourBytes(ExtractorInput input, int bytesToCompare)
+ throws IOException {
+ scratch.reset(/* limit= */ FILE_SIGNATURE_SEGMENT_LENGTH);
+ input.peekFully(scratch.getData(), /* offset= */ 0, FILE_SIGNATURE_SEGMENT_LENGTH);
+ return scratch.readUnsignedInt() == bytesToCompare;
+ }
+}
diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/avif/package-info.java b/libraries/extractor/src/main/java/androidx/media3/extractor/avif/package-info.java
new file mode 100644
index 0000000000..0500ef3911
--- /dev/null
+++ b/libraries/extractor/src/main/java/androidx/media3/extractor/avif/package-info.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2024 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
+ *
+ * http://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.
+ */
+@NonNullApi
+package androidx.media3.extractor.avif;
+
+import androidx.media3.common.util.NonNullApi;
diff --git a/libraries/extractor/src/test/java/androidx/media3/extractor/DefaultExtractorsFactoryTest.java b/libraries/extractor/src/test/java/androidx/media3/extractor/DefaultExtractorsFactoryTest.java
index f77e4281ad..ca86953501 100644
--- a/libraries/extractor/src/test/java/androidx/media3/extractor/DefaultExtractorsFactoryTest.java
+++ b/libraries/extractor/src/test/java/androidx/media3/extractor/DefaultExtractorsFactoryTest.java
@@ -22,6 +22,7 @@ import android.net.Uri;
import androidx.media3.common.MimeTypes;
import androidx.media3.extractor.amr.AmrExtractor;
import androidx.media3.extractor.avi.AviExtractor;
+import androidx.media3.extractor.avif.AvifExtractor;
import androidx.media3.extractor.bmp.BmpExtractor;
import androidx.media3.extractor.flac.FlacExtractor;
import androidx.media3.extractor.flv.FlvExtractor;
@@ -82,7 +83,8 @@ public final class DefaultExtractorsFactoryTest {
PngExtractor.class,
WebpExtractor.class,
BmpExtractor.class,
- HeifExtractor.class)
+ HeifExtractor.class,
+ AvifExtractor.class)
.inOrder();
}
@@ -129,7 +131,8 @@ public final class DefaultExtractorsFactoryTest {
PngExtractor.class,
WebpExtractor.class,
BmpExtractor.class,
- HeifExtractor.class)
+ HeifExtractor.class,
+ AvifExtractor.class)
.inOrder();
}
diff --git a/libraries/extractor/src/test/java/androidx/media3/extractor/avif/AvifExtractorTest.java b/libraries/extractor/src/test/java/androidx/media3/extractor/avif/AvifExtractorTest.java
new file mode 100644
index 0000000000..b50d6e9840
--- /dev/null
+++ b/libraries/extractor/src/test/java/androidx/media3/extractor/avif/AvifExtractorTest.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2024 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
+ *
+ * http://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.extractor.avif;
+
+import androidx.media3.test.utils.ExtractorAsserts;
+import com.google.common.collect.ImmutableList;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.ParameterizedRobolectricTestRunner;
+
+/** Unit tests for {@link AvifExtractor}. */
+@RunWith(ParameterizedRobolectricTestRunner.class)
+public final class AvifExtractorTest {
+
+ @ParameterizedRobolectricTestRunner.Parameters(name = "{0}")
+ public static ImmutableList params() {
+ return ExtractorAsserts.configs();
+ }
+
+ @ParameterizedRobolectricTestRunner.Parameter
+ public ExtractorAsserts.SimulationConfig simulationConfig;
+
+ @Test
+ public void sampleAvif() throws Exception {
+ ExtractorAsserts.assertBehavior(
+ AvifExtractor::new, "media/avif/white-1x1.avif", simulationConfig);
+ }
+}
diff --git a/libraries/test_data/src/test/assets/extractordumps/avif/white-1x1.avif.0.dump b/libraries/test_data/src/test/assets/extractordumps/avif/white-1x1.avif.0.dump
new file mode 100644
index 0000000000..cc8f0789bb
--- /dev/null
+++ b/libraries/test_data/src/test/assets/extractordumps/avif/white-1x1.avif.0.dump
@@ -0,0 +1,16 @@
+seekMap:
+ isSeekable = true
+ duration = UNSET TIME
+ getPosition(0) = [[timeUs=0, position=0]]
+ getPosition(1) = [[timeUs=1, position=0]]
+numberOfTracks = 1
+track 1024:
+ total output bytes = 295
+ sample count = 1
+ format 0:
+ sampleMimeType = image/avif
+ sample 0:
+ time = 0
+ flags = 1
+ data = length 295, hash 24CB12
+tracksEnded = true
diff --git a/libraries/test_data/src/test/assets/extractordumps/avif/white-1x1.avif.unknown_length.dump b/libraries/test_data/src/test/assets/extractordumps/avif/white-1x1.avif.unknown_length.dump
new file mode 100644
index 0000000000..cc8f0789bb
--- /dev/null
+++ b/libraries/test_data/src/test/assets/extractordumps/avif/white-1x1.avif.unknown_length.dump
@@ -0,0 +1,16 @@
+seekMap:
+ isSeekable = true
+ duration = UNSET TIME
+ getPosition(0) = [[timeUs=0, position=0]]
+ getPosition(1) = [[timeUs=1, position=0]]
+numberOfTracks = 1
+track 1024:
+ total output bytes = 295
+ sample count = 1
+ format 0:
+ sampleMimeType = image/avif
+ sample 0:
+ time = 0
+ flags = 1
+ data = length 295, hash 24CB12
+tracksEnded = true
diff --git a/libraries/test_data/src/test/assets/media/avif/white-1x1.avif b/libraries/test_data/src/test/assets/media/avif/white-1x1.avif
new file mode 100644
index 0000000000..672c60e130
Binary files /dev/null and b/libraries/test_data/src/test/assets/media/avif/white-1x1.avif differ
diff --git a/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+ic_launcher_round.webp.dump b/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+ic_launcher_round.webp.dump
new file mode 100644
index 0000000000..4db5c26d48
--- /dev/null
+++ b/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+ic_launcher_round.webp.dump
@@ -0,0 +1,5 @@
+ImageOutput:
+ rendered image count = 1
+ image output #1:
+ presentationTimeUs = 0
+ bitmap hash = 443865884
diff --git a/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+media3test.png+ic_launcher_round.webp.dump b/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+media3test.png+ic_launcher_round.webp.dump
new file mode 100644
index 0000000000..9e1ac033bf
--- /dev/null
+++ b/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+media3test.png+ic_launcher_round.webp.dump
@@ -0,0 +1,8 @@
+ImageOutput:
+ rendered image count = 2
+ image output #1:
+ presentationTimeUs = 0
+ bitmap hash = -389047680
+ image output #2:
+ presentationTimeUs = 0
+ bitmap hash = 443865884
diff --git a/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+media3test.png+non-motion-photo-shortened.png+ic_launcher_round.webp.dump b/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+media3test.png+non-motion-photo-shortened.png+ic_launcher_round.webp.dump
new file mode 100644
index 0000000000..a9504f5f9d
--- /dev/null
+++ b/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+media3test.png+non-motion-photo-shortened.png+ic_launcher_round.webp.dump
@@ -0,0 +1,11 @@
+ImageOutput:
+ rendered image count = 3
+ image output #1:
+ presentationTimeUs = 0
+ bitmap hash = -389047680
+ image output #2:
+ presentationTimeUs = 0
+ bitmap hash = 1367007828
+ image output #3:
+ presentationTimeUs = 0
+ bitmap hash = 443865884
diff --git a/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+media3test.png+non-motion-photo-shortened.png.dump b/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+media3test.png+non-motion-photo-shortened.png.dump
new file mode 100644
index 0000000000..2875428cf6
--- /dev/null
+++ b/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+media3test.png+non-motion-photo-shortened.png.dump
@@ -0,0 +1,8 @@
+ImageOutput:
+ rendered image count = 2
+ image output #1:
+ presentationTimeUs = 0
+ bitmap hash = -389047680
+ image output #2:
+ presentationTimeUs = 0
+ bitmap hash = 1367007828
diff --git a/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+media3test.png.dump b/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+media3test.png.dump
new file mode 100644
index 0000000000..25240d5c5e
--- /dev/null
+++ b/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+media3test.png.dump
@@ -0,0 +1,5 @@
+ImageOutput:
+ rendered image count = 1
+ image output #1:
+ presentationTimeUs = 0
+ bitmap hash = -389047680
diff --git a/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+non-motion-photo-shortened-cropped.bmp+ic_launcher_round.webp.dump b/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+non-motion-photo-shortened-cropped.bmp+ic_launcher_round.webp.dump
new file mode 100644
index 0000000000..4c409dd23d
--- /dev/null
+++ b/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+non-motion-photo-shortened-cropped.bmp+ic_launcher_round.webp.dump
@@ -0,0 +1,8 @@
+ImageOutput:
+ rendered image count = 2
+ image output #1:
+ presentationTimeUs = 0
+ bitmap hash = -1851534335
+ image output #2:
+ presentationTimeUs = 0
+ bitmap hash = 443865884
diff --git a/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+non-motion-photo-shortened-cropped.bmp+media3test.png+ic_launcher_round.webp.dump b/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+non-motion-photo-shortened-cropped.bmp+media3test.png+ic_launcher_round.webp.dump
new file mode 100644
index 0000000000..2933dbb06e
--- /dev/null
+++ b/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+non-motion-photo-shortened-cropped.bmp+media3test.png+ic_launcher_round.webp.dump
@@ -0,0 +1,11 @@
+ImageOutput:
+ rendered image count = 3
+ image output #1:
+ presentationTimeUs = 0
+ bitmap hash = -1851534335
+ image output #2:
+ presentationTimeUs = 0
+ bitmap hash = -389047680
+ image output #3:
+ presentationTimeUs = 0
+ bitmap hash = 443865884
diff --git a/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+non-motion-photo-shortened-cropped.bmp+media3test.png+non-motion-photo-shortened.png+ic_launcher_round.webp.dump b/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+non-motion-photo-shortened-cropped.bmp+media3test.png+non-motion-photo-shortened.png+ic_launcher_round.webp.dump
new file mode 100644
index 0000000000..b9811c028e
--- /dev/null
+++ b/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+non-motion-photo-shortened-cropped.bmp+media3test.png+non-motion-photo-shortened.png+ic_launcher_round.webp.dump
@@ -0,0 +1,14 @@
+ImageOutput:
+ rendered image count = 4
+ image output #1:
+ presentationTimeUs = 0
+ bitmap hash = -1851534335
+ image output #2:
+ presentationTimeUs = 0
+ bitmap hash = -389047680
+ image output #3:
+ presentationTimeUs = 0
+ bitmap hash = 1367007828
+ image output #4:
+ presentationTimeUs = 0
+ bitmap hash = 443865884
diff --git a/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+non-motion-photo-shortened-cropped.bmp+media3test.png+non-motion-photo-shortened.png.dump b/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+non-motion-photo-shortened-cropped.bmp+media3test.png+non-motion-photo-shortened.png.dump
new file mode 100644
index 0000000000..eaad05a0e8
--- /dev/null
+++ b/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+non-motion-photo-shortened-cropped.bmp+media3test.png+non-motion-photo-shortened.png.dump
@@ -0,0 +1,11 @@
+ImageOutput:
+ rendered image count = 3
+ image output #1:
+ presentationTimeUs = 0
+ bitmap hash = -1851534335
+ image output #2:
+ presentationTimeUs = 0
+ bitmap hash = -389047680
+ image output #3:
+ presentationTimeUs = 0
+ bitmap hash = 1367007828
diff --git a/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+non-motion-photo-shortened-cropped.bmp+media3test.png.dump b/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+non-motion-photo-shortened-cropped.bmp+media3test.png.dump
new file mode 100644
index 0000000000..54f61bf98d
--- /dev/null
+++ b/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+non-motion-photo-shortened-cropped.bmp+media3test.png.dump
@@ -0,0 +1,8 @@
+ImageOutput:
+ rendered image count = 2
+ image output #1:
+ presentationTimeUs = 0
+ bitmap hash = -1851534335
+ image output #2:
+ presentationTimeUs = 0
+ bitmap hash = -389047680
diff --git a/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+non-motion-photo-shortened-cropped.bmp+non-motion-photo-shortened.png+ic_launcher_round.webp.dump b/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+non-motion-photo-shortened-cropped.bmp+non-motion-photo-shortened.png+ic_launcher_round.webp.dump
new file mode 100644
index 0000000000..3362401a8d
--- /dev/null
+++ b/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+non-motion-photo-shortened-cropped.bmp+non-motion-photo-shortened.png+ic_launcher_round.webp.dump
@@ -0,0 +1,11 @@
+ImageOutput:
+ rendered image count = 3
+ image output #1:
+ presentationTimeUs = 0
+ bitmap hash = -1851534335
+ image output #2:
+ presentationTimeUs = 0
+ bitmap hash = 1367007828
+ image output #3:
+ presentationTimeUs = 0
+ bitmap hash = 443865884
diff --git a/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+non-motion-photo-shortened-cropped.bmp+non-motion-photo-shortened.png.dump b/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+non-motion-photo-shortened-cropped.bmp+non-motion-photo-shortened.png.dump
new file mode 100644
index 0000000000..e548093b37
--- /dev/null
+++ b/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+non-motion-photo-shortened-cropped.bmp+non-motion-photo-shortened.png.dump
@@ -0,0 +1,8 @@
+ImageOutput:
+ rendered image count = 2
+ image output #1:
+ presentationTimeUs = 0
+ bitmap hash = -1851534335
+ image output #2:
+ presentationTimeUs = 0
+ bitmap hash = 1367007828
diff --git a/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+non-motion-photo-shortened-cropped.bmp.dump b/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+non-motion-photo-shortened-cropped.bmp.dump
new file mode 100644
index 0000000000..4c0728752a
--- /dev/null
+++ b/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+non-motion-photo-shortened-cropped.bmp.dump
@@ -0,0 +1,5 @@
+ImageOutput:
+ rendered image count = 1
+ image output #1:
+ presentationTimeUs = 0
+ bitmap hash = -1851534335
diff --git a/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+non-motion-photo-shortened.png+ic_launcher_round.webp.dump b/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+non-motion-photo-shortened.png+ic_launcher_round.webp.dump
new file mode 100644
index 0000000000..b1456e0e39
--- /dev/null
+++ b/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+non-motion-photo-shortened.png+ic_launcher_round.webp.dump
@@ -0,0 +1,8 @@
+ImageOutput:
+ rendered image count = 2
+ image output #1:
+ presentationTimeUs = 0
+ bitmap hash = 1367007828
+ image output #2:
+ presentationTimeUs = 0
+ bitmap hash = 443865884
diff --git a/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+non-motion-photo-shortened.png.dump b/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+non-motion-photo-shortened.png.dump
new file mode 100644
index 0000000000..0094b367a4
--- /dev/null
+++ b/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif+non-motion-photo-shortened.png.dump
@@ -0,0 +1,5 @@
+ImageOutput:
+ rendered image count = 1
+ image output #1:
+ presentationTimeUs = 0
+ bitmap hash = 1367007828
diff --git a/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif.dump b/libraries/test_data/src/test/assets/playbackdumps/image/white-1x1.avif.dump
new file mode 100644
index 0000000000..e69de29bb2