mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Add support for inferring file format from MIME type
PiperOrigin-RevId: 315283926
This commit is contained in:
parent
99d805f6a8
commit
b1e56304a1
6 changed files with 174 additions and 39 deletions
|
|
@ -15,11 +15,17 @@
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.util;
|
package com.google.android.exoplayer2.util;
|
||||||
|
|
||||||
|
import static com.google.android.exoplayer2.util.MimeTypes.normalizeMimeType;
|
||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import androidx.annotation.IntDef;
|
import androidx.annotation.IntDef;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.annotation.VisibleForTesting;
|
||||||
import java.lang.annotation.Documented;
|
import java.lang.annotation.Documented;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/** Defines common file type constants and helper methods. */
|
/** Defines common file type constants and helper methods. */
|
||||||
public final class FileTypes {
|
public final class FileTypes {
|
||||||
|
|
@ -64,6 +70,8 @@ public final class FileTypes {
|
||||||
/** File type for the WebVTT format. */
|
/** File type for the WebVTT format. */
|
||||||
public static final int WEBVTT = 13;
|
public static final int WEBVTT = 13;
|
||||||
|
|
||||||
|
@VisibleForTesting /* package */ static final String HEADER_CONTENT_TYPE = "Content-Type";
|
||||||
|
|
||||||
private static final String EXTENSION_AC3 = ".ac3";
|
private static final String EXTENSION_AC3 = ".ac3";
|
||||||
private static final String EXTENSION_EC3 = ".ec3";
|
private static final String EXTENSION_EC3 = ".ec3";
|
||||||
private static final String EXTENSION_AC4 = ".ac4";
|
private static final String EXTENSION_AC4 = ".ac4";
|
||||||
|
|
@ -94,13 +102,72 @@ public final class FileTypes {
|
||||||
|
|
||||||
private FileTypes() {}
|
private FileTypes() {}
|
||||||
|
|
||||||
|
/** Returns the {@link Type} corresponding to the response headers provided. */
|
||||||
|
@FileTypes.Type
|
||||||
|
public static int inferFileTypeFromResponseHeaders(Map<String, List<String>> responseHeaders) {
|
||||||
|
@Nullable List<String> contentTypes = responseHeaders.get(HEADER_CONTENT_TYPE);
|
||||||
|
@Nullable
|
||||||
|
String mimeType = contentTypes == null || contentTypes.isEmpty() ? null : contentTypes.get(0);
|
||||||
|
return inferFileTypeFromMimeType(mimeType);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@link Type} corresponding to the filename extension of the provided {@link Uri}.
|
* Returns the {@link Type} corresponding to the MIME type provided.
|
||||||
* The filename is considered to be the last segment of the {@link Uri} path.
|
*
|
||||||
|
* <p>Returns {@link #UNKNOWN} if the mime type is {@code null}.
|
||||||
*/
|
*/
|
||||||
@FileTypes.Type
|
@FileTypes.Type
|
||||||
public static int getFormatFromExtension(Uri uri) {
|
public static int inferFileTypeFromMimeType(@Nullable String mimeType) {
|
||||||
String filename = uri.getLastPathSegment();
|
if (mimeType == null) {
|
||||||
|
return FileTypes.UNKNOWN;
|
||||||
|
}
|
||||||
|
mimeType = normalizeMimeType(mimeType);
|
||||||
|
switch (mimeType) {
|
||||||
|
case MimeTypes.AUDIO_AC3:
|
||||||
|
case MimeTypes.AUDIO_E_AC3:
|
||||||
|
case MimeTypes.AUDIO_E_AC3_JOC:
|
||||||
|
return FileTypes.AC3;
|
||||||
|
case MimeTypes.AUDIO_AC4:
|
||||||
|
return FileTypes.AC4;
|
||||||
|
case MimeTypes.AUDIO_AMR:
|
||||||
|
case MimeTypes.AUDIO_AMR_NB:
|
||||||
|
case MimeTypes.AUDIO_AMR_WB:
|
||||||
|
return FileTypes.AMR;
|
||||||
|
case MimeTypes.AUDIO_FLAC:
|
||||||
|
return FileTypes.FLAC;
|
||||||
|
case MimeTypes.VIDEO_FLV:
|
||||||
|
return FileTypes.FLV;
|
||||||
|
case MimeTypes.VIDEO_MATROSKA:
|
||||||
|
case MimeTypes.AUDIO_MATROSKA:
|
||||||
|
case MimeTypes.VIDEO_WEBM:
|
||||||
|
case MimeTypes.AUDIO_WEBM:
|
||||||
|
case MimeTypes.APPLICATION_WEBM:
|
||||||
|
return FileTypes.MATROSKA;
|
||||||
|
case MimeTypes.AUDIO_MPEG:
|
||||||
|
return FileTypes.MP3;
|
||||||
|
case MimeTypes.VIDEO_MP4:
|
||||||
|
case MimeTypes.AUDIO_MP4:
|
||||||
|
case MimeTypes.APPLICATION_MP4:
|
||||||
|
return FileTypes.MP4;
|
||||||
|
case MimeTypes.AUDIO_OGG:
|
||||||
|
return FileTypes.OGG;
|
||||||
|
case MimeTypes.VIDEO_PS:
|
||||||
|
return FileTypes.PS;
|
||||||
|
case MimeTypes.VIDEO_MP2T:
|
||||||
|
return FileTypes.TS;
|
||||||
|
case MimeTypes.AUDIO_WAV:
|
||||||
|
return FileTypes.WAV;
|
||||||
|
case MimeTypes.TEXT_VTT:
|
||||||
|
return FileTypes.WEBVTT;
|
||||||
|
default:
|
||||||
|
return FileTypes.UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns the {@link Type} corresponding to the {@link Uri} provided. */
|
||||||
|
@FileTypes.Type
|
||||||
|
public static int inferFileTypeFromUri(Uri uri) {
|
||||||
|
@Nullable String filename = uri.getLastPathSegment();
|
||||||
if (filename == null) {
|
if (filename == null) {
|
||||||
return FileTypes.UNKNOWN;
|
return FileTypes.UNKNOWN;
|
||||||
} else if (filename.endsWith(EXTENSION_AC3) || filename.endsWith(EXTENSION_EC3)) {
|
} else if (filename.endsWith(EXTENSION_AC3) || filename.endsWith(EXTENSION_EC3)) {
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@ public final class MimeTypes {
|
||||||
public static final String BASE_TYPE_APPLICATION = "application";
|
public static final String BASE_TYPE_APPLICATION = "application";
|
||||||
|
|
||||||
public static final String VIDEO_MP4 = BASE_TYPE_VIDEO + "/mp4";
|
public static final String VIDEO_MP4 = BASE_TYPE_VIDEO + "/mp4";
|
||||||
|
public static final String VIDEO_MATROSKA = BASE_TYPE_VIDEO + "/x-matroska";
|
||||||
public static final String VIDEO_WEBM = BASE_TYPE_VIDEO + "/webm";
|
public static final String VIDEO_WEBM = BASE_TYPE_VIDEO + "/webm";
|
||||||
public static final String VIDEO_H263 = BASE_TYPE_VIDEO + "/3gpp";
|
public static final String VIDEO_H263 = BASE_TYPE_VIDEO + "/3gpp";
|
||||||
public static final String VIDEO_H264 = BASE_TYPE_VIDEO + "/avc";
|
public static final String VIDEO_H264 = BASE_TYPE_VIDEO + "/avc";
|
||||||
|
|
@ -67,6 +68,7 @@ public final class MimeTypes {
|
||||||
|
|
||||||
public static final String AUDIO_MP4 = BASE_TYPE_AUDIO + "/mp4";
|
public static final String AUDIO_MP4 = BASE_TYPE_AUDIO + "/mp4";
|
||||||
public static final String AUDIO_AAC = BASE_TYPE_AUDIO + "/mp4a-latm";
|
public static final String AUDIO_AAC = BASE_TYPE_AUDIO + "/mp4a-latm";
|
||||||
|
public static final String AUDIO_MATROSKA = BASE_TYPE_AUDIO + "/x-matroska";
|
||||||
public static final String AUDIO_WEBM = BASE_TYPE_AUDIO + "/webm";
|
public static final String AUDIO_WEBM = BASE_TYPE_AUDIO + "/webm";
|
||||||
public static final String AUDIO_MPEG = BASE_TYPE_AUDIO + "/mpeg";
|
public static final String AUDIO_MPEG = BASE_TYPE_AUDIO + "/mpeg";
|
||||||
public static final String AUDIO_MPEG_L1 = BASE_TYPE_AUDIO + "/mpeg-L1";
|
public static final String AUDIO_MPEG_L1 = BASE_TYPE_AUDIO + "/mpeg-L1";
|
||||||
|
|
@ -91,6 +93,7 @@ public final class MimeTypes {
|
||||||
public static final String AUDIO_ALAC = BASE_TYPE_AUDIO + "/alac";
|
public static final String AUDIO_ALAC = BASE_TYPE_AUDIO + "/alac";
|
||||||
public static final String AUDIO_MSGSM = BASE_TYPE_AUDIO + "/gsm";
|
public static final String AUDIO_MSGSM = BASE_TYPE_AUDIO + "/gsm";
|
||||||
public static final String AUDIO_OGG = BASE_TYPE_AUDIO + "/ogg";
|
public static final String AUDIO_OGG = BASE_TYPE_AUDIO + "/ogg";
|
||||||
|
public static final String AUDIO_WAV = BASE_TYPE_AUDIO + "/wav";
|
||||||
public static final String AUDIO_UNKNOWN = BASE_TYPE_AUDIO + "/x-unknown";
|
public static final String AUDIO_UNKNOWN = BASE_TYPE_AUDIO + "/x-unknown";
|
||||||
|
|
||||||
public static final String TEXT_VTT = BASE_TYPE_TEXT + "/vtt";
|
public static final String TEXT_VTT = BASE_TYPE_TEXT + "/vtt";
|
||||||
|
|
@ -502,6 +505,26 @@ public final class MimeTypes {
|
||||||
return new Mp4aObjectType(objectTypeIndication, audioObjectTypeIndication);
|
return new Mp4aObjectType(objectTypeIndication, audioObjectTypeIndication);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalizes the MIME type provided so that equivalent MIME types are uniquely represented.
|
||||||
|
*
|
||||||
|
* @param mimeType The MIME type to normalize. The MIME type provided is returned if its
|
||||||
|
* normalized form is unknown.
|
||||||
|
* @return The normalized MIME type.
|
||||||
|
*/
|
||||||
|
public static String normalizeMimeType(String mimeType) {
|
||||||
|
switch (mimeType) {
|
||||||
|
case BASE_TYPE_AUDIO + "/x-flac":
|
||||||
|
return AUDIO_FLAC;
|
||||||
|
case BASE_TYPE_AUDIO + "/mp3":
|
||||||
|
return AUDIO_MPEG;
|
||||||
|
case BASE_TYPE_AUDIO + "/x-wav":
|
||||||
|
return AUDIO_WAV;
|
||||||
|
default:
|
||||||
|
return mimeType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the top-level type of {@code mimeType}, or null if {@code mimeType} is null or does not
|
* Returns the top-level type of {@code mimeType}, or null if {@code mimeType} is null or does not
|
||||||
* contain a forward slash character ({@code '/'}).
|
* contain a forward slash character ({@code '/'}).
|
||||||
|
|
|
||||||
|
|
@ -1676,6 +1676,7 @@ public final class Util {
|
||||||
* @param mimeType If not null, used to infer the type.
|
* @param mimeType If not null, used to infer the type.
|
||||||
* @return The content type.
|
* @return The content type.
|
||||||
*/
|
*/
|
||||||
|
@C.ContentType
|
||||||
public static int inferContentTypeWithMimeType(Uri uri, @Nullable String mimeType) {
|
public static int inferContentTypeWithMimeType(Uri uri, @Nullable String mimeType) {
|
||||||
if (mimeType == null) {
|
if (mimeType == null) {
|
||||||
return Util.inferContentType(uri);
|
return Util.inferContentType(uri);
|
||||||
|
|
|
||||||
|
|
@ -15,11 +15,17 @@
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.util;
|
package com.google.android.exoplayer2.util;
|
||||||
|
|
||||||
import static com.google.android.exoplayer2.util.FileTypes.getFormatFromExtension;
|
import static com.google.android.exoplayer2.util.FileTypes.HEADER_CONTENT_TYPE;
|
||||||
|
import static com.google.android.exoplayer2.util.FileTypes.inferFileTypeFromMimeType;
|
||||||
|
import static com.google.android.exoplayer2.util.FileTypes.inferFileTypeFromUri;
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
|
@ -28,30 +34,64 @@ import org.junit.runner.RunWith;
|
||||||
public class FileTypesTest {
|
public class FileTypesTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getFormatFromExtension_withExtension_returnsExpectedFormat() {
|
public void inferFileFormat_fromResponseHeaders_returnsExpectedFormat() {
|
||||||
assertThat(getFormatFromExtension(Uri.parse("filename.mp3"))).isEqualTo(FileTypes.MP3);
|
Map<String, List<String>> responseHeaders = new HashMap<>();
|
||||||
|
responseHeaders.put(HEADER_CONTENT_TYPE, Collections.singletonList(MimeTypes.VIDEO_MP4));
|
||||||
|
|
||||||
|
assertThat(FileTypes.inferFileTypeFromResponseHeaders(responseHeaders))
|
||||||
|
.isEqualTo(FileTypes.MP4);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getFormatFromExtension_withExtensionPrefix_returnsExpectedFormat() {
|
public void inferFileFormat_fromResponseHeadersWithUnknownContentType_returnsUnknownFormat() {
|
||||||
assertThat(getFormatFromExtension(Uri.parse("filename.mka"))).isEqualTo(FileTypes.MATROSKA);
|
Map<String, List<String>> responseHeaders = new HashMap<>();
|
||||||
|
responseHeaders.put(HEADER_CONTENT_TYPE, Collections.singletonList("unknown"));
|
||||||
|
|
||||||
|
assertThat(FileTypes.inferFileTypeFromResponseHeaders(responseHeaders))
|
||||||
|
.isEqualTo(FileTypes.UNKNOWN);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getFormatFromExtension_withUnknownExtension_returnsUnknownFormat() {
|
public void inferFileFormat_fromResponseHeadersWithoutContentType_returnsUnknownFormat() {
|
||||||
assertThat(getFormatFromExtension(Uri.parse("filename.unknown"))).isEqualTo(FileTypes.UNKNOWN);
|
assertThat(FileTypes.inferFileTypeFromResponseHeaders(new HashMap<>()))
|
||||||
|
.isEqualTo(FileTypes.UNKNOWN);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getFormatFromExtension_withUriNotEndingWithFilename_returnsExpectedFormat() {
|
public void inferFileFormat_fromMimeType_returnsExpectedFormat() {
|
||||||
|
assertThat(FileTypes.inferFileTypeFromMimeType("audio/x-flac")).isEqualTo(FileTypes.FLAC);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void inferFileFormat_fromUnknownMimeType_returnsUnknownFormat() {
|
||||||
|
assertThat(inferFileTypeFromMimeType(/* mimeType= */ "unknown")).isEqualTo(FileTypes.UNKNOWN);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void inferFileFormat_fromNullMimeType_returnsUnknownFormat() {
|
||||||
|
assertThat(inferFileTypeFromMimeType(/* mimeType= */ null)).isEqualTo(FileTypes.UNKNOWN);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void inferFileFormat_fromUri_returnsExpectedFormat() {
|
||||||
assertThat(
|
assertThat(
|
||||||
getFormatFromExtension(
|
inferFileTypeFromUri(
|
||||||
Uri.parse("http://www.example.com/filename.mp3?query=myquery#fragment")))
|
Uri.parse("http://www.example.com/filename.mp3?query=myquery#fragment")))
|
||||||
.isEqualTo(FileTypes.MP3);
|
.isEqualTo(FileTypes.MP3);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getFormatFromExtension_withNullFilename_returnsUnknownFormat() {
|
public void inferFileFormat_fromUriWithExtensionPrefix_returnsExpectedFormat() {
|
||||||
assertThat(getFormatFromExtension(Uri.EMPTY)).isEqualTo(FileTypes.UNKNOWN);
|
assertThat(inferFileTypeFromUri(Uri.parse("filename.mka"))).isEqualTo(FileTypes.MATROSKA);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void inferFileFormat_fromUriWithUnknownExtension_returnsUnknownFormat() {
|
||||||
|
assertThat(inferFileTypeFromUri(Uri.parse("filename.unknown"))).isEqualTo(FileTypes.UNKNOWN);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void inferFileFormat_fromEmptyUri_returnsUnknownFormat() {
|
||||||
|
assertThat(inferFileTypeFromUri(Uri.EMPTY)).isEqualTo(FileTypes.UNKNOWN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.extractor;
|
package com.google.android.exoplayer2.extractor;
|
||||||
|
|
||||||
import static com.google.android.exoplayer2.util.FileTypes.getFormatFromExtension;
|
import static com.google.android.exoplayer2.util.FileTypes.inferFileTypeFromUri;
|
||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
@ -272,11 +272,11 @@ public final class DefaultExtractorsFactory implements ExtractorsFactory {
|
||||||
public synchronized Extractor[] createExtractors(Uri uri) {
|
public synchronized Extractor[] createExtractors(Uri uri) {
|
||||||
List<Extractor> extractors = new ArrayList<>(/* initialCapacity= */ 14);
|
List<Extractor> extractors = new ArrayList<>(/* initialCapacity= */ 14);
|
||||||
|
|
||||||
@FileTypes.Type int extensionFormat = getFormatFromExtension(uri);
|
@FileTypes.Type int inferredFileType = inferFileTypeFromUri(uri);
|
||||||
addExtractorsForFormat(extensionFormat, extractors);
|
addExtractorsForFormat(inferredFileType, extractors);
|
||||||
|
|
||||||
for (int format : DEFAULT_EXTRACTOR_ORDER) {
|
for (int format : DEFAULT_EXTRACTOR_ORDER) {
|
||||||
if (format != extensionFormat) {
|
if (format != inferredFileType) {
|
||||||
addExtractorsForFormat(format, extractors);
|
addExtractorsForFormat(format, extractors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.source.hls;
|
package com.google.android.exoplayer2.source.hls;
|
||||||
|
|
||||||
import static com.google.android.exoplayer2.util.FileTypes.getFormatFromExtension;
|
import static com.google.android.exoplayer2.util.FileTypes.inferFileTypeFromUri;
|
||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
@ -101,12 +101,12 @@ public final class DefaultHlsExtractorFactory implements HlsExtractorFactory {
|
||||||
|
|
||||||
// Try selecting the extractor by the file extension.
|
// Try selecting the extractor by the file extension.
|
||||||
@Nullable
|
@Nullable
|
||||||
Extractor extractorByFileExtension =
|
Extractor inferredExtractor =
|
||||||
createExtractorByFileExtension(uri, format, muxedCaptionFormats, timestampAdjuster);
|
createInferredExtractor(
|
||||||
|
uri, format, muxedCaptionFormats, timestampAdjuster, responseHeaders);
|
||||||
extractorInput.resetPeekPosition();
|
extractorInput.resetPeekPosition();
|
||||||
if (extractorByFileExtension != null
|
if (inferredExtractor != null && sniffQuietly(inferredExtractor, extractorInput)) {
|
||||||
&& sniffQuietly(extractorByFileExtension, extractorInput)) {
|
return buildResult(inferredExtractor);
|
||||||
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
|
||||||
|
|
@ -114,9 +114,9 @@ public final class DefaultHlsExtractorFactory implements HlsExtractorFactory {
|
||||||
// https://docs.google.com/document/d/1w2mKaWMxfz2Ei8-LdxqbPs1VLe_oudB-eryXXw9OvQQ.
|
// https://docs.google.com/document/d/1w2mKaWMxfz2Ei8-LdxqbPs1VLe_oudB-eryXXw9OvQQ.
|
||||||
|
|
||||||
// Extractor to be used if the type is not recognized.
|
// Extractor to be used if the type is not recognized.
|
||||||
@Nullable Extractor fallBackExtractor = extractorByFileExtension;
|
@Nullable Extractor fallBackExtractor = inferredExtractor;
|
||||||
|
|
||||||
if (!(extractorByFileExtension instanceof FragmentedMp4Extractor)) {
|
if (!(inferredExtractor instanceof FragmentedMp4Extractor)) {
|
||||||
FragmentedMp4Extractor fragmentedMp4Extractor =
|
FragmentedMp4Extractor fragmentedMp4Extractor =
|
||||||
createFragmentedMp4Extractor(timestampAdjuster, format, muxedCaptionFormats);
|
createFragmentedMp4Extractor(timestampAdjuster, format, muxedCaptionFormats);
|
||||||
if (sniffQuietly(fragmentedMp4Extractor, extractorInput)) {
|
if (sniffQuietly(fragmentedMp4Extractor, extractorInput)) {
|
||||||
|
|
@ -124,14 +124,14 @@ public final class DefaultHlsExtractorFactory implements HlsExtractorFactory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(extractorByFileExtension instanceof WebvttExtractor)) {
|
if (!(inferredExtractor instanceof WebvttExtractor)) {
|
||||||
WebvttExtractor webvttExtractor = new WebvttExtractor(format.language, timestampAdjuster);
|
WebvttExtractor webvttExtractor = new WebvttExtractor(format.language, timestampAdjuster);
|
||||||
if (sniffQuietly(webvttExtractor, extractorInput)) {
|
if (sniffQuietly(webvttExtractor, extractorInput)) {
|
||||||
return buildResult(webvttExtractor);
|
return buildResult(webvttExtractor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(extractorByFileExtension instanceof TsExtractor)) {
|
if (!(inferredExtractor instanceof TsExtractor)) {
|
||||||
TsExtractor tsExtractor =
|
TsExtractor tsExtractor =
|
||||||
createTsExtractor(
|
createTsExtractor(
|
||||||
payloadReaderFactoryFlags,
|
payloadReaderFactoryFlags,
|
||||||
|
|
@ -147,28 +147,28 @@ public final class DefaultHlsExtractorFactory implements HlsExtractorFactory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(extractorByFileExtension instanceof AdtsExtractor)) {
|
if (!(inferredExtractor instanceof AdtsExtractor)) {
|
||||||
AdtsExtractor adtsExtractor = new AdtsExtractor();
|
AdtsExtractor adtsExtractor = new AdtsExtractor();
|
||||||
if (sniffQuietly(adtsExtractor, extractorInput)) {
|
if (sniffQuietly(adtsExtractor, extractorInput)) {
|
||||||
return buildResult(adtsExtractor);
|
return buildResult(adtsExtractor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(extractorByFileExtension instanceof Ac3Extractor)) {
|
if (!(inferredExtractor instanceof Ac3Extractor)) {
|
||||||
Ac3Extractor ac3Extractor = new Ac3Extractor();
|
Ac3Extractor ac3Extractor = new Ac3Extractor();
|
||||||
if (sniffQuietly(ac3Extractor, extractorInput)) {
|
if (sniffQuietly(ac3Extractor, extractorInput)) {
|
||||||
return buildResult(ac3Extractor);
|
return buildResult(ac3Extractor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(extractorByFileExtension instanceof Ac4Extractor)) {
|
if (!(inferredExtractor instanceof Ac4Extractor)) {
|
||||||
Ac4Extractor ac4Extractor = new Ac4Extractor();
|
Ac4Extractor ac4Extractor = new Ac4Extractor();
|
||||||
if (sniffQuietly(ac4Extractor, extractorInput)) {
|
if (sniffQuietly(ac4Extractor, extractorInput)) {
|
||||||
return buildResult(ac4Extractor);
|
return buildResult(ac4Extractor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(extractorByFileExtension instanceof Mp3Extractor)) {
|
if (!(inferredExtractor instanceof Mp3Extractor)) {
|
||||||
Mp3Extractor mp3Extractor =
|
Mp3Extractor mp3Extractor =
|
||||||
new Mp3Extractor(/* flags= */ 0, /* forcedFirstSampleTimestampUs= */ 0);
|
new Mp3Extractor(/* flags= */ 0, /* forcedFirstSampleTimestampUs= */ 0);
|
||||||
if (sniffQuietly(mp3Extractor, extractorInput)) {
|
if (sniffQuietly(mp3Extractor, extractorInput)) {
|
||||||
|
|
@ -180,16 +180,20 @@ public final class DefaultHlsExtractorFactory implements HlsExtractorFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private Extractor createExtractorByFileExtension(
|
private Extractor createInferredExtractor(
|
||||||
Uri uri,
|
Uri uri,
|
||||||
Format format,
|
Format format,
|
||||||
@Nullable List<Format> muxedCaptionFormats,
|
@Nullable List<Format> muxedCaptionFormats,
|
||||||
TimestampAdjuster timestampAdjuster) {
|
TimestampAdjuster timestampAdjuster,
|
||||||
if (MimeTypes.TEXT_VTT.equals(format.sampleMimeType)) {
|
Map<String, List<String>> responseHeaders) {
|
||||||
return new WebvttExtractor(format.language, timestampAdjuster);
|
@FileTypes.Type int fileType = FileTypes.inferFileTypeFromMimeType(format.sampleMimeType);
|
||||||
|
if (fileType == FileTypes.UNKNOWN) {
|
||||||
|
fileType = FileTypes.inferFileTypeFromResponseHeaders(responseHeaders);
|
||||||
}
|
}
|
||||||
@FileTypes.Type int fileFormat = getFormatFromExtension(uri);
|
if (fileType == FileTypes.UNKNOWN) {
|
||||||
switch (fileFormat) {
|
fileType = inferFileTypeFromUri(uri);
|
||||||
|
}
|
||||||
|
switch (fileType) {
|
||||||
case FileTypes.WEBVTT:
|
case FileTypes.WEBVTT:
|
||||||
return new WebvttExtractor(format.language, timestampAdjuster);
|
return new WebvttExtractor(format.language, timestampAdjuster);
|
||||||
case FileTypes.ADTS:
|
case FileTypes.ADTS:
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue