java.lang.Object
↳androidx.media3.extractor.DefaultExtractorsFactory
Gradle dependencies
compile group: 'androidx.media3', name: 'media3-extractor', version: '1.0.0-alpha03'
- groupId: androidx.media3
- artifactId: media3-extractor
- version: 1.0.0-alpha03
Artifact androidx.media3:media3-extractor:1.0.0-alpha03 it located at Google repository (https://maven.google.com/)
Overview
An ExtractorsFactory that provides an array of extractors for the following formats:
Summary
Methods |
---|
public synchronized Extractor | createExtractors()
|
public synchronized Extractor | createExtractors(Uri uri, java.util.Map<java.lang.String, java.util.List> responseHeaders)
|
public synchronized DefaultExtractorsFactory | setAdtsExtractorFlags(int flags)
Sets flags for AdtsExtractor instances created by the factory. |
public synchronized DefaultExtractorsFactory | setAmrExtractorFlags(int flags)
Sets flags for AmrExtractor instances created by the factory. |
public synchronized DefaultExtractorsFactory | setConstantBitrateSeekingAlwaysEnabled(boolean constantBitrateSeekingAlwaysEnabled)
Convenience method to set whether approximate seeking using constant bitrate assumptions should
be enabled for all extractors that support it, and if it should be enabled even if the content
length (and hence the duration of the media) is unknown. |
public synchronized DefaultExtractorsFactory | setConstantBitrateSeekingEnabled(boolean constantBitrateSeekingEnabled)
Convenience method to set whether approximate seeking using constant bitrate assumptions should
be enabled for all extractors that support it. |
public synchronized DefaultExtractorsFactory | setFlacExtractorFlags(int flags)
Sets flags for FlacExtractor instances created by the factory. |
public synchronized DefaultExtractorsFactory | setFragmentedMp4ExtractorFlags(int flags)
Sets flags for FragmentedMp4Extractor instances created by the factory. |
public synchronized DefaultExtractorsFactory | setMatroskaExtractorFlags(int flags)
Sets flags for MatroskaExtractor instances created by the factory. |
public synchronized DefaultExtractorsFactory | setMp3ExtractorFlags(int flags)
Sets flags for Mp3Extractor instances created by the factory. |
public synchronized DefaultExtractorsFactory | setMp4ExtractorFlags(int flags)
Sets flags for Mp4Extractor instances created by the factory. |
public synchronized DefaultExtractorsFactory | setTsExtractorFlags(int flags)
Sets flags for DefaultTsPayloadReaderFactorys used by TsExtractor instances
created by the factory. |
public synchronized DefaultExtractorsFactory | setTsExtractorMode(int mode)
Sets the mode for TsExtractor instances created by the factory. |
public synchronized DefaultExtractorsFactory | setTsExtractorTimestampSearchBytes(int timestampSearchBytes)
Sets the number of bytes searched to find a timestamp for TsExtractor instances created
by the factory. |
from java.lang.Object | clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Constructors
public
DefaultExtractorsFactory()
Methods
Convenience method to set whether approximate seeking using constant bitrate assumptions should
be enabled for all extractors that support it. If set to true, the flags required to enable
this functionality will be OR'd with those passed to the setters when creating extractor
instances. If set to false then the flags passed to the setters will be used without
modification.
Parameters:
constantBitrateSeekingEnabled: Whether approximate seeking using a constant bitrate
assumption should be enabled for all extractors that support it.
Returns:
The factory, for convenience.
public synchronized
DefaultExtractorsFactory setConstantBitrateSeekingAlwaysEnabled(boolean constantBitrateSeekingAlwaysEnabled)
Convenience method to set whether approximate seeking using constant bitrate assumptions should
be enabled for all extractors that support it, and if it should be enabled even if the content
length (and hence the duration of the media) is unknown. If set to true, the flags required to
enable this functionality will be OR'd with those passed to the setters when creating extractor
instances. If set to false then the flags passed to the setters will be used without
modification.
When seeking into content where the length is unknown, application code should ensure that
requested seek positions are valid, or should be ready to handle playback failures reported
through with PlaybackException.errorCode set to
PlaybackException.ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE.
Parameters:
constantBitrateSeekingAlwaysEnabled: Whether approximate seeking using a constant bitrate
assumption should be enabled for all extractors that support it, including when the content
duration is unknown.
Returns:
The factory, for convenience.
Sets flags for AdtsExtractor instances created by the factory.
Parameters:
flags: The flags to use.
Returns:
The factory, for convenience.
See also: AdtsExtractor.AdtsExtractor(int)
Sets flags for AmrExtractor instances created by the factory.
Parameters:
flags: The flags to use.
Returns:
The factory, for convenience.
See also: AmrExtractor.AmrExtractor(int)
Sets flags for FlacExtractor instances created by the factory. The flags are also used
by androidx.media3.decoder.flac.FlacExtractor instances if the FLAC extension is being
used.
Parameters:
flags: The flags to use.
Returns:
The factory, for convenience.
See also: FlacExtractor.FlacExtractor(int)
Sets flags for MatroskaExtractor instances created by the factory.
Parameters:
flags: The flags to use.
Returns:
The factory, for convenience.
See also: MatroskaExtractor.MatroskaExtractor(int)
Sets flags for Mp4Extractor instances created by the factory.
Parameters:
flags: The flags to use.
Returns:
The factory, for convenience.
See also: Mp4Extractor.Mp4Extractor(int)
Sets flags for FragmentedMp4Extractor instances created by the factory.
Parameters:
flags: The flags to use.
Returns:
The factory, for convenience.
See also: FragmentedMp4Extractor.FragmentedMp4Extractor(int)
Sets flags for Mp3Extractor instances created by the factory.
Parameters:
flags: The flags to use.
Returns:
The factory, for convenience.
See also: Mp3Extractor.Mp3Extractor(int)
Sets the mode for TsExtractor instances created by the factory.
Parameters:
mode: The mode to use.
Returns:
The factory, for convenience.
See also: TsExtractor.TsExtractor(int, TimestampAdjuster, TsPayloadReader.Factory, int)
Sets flags for DefaultTsPayloadReaderFactorys used by TsExtractor instances
created by the factory.
Parameters:
flags: The flags to use.
Returns:
The factory, for convenience.
See also: TsExtractor.TsExtractor(int)
Sets the number of bytes searched to find a timestamp for TsExtractor instances created
by the factory.
Parameters:
timestampSearchBytes: The number of search bytes to use.
Returns:
The factory, for convenience.
See also: TsExtractor.TsExtractor(int, TimestampAdjuster, TsPayloadReader.Factory, int)
public synchronized
Extractor createExtractors()
public synchronized
Extractor createExtractors(Uri uri, java.util.Map<java.lang.String, java.util.List> responseHeaders)
Source
/*
* Copyright (C) 2016 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;
import static androidx.media3.common.FileTypes.inferFileTypeFromResponseHeaders;
import static androidx.media3.common.FileTypes.inferFileTypeFromUri;
import android.net.Uri;
import androidx.annotation.GuardedBy;
import androidx.annotation.Nullable;
import androidx.media3.common.FileTypes;
import androidx.media3.common.PlaybackException;
import androidx.media3.common.Player;
import androidx.media3.common.util.TimestampAdjuster;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.extractor.amr.AmrExtractor;
import androidx.media3.extractor.flac.FlacExtractor;
import androidx.media3.extractor.flv.FlvExtractor;
import androidx.media3.extractor.jpeg.JpegExtractor;
import androidx.media3.extractor.mkv.MatroskaExtractor;
import androidx.media3.extractor.mp3.Mp3Extractor;
import androidx.media3.extractor.mp4.FragmentedMp4Extractor;
import androidx.media3.extractor.mp4.Mp4Extractor;
import androidx.media3.extractor.ogg.OggExtractor;
import androidx.media3.extractor.ts.Ac3Extractor;
import androidx.media3.extractor.ts.Ac4Extractor;
import androidx.media3.extractor.ts.AdtsExtractor;
import androidx.media3.extractor.ts.DefaultTsPayloadReaderFactory;
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 java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* An {@link ExtractorsFactory} that provides an array of extractors for the following formats:
*
* <ul>
* <li>MP4, including M4A ({@link Mp4Extractor})
* <li>fMP4 ({@link FragmentedMp4Extractor})
* <li>Matroska and WebM ({@link MatroskaExtractor})
* <li>Ogg Vorbis/FLAC ({@link OggExtractor}
* <li>MP3 ({@link Mp3Extractor})
* <li>AAC ({@link AdtsExtractor})
* <li>MPEG TS ({@link TsExtractor})
* <li>MPEG PS ({@link PsExtractor})
* <li>FLV ({@link FlvExtractor})
* <li>WAV ({@link WavExtractor})
* <li>AC3 ({@link Ac3Extractor})
* <li>AC4 ({@link Ac4Extractor})
* <li>AMR ({@link AmrExtractor})
* <li>FLAC
* <ul>
* <li>If available, the FLAC extension's {@code androidx.media3.decoder.flac.FlacExtractor}
* is used.
* <li>Otherwise, the core {@link FlacExtractor} is used. Note that Android devices do not
* generally include a FLAC decoder before API 27. This can be worked around by using
* the FLAC extension or the FFmpeg extension.
* </ul>
* <li>JPEG ({@link JpegExtractor})
* </ul>
*/
@UnstableApi
public final class DefaultExtractorsFactory implements ExtractorsFactory {
// Extractors order is optimized according to
// https://docs.google.com/document/d/1w2mKaWMxfz2Ei8-LdxqbPs1VLe_oudB-eryXXw9OvQQ.
// The JPEG extractor appears after audio/video extractors because we expect audio/video input to
// be more common.
private static final int[] DEFAULT_EXTRACTOR_ORDER =
new int[] {
FileTypes.FLV,
FileTypes.FLAC,
FileTypes.WAV,
FileTypes.MP4,
FileTypes.AMR,
FileTypes.PS,
FileTypes.OGG,
FileTypes.TS,
FileTypes.MATROSKA,
FileTypes.ADTS,
FileTypes.AC3,
FileTypes.AC4,
FileTypes.MP3,
FileTypes.JPEG,
};
private static final FlacExtensionLoader FLAC_EXTENSION_LOADER = new FlacExtensionLoader();
private boolean constantBitrateSeekingEnabled;
private boolean constantBitrateSeekingAlwaysEnabled;
private @AdtsExtractor.Flags int adtsFlags;
private @AmrExtractor.Flags int amrFlags;
private @FlacExtractor.Flags int flacFlags;
private @MatroskaExtractor.Flags int matroskaFlags;
private @Mp4Extractor.Flags int mp4Flags;
private @FragmentedMp4Extractor.Flags int fragmentedMp4Flags;
private @Mp3Extractor.Flags int mp3Flags;
private @TsExtractor.Mode int tsMode;
private @DefaultTsPayloadReaderFactory.Flags int tsFlags;
private int tsTimestampSearchBytes;
public DefaultExtractorsFactory() {
tsMode = TsExtractor.MODE_SINGLE_PMT;
tsTimestampSearchBytes = TsExtractor.DEFAULT_TIMESTAMP_SEARCH_BYTES;
}
/**
* Convenience method to set whether approximate seeking using constant bitrate assumptions should
* be enabled for all extractors that support it. If set to true, the flags required to enable
* this functionality will be OR'd with those passed to the setters when creating extractor
* instances. If set to false then the flags passed to the setters will be used without
* modification.
*
* @param constantBitrateSeekingEnabled Whether approximate seeking using a constant bitrate
* assumption should be enabled for all extractors that support it.
* @return The factory, for convenience.
*/
public synchronized DefaultExtractorsFactory setConstantBitrateSeekingEnabled(
boolean constantBitrateSeekingEnabled) {
this.constantBitrateSeekingEnabled = constantBitrateSeekingEnabled;
return this;
}
/**
* Convenience method to set whether approximate seeking using constant bitrate assumptions should
* be enabled for all extractors that support it, and if it should be enabled even if the content
* length (and hence the duration of the media) is unknown. If set to true, the flags required to
* enable this functionality will be OR'd with those passed to the setters when creating extractor
* instances. If set to false then the flags passed to the setters will be used without
* modification.
*
* <p>When seeking into content where the length is unknown, application code should ensure that
* requested seek positions are valid, or should be ready to handle playback failures reported
* through {@link Player.Listener#onPlayerError} with {@link PlaybackException#errorCode} set to
* {@link PlaybackException#ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE}.
*
* @param constantBitrateSeekingAlwaysEnabled Whether approximate seeking using a constant bitrate
* assumption should be enabled for all extractors that support it, including when the content
* duration is unknown.
* @return The factory, for convenience.
*/
public synchronized DefaultExtractorsFactory setConstantBitrateSeekingAlwaysEnabled(
boolean constantBitrateSeekingAlwaysEnabled) {
this.constantBitrateSeekingAlwaysEnabled = constantBitrateSeekingAlwaysEnabled;
return this;
}
/**
* Sets flags for {@link AdtsExtractor} instances created by the factory.
*
* @see AdtsExtractor#AdtsExtractor(int)
* @param flags The flags to use.
* @return The factory, for convenience.
*/
public synchronized DefaultExtractorsFactory setAdtsExtractorFlags(
@AdtsExtractor.Flags int flags) {
this.adtsFlags = flags;
return this;
}
/**
* Sets flags for {@link AmrExtractor} instances created by the factory.
*
* @see AmrExtractor#AmrExtractor(int)
* @param flags The flags to use.
* @return The factory, for convenience.
*/
public synchronized DefaultExtractorsFactory setAmrExtractorFlags(@AmrExtractor.Flags int flags) {
this.amrFlags = flags;
return this;
}
/**
* Sets flags for {@link FlacExtractor} instances created by the factory. The flags are also used
* by {@code androidx.media3.decoder.flac.FlacExtractor} instances if the FLAC extension is being
* used.
*
* @see FlacExtractor#FlacExtractor(int)
* @param flags The flags to use.
* @return The factory, for convenience.
*/
public synchronized DefaultExtractorsFactory setFlacExtractorFlags(
@FlacExtractor.Flags int flags) {
this.flacFlags = flags;
return this;
}
/**
* Sets flags for {@link MatroskaExtractor} instances created by the factory.
*
* @see MatroskaExtractor#MatroskaExtractor(int)
* @param flags The flags to use.
* @return The factory, for convenience.
*/
public synchronized DefaultExtractorsFactory setMatroskaExtractorFlags(
@MatroskaExtractor.Flags int flags) {
this.matroskaFlags = flags;
return this;
}
/**
* Sets flags for {@link Mp4Extractor} instances created by the factory.
*
* @see Mp4Extractor#Mp4Extractor(int)
* @param flags The flags to use.
* @return The factory, for convenience.
*/
public synchronized DefaultExtractorsFactory setMp4ExtractorFlags(@Mp4Extractor.Flags int flags) {
this.mp4Flags = flags;
return this;
}
/**
* Sets flags for {@link FragmentedMp4Extractor} instances created by the factory.
*
* @see FragmentedMp4Extractor#FragmentedMp4Extractor(int)
* @param flags The flags to use.
* @return The factory, for convenience.
*/
public synchronized DefaultExtractorsFactory setFragmentedMp4ExtractorFlags(
@FragmentedMp4Extractor.Flags int flags) {
this.fragmentedMp4Flags = flags;
return this;
}
/**
* Sets flags for {@link Mp3Extractor} instances created by the factory.
*
* @see Mp3Extractor#Mp3Extractor(int)
* @param flags The flags to use.
* @return The factory, for convenience.
*/
public synchronized DefaultExtractorsFactory setMp3ExtractorFlags(@Mp3Extractor.Flags int flags) {
mp3Flags = flags;
return this;
}
/**
* Sets the mode for {@link TsExtractor} instances created by the factory.
*
* @see TsExtractor#TsExtractor(int, TimestampAdjuster, TsPayloadReader.Factory, int)
* @param mode The mode to use.
* @return The factory, for convenience.
*/
public synchronized DefaultExtractorsFactory setTsExtractorMode(@TsExtractor.Mode int mode) {
tsMode = mode;
return this;
}
/**
* Sets flags for {@link DefaultTsPayloadReaderFactory}s used by {@link TsExtractor} instances
* created by the factory.
*
* @see TsExtractor#TsExtractor(int)
* @param flags The flags to use.
* @return The factory, for convenience.
*/
public synchronized DefaultExtractorsFactory setTsExtractorFlags(
@DefaultTsPayloadReaderFactory.Flags int flags) {
tsFlags = flags;
return this;
}
/**
* Sets the number of bytes searched to find a timestamp for {@link TsExtractor} instances created
* by the factory.
*
* @see TsExtractor#TsExtractor(int, TimestampAdjuster, TsPayloadReader.Factory, int)
* @param timestampSearchBytes The number of search bytes to use.
* @return The factory, for convenience.
*/
public synchronized DefaultExtractorsFactory setTsExtractorTimestampSearchBytes(
int timestampSearchBytes) {
tsTimestampSearchBytes = timestampSearchBytes;
return this;
}
@Override
public synchronized Extractor[] createExtractors() {
return createExtractors(Uri.EMPTY, new HashMap<>());
}
@Override
public synchronized Extractor[] createExtractors(
Uri uri, Map<String, List<String>> responseHeaders) {
List<Extractor> extractors = new ArrayList<>(/* initialCapacity= */ 14);
@FileTypes.Type
int responseHeadersInferredFileType = inferFileTypeFromResponseHeaders(responseHeaders);
if (responseHeadersInferredFileType != FileTypes.UNKNOWN) {
addExtractorsForFileType(responseHeadersInferredFileType, extractors);
}
@FileTypes.Type int uriInferredFileType = inferFileTypeFromUri(uri);
if (uriInferredFileType != FileTypes.UNKNOWN
&& uriInferredFileType != responseHeadersInferredFileType) {
addExtractorsForFileType(uriInferredFileType, extractors);
}
for (int fileType : DEFAULT_EXTRACTOR_ORDER) {
if (fileType != responseHeadersInferredFileType && fileType != uriInferredFileType) {
addExtractorsForFileType(fileType, extractors);
}
}
return extractors.toArray(new Extractor[extractors.size()]);
}
private void addExtractorsForFileType(@FileTypes.Type int fileType, List<Extractor> extractors) {
switch (fileType) {
case FileTypes.AC3:
extractors.add(new Ac3Extractor());
break;
case FileTypes.AC4:
extractors.add(new Ac4Extractor());
break;
case FileTypes.ADTS:
extractors.add(
new AdtsExtractor(
adtsFlags
| (constantBitrateSeekingEnabled
? AdtsExtractor.FLAG_ENABLE_CONSTANT_BITRATE_SEEKING
: 0)
| (constantBitrateSeekingAlwaysEnabled
? AdtsExtractor.FLAG_ENABLE_CONSTANT_BITRATE_SEEKING_ALWAYS
: 0)));
break;
case FileTypes.AMR:
extractors.add(
new AmrExtractor(
amrFlags
| (constantBitrateSeekingEnabled
? AmrExtractor.FLAG_ENABLE_CONSTANT_BITRATE_SEEKING
: 0)
| (constantBitrateSeekingAlwaysEnabled
? AmrExtractor.FLAG_ENABLE_CONSTANT_BITRATE_SEEKING_ALWAYS
: 0)));
break;
case FileTypes.FLAC:
@Nullable Extractor flacExtractor = FLAC_EXTENSION_LOADER.getExtractor(flacFlags);
if (flacExtractor != null) {
extractors.add(flacExtractor);
} else {
extractors.add(new FlacExtractor(flacFlags));
}
break;
case FileTypes.FLV:
extractors.add(new FlvExtractor());
break;
case FileTypes.MATROSKA:
extractors.add(new MatroskaExtractor(matroskaFlags));
break;
case FileTypes.MP3:
extractors.add(
new Mp3Extractor(
mp3Flags
| (constantBitrateSeekingEnabled
? Mp3Extractor.FLAG_ENABLE_CONSTANT_BITRATE_SEEKING
: 0)
| (constantBitrateSeekingAlwaysEnabled
? Mp3Extractor.FLAG_ENABLE_CONSTANT_BITRATE_SEEKING_ALWAYS
: 0)));
break;
case FileTypes.MP4:
extractors.add(new FragmentedMp4Extractor(fragmentedMp4Flags));
extractors.add(new Mp4Extractor(mp4Flags));
break;
case FileTypes.OGG:
extractors.add(new OggExtractor());
break;
case FileTypes.PS:
extractors.add(new PsExtractor());
break;
case FileTypes.TS:
extractors.add(new TsExtractor(tsMode, tsFlags, tsTimestampSearchBytes));
break;
case FileTypes.WAV:
extractors.add(new WavExtractor());
break;
case FileTypes.JPEG:
extractors.add(new JpegExtractor());
break;
case FileTypes.WEBVTT:
case FileTypes.UNKNOWN:
default:
break;
}
}
private static final class FlacExtensionLoader {
private final AtomicBoolean extensionLoaded;
@GuardedBy("extensionLoaded")
@Nullable
private Constructor<? extends Extractor> extractorConstructor;
public FlacExtensionLoader() {
extensionLoaded = new AtomicBoolean(false);
}
@Nullable
public Extractor getExtractor(int flags) {
@Nullable
Constructor<? extends Extractor> extractorConstructor = maybeLoadExtractorConstructor();
if (extractorConstructor == null) {
return null;
}
try {
return extractorConstructor.newInstance(flags);
} catch (Exception e) {
throw new IllegalStateException("Unexpected error creating FLAC extractor", e);
}
}
@Nullable
private Constructor<? extends Extractor> maybeLoadExtractorConstructor() {
synchronized (extensionLoaded) {
if (extensionLoaded.get()) {
return extractorConstructor;
}
try {
@SuppressWarnings("nullness:argument")
boolean isFlacNativeLibraryAvailable =
Boolean.TRUE.equals(
Class.forName("androidx.media3.decoder.flac.FlacLibrary")
.getMethod("isAvailable")
.invoke(/* obj= */ null));
if (isFlacNativeLibraryAvailable) {
extractorConstructor =
Class.forName("androidx.media3.decoder.flac.FlacExtractor")
.asSubclass(Extractor.class)
.getConstructor(int.class);
}
} catch (ClassNotFoundException e) {
// Expected if the app was built without the FLAC extension.
} catch (Exception e) {
// The FLAC extension is present, but instantiation failed.
throw new RuntimeException("Error instantiating FLAC extension", e);
}
extensionLoaded.set(true);
return extractorConstructor;
}
}
}
}