Commit c01c2c34 by olly Committed by Oliver Woodman

Store full accessibility descriptors in parsed DASH manifest

Issue: #2362

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=145402640
parent 4efdd14c
...@@ -213,7 +213,7 @@ public class OfflineLicenseHelperTest extends InstrumentationTestCase { ...@@ -213,7 +213,7 @@ public class OfflineLicenseHelperTest extends InstrumentationTestCase {
} }
private static AdaptationSet newAdaptationSets(Representation... representations) { private static AdaptationSet newAdaptationSets(Representation... representations) {
return new AdaptationSet(0, C.TRACK_TYPE_VIDEO, Arrays.asList(representations)); return new AdaptationSet(0, C.TRACK_TYPE_VIDEO, Arrays.asList(representations), null);
} }
private static Representation newRepresentations(DrmInitData drmInitData) { private static Representation newRepresentations(DrmInitData drmInitData) {
......
...@@ -20,6 +20,8 @@ import android.test.InstrumentationTestCase; ...@@ -20,6 +20,8 @@ import android.test.InstrumentationTestCase;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.testutil.TestUtil; import com.google.android.exoplayer2.testutil.TestUtil;
import java.io.IOException; import java.io.IOException;
import java.util.Collections;
import java.util.List;
/** /**
* Unit tests for {@link DashManifestParser}. * Unit tests for {@link DashManifestParser}.
...@@ -70,34 +72,57 @@ public class DashManifestParserTest extends InstrumentationTestCase { ...@@ -70,34 +72,57 @@ public class DashManifestParserTest extends InstrumentationTestCase {
} }
public void testParseCea608AccessibilityChannel() { public void testParseCea608AccessibilityChannel() {
assertEquals(1, DashManifestParser.parseCea608AccessibilityChannel("CC1=eng")); assertEquals(1, DashManifestParser.parseCea608AccessibilityChannel(
assertEquals(2, DashManifestParser.parseCea608AccessibilityChannel("CC2=eng")); buildCea608AccessibilityDescriptors("CC1=eng")));
assertEquals(3, DashManifestParser.parseCea608AccessibilityChannel("CC3=eng")); assertEquals(2, DashManifestParser.parseCea608AccessibilityChannel(
assertEquals(4, DashManifestParser.parseCea608AccessibilityChannel("CC4=eng")); buildCea608AccessibilityDescriptors("CC2=eng")));
assertEquals(3, DashManifestParser.parseCea608AccessibilityChannel(
buildCea608AccessibilityDescriptors("CC3=eng")));
assertEquals(4, DashManifestParser.parseCea608AccessibilityChannel(
buildCea608AccessibilityDescriptors("CC4=eng")));
assertEquals(Format.NO_VALUE, DashManifestParser.parseCea608AccessibilityChannel(null)); assertEquals(Format.NO_VALUE, DashManifestParser.parseCea608AccessibilityChannel(
assertEquals(Format.NO_VALUE, DashManifestParser.parseCea608AccessibilityChannel("")); buildCea608AccessibilityDescriptors(null)));
assertEquals(Format.NO_VALUE, DashManifestParser.parseCea608AccessibilityChannel("CC0=eng")); assertEquals(Format.NO_VALUE, DashManifestParser.parseCea608AccessibilityChannel(
assertEquals(Format.NO_VALUE, DashManifestParser.parseCea608AccessibilityChannel("CC5=eng")); buildCea608AccessibilityDescriptors("")));
assertEquals(Format.NO_VALUE, assertEquals(Format.NO_VALUE, DashManifestParser.parseCea608AccessibilityChannel(
DashManifestParser.parseCea608AccessibilityChannel("Wrong format")); buildCea608AccessibilityDescriptors("CC0=eng")));
assertEquals(Format.NO_VALUE, DashManifestParser.parseCea608AccessibilityChannel(
buildCea608AccessibilityDescriptors("CC5=eng")));
assertEquals(Format.NO_VALUE, DashManifestParser.parseCea608AccessibilityChannel(
buildCea608AccessibilityDescriptors("Wrong format")));
} }
public void testParseCea708AccessibilityChannel() { public void testParseCea708AccessibilityChannel() {
assertEquals(1, DashManifestParser.parseCea708AccessibilityChannel("1=lang:eng")); assertEquals(1, DashManifestParser.parseCea708AccessibilityChannel(
assertEquals(2, DashManifestParser.parseCea708AccessibilityChannel("2=lang:eng")); buildCea708AccessibilityDescriptors("1=lang:eng")));
assertEquals(3, DashManifestParser.parseCea708AccessibilityChannel("3=lang:eng")); assertEquals(2, DashManifestParser.parseCea708AccessibilityChannel(
assertEquals(62, DashManifestParser.parseCea708AccessibilityChannel("62=lang:eng")); buildCea708AccessibilityDescriptors("2=lang:eng")));
assertEquals(63, DashManifestParser.parseCea708AccessibilityChannel("63=lang:eng")); assertEquals(3, DashManifestParser.parseCea708AccessibilityChannel(
buildCea708AccessibilityDescriptors("3=lang:eng")));
assertEquals(62, DashManifestParser.parseCea708AccessibilityChannel(
buildCea708AccessibilityDescriptors("62=lang:eng")));
assertEquals(63, DashManifestParser.parseCea708AccessibilityChannel(
buildCea708AccessibilityDescriptors("63=lang:eng")));
assertEquals(Format.NO_VALUE, DashManifestParser.parseCea708AccessibilityChannel(null)); assertEquals(Format.NO_VALUE, DashManifestParser.parseCea708AccessibilityChannel(
assertEquals(Format.NO_VALUE, DashManifestParser.parseCea708AccessibilityChannel("")); buildCea708AccessibilityDescriptors(null)));
assertEquals(Format.NO_VALUE, assertEquals(Format.NO_VALUE, DashManifestParser.parseCea708AccessibilityChannel(
DashManifestParser.parseCea708AccessibilityChannel("0=lang:eng")); buildCea708AccessibilityDescriptors("")));
assertEquals(Format.NO_VALUE, assertEquals(Format.NO_VALUE, DashManifestParser.parseCea708AccessibilityChannel(
DashManifestParser.parseCea708AccessibilityChannel("64=lang:eng")); buildCea708AccessibilityDescriptors("0=lang:eng")));
assertEquals(Format.NO_VALUE, assertEquals(Format.NO_VALUE, DashManifestParser.parseCea708AccessibilityChannel(
DashManifestParser.parseCea708AccessibilityChannel("Wrong format")); buildCea708AccessibilityDescriptors("64=lang:eng")));
assertEquals(Format.NO_VALUE, DashManifestParser.parseCea708AccessibilityChannel(
buildCea708AccessibilityDescriptors("Wrong format")));
}
private static List<SchemeValuePair> buildCea608AccessibilityDescriptors(String value) {
return Collections.singletonList(new SchemeValuePair("urn:scte:dash:cc:cea-608:2015", value));
}
private static List<SchemeValuePair> buildCea708AccessibilityDescriptors(String value) {
return Collections.singletonList(new SchemeValuePair("urn:scte:dash:cc:cea-708:2015", value));
} }
} }
...@@ -46,16 +46,26 @@ public class AdaptationSet { ...@@ -46,16 +46,26 @@ public class AdaptationSet {
public final List<Representation> representations; public final List<Representation> representations;
/** /**
* The accessibility descriptors in the adaptation set.
*/
public final List<SchemeValuePair> accessibilityDescriptors;
/**
* @param id A non-negative identifier for the adaptation set that's unique in the scope of its * @param id A non-negative identifier for the adaptation set that's unique in the scope of its
* containing period, or {@link #ID_UNSET} if not specified. * containing period, or {@link #ID_UNSET} if not specified.
* @param type The type of the adaptation set. One of the {@link com.google.android.exoplayer2.C} * @param type The type of the adaptation set. One of the {@link com.google.android.exoplayer2.C}
* {@code TRACK_TYPE_*} constants. * {@code TRACK_TYPE_*} constants.
* @param representations The {@link Representation}s in the adaptation set. * @param representations The {@link Representation}s in the adaptation set.
* @param accessibilityDescriptors The accessibility descriptors in the adaptation set.
*/ */
public AdaptationSet(int id, int type, List<Representation> representations) { public AdaptationSet(int id, int type, List<Representation> representations,
List<SchemeValuePair> accessibilityDescriptors) {
this.id = id; this.id = id;
this.type = type; this.type = type;
this.representations = Collections.unmodifiableList(representations); this.representations = Collections.unmodifiableList(representations);
this.accessibilityDescriptors = accessibilityDescriptors == null
? Collections.<SchemeValuePair>emptyList()
: Collections.unmodifiableList(accessibilityDescriptors);
} }
} }
...@@ -238,9 +238,9 @@ public class DashManifestParser extends DefaultHandler ...@@ -238,9 +238,9 @@ public class DashManifestParser extends DefaultHandler
int audioChannels = Format.NO_VALUE; int audioChannels = Format.NO_VALUE;
int audioSamplingRate = parseInt(xpp, "audioSamplingRate", Format.NO_VALUE); int audioSamplingRate = parseInt(xpp, "audioSamplingRate", Format.NO_VALUE);
String language = xpp.getAttributeValue(null, "lang"); String language = xpp.getAttributeValue(null, "lang");
int accessibilityChannel = Format.NO_VALUE;
ArrayList<SchemeData> drmSchemeDatas = new ArrayList<>(); ArrayList<SchemeData> drmSchemeDatas = new ArrayList<>();
ArrayList<InbandEventStream> inbandEventStreams = new ArrayList<>(); ArrayList<SchemeValuePair> inbandEventStreams = new ArrayList<>();
ArrayList<SchemeValuePair> accessibilityDescriptors = new ArrayList<>();
List<RepresentationInfo> representationInfos = new ArrayList<>(); List<RepresentationInfo> representationInfos = new ArrayList<>();
@C.SelectionFlags int selectionFlags = 0; @C.SelectionFlags int selectionFlags = 0;
...@@ -265,11 +265,11 @@ public class DashManifestParser extends DefaultHandler ...@@ -265,11 +265,11 @@ public class DashManifestParser extends DefaultHandler
} else if (XmlPullParserUtil.isStartTag(xpp, "AudioChannelConfiguration")) { } else if (XmlPullParserUtil.isStartTag(xpp, "AudioChannelConfiguration")) {
audioChannels = parseAudioChannelConfiguration(xpp); audioChannels = parseAudioChannelConfiguration(xpp);
} else if (XmlPullParserUtil.isStartTag(xpp, "Accessibility")) { } else if (XmlPullParserUtil.isStartTag(xpp, "Accessibility")) {
accessibilityChannel = parseAccessibilityValue(xpp); accessibilityDescriptors.add(parseAccessibility(xpp));
} else if (XmlPullParserUtil.isStartTag(xpp, "Representation")) { } else if (XmlPullParserUtil.isStartTag(xpp, "Representation")) {
RepresentationInfo representationInfo = parseRepresentation(xpp, baseUrl, mimeType, codecs, RepresentationInfo representationInfo = parseRepresentation(xpp, baseUrl, mimeType, codecs,
width, height, frameRate, audioChannels, audioSamplingRate, language, width, height, frameRate, audioChannels, audioSamplingRate, language,
accessibilityChannel, selectionFlags, segmentBase); selectionFlags, accessibilityDescriptors, segmentBase);
contentType = checkContentTypeConsistency(contentType, contentType = checkContentTypeConsistency(contentType,
getContentType(representationInfo.format)); getContentType(representationInfo.format));
representationInfos.add(representationInfo); representationInfos.add(representationInfo);
...@@ -293,12 +293,12 @@ public class DashManifestParser extends DefaultHandler ...@@ -293,12 +293,12 @@ public class DashManifestParser extends DefaultHandler
drmSchemeDatas, inbandEventStreams)); drmSchemeDatas, inbandEventStreams));
} }
return buildAdaptationSet(id, contentType, representations); return buildAdaptationSet(id, contentType, representations, accessibilityDescriptors);
} }
protected AdaptationSet buildAdaptationSet(int id, int contentType, protected AdaptationSet buildAdaptationSet(int id, int contentType,
List<Representation> representations) { List<Representation> representations, List<SchemeValuePair> accessibilityDescriptors) {
return new AdaptationSet(id, contentType, representations); return new AdaptationSet(id, contentType, representations, accessibilityDescriptors);
} }
protected int parseContentType(XmlPullParser xpp) { protected int parseContentType(XmlPullParser xpp) {
...@@ -367,16 +367,24 @@ public class DashManifestParser extends DefaultHandler ...@@ -367,16 +367,24 @@ public class DashManifestParser extends DefaultHandler
* @param xpp The parser from which to read. * @param xpp The parser from which to read.
* @throws XmlPullParserException If an error occurs parsing the element. * @throws XmlPullParserException If an error occurs parsing the element.
* @throws IOException If an error occurs reading the element. * @throws IOException If an error occurs reading the element.
* @return {@link InbandEventStream} parsed from the element. * @return A {@link SchemeValuePair} parsed from the element.
*/ */
protected InbandEventStream parseInbandEventStream(XmlPullParser xpp) protected SchemeValuePair parseInbandEventStream(XmlPullParser xpp)
throws XmlPullParserException, IOException { throws XmlPullParserException, IOException {
String schemeIdUri = parseString(xpp, "schemeIdUri", null); return parseSchemeValuePair(xpp, "InbandEventStream");
String value = parseString(xpp, "value", null); }
do {
xpp.next(); /**
} while (!XmlPullParserUtil.isEndTag(xpp, "InbandEventStream")); * Parses an Accessibility element.
return new InbandEventStream(schemeIdUri, value); *
* @param xpp The parser from which to read.
* @throws XmlPullParserException If an error occurs parsing the element.
* @throws IOException If an error occurs reading the element.
* @return A {@link SchemeValuePair} parsed from the element.
*/
protected SchemeValuePair parseAccessibility(XmlPullParser xpp)
throws XmlPullParserException, IOException {
return parseSchemeValuePair(xpp, "Accessibility");
} }
/** /**
...@@ -415,8 +423,9 @@ public class DashManifestParser extends DefaultHandler ...@@ -415,8 +423,9 @@ public class DashManifestParser extends DefaultHandler
String adaptationSetMimeType, String adaptationSetCodecs, int adaptationSetWidth, String adaptationSetMimeType, String adaptationSetCodecs, int adaptationSetWidth,
int adaptationSetHeight, float adaptationSetFrameRate, int adaptationSetAudioChannels, int adaptationSetHeight, float adaptationSetFrameRate, int adaptationSetAudioChannels,
int adaptationSetAudioSamplingRate, String adaptationSetLanguage, int adaptationSetAudioSamplingRate, String adaptationSetLanguage,
int adaptationSetAccessibilityChannel, @C.SelectionFlags int adaptationSetSelectionFlags, @C.SelectionFlags int adaptationSetSelectionFlags,
SegmentBase segmentBase) throws XmlPullParserException, IOException { List<SchemeValuePair> adaptationSetAccessibilityDescriptors, SegmentBase segmentBase)
throws XmlPullParserException, IOException {
String id = xpp.getAttributeValue(null, "id"); String id = xpp.getAttributeValue(null, "id");
int bandwidth = parseInt(xpp, "bandwidth", Format.NO_VALUE); int bandwidth = parseInt(xpp, "bandwidth", Format.NO_VALUE);
...@@ -428,7 +437,7 @@ public class DashManifestParser extends DefaultHandler ...@@ -428,7 +437,7 @@ public class DashManifestParser extends DefaultHandler
int audioChannels = adaptationSetAudioChannels; int audioChannels = adaptationSetAudioChannels;
int audioSamplingRate = parseInt(xpp, "audioSamplingRate", adaptationSetAudioSamplingRate); int audioSamplingRate = parseInt(xpp, "audioSamplingRate", adaptationSetAudioSamplingRate);
ArrayList<SchemeData> drmSchemeDatas = new ArrayList<>(); ArrayList<SchemeData> drmSchemeDatas = new ArrayList<>();
ArrayList<InbandEventStream> inbandEventStreams = new ArrayList<>(); ArrayList<SchemeValuePair> inbandEventStreams = new ArrayList<>();
boolean seenFirstBaseUrl = false; boolean seenFirstBaseUrl = false;
do { do {
...@@ -457,8 +466,8 @@ public class DashManifestParser extends DefaultHandler ...@@ -457,8 +466,8 @@ public class DashManifestParser extends DefaultHandler
} while (!XmlPullParserUtil.isEndTag(xpp, "Representation")); } while (!XmlPullParserUtil.isEndTag(xpp, "Representation"));
Format format = buildFormat(id, mimeType, width, height, frameRate, audioChannels, Format format = buildFormat(id, mimeType, width, height, frameRate, audioChannels,
audioSamplingRate, bandwidth, adaptationSetLanguage, adaptationSetAccessibilityChannel, audioSamplingRate, bandwidth, adaptationSetLanguage, adaptationSetSelectionFlags,
adaptationSetSelectionFlags, codecs); adaptationSetAccessibilityDescriptors, codecs);
segmentBase = segmentBase != null ? segmentBase : new SingleSegmentBase(); segmentBase = segmentBase != null ? segmentBase : new SingleSegmentBase();
return new RepresentationInfo(format, baseUrl, segmentBase, drmSchemeDatas, inbandEventStreams); return new RepresentationInfo(format, baseUrl, segmentBase, drmSchemeDatas, inbandEventStreams);
...@@ -466,7 +475,8 @@ public class DashManifestParser extends DefaultHandler ...@@ -466,7 +475,8 @@ public class DashManifestParser extends DefaultHandler
protected Format buildFormat(String id, String containerMimeType, int width, int height, protected Format buildFormat(String id, String containerMimeType, int width, int height,
float frameRate, int audioChannels, int audioSamplingRate, int bitrate, String language, float frameRate, int audioChannels, int audioSamplingRate, int bitrate, String language,
int accessiblityChannel, @C.SelectionFlags int selectionFlags, String codecs) { @C.SelectionFlags int selectionFlags, List<SchemeValuePair> accessibilityDescriptors,
String codecs) {
String sampleMimeType = getSampleMimeType(containerMimeType, codecs); String sampleMimeType = getSampleMimeType(containerMimeType, codecs);
if (sampleMimeType != null) { if (sampleMimeType != null) {
if (MimeTypes.isVideo(sampleMimeType)) { if (MimeTypes.isVideo(sampleMimeType)) {
...@@ -476,8 +486,16 @@ public class DashManifestParser extends DefaultHandler ...@@ -476,8 +486,16 @@ public class DashManifestParser extends DefaultHandler
return Format.createAudioContainerFormat(id, containerMimeType, sampleMimeType, codecs, return Format.createAudioContainerFormat(id, containerMimeType, sampleMimeType, codecs,
bitrate, audioChannels, audioSamplingRate, null, selectionFlags, language); bitrate, audioChannels, audioSamplingRate, null, selectionFlags, language);
} else if (mimeTypeIsRawText(sampleMimeType)) { } else if (mimeTypeIsRawText(sampleMimeType)) {
int accessibilityChannel;
if (MimeTypes.APPLICATION_CEA608.equals(sampleMimeType)) {
accessibilityChannel = parseCea608AccessibilityChannel(accessibilityDescriptors);
} else if (MimeTypes.APPLICATION_CEA708.equals(sampleMimeType)) {
accessibilityChannel = parseCea708AccessibilityChannel(accessibilityDescriptors);
} else {
accessibilityChannel = Format.NO_VALUE;
}
return Format.createTextContainerFormat(id, containerMimeType, sampleMimeType, codecs, return Format.createTextContainerFormat(id, containerMimeType, sampleMimeType, codecs,
bitrate, selectionFlags, language, accessiblityChannel); bitrate, selectionFlags, language, accessibilityChannel);
} }
} }
return Format.createContainerFormat(id, containerMimeType, sampleMimeType, codecs, bitrate, return Format.createContainerFormat(id, containerMimeType, sampleMimeType, codecs, bitrate,
...@@ -486,14 +504,14 @@ public class DashManifestParser extends DefaultHandler ...@@ -486,14 +504,14 @@ public class DashManifestParser extends DefaultHandler
protected Representation buildRepresentation(RepresentationInfo representationInfo, protected Representation buildRepresentation(RepresentationInfo representationInfo,
String contentId, ArrayList<SchemeData> extraDrmSchemeDatas, String contentId, ArrayList<SchemeData> extraDrmSchemeDatas,
ArrayList<InbandEventStream> extraInbandEventStreams) { ArrayList<SchemeValuePair> extraInbandEventStreams) {
Format format = representationInfo.format; Format format = representationInfo.format;
ArrayList<SchemeData> drmSchemeDatas = representationInfo.drmSchemeDatas; ArrayList<SchemeData> drmSchemeDatas = representationInfo.drmSchemeDatas;
drmSchemeDatas.addAll(extraDrmSchemeDatas); drmSchemeDatas.addAll(extraDrmSchemeDatas);
if (!drmSchemeDatas.isEmpty()) { if (!drmSchemeDatas.isEmpty()) {
format = format.copyWithDrmInitData(new DrmInitData(drmSchemeDatas)); format = format.copyWithDrmInitData(new DrmInitData(drmSchemeDatas));
} }
ArrayList<InbandEventStream> inbandEventStremas = representationInfo.inbandEventStreams; ArrayList<SchemeValuePair> inbandEventStremas = representationInfo.inbandEventStreams;
inbandEventStremas.addAll(extraInbandEventStreams); inbandEventStremas.addAll(extraInbandEventStreams);
return Representation.newInstance(contentId, Representation.REVISION_ID_DEFAULT, format, return Representation.newInstance(contentId, Representation.REVISION_ID_DEFAULT, format,
representationInfo.baseUrl, representationInfo.segmentBase, inbandEventStremas); representationInfo.baseUrl, representationInfo.segmentBase, inbandEventStremas);
...@@ -785,52 +803,57 @@ public class DashManifestParser extends DefaultHandler ...@@ -785,52 +803,57 @@ public class DashManifestParser extends DefaultHandler
} }
} }
private static int parseAccessibilityValue(XmlPullParser xpp) /**
throws IOException, XmlPullParserException { * Parses a {@link SchemeValuePair} from an element.
*
* @param xpp The parser from which to read.
* @param tag The tag of the element being parsed.
* @throws XmlPullParserException If an error occurs parsing the element.
* @throws IOException If an error occurs reading the element.
* @return The parsed {@link SchemeValuePair}.
*/
protected static SchemeValuePair parseSchemeValuePair(XmlPullParser xpp, String tag)
throws XmlPullParserException, IOException {
String schemeIdUri = parseString(xpp, "schemeIdUri", null); String schemeIdUri = parseString(xpp, "schemeIdUri", null);
String valueString = parseString(xpp, "value", null); String value = parseString(xpp, "value", null);
int accessibilityValue;
if (schemeIdUri == null || valueString == null) {
accessibilityValue = Format.NO_VALUE;
} else if ("urn:scte:dash:cc:cea-608:2015".equals(schemeIdUri)) {
accessibilityValue = parseCea608AccessibilityChannel(valueString);
} else if ("urn:scte:dash:cc:cea-708:2015".equals(schemeIdUri)) {
accessibilityValue = parseCea708AccessibilityChannel(valueString);
} else {
accessibilityValue = Format.NO_VALUE;
}
do { do {
xpp.next(); xpp.next();
} while (!XmlPullParserUtil.isEndTag(xpp, "Accessibility")); } while (!XmlPullParserUtil.isEndTag(xpp, tag));
return accessibilityValue; return new SchemeValuePair(schemeIdUri, value);
} }
static int parseCea608AccessibilityChannel(String accessibilityValueString) { protected static int parseCea608AccessibilityChannel(
if (accessibilityValueString == null) { List<SchemeValuePair> accessibilityDescriptors) {
return Format.NO_VALUE; for (int i = 0; i < accessibilityDescriptors.size(); i++) {
} SchemeValuePair descriptor = accessibilityDescriptors.get(i);
Matcher accessibilityValueMatcher = if ("urn:scte:dash:cc:cea-608:2015".equals(descriptor.schemeIdUri)
CEA_608_ACCESSIBILITY_PATTERN.matcher(accessibilityValueString); && descriptor.value != null) {
if (accessibilityValueMatcher.matches()) { Matcher accessibilityValueMatcher = CEA_608_ACCESSIBILITY_PATTERN.matcher(descriptor.value);
return Integer.parseInt(accessibilityValueMatcher.group(1)); if (accessibilityValueMatcher.matches()) {
} else { return Integer.parseInt(accessibilityValueMatcher.group(1));
Log.w(TAG, "Unable to parse channel number from " + accessibilityValueString); } else {
return Format.NO_VALUE; Log.w(TAG, "Unable to parse CEA-608 channel number from: " + descriptor.value);
} }
} }
static int parseCea708AccessibilityChannel(String accessibilityValueString) {
if (accessibilityValueString == null) {
return Format.NO_VALUE;
} }
Matcher accessibilityValueMatcher = return Format.NO_VALUE;
CEA_708_ACCESSIBILITY_PATTERN.matcher(accessibilityValueString); }
if (accessibilityValueMatcher.matches()) {
return Integer.parseInt(accessibilityValueMatcher.group(1)); protected static int parseCea708AccessibilityChannel(
} else { List<SchemeValuePair> accessibilityDescriptors) {
Log.w(TAG, "Unable to parse service block number from " + accessibilityValueString); for (int i = 0; i < accessibilityDescriptors.size(); i++) {
return Format.NO_VALUE; SchemeValuePair descriptor = accessibilityDescriptors.get(i);
if ("urn:scte:dash:cc:cea-708:2015".equals(descriptor.schemeIdUri)
&& descriptor.value != null) {
Matcher accessibilityValueMatcher = CEA_708_ACCESSIBILITY_PATTERN.matcher(descriptor.value);
if (accessibilityValueMatcher.matches()) {
return Integer.parseInt(accessibilityValueMatcher.group(1));
} else {
Log.w(TAG, "Unable to parse CEA-708 service block number from: " + descriptor.value);
}
}
} }
return Format.NO_VALUE;
} }
protected static float parseFrameRate(XmlPullParser xpp, float defaultValue) { protected static float parseFrameRate(XmlPullParser xpp, float defaultValue) {
...@@ -897,10 +920,10 @@ public class DashManifestParser extends DefaultHandler ...@@ -897,10 +920,10 @@ public class DashManifestParser extends DefaultHandler
public final String baseUrl; public final String baseUrl;
public final SegmentBase segmentBase; public final SegmentBase segmentBase;
public final ArrayList<SchemeData> drmSchemeDatas; public final ArrayList<SchemeData> drmSchemeDatas;
public final ArrayList<InbandEventStream> inbandEventStreams; public final ArrayList<SchemeValuePair> inbandEventStreams;
public RepresentationInfo(Format format, String baseUrl, SegmentBase segmentBase, public RepresentationInfo(Format format, String baseUrl, SegmentBase segmentBase,
ArrayList<SchemeData> drmSchemeDatas, ArrayList<InbandEventStream> inbandEventStreams) { ArrayList<SchemeData> drmSchemeDatas, ArrayList<SchemeValuePair> inbandEventStreams) {
this.format = format; this.format = format;
this.baseUrl = baseUrl; this.baseUrl = baseUrl;
this.segmentBase = segmentBase; this.segmentBase = segmentBase;
......
...@@ -63,9 +63,9 @@ public abstract class Representation { ...@@ -63,9 +63,9 @@ public abstract class Representation {
*/ */
public final long presentationTimeOffsetUs; public final long presentationTimeOffsetUs;
/** /**
* The {@link InbandEventStream}s in the representation. Never null, but may be empty. * The in-band event streams in the representation. Never null, but may be empty.
*/ */
public final List<InbandEventStream> inbandEventStreams; public final List<SchemeValuePair> inbandEventStreams;
private final RangedUri initializationUri; private final RangedUri initializationUri;
...@@ -92,11 +92,11 @@ public abstract class Representation { ...@@ -92,11 +92,11 @@ public abstract class Representation {
* @param format The format of the representation. * @param format The format of the representation.
* @param baseUrl The base URL. * @param baseUrl The base URL.
* @param segmentBase A segment base element for the representation. * @param segmentBase A segment base element for the representation.
* @param inbandEventStreams The {@link InbandEventStream}s in the representation. May be null. * @param inbandEventStreams The in-band event streams in the representation. May be null.
* @return The constructed instance. * @return The constructed instance.
*/ */
public static Representation newInstance(String contentId, long revisionId, Format format, public static Representation newInstance(String contentId, long revisionId, Format format,
String baseUrl, SegmentBase segmentBase, List<InbandEventStream> inbandEventStreams) { String baseUrl, SegmentBase segmentBase, List<SchemeValuePair> inbandEventStreams) {
return newInstance(contentId, revisionId, format, baseUrl, segmentBase, inbandEventStreams, return newInstance(contentId, revisionId, format, baseUrl, segmentBase, inbandEventStreams,
null); null);
} }
...@@ -109,13 +109,13 @@ public abstract class Representation { ...@@ -109,13 +109,13 @@ public abstract class Representation {
* @param format The format of the representation. * @param format The format of the representation.
* @param baseUrl The base URL of the representation. * @param baseUrl The base URL of the representation.
* @param segmentBase A segment base element for the representation. * @param segmentBase A segment base element for the representation.
* @param inbandEventStreams The {@link InbandEventStream}s in the representation. May be null. * @param inbandEventStreams The in-band event streams in the representation. May be null.
* @param customCacheKey A custom value to be returned from {@link #getCacheKey()}, or null. This * @param customCacheKey A custom value to be returned from {@link #getCacheKey()}, or null. This
* parameter is ignored if {@code segmentBase} consists of multiple segments. * parameter is ignored if {@code segmentBase} consists of multiple segments.
* @return The constructed instance. * @return The constructed instance.
*/ */
public static Representation newInstance(String contentId, long revisionId, Format format, public static Representation newInstance(String contentId, long revisionId, Format format,
String baseUrl, SegmentBase segmentBase, List<InbandEventStream> inbandEventStreams, String baseUrl, SegmentBase segmentBase, List<SchemeValuePair> inbandEventStreams,
String customCacheKey) { String customCacheKey) {
if (segmentBase instanceof SingleSegmentBase) { if (segmentBase instanceof SingleSegmentBase) {
return new SingleSegmentRepresentation(contentId, revisionId, format, baseUrl, return new SingleSegmentRepresentation(contentId, revisionId, format, baseUrl,
...@@ -130,13 +130,13 @@ public abstract class Representation { ...@@ -130,13 +130,13 @@ public abstract class Representation {
} }
private Representation(String contentId, long revisionId, Format format, String baseUrl, private Representation(String contentId, long revisionId, Format format, String baseUrl,
SegmentBase segmentBase, List<InbandEventStream> inbandEventStreams) { SegmentBase segmentBase, List<SchemeValuePair> inbandEventStreams) {
this.contentId = contentId; this.contentId = contentId;
this.revisionId = revisionId; this.revisionId = revisionId;
this.format = format; this.format = format;
this.baseUrl = baseUrl; this.baseUrl = baseUrl;
this.inbandEventStreams = inbandEventStreams == null this.inbandEventStreams = inbandEventStreams == null
? Collections.<InbandEventStream>emptyList() ? Collections.<SchemeValuePair>emptyList()
: Collections.unmodifiableList(inbandEventStreams); : Collections.unmodifiableList(inbandEventStreams);
initializationUri = segmentBase.getInitialization(this); initializationUri = segmentBase.getInitialization(this);
presentationTimeOffsetUs = segmentBase.getPresentationTimeOffsetUs(); presentationTimeOffsetUs = segmentBase.getPresentationTimeOffsetUs();
...@@ -195,13 +195,13 @@ public abstract class Representation { ...@@ -195,13 +195,13 @@ public abstract class Representation {
* @param initializationEnd The offset of the last byte of initialization data. * @param initializationEnd The offset of the last byte of initialization data.
* @param indexStart The offset of the first byte of index data. * @param indexStart The offset of the first byte of index data.
* @param indexEnd The offset of the last byte of index data. * @param indexEnd The offset of the last byte of index data.
* @param inbandEventStreams The {@link InbandEventStream}s in the representation. May be null. * @param inbandEventStreams The in-band event streams in the representation. May be null.
* @param customCacheKey A custom value to be returned from {@link #getCacheKey()}, or null. * @param customCacheKey A custom value to be returned from {@link #getCacheKey()}, or null.
* @param contentLength The content length, or {@link C#LENGTH_UNSET} if unknown. * @param contentLength The content length, or {@link C#LENGTH_UNSET} if unknown.
*/ */
public static SingleSegmentRepresentation newInstance(String contentId, long revisionId, public static SingleSegmentRepresentation newInstance(String contentId, long revisionId,
Format format, String uri, long initializationStart, long initializationEnd, Format format, String uri, long initializationStart, long initializationEnd,
long indexStart, long indexEnd, List<InbandEventStream> inbandEventStreams, long indexStart, long indexEnd, List<SchemeValuePair> inbandEventStreams,
String customCacheKey, long contentLength) { String customCacheKey, long contentLength) {
RangedUri rangedUri = new RangedUri(null, initializationStart, RangedUri rangedUri = new RangedUri(null, initializationStart,
initializationEnd - initializationStart + 1); initializationEnd - initializationStart + 1);
...@@ -217,12 +217,12 @@ public abstract class Representation { ...@@ -217,12 +217,12 @@ public abstract class Representation {
* @param format The format of the representation. * @param format The format of the representation.
* @param baseUrl The base URL of the representation. * @param baseUrl The base URL of the representation.
* @param segmentBase The segment base underlying the representation. * @param segmentBase The segment base underlying the representation.
* @param inbandEventStreams The {@link InbandEventStream}s in the representation. May be null. * @param inbandEventStreams The in-band event streams in the representation. May be null.
* @param customCacheKey A custom value to be returned from {@link #getCacheKey()}, or null. * @param customCacheKey A custom value to be returned from {@link #getCacheKey()}, or null.
* @param contentLength The content length, or {@link C#LENGTH_UNSET} if unknown. * @param contentLength The content length, or {@link C#LENGTH_UNSET} if unknown.
*/ */
public SingleSegmentRepresentation(String contentId, long revisionId, Format format, public SingleSegmentRepresentation(String contentId, long revisionId, Format format,
String baseUrl, SingleSegmentBase segmentBase, List<InbandEventStream> inbandEventStreams, String baseUrl, SingleSegmentBase segmentBase, List<SchemeValuePair> inbandEventStreams,
String customCacheKey, long contentLength) { String customCacheKey, long contentLength) {
super(contentId, revisionId, format, baseUrl, segmentBase, inbandEventStreams); super(contentId, revisionId, format, baseUrl, segmentBase, inbandEventStreams);
this.uri = Uri.parse(baseUrl); this.uri = Uri.parse(baseUrl);
...@@ -267,10 +267,10 @@ public abstract class Representation { ...@@ -267,10 +267,10 @@ public abstract class Representation {
* @param format The format of the representation. * @param format The format of the representation.
* @param baseUrl The base URL of the representation. * @param baseUrl The base URL of the representation.
* @param segmentBase The segment base underlying the representation. * @param segmentBase The segment base underlying the representation.
* @param inbandEventStreams The {@link InbandEventStream}s in the representation. May be null. * @param inbandEventStreams The in-band event streams in the representation. May be null.
*/ */
public MultiSegmentRepresentation(String contentId, long revisionId, Format format, public MultiSegmentRepresentation(String contentId, long revisionId, Format format,
String baseUrl, MultiSegmentBase segmentBase, List<InbandEventStream> inbandEventStreams) { String baseUrl, MultiSegmentBase segmentBase, List<SchemeValuePair> inbandEventStreams) {
super(contentId, revisionId, format, baseUrl, segmentBase, inbandEventStreams); super(contentId, revisionId, format, baseUrl, segmentBase, inbandEventStreams);
this.segmentBase = segmentBase; this.segmentBase = segmentBase;
} }
......
...@@ -18,14 +18,14 @@ package com.google.android.exoplayer2.source.dash.manifest; ...@@ -18,14 +18,14 @@ package com.google.android.exoplayer2.source.dash.manifest;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
/** /**
* Represents a DASH in-band event stream. * A pair consisting of a scheme ID and value.
*/ */
public class InbandEventStream { public class SchemeValuePair {
public final String schemeIdUri; public final String schemeIdUri;
public final String value; public final String value;
public InbandEventStream(String schemeIdUri, String value) { public SchemeValuePair(String schemeIdUri, String value) {
this.schemeIdUri = schemeIdUri; this.schemeIdUri = schemeIdUri;
this.value = value; this.value = value;
} }
...@@ -38,7 +38,7 @@ public class InbandEventStream { ...@@ -38,7 +38,7 @@ public class InbandEventStream {
if (obj == null || getClass() != obj.getClass()) { if (obj == null || getClass() != obj.getClass()) {
return false; return false;
} }
InbandEventStream other = (InbandEventStream) obj; SchemeValuePair other = (SchemeValuePair) obj;
return Util.areEqual(schemeIdUri, other.schemeIdUri) && Util.areEqual(value, other.value); return Util.areEqual(schemeIdUri, other.schemeIdUri) && Util.areEqual(value, other.value);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment