Add WebpExtractor to DefaultExtractorsFactory

PiperOrigin-RevId: 563063506
This commit is contained in:
tofunmi 2023-09-06 04:24:25 -07:00 committed by Copybara-Service
parent 100af0b2de
commit 45e15d48c4
5 changed files with 46 additions and 13 deletions

View File

@ -55,6 +55,7 @@ public final class FileTypes {
* <li>{@link #MIDI} * <li>{@link #MIDI}
* <li>{@link #AVI} * <li>{@link #AVI}
* <li>{@link #PNG} * <li>{@link #PNG}
* <li>{@link #WEBP}
* </ul> * </ul>
*/ */
@Documented @Documented
@ -62,7 +63,7 @@ public final class FileTypes {
@Target(TYPE_USE) @Target(TYPE_USE)
@IntDef({ @IntDef({
UNKNOWN, AC3, AC4, ADTS, AMR, FLAC, FLV, MATROSKA, MP3, MP4, OGG, PS, TS, WAV, WEBVTT, JPEG, 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 {} public @interface Type {}
@ -123,6 +124,9 @@ public final class FileTypes {
/** File type for the PNG format. */ /** File type for the PNG format. */
public static final int PNG = 17; 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"; @VisibleForTesting /* package */ static final String HEADER_CONTENT_TYPE = "Content-Type";
private static final String EXTENSION_AC3 = ".ac3"; 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_JPEG = ".jpeg";
private static final String EXTENSION_AVI = ".avi"; private static final String EXTENSION_AVI = ".avi";
private static final String EXTENSION_PNG = ".png"; private static final String EXTENSION_PNG = ".png";
private static final String EXTENSION_WEBP = ".webp";
private FileTypes() {} private FileTypes() {}
@ -226,6 +231,8 @@ public final class FileTypes {
return FileTypes.AVI; return FileTypes.AVI;
case MimeTypes.IMAGE_PNG: case MimeTypes.IMAGE_PNG:
return FileTypes.PNG; return FileTypes.PNG;
case MimeTypes.IMAGE_WEBP:
return FileTypes.WEBP;
default: default:
return FileTypes.UNKNOWN; return FileTypes.UNKNOWN;
} }
@ -295,6 +302,8 @@ public final class FileTypes {
return FileTypes.AVI; return FileTypes.AVI;
} else if (filename.endsWith(EXTENSION_PNG)) { } else if (filename.endsWith(EXTENSION_PNG)) {
return FileTypes.PNG; return FileTypes.PNG;
} else if (filename.endsWith(EXTENSION_WEBP)) {
return FileTypes.WEBP;
} else { } else {
return FileTypes.UNKNOWN; return FileTypes.UNKNOWN;
} }

View File

@ -50,6 +50,7 @@ import androidx.media3.extractor.ts.PsExtractor;
import androidx.media3.extractor.ts.TsExtractor; import androidx.media3.extractor.ts.TsExtractor;
import androidx.media3.extractor.ts.TsPayloadReader; import androidx.media3.extractor.ts.TsPayloadReader;
import androidx.media3.extractor.wav.WavExtractor; import androidx.media3.extractor.wav.WavExtractor;
import androidx.media3.extractor.webp.WebpExtractor;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
@ -87,6 +88,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
* </ul> * </ul>
* <li>JPEG ({@link JpegExtractor}) * <li>JPEG ({@link JpegExtractor})
* <li>PNG ({@link PngExtractor}) * <li>PNG ({@link PngExtractor})
* <li>WEBP ({@link WebpExtractor})
* <li>MIDI, if available, the MIDI extension's {@code androidx.media3.decoder.midi.MidiExtractor} * <li>MIDI, if available, the MIDI extension's {@code androidx.media3.decoder.midi.MidiExtractor}
* is used. * is used.
* </ul> * </ul>
@ -119,6 +121,7 @@ public final class DefaultExtractorsFactory implements ExtractorsFactory {
FileTypes.MIDI, FileTypes.MIDI,
FileTypes.JPEG, FileTypes.JPEG,
FileTypes.PNG, FileTypes.PNG,
FileTypes.WEBP
}; };
private static final ExtensionLoader FLAC_EXTENSION_LOADER = private static final ExtensionLoader FLAC_EXTENSION_LOADER =
@ -512,6 +515,9 @@ public final class DefaultExtractorsFactory implements ExtractorsFactory {
case FileTypes.PNG: case FileTypes.PNG:
extractors.add(new PngExtractor()); extractors.add(new PngExtractor());
break; break;
case FileTypes.WEBP:
extractors.add(new WebpExtractor());
break;
case FileTypes.WEBVTT: case FileTypes.WEBVTT:
case FileTypes.UNKNOWN: case FileTypes.UNKNOWN:
default: default:

View File

@ -41,7 +41,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
* <p>Used as a component in other extractors. * <p>Used as a component in other extractors.
*/ */
@UnstableApi @UnstableApi
/* package */ public final class SingleSampleExtractorHelper { public final class SingleSampleExtractorHelper {
/** Parser states. */ /** Parser states. */
@Documented @Documented
@ -66,6 +66,11 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
private @MonotonicNonNull ExtractorOutput extractorOutput; private @MonotonicNonNull ExtractorOutput extractorOutput;
private @MonotonicNonNull TrackOutput trackOutput; private @MonotonicNonNull TrackOutput trackOutput;
/**
* Returns whether the {@link ExtractorInput} has the given {@code fileSignature}.
*
* <p>@see Extractor#sniff(ExtractorInput)
*/
public boolean sniff(ExtractorInput input, int fileSignature, int fileSignatureLength) public boolean sniff(ExtractorInput input, int fileSignature, int fileSignatureLength)
throws IOException { throws IOException {
ParsableByteArray scratch = new ParsableByteArray(fileSignatureLength); ParsableByteArray scratch = new ParsableByteArray(fileSignatureLength);
@ -73,11 +78,25 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
return scratch.readUnsignedShort() == fileSignature; return scratch.readUnsignedShort() == fileSignature;
} }
/**
* See {@link Extractor#init(ExtractorOutput)}.
*
* <p>Outputs format with {@code containerMimeType}.
*/
public void init(ExtractorOutput output, String containerMimeType) { public void init(ExtractorOutput output, String containerMimeType) {
extractorOutput = output; extractorOutput = output;
outputImageTrackAndSeekMap(containerMimeType); 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) public @Extractor.ReadResult int read(ExtractorInput input, PositionHolder seekPosition)
throws IOException { throws IOException {
switch (state) { 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") @RequiresNonNull("this.extractorOutput")
private void outputImageTrackAndSeekMap(String containerMimeType) { private void outputImageTrackAndSeekMap(String containerMimeType) {
trackOutput = extractorOutput.track(IMAGE_TRACK_ID, C.TRACK_TYPE_IMAGE); trackOutput = extractorOutput.track(IMAGE_TRACK_ID, C.TRACK_TYPE_IMAGE);

View File

@ -35,18 +35,19 @@ public final class WebpExtractor implements Extractor {
private static final int RIFF_FILE_SIGNATURE = 0x52494646; private static final int RIFF_FILE_SIGNATURE = 0x52494646;
private static final int WEBP_FILE_SIGNATURE = 0x57454250; private static final int WEBP_FILE_SIGNATURE = 0x57454250;
private final ParsableByteArray scratch;
private final SingleSampleExtractorHelper imageExtractor; private final SingleSampleExtractorHelper imageExtractor;
/** Creates an instance. */ /** Creates an instance. */
public WebpExtractor() { public WebpExtractor() {
scratch = new ParsableByteArray(FILE_SIGNATURE_SEGMENT_LENGTH);
imageExtractor = new SingleSampleExtractorHelper(); imageExtractor = new SingleSampleExtractorHelper();
} }
@Override @Override
public boolean sniff(ExtractorInput input) throws IOException { public boolean sniff(ExtractorInput input) throws IOException {
// The full file signature for the format webp is RIFF????WEBP. // 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); input.peekFully(scratch.getData(), /* offset= */ 0, FILE_SIGNATURE_SEGMENT_LENGTH);
if (scratch.readUnsignedInt() != RIFF_FILE_SIGNATURE) { if (scratch.readUnsignedInt() != RIFF_FILE_SIGNATURE) {
return false; return false;
@ -57,6 +58,8 @@ public final class WebpExtractor implements Extractor {
input.peekFully(scratch.getData(), /* offset= */ 0, FILE_SIGNATURE_SEGMENT_LENGTH); input.peekFully(scratch.getData(), /* offset= */ 0, FILE_SIGNATURE_SEGMENT_LENGTH);
return scratch.readUnsignedInt() == WEBP_FILE_SIGNATURE; return scratch.readUnsignedInt() == WEBP_FILE_SIGNATURE;
// return imageExtractor.sniff(input, RIFF_FILE_SIGNATURE, FILE_SIGNATURE_SEGMENT_LENGTH);
} }
@Override @Override

View File

@ -38,6 +38,7 @@ import androidx.media3.extractor.ts.AdtsExtractor;
import androidx.media3.extractor.ts.PsExtractor; import androidx.media3.extractor.ts.PsExtractor;
import androidx.media3.extractor.ts.TsExtractor; import androidx.media3.extractor.ts.TsExtractor;
import androidx.media3.extractor.wav.WavExtractor; import androidx.media3.extractor.wav.WavExtractor;
import androidx.media3.extractor.webp.WebpExtractor;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -76,7 +77,8 @@ public final class DefaultExtractorsFactoryTest {
Mp3Extractor.class, Mp3Extractor.class,
AviExtractor.class, AviExtractor.class,
JpegExtractor.class, JpegExtractor.class,
PngExtractor.class) PngExtractor.class,
WebpExtractor.class)
.inOrder(); .inOrder();
} }
@ -120,7 +122,8 @@ public final class DefaultExtractorsFactoryTest {
Ac4Extractor.class, Ac4Extractor.class,
AviExtractor.class, AviExtractor.class,
JpegExtractor.class, JpegExtractor.class,
PngExtractor.class) PngExtractor.class,
WebpExtractor.class)
.inOrder(); .inOrder();
} }