From 45e15d48c4b50bb77af6722b6f738ad9acbc284b Mon Sep 17 00:00:00 2001 From: tofunmi Date: Wed, 6 Sep 2023 04:24:25 -0700 Subject: [PATCH] Add WebpExtractor to DefaultExtractorsFactory PiperOrigin-RevId: 563063506 --- .../androidx/media3/common/FileTypes.java | 11 +++++++- .../extractor/DefaultExtractorsFactory.java | 6 ++++ .../SingleSampleExtractorHelper.java | 28 +++++++++++++------ .../media3/extractor/webp/WebpExtractor.java | 7 +++-- .../DefaultExtractorsFactoryTest.java | 7 +++-- 5 files changed, 46 insertions(+), 13 deletions(-) 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 0c84ed1035..99e833ba4c 100644 --- a/libraries/common/src/main/java/androidx/media3/common/FileTypes.java +++ b/libraries/common/src/main/java/androidx/media3/common/FileTypes.java @@ -55,6 +55,7 @@ public final class FileTypes { *
  • {@link #MIDI} *
  • {@link #AVI} *
  • {@link #PNG} + *
  • {@link #WEBP} * */ @Documented @@ -62,7 +63,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 + MIDI, AVI, PNG, WEBP }) public @interface Type {} @@ -123,6 +124,9 @@ public final class FileTypes { /** File type for the PNG format. */ public static final int PNG = 17; + /** File type for the WEBP format. */ + public static final int WEBP = 18; + @VisibleForTesting /* package */ static final String HEADER_CONTENT_TYPE = "Content-Type"; private static final String EXTENSION_AC3 = ".ac3"; @@ -159,6 +163,7 @@ public final class FileTypes { private static final String EXTENSION_JPEG = ".jpeg"; private static final String EXTENSION_AVI = ".avi"; private static final String EXTENSION_PNG = ".png"; + private static final String EXTENSION_WEBP = ".webp"; private FileTypes() {} @@ -226,6 +231,8 @@ public final class FileTypes { return FileTypes.AVI; case MimeTypes.IMAGE_PNG: return FileTypes.PNG; + case MimeTypes.IMAGE_WEBP: + return FileTypes.WEBP; default: return FileTypes.UNKNOWN; } @@ -295,6 +302,8 @@ public final class FileTypes { return FileTypes.AVI; } else if (filename.endsWith(EXTENSION_PNG)) { return FileTypes.PNG; + } else if (filename.endsWith(EXTENSION_WEBP)) { + return FileTypes.WEBP; } else { return FileTypes.UNKNOWN; } 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 cff473237c..41c14f90c0 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/DefaultExtractorsFactory.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/DefaultExtractorsFactory.java @@ -50,6 +50,7 @@ import androidx.media3.extractor.ts.PsExtractor; import androidx.media3.extractor.ts.TsExtractor; import androidx.media3.extractor.ts.TsPayloadReader; import androidx.media3.extractor.wav.WavExtractor; +import androidx.media3.extractor.webp.WebpExtractor; import com.google.common.collect.ImmutableList; import com.google.errorprone.annotations.CanIgnoreReturnValue; import java.lang.reflect.Constructor; @@ -87,6 +88,7 @@ import java.util.concurrent.atomic.AtomicBoolean; * *
  • JPEG ({@link JpegExtractor}) *
  • PNG ({@link PngExtractor}) + *
  • WEBP ({@link WebpExtractor}) *
  • MIDI, if available, the MIDI extension's {@code androidx.media3.decoder.midi.MidiExtractor} * is used. * @@ -119,6 +121,7 @@ public final class DefaultExtractorsFactory implements ExtractorsFactory { FileTypes.MIDI, FileTypes.JPEG, FileTypes.PNG, + FileTypes.WEBP }; private static final ExtensionLoader FLAC_EXTENSION_LOADER = @@ -512,6 +515,9 @@ public final class DefaultExtractorsFactory implements ExtractorsFactory { case FileTypes.PNG: extractors.add(new PngExtractor()); break; + case FileTypes.WEBP: + extractors.add(new WebpExtractor()); + break; case FileTypes.WEBVTT: case FileTypes.UNKNOWN: default: diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/SingleSampleExtractorHelper.java b/libraries/extractor/src/main/java/androidx/media3/extractor/SingleSampleExtractorHelper.java index 4bca96713a..4f5da32b2a 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/SingleSampleExtractorHelper.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/SingleSampleExtractorHelper.java @@ -41,7 +41,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; *

    Used as a component in other extractors. */ @UnstableApi -/* package */ public final class SingleSampleExtractorHelper { +public final class SingleSampleExtractorHelper { /** Parser states. */ @Documented @@ -66,6 +66,11 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; private @MonotonicNonNull ExtractorOutput extractorOutput; private @MonotonicNonNull TrackOutput trackOutput; + /** + * Returns whether the {@link ExtractorInput} has the given {@code fileSignature}. + * + *

    @see Extractor#sniff(ExtractorInput) + */ public boolean sniff(ExtractorInput input, int fileSignature, int fileSignatureLength) throws IOException { ParsableByteArray scratch = new ParsableByteArray(fileSignatureLength); @@ -73,11 +78,25 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; return scratch.readUnsignedShort() == fileSignature; } + /** + * See {@link Extractor#init(ExtractorOutput)}. + * + *

    Outputs format with {@code containerMimeType}. + */ public void init(ExtractorOutput output, String containerMimeType) { extractorOutput = output; outputImageTrackAndSeekMap(containerMimeType); } + /** See {@link Extractor#seek(long, long)}. */ + public void seek(long position) { + if (position == 0 || state == STATE_READING) { + state = STATE_READING; + size = 0; + } + } + + /** See {@link Extractor#read(ExtractorInput, PositionHolder)}. */ public @Extractor.ReadResult int read(ExtractorInput input, PositionHolder seekPosition) throws IOException { switch (state) { @@ -105,13 +124,6 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; } } - public void seek(long position) { - if (position == 0 || state == STATE_READING) { - state = STATE_READING; - size = 0; - } - } - @RequiresNonNull("this.extractorOutput") private void outputImageTrackAndSeekMap(String containerMimeType) { trackOutput = extractorOutput.track(IMAGE_TRACK_ID, C.TRACK_TYPE_IMAGE); diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/webp/WebpExtractor.java b/libraries/extractor/src/main/java/androidx/media3/extractor/webp/WebpExtractor.java index a99ccbebf7..a56667cdc9 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/webp/WebpExtractor.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/webp/WebpExtractor.java @@ -35,18 +35,19 @@ public final class WebpExtractor implements Extractor { private static final int RIFF_FILE_SIGNATURE = 0x52494646; private static final int WEBP_FILE_SIGNATURE = 0x57454250; + private final ParsableByteArray scratch; private final SingleSampleExtractorHelper imageExtractor; /** Creates an instance. */ public WebpExtractor() { + scratch = new ParsableByteArray(FILE_SIGNATURE_SEGMENT_LENGTH); imageExtractor = new SingleSampleExtractorHelper(); } @Override public boolean sniff(ExtractorInput input) throws IOException { // The full file signature for the format webp is RIFF????WEBP. - ParsableByteArray scratch = new ParsableByteArray(FILE_SIGNATURE_SEGMENT_LENGTH); - + scratch.reset(/* limit= */ FILE_SIGNATURE_SEGMENT_LENGTH); input.peekFully(scratch.getData(), /* offset= */ 0, FILE_SIGNATURE_SEGMENT_LENGTH); if (scratch.readUnsignedInt() != RIFF_FILE_SIGNATURE) { return false; @@ -57,6 +58,8 @@ public final class WebpExtractor implements Extractor { input.peekFully(scratch.getData(), /* offset= */ 0, FILE_SIGNATURE_SEGMENT_LENGTH); return scratch.readUnsignedInt() == WEBP_FILE_SIGNATURE; + // return imageExtractor.sniff(input, RIFF_FILE_SIGNATURE, FILE_SIGNATURE_SEGMENT_LENGTH); + } @Override 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 3e60aa0512..b76ec4c564 100644 --- a/libraries/extractor/src/test/java/androidx/media3/extractor/DefaultExtractorsFactoryTest.java +++ b/libraries/extractor/src/test/java/androidx/media3/extractor/DefaultExtractorsFactoryTest.java @@ -38,6 +38,7 @@ import androidx.media3.extractor.ts.AdtsExtractor; import androidx.media3.extractor.ts.PsExtractor; import androidx.media3.extractor.ts.TsExtractor; import androidx.media3.extractor.wav.WavExtractor; +import androidx.media3.extractor.webp.WebpExtractor; import androidx.test.ext.junit.runners.AndroidJUnit4; import java.util.ArrayList; import java.util.Collections; @@ -76,7 +77,8 @@ public final class DefaultExtractorsFactoryTest { Mp3Extractor.class, AviExtractor.class, JpegExtractor.class, - PngExtractor.class) + PngExtractor.class, + WebpExtractor.class) .inOrder(); } @@ -120,7 +122,8 @@ public final class DefaultExtractorsFactoryTest { Ac4Extractor.class, AviExtractor.class, JpegExtractor.class, - PngExtractor.class) + PngExtractor.class, + WebpExtractor.class) .inOrder(); }