Optimize extractors sniffing order

Issue: #6410
PiperOrigin-RevId: 305436352
This commit is contained in:
kimvde 2020-04-08 10:20:36 +01:00 committed by Oliver Woodman
parent 4e2a0f6032
commit 703fb777c4
3 changed files with 77 additions and 58 deletions

View File

@ -109,6 +109,9 @@
* Cast extension: Implement playlist API and deprecate the old queue * Cast extension: Implement playlist API and deprecate the old queue
manipulation API. manipulation API.
* Demo app: Retain previous position in list of samples. * Demo app: Retain previous position in list of samples.
* Change the order of extractors for sniffing to reduce start-up latency in
`DefaultExtractorsFactory` and `DefaultHlsExtractorsFactory`
([#6410](https://github.com/google/ExoPlayer/issues/6410)).
### 2.11.4 (2020-04-08) ### 2.11.4 (2020-04-08)

View File

@ -241,44 +241,46 @@ public final class DefaultExtractorsFactory implements ExtractorsFactory {
@Override @Override
public synchronized Extractor[] createExtractors() { public synchronized Extractor[] createExtractors() {
Extractor[] extractors = new Extractor[14]; Extractor[] extractors = new Extractor[14];
extractors[0] = new MatroskaExtractor(matroskaFlags); // Extractors order is optimized according to
extractors[1] = new FragmentedMp4Extractor(fragmentedMp4Flags); // https://docs.google.com/document/d/1w2mKaWMxfz2Ei8-LdxqbPs1VLe_oudB-eryXXw9OvQQ.
extractors[2] = new Mp4Extractor(mp4Flags); extractors[0] = new FlvExtractor();
extractors[3] =
new Mp3Extractor(
mp3Flags
| (constantBitrateSeekingEnabled
? Mp3Extractor.FLAG_ENABLE_CONSTANT_BITRATE_SEEKING
: 0));
extractors[4] =
new AdtsExtractor(
adtsFlags
| (constantBitrateSeekingEnabled
? AdtsExtractor.FLAG_ENABLE_CONSTANT_BITRATE_SEEKING
: 0));
extractors[5] = new Ac3Extractor();
extractors[6] = new TsExtractor(tsMode, tsFlags);
extractors[7] = new FlvExtractor();
extractors[8] = new OggExtractor();
extractors[9] = new PsExtractor();
extractors[10] = new WavExtractor();
extractors[11] =
new AmrExtractor(
amrFlags
| (constantBitrateSeekingEnabled
? AmrExtractor.FLAG_ENABLE_CONSTANT_BITRATE_SEEKING
: 0));
extractors[12] = new Ac4Extractor();
if (FLAC_EXTENSION_EXTRACTOR_CONSTRUCTOR != null) { if (FLAC_EXTENSION_EXTRACTOR_CONSTRUCTOR != null) {
try { try {
extractors[13] = FLAC_EXTENSION_EXTRACTOR_CONSTRUCTOR.newInstance(); extractors[1] = FLAC_EXTENSION_EXTRACTOR_CONSTRUCTOR.newInstance();
} catch (Exception e) { } catch (Exception e) {
// Should never happen. // Should never happen.
throw new IllegalStateException("Unexpected error creating FLAC extractor", e); throw new IllegalStateException("Unexpected error creating FLAC extractor", e);
} }
} else { } else {
extractors[13] = new FlacExtractor(coreFlacFlags); extractors[1] = new FlacExtractor(coreFlacFlags);
} }
extractors[2] = new WavExtractor();
extractors[3] = new FragmentedMp4Extractor(fragmentedMp4Flags);
extractors[4] = new Mp4Extractor(mp4Flags);
extractors[5] =
new AmrExtractor(
amrFlags
| (constantBitrateSeekingEnabled
? AmrExtractor.FLAG_ENABLE_CONSTANT_BITRATE_SEEKING
: 0));
extractors[6] = new PsExtractor();
extractors[7] = new OggExtractor();
extractors[8] = new TsExtractor(tsMode, tsFlags);
extractors[9] = new MatroskaExtractor(matroskaFlags);
extractors[10] =
new AdtsExtractor(
adtsFlags
| (constantBitrateSeekingEnabled
? AdtsExtractor.FLAG_ENABLE_CONSTANT_BITRATE_SEEKING
: 0));
extractors[11] = new Ac3Extractor();
extractors[12] = new Ac4Extractor();
extractors[13] =
new Mp3Extractor(
mp3Flags
| (constantBitrateSeekingEnabled
? Mp3Extractor.FLAG_ENABLE_CONSTANT_BITRATE_SEEKING
: 0));
return extractors; return extractors;
} }

View File

@ -29,6 +29,7 @@ import com.google.android.exoplayer2.extractor.ts.AdtsExtractor;
import com.google.android.exoplayer2.extractor.ts.DefaultTsPayloadReaderFactory; import com.google.android.exoplayer2.extractor.ts.DefaultTsPayloadReaderFactory;
import com.google.android.exoplayer2.extractor.ts.TsExtractor; import com.google.android.exoplayer2.extractor.ts.TsExtractor;
import com.google.android.exoplayer2.metadata.Metadata; import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.TimestampAdjuster; import com.google.android.exoplayer2.util.TimestampAdjuster;
import java.io.EOFException; import java.io.EOFException;
@ -51,6 +52,8 @@ public final class DefaultHlsExtractorFactory implements HlsExtractorFactory {
public static final String M4_FILE_EXTENSION_PREFIX = ".m4"; public static final String M4_FILE_EXTENSION_PREFIX = ".m4";
public static final String MP4_FILE_EXTENSION_PREFIX = ".mp4"; public static final String MP4_FILE_EXTENSION_PREFIX = ".mp4";
public static final String CMF_FILE_EXTENSION_PREFIX = ".cmf"; public static final String CMF_FILE_EXTENSION_PREFIX = ".cmf";
public static final String TS_FILE_EXTENSION = ".ts";
public static final String TS_FILE_EXTENSION_PREFIX = ".ts";
public static final String VTT_FILE_EXTENSION = ".vtt"; public static final String VTT_FILE_EXTENSION = ".vtt";
public static final String WEBVTT_FILE_EXTENSION = ".webvtt"; public static final String WEBVTT_FILE_EXTENSION = ".webvtt";
@ -94,7 +97,7 @@ public final class DefaultHlsExtractorFactory implements HlsExtractorFactory {
throws IOException { throws IOException {
if (previousExtractor != null) { if (previousExtractor != null) {
// A extractor has already been successfully used. Return one of the same type. // An extractor has already been successfully used. Return one of the same type.
if (isReusable(previousExtractor)) { if (isReusable(previousExtractor)) {
return buildResult(previousExtractor); return buildResult(previousExtractor);
} else { } else {
@ -108,15 +111,29 @@ public final class DefaultHlsExtractorFactory implements HlsExtractorFactory {
} }
// Try selecting the extractor by the file extension. // Try selecting the extractor by the file extension.
@Nullable
Extractor extractorByFileExtension = Extractor extractorByFileExtension =
createExtractorByFileExtension(uri, format, muxedCaptionFormats, timestampAdjuster); createExtractorByFileExtension(uri, format, muxedCaptionFormats, timestampAdjuster);
extractorInput.resetPeekPosition(); extractorInput.resetPeekPosition();
if (sniffQuietly(extractorByFileExtension, extractorInput)) { if (extractorByFileExtension != null
&& sniffQuietly(extractorByFileExtension, extractorInput)) {
return buildResult(extractorByFileExtension); return buildResult(extractorByFileExtension);
} }
// We need to manually sniff each known type, without retrying the one selected by file // We need to manually sniff each known type, without retrying the one selected by file
// extension. // extension. Extractors order is optimized according to
// https://docs.google.com/document/d/1w2mKaWMxfz2Ei8-LdxqbPs1VLe_oudB-eryXXw9OvQQ.
// Extractor to be used if the type is not recognized.
@Nullable Extractor fallBackExtractor = extractorByFileExtension;
if (!(extractorByFileExtension instanceof FragmentedMp4Extractor)) {
FragmentedMp4Extractor fragmentedMp4Extractor =
createFragmentedMp4Extractor(timestampAdjuster, format, muxedCaptionFormats);
if (sniffQuietly(fragmentedMp4Extractor, extractorInput)) {
return buildResult(fragmentedMp4Extractor);
}
}
if (!(extractorByFileExtension instanceof WebvttExtractor)) { if (!(extractorByFileExtension instanceof WebvttExtractor)) {
WebvttExtractor webvttExtractor = new WebvttExtractor(format.language, timestampAdjuster); WebvttExtractor webvttExtractor = new WebvttExtractor(format.language, timestampAdjuster);
@ -125,6 +142,22 @@ public final class DefaultHlsExtractorFactory implements HlsExtractorFactory {
} }
} }
if (!(extractorByFileExtension instanceof TsExtractor)) {
TsExtractor tsExtractor =
createTsExtractor(
payloadReaderFactoryFlags,
exposeCea608WhenMissingDeclarations,
format,
muxedCaptionFormats,
timestampAdjuster);
if (sniffQuietly(tsExtractor, extractorInput)) {
return buildResult(tsExtractor);
}
if (fallBackExtractor == null) {
fallBackExtractor = tsExtractor;
}
}
if (!(extractorByFileExtension instanceof AdtsExtractor)) { if (!(extractorByFileExtension instanceof AdtsExtractor)) {
AdtsExtractor adtsExtractor = new AdtsExtractor(); AdtsExtractor adtsExtractor = new AdtsExtractor();
if (sniffQuietly(adtsExtractor, extractorInput)) { if (sniffQuietly(adtsExtractor, extractorInput)) {
@ -154,31 +187,10 @@ public final class DefaultHlsExtractorFactory implements HlsExtractorFactory {
} }
} }
if (!(extractorByFileExtension instanceof FragmentedMp4Extractor)) { return buildResult(Assertions.checkNotNull(fallBackExtractor));
FragmentedMp4Extractor fragmentedMp4Extractor =
createFragmentedMp4Extractor(timestampAdjuster, format, muxedCaptionFormats);
if (sniffQuietly(fragmentedMp4Extractor, extractorInput)) {
return buildResult(fragmentedMp4Extractor);
}
}
if (!(extractorByFileExtension instanceof TsExtractor)) {
TsExtractor tsExtractor =
createTsExtractor(
payloadReaderFactoryFlags,
exposeCea608WhenMissingDeclarations,
format,
muxedCaptionFormats,
timestampAdjuster);
if (sniffQuietly(tsExtractor, extractorInput)) {
return buildResult(tsExtractor);
}
}
// Fall back on the extractor created by file extension.
return buildResult(extractorByFileExtension);
} }
@Nullable
private Extractor createExtractorByFileExtension( private Extractor createExtractorByFileExtension(
Uri uri, Uri uri,
Format format, Format format,
@ -206,14 +218,16 @@ public final class DefaultHlsExtractorFactory implements HlsExtractorFactory {
|| lastPathSegment.startsWith(MP4_FILE_EXTENSION_PREFIX, lastPathSegment.length() - 5) || lastPathSegment.startsWith(MP4_FILE_EXTENSION_PREFIX, lastPathSegment.length() - 5)
|| lastPathSegment.startsWith(CMF_FILE_EXTENSION_PREFIX, lastPathSegment.length() - 5)) { || lastPathSegment.startsWith(CMF_FILE_EXTENSION_PREFIX, lastPathSegment.length() - 5)) {
return createFragmentedMp4Extractor(timestampAdjuster, format, muxedCaptionFormats); return createFragmentedMp4Extractor(timestampAdjuster, format, muxedCaptionFormats);
} else { } else if (lastPathSegment.endsWith(TS_FILE_EXTENSION)
// For any other file extension, we assume TS format. || lastPathSegment.startsWith(TS_FILE_EXTENSION_PREFIX, lastPathSegment.length() - 4)) {
return createTsExtractor( return createTsExtractor(
payloadReaderFactoryFlags, payloadReaderFactoryFlags,
exposeCea608WhenMissingDeclarations, exposeCea608WhenMissingDeclarations,
format, format,
muxedCaptionFormats, muxedCaptionFormats,
timestampAdjuster); timestampAdjuster);
} else {
return null;
} }
} }