Add WebpExtractor to DefaultExtractorsFactory
PiperOrigin-RevId: 563063506
This commit is contained in:
parent
100af0b2de
commit
45e15d48c4
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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:
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user