Add support for HLS track selection flags

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=125658752
This commit is contained in:
aquilescanta 2016-06-23 02:52:41 -07:00 committed by Oliver Woodman
parent 3e6c0ced82
commit 762ec41f95
4 changed files with 44 additions and 8 deletions

View File

@ -60,6 +60,11 @@ public final class Format implements Parcelable {
* Indicates that the track must be displayed. Only applies to text tracks. * Indicates that the track must be displayed. Only applies to text tracks.
*/ */
public static final int SELECTION_FLAG_FORCED = 2; public static final int SELECTION_FLAG_FORCED = 2;
/**
* Indicates that the player may choose to play the track in absence of an explicit user
* preference.
*/
public static final int SELECTION_FLAG_AUTOSELECT = 4;
/** /**
* A value for {@link #subsampleOffsetUs} to indicate that subsample timestamps are relative to * A value for {@link #subsampleOffsetUs} to indicate that subsample timestamps are relative to
@ -391,6 +396,7 @@ public final class Format implements Parcelable {
String codecs = this.codecs == null ? manifestFormat.codecs : this.codecs; String codecs = this.codecs == null ? manifestFormat.codecs : this.codecs;
int bitrate = this.bitrate == NO_VALUE ? manifestFormat.bitrate : this.bitrate; int bitrate = this.bitrate == NO_VALUE ? manifestFormat.bitrate : this.bitrate;
float frameRate = this.frameRate == NO_VALUE ? manifestFormat.frameRate : this.frameRate; float frameRate = this.frameRate == NO_VALUE ? manifestFormat.frameRate : this.frameRate;
int selectionFlags = this.selectionFlags | manifestFormat.selectionFlags;
String language = this.language == null ? manifestFormat.language : this.language; String language = this.language == null ? manifestFormat.language : this.language;
DrmInitData drmInitData = (preferManifestDrmInitData && manifestFormat.drmInitData != null) DrmInitData drmInitData = (preferManifestDrmInitData && manifestFormat.drmInitData != null)
|| this.drmInitData == null ? manifestFormat.drmInitData : this.drmInitData; || this.drmInitData == null ? manifestFormat.drmInitData : this.drmInitData;

View File

@ -510,7 +510,8 @@ import java.util.List;
return sampleFormat; return sampleFormat;
} }
return sampleFormat.copyWithContainerInfo(containerFormat.id, containerFormat.bitrate, return sampleFormat.copyWithContainerInfo(containerFormat.id, containerFormat.bitrate,
containerFormat.width, containerFormat.height, 0, containerFormat.language); containerFormat.width, containerFormat.height, containerFormat.selectionFlags,
containerFormat.language);
} }
private void maybeStartLoading() { private void maybeStartLoading() {

View File

@ -25,6 +25,9 @@ import java.util.regex.Pattern;
*/ */
/* package */ final class HlsParserUtil { /* package */ final class HlsParserUtil {
private static final String BOOLEAN_TRUE_VALUE = "YES";
private static final String BOOLEAN_FALSE_VALUE = "NO";
private HlsParserUtil() {} private HlsParserUtil() {}
public static String parseStringAttr(String line, Pattern pattern, String tag) public static String parseStringAttr(String line, Pattern pattern, String tag)
@ -54,4 +57,17 @@ import java.util.regex.Pattern;
return null; return null;
} }
public static boolean parseBooleanAttribute(String line, Pattern pattern, boolean defaultValue) {
Matcher matcher = pattern.matcher(line);
if (matcher.find()) {
return matcher.group(1).equals(BOOLEAN_TRUE_VALUE);
}
return defaultValue;
}
public static Pattern compileBooleanAttrPattern(String attribute) {
return Pattern.compile(attribute + "=(" + BOOLEAN_FALSE_VALUE + "|" + BOOLEAN_TRUE_VALUE + ")");
}
} }

View File

@ -62,6 +62,9 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
private static final String URI_ATTR = "URI"; private static final String URI_ATTR = "URI";
private static final String IV_ATTR = "IV"; private static final String IV_ATTR = "IV";
private static final String INSTREAM_ID_ATTR = "INSTREAM-ID"; private static final String INSTREAM_ID_ATTR = "INSTREAM-ID";
private static final String AUTOSELECT_ATTR = "AUTOSELECT";
private static final String DEFAULT_ATTR = "DEFAULT";
private static final String FORCED_ATTR = "FORCED";
private static final String AUDIO_TYPE = "AUDIO"; private static final String AUDIO_TYPE = "AUDIO";
private static final String VIDEO_TYPE = "VIDEO"; private static final String VIDEO_TYPE = "VIDEO";
@ -103,10 +106,12 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
Pattern.compile(NAME_ATTR + "=\"(.+?)\""); Pattern.compile(NAME_ATTR + "=\"(.+?)\"");
private static final Pattern INSTREAM_ID_ATTR_REGEX = private static final Pattern INSTREAM_ID_ATTR_REGEX =
Pattern.compile(INSTREAM_ID_ATTR + "=\"(.+?)\""); Pattern.compile(INSTREAM_ID_ATTR + "=\"(.+?)\"");
// private static final Pattern AUTOSELECT_ATTR_REGEX = private static final Pattern AUTOSELECT_ATTR_REGEX =
// HlsParserUtil.compileBooleanAttrPattern(AUTOSELECT_ATTR); HlsParserUtil.compileBooleanAttrPattern(AUTOSELECT_ATTR);
// private static final Pattern DEFAULT_ATTR_REGEX = private static final Pattern DEFAULT_ATTR_REGEX =
// HlsParserUtil.compileBooleanAttrPattern(DEFAULT_ATTR); HlsParserUtil.compileBooleanAttrPattern(DEFAULT_ATTR);
private static final Pattern FORCED_ATTR_REGEX =
HlsParserUtil.compileBooleanAttrPattern(FORCED_ATTR);
@Override @Override
public HlsPlaylist parse(Uri uri, InputStream inputStream) throws IOException { public HlsPlaylist parse(Uri uri, InputStream inputStream) throws IOException {
@ -159,6 +164,13 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
while (iterator.hasNext()) { while (iterator.hasNext()) {
line = iterator.next(); line = iterator.next();
if (line.startsWith(MEDIA_TAG)) { if (line.startsWith(MEDIA_TAG)) {
boolean isDefault = HlsParserUtil.parseBooleanAttribute(line, DEFAULT_ATTR_REGEX, false);
boolean isForced = HlsParserUtil.parseBooleanAttribute(line, FORCED_ATTR_REGEX, false);
boolean isAutoselect = HlsParserUtil.parseBooleanAttribute(line, AUTOSELECT_ATTR_REGEX,
false);
int selectionFlags = (isDefault ? Format.SELECTION_FLAG_DEFAULT : 0)
| (isForced ? Format.SELECTION_FLAG_FORCED : 0)
| (isAutoselect ? Format.SELECTION_FLAG_AUTOSELECT : 0);
String type = HlsParserUtil.parseStringAttr(line, TYPE_ATTR_REGEX, TYPE_ATTR); String type = HlsParserUtil.parseStringAttr(line, TYPE_ATTR_REGEX, TYPE_ATTR);
if (CLOSED_CAPTIONS_TYPE.equals(type)) { if (CLOSED_CAPTIONS_TYPE.equals(type)) {
String instreamId = HlsParserUtil.parseStringAttr(line, INSTREAM_ID_ATTR_REGEX, String instreamId = HlsParserUtil.parseStringAttr(line, INSTREAM_ID_ATTR_REGEX,
@ -168,7 +180,8 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
String captionName = HlsParserUtil.parseStringAttr(line, NAME_ATTR_REGEX, NAME_ATTR); String captionName = HlsParserUtil.parseStringAttr(line, NAME_ATTR_REGEX, NAME_ATTR);
String language = HlsParserUtil.parseOptionalStringAttr(line, LANGUAGE_ATTR_REGEX); String language = HlsParserUtil.parseOptionalStringAttr(line, LANGUAGE_ATTR_REGEX);
muxedCaptionFormat = Format.createTextContainerFormat(captionName, muxedCaptionFormat = Format.createTextContainerFormat(captionName,
MimeTypes.APPLICATION_M3U8, MimeTypes.APPLICATION_EIA608, null, -1, 0, language); MimeTypes.APPLICATION_M3U8, MimeTypes.APPLICATION_EIA608, null, -1, selectionFlags,
language);
} }
} else if (SUBTITLES_TYPE.equals(type)) { } else if (SUBTITLES_TYPE.equals(type)) {
// We assume all subtitles belong to the same group. // We assume all subtitles belong to the same group.
@ -176,7 +189,7 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
String uri = HlsParserUtil.parseStringAttr(line, URI_ATTR_REGEX, URI_ATTR); String uri = HlsParserUtil.parseStringAttr(line, URI_ATTR_REGEX, URI_ATTR);
String language = HlsParserUtil.parseOptionalStringAttr(line, LANGUAGE_ATTR_REGEX); String language = HlsParserUtil.parseOptionalStringAttr(line, LANGUAGE_ATTR_REGEX);
Format format = Format.createTextContainerFormat(subtitleName, MimeTypes.APPLICATION_M3U8, Format format = Format.createTextContainerFormat(subtitleName, MimeTypes.APPLICATION_M3U8,
MimeTypes.TEXT_VTT, null, bitrate, 0, language); MimeTypes.TEXT_VTT, null, bitrate, selectionFlags, language);
subtitles.add(new Variant(uri, format, codecs)); subtitles.add(new Variant(uri, format, codecs));
} else if (AUDIO_TYPE.equals(type)) { } else if (AUDIO_TYPE.equals(type)) {
// We assume all audios belong to the same group. // We assume all audios belong to the same group.
@ -185,7 +198,7 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
String audioName = HlsParserUtil.parseStringAttr(line, NAME_ATTR_REGEX, NAME_ATTR); String audioName = HlsParserUtil.parseStringAttr(line, NAME_ATTR_REGEX, NAME_ATTR);
int audioBitrate = uri != null ? bitrate : -1; int audioBitrate = uri != null ? bitrate : -1;
Format format = Format.createAudioContainerFormat(audioName, MimeTypes.APPLICATION_M3U8, Format format = Format.createAudioContainerFormat(audioName, MimeTypes.APPLICATION_M3U8,
null, null, audioBitrate, -1, -1, null, 0, language); null, null, audioBitrate, -1, -1, null, selectionFlags, language);
if (uri != null) { if (uri != null) {
audios.add(new Variant(uri, format, codecs)); audios.add(new Variant(uri, format, codecs));
} else { } else {