Skip to content

Commit

Permalink
Parse CHARACTERISTICS attribute for EXT-X-MEDIA tags
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 239844963
  • Loading branch information
ojw28 committed Mar 22, 2019
1 parent cdd433a commit 77d597d
Show file tree
Hide file tree
Showing 9 changed files with 65 additions and 39 deletions.
1 change: 1 addition & 0 deletions RELEASENOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
* Form an adaptive track group out of audio renditions with matching name.
* Support encrypted initialization segments
([#5441](https://github.com/google/ExoPlayer/issues/5441)).
* Parse `EXT-X-MEDIA` `CHARACTERISTICS` attribute into `Format.roleFlags`.
* `ExtractorMediaSource` renamed to `ProgressiveMediaSource`.
* Support for playing spherical videos on Daydream.
* Improve decoder re-use between playbacks. TODO: Write and link a blog post
Expand Down
30 changes: 20 additions & 10 deletions library/core/src/main/java/com/google/android/exoplayer2/C.java
Original file line number Diff line number Diff line change
Expand Up @@ -980,11 +980,12 @@ private C() {}
public static final int NETWORK_TYPE_OTHER = 8;

/**
* Track role flags. Possible values are {@link #ROLE_FLAG_MAIN}, {@link #ROLE_FLAG_ALTERNATE},
* {@link #ROLE_FLAG_SUPPLEMENTARY}, {@link #ROLE_FLAG_COMMENTARY}, {@link #ROLE_FLAG_DUB}, {@link
* #ROLE_FLAG_EMERGENCY}, {@link #ROLE_FLAG_CAPTION}, {@link #ROLE_FLAG_SUBTITLE}, {@link
* #ROLE_FLAG_SIGN}, {@link #ROLE_FLAG_ENHANCED_AUDIO_INTELLIGIBILITY}, {@link
* #ROLE_FLAG_DESCRIPTION}.
* Track role flags. Possible flag values are {@link #ROLE_FLAG_MAIN}, {@link
* #ROLE_FLAG_ALTERNATE}, {@link #ROLE_FLAG_SUPPLEMENTARY}, {@link #ROLE_FLAG_COMMENTARY}, {@link
* #ROLE_FLAG_DUB}, {@link #ROLE_FLAG_EMERGENCY}, {@link #ROLE_FLAG_CAPTION}, {@link
* #ROLE_FLAG_SUBTITLE}, {@link #ROLE_FLAG_SIGN}, {@link #ROLE_FLAG_DESCRIBES_VIDEO}, {@link
* #ROLE_FLAG_DESCRIBES_MUSIC_AND_SOUND}, {@link #ROLE_FLAG_ENHANCED_DIALOG_INTELLIGIBILITY},
* {@link #ROLE_FLAG_TRANSCRIBES_DIALOG} and {@link #ROLE_FLAG_EASY_TO_READ}.
*/
@Documented
@Retention(RetentionPolicy.SOURCE)
Expand All @@ -1000,8 +1001,11 @@ private C() {}
ROLE_FLAG_CAPTION,
ROLE_FLAG_SUBTITLE,
ROLE_FLAG_SIGN,
ROLE_FLAG_ENHANCED_AUDIO_INTELLIGIBILITY,
ROLE_FLAG_DESCRIPTION
ROLE_FLAG_DESCRIBES_VIDEO,
ROLE_FLAG_DESCRIBES_MUSIC_AND_SOUND,
ROLE_FLAG_ENHANCED_DIALOG_INTELLIGIBILITY,
ROLE_FLAG_TRANSCRIBES_DIALOG,
ROLE_FLAG_EASY_TO_READ
})
public @interface RoleFlags {}
/** Indicates a main track. */
Expand Down Expand Up @@ -1037,10 +1041,16 @@ private C() {}
public static final int ROLE_FLAG_SUBTITLE = 1 << 7;
/** Indicates the track contains a visual sign-language interpretation of an audio track. */
public static final int ROLE_FLAG_SIGN = 1 << 8;
/** Indicates the track is designed for improved intelligibility of dialogue. */
public static final int ROLE_FLAG_ENHANCED_AUDIO_INTELLIGIBILITY = 1 << 9;
/** Indicates the track contains an audio or textual description of a video track. */
public static final int ROLE_FLAG_DESCRIPTION = 1 << 10;
public static final int ROLE_FLAG_DESCRIBES_VIDEO = 1 << 9;
/** Indicates the track contains a textual description of music and sound. */
public static final int ROLE_FLAG_DESCRIBES_MUSIC_AND_SOUND = 1 << 10;
/** Indicates the track is designed for improved intelligibility of dialogue. */
public static final int ROLE_FLAG_ENHANCED_DIALOG_INTELLIGIBILITY = 1 << 11;
/** Indicates the track contains a transcription of spoken dialog. */
public static final int ROLE_FLAG_TRANSCRIBES_DIALOG = 1 << 12;
/** Indicates the track contains a text that has been edited for ease of reading. */
public static final int ROLE_FLAG_EASY_TO_READ = 1 << 13;

/**
* Converts a time in microseconds to the corresponding time in milliseconds, preserving
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -523,26 +523,6 @@ public static Format createAudioSampleFormat(

// Text.

@Deprecated
public static Format createTextContainerFormat(
@Nullable String id,
@Nullable String containerMimeType,
@Nullable String sampleMimeType,
@Nullable String codecs,
int bitrate,
@C.SelectionFlags int selectionFlags,
@Nullable String language) {
return createTextContainerFormat(
id,
/* label= */ null,
containerMimeType,
sampleMimeType,
codecs,
bitrate,
selectionFlags,
language);
}

public static Format createTextContainerFormat(
@Nullable String id,
@Nullable String label,
Expand All @@ -551,6 +531,7 @@ public static Format createTextContainerFormat(
@Nullable String codecs,
int bitrate,
@C.SelectionFlags int selectionFlags,
@C.RoleFlags int roleFlags,
@Nullable String language) {
return createTextContainerFormat(
id,
Expand All @@ -560,7 +541,7 @@ public static Format createTextContainerFormat(
codecs,
bitrate,
selectionFlags,
/* roleFlags= */ 0,
roleFlags,
language,
/* accessibilityChannel= */ NO_VALUE);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1603,6 +1603,7 @@ private static Format buildTextFormat(String id, String language, int selectionF
/* codecs= */ null,
/* bitrate= */ Format.NO_VALUE,
selectionFlags,
/* roleFlags= */ 0,
language);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1128,9 +1128,9 @@ protected int parseDashRoleSchemeValue(String value) {
case "sign":
return C.ROLE_FLAG_SIGN;
case "description":
return C.ROLE_FLAG_DESCRIPTION;
return C.ROLE_FLAG_DESCRIBES_VIDEO;
case "enhanced-audio-intelligibility":
return C.ROLE_FLAG_ENHANCED_AUDIO_INTELLIGIBILITY;
return C.ROLE_FLAG_ENHANCED_DIALOG_INTELLIGIBILITY;
default:
return 0;
}
Expand All @@ -1143,9 +1143,9 @@ protected int parseTvaAudioPurposeCsValue(String value) {
}
switch (value) {
case "1": // Audio description for the visually impaired.
return C.ROLE_FLAG_DESCRIPTION;
return C.ROLE_FLAG_DESCRIBES_VIDEO;
case "2": // Audio description for the hard of hearing.
return C.ROLE_FLAG_ENHANCED_AUDIO_INTELLIGIBILITY;
return C.ROLE_FLAG_ENHANCED_DIALOG_INTELLIGIBILITY;
case "3": // Supplemental commentary.
return C.ROLE_FLAG_SUPPLEMENTARY;
case "4": // Director's commentary.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -703,27 +703,30 @@ private static Format deriveVideoFormat(Format variantFormat) {
variantFormat.frameRate,
/* initializationData= */ null,
variantFormat.selectionFlags,
/* roleFlags= */ 0);
variantFormat.roleFlags);
}

private static Format deriveAudioFormat(
Format variantFormat, Format mediaTagFormat, boolean isPrimaryTrackInVariant) {
String codecs;
int channelCount = Format.NO_VALUE;
int selectionFlags = 0;
int roleFlags = 0;
String language = null;
String label = null;
if (mediaTagFormat != null) {
codecs = mediaTagFormat.codecs;
channelCount = mediaTagFormat.channelCount;
selectionFlags = mediaTagFormat.selectionFlags;
roleFlags = mediaTagFormat.roleFlags;
language = mediaTagFormat.language;
label = mediaTagFormat.label;
} else {
codecs = Util.getCodecsOfType(variantFormat.codecs, C.TRACK_TYPE_AUDIO);
if (isPrimaryTrackInVariant) {
channelCount = variantFormat.channelCount;
selectionFlags = variantFormat.selectionFlags;
roleFlags = mediaTagFormat.roleFlags;
language = variantFormat.language;
label = variantFormat.label;
}
Expand All @@ -741,7 +744,7 @@ private static Format deriveAudioFormat(
/* sampleRate= */ Format.NO_VALUE,
/* initializationData= */ null,
selectionFlags,
/* roleFlags= */ 0,
roleFlags,
language);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import android.net.Uri;
import androidx.annotation.Nullable;
import android.text.TextUtils;
import android.util.Base64;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
Expand Down Expand Up @@ -145,6 +146,7 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
private static final Pattern REGEX_LANGUAGE = Pattern.compile("LANGUAGE=\"(.+?)\"");
private static final Pattern REGEX_NAME = Pattern.compile("NAME=\"(.+?)\"");
private static final Pattern REGEX_GROUP_ID = Pattern.compile("GROUP-ID=\"(.+?)\"");
private static final Pattern REGEX_CHARACTERISTICS = Pattern.compile("CHARACTERISTICS=\"(.+?)\"");
private static final Pattern REGEX_INSTREAM_ID =
Pattern.compile("INSTREAM-ID=\"((?:CC|SERVICE)\\d+)\"");
private static final Pattern REGEX_AUTOSELECT = compileBooleanAttrPattern("AUTOSELECT");
Expand Down Expand Up @@ -339,6 +341,7 @@ private static HlsMasterPlaylist parseMasterPlaylist(LineIterator iterator, Stri
for (int i = 0; i < mediaTags.size(); i++) {
line = mediaTags.get(i);
@C.SelectionFlags int selectionFlags = parseSelectionFlags(line);
@C.RoleFlags int roleFlags = parseRoleFlags(line, variableDefinitions);
String uri = parseOptionalStringAttr(line, REGEX_URI, variableDefinitions);
String name = parseStringAttr(line, REGEX_NAME, variableDefinitions);
String language = parseOptionalStringAttr(line, REGEX_LANGUAGE, variableDefinitions);
Expand All @@ -362,7 +365,7 @@ private static HlsMasterPlaylist parseMasterPlaylist(LineIterator iterator, Stri
/* sampleRate= */ Format.NO_VALUE,
/* initializationData= */ null,
selectionFlags,
/* roleFlags= */ 0,
roleFlags,
language);
if (isMediaTagMuxed(variants, uri)) {
muxedAudioFormat = format;
Expand All @@ -380,6 +383,7 @@ private static HlsMasterPlaylist parseMasterPlaylist(LineIterator iterator, Stri
/* codecs= */ null,
/* bitrate= */ Format.NO_VALUE,
selectionFlags,
roleFlags,
language);
subtitles.add(new HlsMasterPlaylist.HlsUrl(uri, format, name));
break;
Expand All @@ -406,7 +410,7 @@ private static HlsMasterPlaylist parseMasterPlaylist(LineIterator iterator, Stri
/* codecs= */ null,
/* bitrate= */ Format.NO_VALUE,
selectionFlags,
/* roleFlags= */ 0,
roleFlags,
language,
accessibilityChannel));
break;
Expand Down Expand Up @@ -678,6 +682,30 @@ private static int parseSelectionFlags(String line) {
return flags;
}

@C.RoleFlags
private static int parseRoleFlags(String line, Map<String, String> variableDefinitions) {
String concatenatedCharacteristics =
parseOptionalStringAttr(line, REGEX_CHARACTERISTICS, variableDefinitions);
if (TextUtils.isEmpty(concatenatedCharacteristics)) {
return 0;
}
String[] characteristics = Util.split(concatenatedCharacteristics, ",");
@C.RoleFlags int roleFlags = 0;
if (Util.contains(characteristics, "public.accessibility.describes-video")) {
roleFlags |= C.ROLE_FLAG_DESCRIBES_VIDEO;
}
if (Util.contains(characteristics, "public.accessibility.transcribes-spoken-dialog")) {
roleFlags |= C.ROLE_FLAG_TRANSCRIBES_DIALOG;
}
if (Util.contains(characteristics, "public.accessibility.describes-music-and-sound")) {
roleFlags |= C.ROLE_FLAG_DESCRIBES_MUSIC_AND_SOUND;
}
if (Util.contains(characteristics, "public.easy-to-read")) {
roleFlags |= C.ROLE_FLAG_EASY_TO_READ;
}
return roleFlags;
}

private static int parseChannelsAttribute(String line, Map<String, String> variableDefinitions) {
String channelsString = parseOptionalStringAttr(line, REGEX_CHANNELS, variableDefinitions);
return channelsString != null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ private static Format createSubtitleFormat(String language) {
/* codecs= */ null,
/* bitrate= */ Format.NO_VALUE,
/* selectionFlags= */ 0,
/* roleFlags= */ 0,
language);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,7 @@ public void parseStartTag(XmlPullParser parser) throws ParserException {
/* codecs= */ null,
bitrate,
/* selectionFlags= */ 0,
/* roleFlags= */ 0,
language);
} else {
format =
Expand Down

0 comments on commit 77d597d

Please sign in to comment.