mirror of
https://github.com/samsonjs/media.git
synced 2026-04-01 10:35:48 +00:00
Clean up manifest MIME type and codec parsing
PiperOrigin-RevId: 305258836
This commit is contained in:
parent
f9679a2cfb
commit
74a9d8f680
4 changed files with 87 additions and 70 deletions
|
|
@ -133,14 +133,23 @@ public final class MimeTypes {
|
|||
return BASE_TYPE_VIDEO.equals(getTopLevelType(mimeType));
|
||||
}
|
||||
|
||||
/** Returns whether the given string is a text MIME type. */
|
||||
/**
|
||||
* Returns whether the given string is a text MIME type, including known text types that use
|
||||
* "application" as their base type.
|
||||
*/
|
||||
public static boolean isText(@Nullable String mimeType) {
|
||||
return BASE_TYPE_TEXT.equals(getTopLevelType(mimeType));
|
||||
}
|
||||
|
||||
/** Returns whether the given string is an application MIME type. */
|
||||
public static boolean isApplication(@Nullable String mimeType) {
|
||||
return BASE_TYPE_APPLICATION.equals(getTopLevelType(mimeType));
|
||||
return BASE_TYPE_TEXT.equals(getTopLevelType(mimeType))
|
||||
|| APPLICATION_CEA608.equals(mimeType)
|
||||
|| APPLICATION_CEA708.equals(mimeType)
|
||||
|| APPLICATION_MP4CEA608.equals(mimeType)
|
||||
|| APPLICATION_SUBRIP.equals(mimeType)
|
||||
|| APPLICATION_TTML.equals(mimeType)
|
||||
|| APPLICATION_TX3G.equals(mimeType)
|
||||
|| APPLICATION_MP4VTT.equals(mimeType)
|
||||
|| APPLICATION_RAWCC.equals(mimeType)
|
||||
|| APPLICATION_VOBSUB.equals(mimeType)
|
||||
|| APPLICATION_PGS.equals(mimeType)
|
||||
|| APPLICATION_DVBSUBS.equals(mimeType);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -210,6 +219,27 @@ public final class MimeTypes {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Derives a text sample mimeType from a codecs attribute.
|
||||
*
|
||||
* @param codecs The codecs attribute.
|
||||
* @return The derived text mimeType, or null if it could not be derived.
|
||||
*/
|
||||
@Nullable
|
||||
public static String getTextMediaMimeType(@Nullable String codecs) {
|
||||
if (codecs == null) {
|
||||
return null;
|
||||
}
|
||||
String[] codecList = Util.splitCodecs(codecs);
|
||||
for (String codec : codecList) {
|
||||
@Nullable String mimeType = getMediaMimeType(codec);
|
||||
if (mimeType != null && isText(mimeType)) {
|
||||
return mimeType;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Derives a mimeType from a codec identifier, as defined in RFC 6381.
|
||||
*
|
||||
|
|
@ -274,6 +304,10 @@ public final class MimeTypes {
|
|||
return MimeTypes.APPLICATION_TTML;
|
||||
} else if (codec.startsWith("wvtt")) {
|
||||
return MimeTypes.TEXT_VTT;
|
||||
} else if (codec.contains("cea708")) {
|
||||
return MimeTypes.APPLICATION_CEA708;
|
||||
} else if (codec.contains("eia608") || codec.contains("cea608")) {
|
||||
return MimeTypes.APPLICATION_CEA608;
|
||||
} else {
|
||||
return getCustomMimeTypeForCodec(codec);
|
||||
}
|
||||
|
|
@ -350,12 +384,7 @@ public final class MimeTypes {
|
|||
return C.TRACK_TYPE_AUDIO;
|
||||
} else if (isVideo(mimeType)) {
|
||||
return C.TRACK_TYPE_VIDEO;
|
||||
} else if (isText(mimeType) || APPLICATION_CEA608.equals(mimeType)
|
||||
|| APPLICATION_CEA708.equals(mimeType) || APPLICATION_MP4CEA608.equals(mimeType)
|
||||
|| APPLICATION_SUBRIP.equals(mimeType) || APPLICATION_TTML.equals(mimeType)
|
||||
|| APPLICATION_TX3G.equals(mimeType) || APPLICATION_MP4VTT.equals(mimeType)
|
||||
|| APPLICATION_RAWCC.equals(mimeType) || APPLICATION_VOBSUB.equals(mimeType)
|
||||
|| APPLICATION_PGS.equals(mimeType) || APPLICATION_DVBSUBS.equals(mimeType)) {
|
||||
} else if (isText(mimeType)) {
|
||||
return C.TRACK_TYPE_TEXT;
|
||||
} else if (APPLICATION_ID3.equals(mimeType)
|
||||
|| APPLICATION_EMSG.equals(mimeType)
|
||||
|
|
|
|||
|
|
@ -25,6 +25,29 @@ import org.junit.runner.RunWith;
|
|||
@RunWith(AndroidJUnit4.class)
|
||||
public final class MimeTypesTest {
|
||||
|
||||
@Test
|
||||
public void isText_returnsCorrectResult() {
|
||||
assertThat(MimeTypes.isText(MimeTypes.TEXT_VTT)).isTrue();
|
||||
assertThat(MimeTypes.isText(MimeTypes.TEXT_SSA)).isTrue();
|
||||
assertThat(MimeTypes.isText(MimeTypes.APPLICATION_CEA608)).isTrue();
|
||||
assertThat(MimeTypes.isText(MimeTypes.APPLICATION_CEA708)).isTrue();
|
||||
assertThat(MimeTypes.isText(MimeTypes.APPLICATION_MP4CEA608)).isTrue();
|
||||
assertThat(MimeTypes.isText(MimeTypes.APPLICATION_SUBRIP)).isTrue();
|
||||
assertThat(MimeTypes.isText(MimeTypes.APPLICATION_TTML)).isTrue();
|
||||
assertThat(MimeTypes.isText(MimeTypes.APPLICATION_TX3G)).isTrue();
|
||||
assertThat(MimeTypes.isText(MimeTypes.APPLICATION_MP4VTT)).isTrue();
|
||||
assertThat(MimeTypes.isText(MimeTypes.APPLICATION_VOBSUB)).isTrue();
|
||||
assertThat(MimeTypes.isText(MimeTypes.APPLICATION_PGS)).isTrue();
|
||||
assertThat(MimeTypes.isText(MimeTypes.APPLICATION_DVBSUBS)).isTrue();
|
||||
assertThat(MimeTypes.isText("text/custom")).isTrue();
|
||||
|
||||
assertThat(MimeTypes.isText(MimeTypes.VIDEO_MP4)).isFalse();
|
||||
assertThat(MimeTypes.isText(MimeTypes.VIDEO_H264)).isFalse();
|
||||
assertThat(MimeTypes.isText(MimeTypes.AUDIO_MP4)).isFalse();
|
||||
assertThat(MimeTypes.isText(MimeTypes.AUDIO_AAC)).isFalse();
|
||||
assertThat(MimeTypes.isText("application/custom")).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getMediaMimeType_fromValidCodecs_returnsCorrectMimeType() {
|
||||
assertThat(MimeTypes.getMediaMimeType("avc1")).isEqualTo(MimeTypes.VIDEO_H264);
|
||||
|
|
@ -77,6 +100,9 @@ public final class MimeTypesTest {
|
|||
assertThat(MimeTypes.getMediaMimeType("wvtt")).isEqualTo(MimeTypes.TEXT_VTT);
|
||||
assertThat(MimeTypes.getMediaMimeType("stpp.")).isEqualTo(MimeTypes.APPLICATION_TTML);
|
||||
assertThat(MimeTypes.getMediaMimeType("stpp.ttml.im1t")).isEqualTo(MimeTypes.APPLICATION_TTML);
|
||||
assertThat(MimeTypes.getMediaMimeType("eia608.")).isEqualTo(MimeTypes.APPLICATION_CEA608);
|
||||
assertThat(MimeTypes.getMediaMimeType("cea608")).isEqualTo(MimeTypes.APPLICATION_CEA608);
|
||||
assertThat(MimeTypes.getMediaMimeType("cea708")).isEqualTo(MimeTypes.APPLICATION_CEA708);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -772,10 +772,6 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
|||
|| mimeType.startsWith(MimeTypes.APPLICATION_WEBM);
|
||||
}
|
||||
|
||||
private static boolean mimeTypeIsRawText(String mimeType) {
|
||||
return MimeTypes.isText(mimeType) || MimeTypes.APPLICATION_TTML.equals(mimeType);
|
||||
}
|
||||
|
||||
private static @Nullable ChunkExtractorWrapper createExtractorWrapper(
|
||||
int trackType,
|
||||
Representation representation,
|
||||
|
|
@ -783,12 +779,15 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
|||
List<Format> closedCaptionFormats,
|
||||
@Nullable TrackOutput playerEmsgTrackOutput) {
|
||||
String containerMimeType = representation.format.containerMimeType;
|
||||
if (mimeTypeIsRawText(containerMimeType)) {
|
||||
return null;
|
||||
}
|
||||
Extractor extractor;
|
||||
if (MimeTypes.APPLICATION_RAWCC.equals(containerMimeType)) {
|
||||
extractor = new RawCcExtractor(representation.format);
|
||||
if (MimeTypes.isText(containerMimeType)) {
|
||||
if (MimeTypes.APPLICATION_RAWCC.equals(containerMimeType)) {
|
||||
// RawCC is special because it's a text specific container format.
|
||||
extractor = new RawCcExtractor(representation.format);
|
||||
} else {
|
||||
// All other text types are raw formats that do not need an extractor.
|
||||
return null;
|
||||
}
|
||||
} else if (mimeTypeIsWebm(containerMimeType)) {
|
||||
extractor = new MatroskaExtractor(MatroskaExtractor.FLAG_DISABLE_SEEK_FOR_CUES);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -337,8 +337,9 @@ public class DashManifestParser extends DefaultHandler
|
|||
supplementalProperties,
|
||||
segmentBase,
|
||||
periodDurationMs);
|
||||
contentType = checkContentTypeConsistency(contentType,
|
||||
getContentType(representationInfo.format));
|
||||
contentType =
|
||||
checkContentTypeConsistency(
|
||||
contentType, MimeTypes.getTrackType(representationInfo.format.sampleMimeType));
|
||||
representationInfos.add(representationInfo);
|
||||
} else if (XmlPullParserUtil.isStartTag(xpp, "SegmentBase")) {
|
||||
segmentBase = parseSegmentBase(xpp, (SingleSegmentBase) segmentBase);
|
||||
|
|
@ -389,20 +390,6 @@ public class DashManifestParser extends DefaultHandler
|
|||
: C.TRACK_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
protected int getContentType(Format format) {
|
||||
String sampleMimeType = format.sampleMimeType;
|
||||
if (TextUtils.isEmpty(sampleMimeType)) {
|
||||
return C.TRACK_TYPE_UNKNOWN;
|
||||
} else if (MimeTypes.isVideo(sampleMimeType)) {
|
||||
return C.TRACK_TYPE_VIDEO;
|
||||
} else if (MimeTypes.isAudio(sampleMimeType)) {
|
||||
return C.TRACK_TYPE_AUDIO;
|
||||
} else if (mimeTypeIsRawText(sampleMimeType)) {
|
||||
return C.TRACK_TYPE_TEXT;
|
||||
}
|
||||
return C.TRACK_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a ContentProtection element.
|
||||
*
|
||||
|
|
@ -620,7 +607,7 @@ public class DashManifestParser extends DefaultHandler
|
|||
formatBuilder.setWidth(width).setHeight(height).setFrameRate(frameRate);
|
||||
} else if (MimeTypes.isAudio(sampleMimeType)) {
|
||||
formatBuilder.setChannelCount(audioChannels).setSampleRate(audioSamplingRate);
|
||||
} else if (mimeTypeIsRawText(sampleMimeType)) {
|
||||
} else if (MimeTypes.isText(sampleMimeType)) {
|
||||
int accessibilityChannel = Format.NO_VALUE;
|
||||
if (MimeTypes.APPLICATION_CEA608.equals(sampleMimeType)) {
|
||||
accessibilityChannel = parseCea608AccessibilityChannel(accessibilityDescriptors);
|
||||
|
|
@ -1310,43 +1297,19 @@ public class DashManifestParser extends DefaultHandler
|
|||
return MimeTypes.getAudioMediaMimeType(codecs);
|
||||
} else if (MimeTypes.isVideo(containerMimeType)) {
|
||||
return MimeTypes.getVideoMediaMimeType(codecs);
|
||||
} else if (mimeTypeIsRawText(containerMimeType)) {
|
||||
} else if (MimeTypes.isText(containerMimeType)) {
|
||||
if (MimeTypes.APPLICATION_RAWCC.equals(containerMimeType)) {
|
||||
// RawCC is special because it's a text specific container format.
|
||||
return MimeTypes.getTextMediaMimeType(codecs);
|
||||
}
|
||||
// All other text types are raw formats.
|
||||
return containerMimeType;
|
||||
} else if (MimeTypes.APPLICATION_MP4.equals(containerMimeType)) {
|
||||
if (codecs != null) {
|
||||
if (codecs.startsWith("stpp")) {
|
||||
return MimeTypes.APPLICATION_TTML;
|
||||
} else if (codecs.startsWith("wvtt")) {
|
||||
return MimeTypes.APPLICATION_MP4VTT;
|
||||
}
|
||||
}
|
||||
} else if (MimeTypes.APPLICATION_RAWCC.equals(containerMimeType)) {
|
||||
if (codecs != null) {
|
||||
if (codecs.contains("cea708")) {
|
||||
return MimeTypes.APPLICATION_CEA708;
|
||||
} else if (codecs.contains("eia608") || codecs.contains("cea608")) {
|
||||
return MimeTypes.APPLICATION_CEA608;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return MimeTypes.getMediaMimeType(codecs);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether a mimeType is a text sample mimeType.
|
||||
*
|
||||
* @param mimeType The mimeType.
|
||||
* @return Whether the mimeType is a text sample mimeType.
|
||||
*/
|
||||
private static boolean mimeTypeIsRawText(@Nullable String mimeType) {
|
||||
return MimeTypes.isText(mimeType)
|
||||
|| MimeTypes.APPLICATION_TTML.equals(mimeType)
|
||||
|| MimeTypes.APPLICATION_MP4VTT.equals(mimeType)
|
||||
|| MimeTypes.APPLICATION_CEA708.equals(mimeType)
|
||||
|| MimeTypes.APPLICATION_CEA608.equals(mimeType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks two languages for consistency, returning the consistent language, or throwing an {@link
|
||||
* IllegalStateException} if the languages are inconsistent.
|
||||
|
|
|
|||
Loading…
Reference in a new issue