Parse SupplementalProperty elements in DASH adaptation sets

This will be used to merge adaptation sets that are marked for
seamless switching into single TrackGroups in DashMediaSource.

Issue: #2431

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=157209358
This commit is contained in:
olly 2017-05-26 04:48:11 -07:00 committed by Oliver Woodman
parent 5092efe301
commit 9737046e53
9 changed files with 97 additions and 89 deletions

View file

@ -62,7 +62,7 @@ public final class DashUtilTest extends TestCase {
} }
private static AdaptationSet newAdaptationSets(Representation... representations) { private static AdaptationSet newAdaptationSets(Representation... representations) {
return new AdaptationSet(0, C.TRACK_TYPE_VIDEO, Arrays.asList(representations), null); return new AdaptationSet(0, C.TRACK_TYPE_VIDEO, Arrays.asList(representations), null, null);
} }
private static Representation newRepresentations(DrmInitData drmInitData) { private static Representation newRepresentations(DrmInitData drmInitData) {

View file

@ -115,12 +115,12 @@ public class DashManifestParserTest extends InstrumentationTestCase {
buildCea708AccessibilityDescriptors("Wrong format"))); buildCea708AccessibilityDescriptors("Wrong format")));
} }
private static List<SchemeValuePair> buildCea608AccessibilityDescriptors(String value) { private static List<Descriptor> buildCea608AccessibilityDescriptors(String value) {
return Collections.singletonList(new SchemeValuePair("urn:scte:dash:cc:cea-608:2015", value)); return Collections.singletonList(new Descriptor("urn:scte:dash:cc:cea-608:2015", value, null));
} }
private static List<SchemeValuePair> buildCea708AccessibilityDescriptors(String value) { private static List<Descriptor> buildCea708AccessibilityDescriptors(String value) {
return Collections.singletonList(new SchemeValuePair("urn:scte:dash:cc:cea-708:2015", value)); return Collections.singletonList(new Descriptor("urn:scte:dash:cc:cea-708:2015", value, null));
} }
} }

View file

@ -30,8 +30,6 @@ import junit.framework.TestCase;
public class DashManifestTest extends TestCase { public class DashManifestTest extends TestCase {
private static final UtcTimingElement DUMMY_UTC_TIMING = new UtcTimingElement("", ""); private static final UtcTimingElement DUMMY_UTC_TIMING = new UtcTimingElement("", "");
private static final List<SchemeValuePair> DUMMY_ACCESSIBILITY_DESCRIPTORS =
Collections.emptyList();
private static final SingleSegmentBase DUMMY_SEGMENT_BASE = new SingleSegmentBase(); private static final SingleSegmentBase DUMMY_SEGMENT_BASE = new SingleSegmentBase();
private static final Format DUMMY_FORMAT = Format.createSampleFormat("", "", 0); private static final Format DUMMY_FORMAT = Format.createSampleFormat("", "", 0);
@ -190,8 +188,7 @@ public class DashManifestTest extends TestCase {
} }
private static AdaptationSet newAdaptationSet(int seed, Representation... representations) { private static AdaptationSet newAdaptationSet(int seed, Representation... representations) {
return new AdaptationSet(++seed, ++seed, Arrays.asList(representations), return new AdaptationSet(++seed, ++seed, Arrays.asList(representations), null, null);
DUMMY_ACCESSIBILITY_DESCRIPTORS);
} }
} }

View file

@ -30,8 +30,8 @@ import com.google.android.exoplayer2.source.chunk.ChunkSampleStream;
import com.google.android.exoplayer2.source.chunk.ChunkSampleStream.EmbeddedSampleStream; import com.google.android.exoplayer2.source.chunk.ChunkSampleStream.EmbeddedSampleStream;
import com.google.android.exoplayer2.source.dash.manifest.AdaptationSet; import com.google.android.exoplayer2.source.dash.manifest.AdaptationSet;
import com.google.android.exoplayer2.source.dash.manifest.DashManifest; import com.google.android.exoplayer2.source.dash.manifest.DashManifest;
import com.google.android.exoplayer2.source.dash.manifest.Descriptor;
import com.google.android.exoplayer2.source.dash.manifest.Representation; import com.google.android.exoplayer2.source.dash.manifest.Representation;
import com.google.android.exoplayer2.source.dash.manifest.SchemeValuePair;
import com.google.android.exoplayer2.trackselection.TrackSelection; import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.LoaderErrorThrower; import com.google.android.exoplayer2.upstream.LoaderErrorThrower;
@ -319,9 +319,9 @@ import java.util.List;
} }
private static boolean hasCea608Track(AdaptationSet adaptationSet) { private static boolean hasCea608Track(AdaptationSet adaptationSet) {
List<SchemeValuePair> descriptors = adaptationSet.accessibilityDescriptors; List<Descriptor> descriptors = adaptationSet.accessibilityDescriptors;
for (int i = 0; i < descriptors.size(); i++) { for (int i = 0; i < descriptors.size(); i++) {
SchemeValuePair descriptor = descriptors.get(i); Descriptor descriptor = descriptors.get(i);
if ("urn:scte:dash:cc:cea-608:2015".equals(descriptor.schemeIdUri)) { if ("urn:scte:dash:cc:cea-608:2015".equals(descriptor.schemeIdUri)) {
return true; return true;
} }

View file

@ -41,31 +41,40 @@ public class AdaptationSet {
public final int type; public final int type;
/** /**
* The {@link Representation}s in the adaptation set. * {@link Representation}s in the adaptation set.
*/ */
public final List<Representation> representations; public final List<Representation> representations;
/** /**
* The accessibility descriptors in the adaptation set. * Accessibility descriptors in the adaptation set.
*/ */
public final List<SchemeValuePair> accessibilityDescriptors; public final List<Descriptor> accessibilityDescriptors;
/**
* Supplemental properties in the adaptation set.
*/
public final List<Descriptor> supplementalProperties;
/** /**
* @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 {@link Representation}s in the adaptation set.
* @param accessibilityDescriptors The accessibility descriptors in the adaptation set. * @param accessibilityDescriptors Accessibility descriptors in the adaptation set.
* @param supplementalProperties Supplemental properties 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) { List<Descriptor> accessibilityDescriptors, List<Descriptor> supplementalProperties) {
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 this.accessibilityDescriptors = accessibilityDescriptors == null
? Collections.<SchemeValuePair>emptyList() ? Collections.<Descriptor>emptyList()
: Collections.unmodifiableList(accessibilityDescriptors); : Collections.unmodifiableList(accessibilityDescriptors);
this.supplementalProperties = supplementalProperties == null
? Collections.<Descriptor>emptyList()
: Collections.unmodifiableList(supplementalProperties);
} }
} }

View file

@ -134,7 +134,8 @@ public class DashManifest {
} while(key.periodIndex == periodIndex && key.adaptationSetIndex == adaptationSetIndex); } while(key.periodIndex == periodIndex && key.adaptationSetIndex == adaptationSetIndex);
copyAdaptationSets.add(new AdaptationSet(adaptationSet.id, adaptationSet.type, copyAdaptationSets.add(new AdaptationSet(adaptationSet.id, adaptationSet.type,
copyRepresentations, adaptationSet.accessibilityDescriptors)); copyRepresentations, adaptationSet.accessibilityDescriptors,
adaptationSet.supplementalProperties));
} while(key.periodIndex == periodIndex); } while(key.periodIndex == periodIndex);
// Add back the last key which doesn't belong to the period being processed // Add back the last key which doesn't belong to the period being processed
keys.addFirst(key); keys.addFirst(key);

View file

@ -239,8 +239,9 @@ public class DashManifestParser extends DefaultHandler
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");
ArrayList<SchemeData> drmSchemeDatas = new ArrayList<>(); ArrayList<SchemeData> drmSchemeDatas = new ArrayList<>();
ArrayList<SchemeValuePair> inbandEventStreams = new ArrayList<>(); ArrayList<Descriptor> inbandEventStreams = new ArrayList<>();
ArrayList<SchemeValuePair> accessibilityDescriptors = new ArrayList<>(); ArrayList<Descriptor> accessibilityDescriptors = new ArrayList<>();
ArrayList<Descriptor> supplementalProperties = new ArrayList<>();
List<RepresentationInfo> representationInfos = new ArrayList<>(); List<RepresentationInfo> representationInfos = new ArrayList<>();
@C.SelectionFlags int selectionFlags = 0; @C.SelectionFlags int selectionFlags = 0;
@ -265,7 +266,9 @@ 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")) {
accessibilityDescriptors.add(parseAccessibility(xpp)); accessibilityDescriptors.add(parseDescriptor(xpp, "Accessibility"));
} else if (XmlPullParserUtil.isStartTag(xpp, "SupplementalProperty")) {
supplementalProperties.add(parseDescriptor(xpp, "SupplementalProperty"));
} 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,
@ -280,7 +283,7 @@ public class DashManifestParser extends DefaultHandler
} else if (XmlPullParserUtil.isStartTag(xpp, "SegmentTemplate")) { } else if (XmlPullParserUtil.isStartTag(xpp, "SegmentTemplate")) {
segmentBase = parseSegmentTemplate(xpp, (SegmentTemplate) segmentBase); segmentBase = parseSegmentTemplate(xpp, (SegmentTemplate) segmentBase);
} else if (XmlPullParserUtil.isStartTag(xpp, "InbandEventStream")) { } else if (XmlPullParserUtil.isStartTag(xpp, "InbandEventStream")) {
inbandEventStreams.add(parseInbandEventStream(xpp)); inbandEventStreams.add(parseDescriptor(xpp, "InbandEventStream"));
} else if (XmlPullParserUtil.isStartTag(xpp)) { } else if (XmlPullParserUtil.isStartTag(xpp)) {
parseAdaptationSetChild(xpp); parseAdaptationSetChild(xpp);
} }
@ -293,12 +296,15 @@ public class DashManifestParser extends DefaultHandler
drmSchemeDatas, inbandEventStreams)); drmSchemeDatas, inbandEventStreams));
} }
return buildAdaptationSet(id, contentType, representations, accessibilityDescriptors); return buildAdaptationSet(id, contentType, representations, accessibilityDescriptors,
supplementalProperties);
} }
protected AdaptationSet buildAdaptationSet(int id, int contentType, protected AdaptationSet buildAdaptationSet(int id, int contentType,
List<Representation> representations, List<SchemeValuePair> accessibilityDescriptors) { List<Representation> representations, List<Descriptor> accessibilityDescriptors,
return new AdaptationSet(id, contentType, representations, accessibilityDescriptors); List<Descriptor> supplementalProperties) {
return new AdaptationSet(id, contentType, representations, accessibilityDescriptors,
supplementalProperties);
} }
protected int parseContentType(XmlPullParser xpp) { protected int parseContentType(XmlPullParser xpp) {
@ -366,32 +372,6 @@ public class DashManifestParser extends DefaultHandler
: null; : null;
} }
/**
* Parses an InbandEventStream element.
*
* @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 parseInbandEventStream(XmlPullParser xpp)
throws XmlPullParserException, IOException {
return parseSchemeValuePair(xpp, "InbandEventStream");
}
/**
* Parses an Accessibility element.
*
* @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");
}
/** /**
* Parses a Role element. * Parses a Role element.
* *
@ -429,7 +409,7 @@ public class DashManifestParser extends DefaultHandler
int adaptationSetHeight, float adaptationSetFrameRate, int adaptationSetAudioChannels, int adaptationSetHeight, float adaptationSetFrameRate, int adaptationSetAudioChannels,
int adaptationSetAudioSamplingRate, String adaptationSetLanguage, int adaptationSetAudioSamplingRate, String adaptationSetLanguage,
@C.SelectionFlags int adaptationSetSelectionFlags, @C.SelectionFlags int adaptationSetSelectionFlags,
List<SchemeValuePair> adaptationSetAccessibilityDescriptors, SegmentBase segmentBase) List<Descriptor> adaptationSetAccessibilityDescriptors, SegmentBase segmentBase)
throws XmlPullParserException, IOException { 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);
@ -442,7 +422,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<SchemeValuePair> inbandEventStreams = new ArrayList<>(); ArrayList<Descriptor> inbandEventStreams = new ArrayList<>();
boolean seenFirstBaseUrl = false; boolean seenFirstBaseUrl = false;
do { do {
@ -466,7 +446,7 @@ public class DashManifestParser extends DefaultHandler
drmSchemeDatas.add(contentProtection); drmSchemeDatas.add(contentProtection);
} }
} else if (XmlPullParserUtil.isStartTag(xpp, "InbandEventStream")) { } else if (XmlPullParserUtil.isStartTag(xpp, "InbandEventStream")) {
inbandEventStreams.add(parseInbandEventStream(xpp)); inbandEventStreams.add(parseDescriptor(xpp, "InbandEventStream"));
} }
} while (!XmlPullParserUtil.isEndTag(xpp, "Representation")); } while (!XmlPullParserUtil.isEndTag(xpp, "Representation"));
@ -480,7 +460,7 @@ 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,
@C.SelectionFlags int selectionFlags, List<SchemeValuePair> accessibilityDescriptors, @C.SelectionFlags int selectionFlags, List<Descriptor> accessibilityDescriptors,
String codecs) { String codecs) {
String sampleMimeType = getSampleMimeType(containerMimeType, codecs); String sampleMimeType = getSampleMimeType(containerMimeType, codecs);
if (sampleMimeType != null) { if (sampleMimeType != null) {
@ -509,14 +489,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<SchemeValuePair> extraInbandEventStreams) { ArrayList<Descriptor> 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<SchemeValuePair> inbandEventStremas = representationInfo.inbandEventStreams; ArrayList<Descriptor> 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);
@ -809,28 +789,29 @@ public class DashManifestParser extends DefaultHandler
} }
/** /**
* Parses a {@link SchemeValuePair} from an element. * Parses a {@link Descriptor} from an element.
* *
* @param xpp The parser from which to read. * @param xpp The parser from which to read.
* @param tag The tag of the element being parsed. * @param tag The tag of the element being parsed.
* @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 The parsed {@link SchemeValuePair}. * @return The parsed {@link Descriptor}.
*/ */
protected static SchemeValuePair parseSchemeValuePair(XmlPullParser xpp, String tag) protected static Descriptor parseDescriptor(XmlPullParser xpp, String tag)
throws XmlPullParserException, IOException { throws XmlPullParserException, IOException {
String schemeIdUri = parseString(xpp, "schemeIdUri", null); String schemeIdUri = parseString(xpp, "schemeIdUri", "");
String value = parseString(xpp, "value", null); String value = parseString(xpp, "value", null);
String id = parseString(xpp, "id", null);
do { do {
xpp.next(); xpp.next();
} while (!XmlPullParserUtil.isEndTag(xpp, tag)); } while (!XmlPullParserUtil.isEndTag(xpp, tag));
return new SchemeValuePair(schemeIdUri, value); return new Descriptor(schemeIdUri, value, id);
} }
protected static int parseCea608AccessibilityChannel( protected static int parseCea608AccessibilityChannel(
List<SchemeValuePair> accessibilityDescriptors) { List<Descriptor> accessibilityDescriptors) {
for (int i = 0; i < accessibilityDescriptors.size(); i++) { for (int i = 0; i < accessibilityDescriptors.size(); i++) {
SchemeValuePair descriptor = accessibilityDescriptors.get(i); Descriptor descriptor = accessibilityDescriptors.get(i);
if ("urn:scte:dash:cc:cea-608:2015".equals(descriptor.schemeIdUri) if ("urn:scte:dash:cc:cea-608:2015".equals(descriptor.schemeIdUri)
&& descriptor.value != null) { && descriptor.value != null) {
Matcher accessibilityValueMatcher = CEA_608_ACCESSIBILITY_PATTERN.matcher(descriptor.value); Matcher accessibilityValueMatcher = CEA_608_ACCESSIBILITY_PATTERN.matcher(descriptor.value);
@ -845,9 +826,9 @@ public class DashManifestParser extends DefaultHandler
} }
protected static int parseCea708AccessibilityChannel( protected static int parseCea708AccessibilityChannel(
List<SchemeValuePair> accessibilityDescriptors) { List<Descriptor> accessibilityDescriptors) {
for (int i = 0; i < accessibilityDescriptors.size(); i++) { for (int i = 0; i < accessibilityDescriptors.size(); i++) {
SchemeValuePair descriptor = accessibilityDescriptors.get(i); Descriptor descriptor = accessibilityDescriptors.get(i);
if ("urn:scte:dash:cc:cea-708:2015".equals(descriptor.schemeIdUri) if ("urn:scte:dash:cc:cea-708:2015".equals(descriptor.schemeIdUri)
&& descriptor.value != null) { && descriptor.value != null) {
Matcher accessibilityValueMatcher = CEA_708_ACCESSIBILITY_PATTERN.matcher(descriptor.value); Matcher accessibilityValueMatcher = CEA_708_ACCESSIBILITY_PATTERN.matcher(descriptor.value);
@ -925,10 +906,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<SchemeValuePair> inbandEventStreams; public final ArrayList<Descriptor> inbandEventStreams;
public RepresentationInfo(Format format, String baseUrl, SegmentBase segmentBase, public RepresentationInfo(Format format, String baseUrl, SegmentBase segmentBase,
ArrayList<SchemeData> drmSchemeDatas, ArrayList<SchemeValuePair> inbandEventStreams) { ArrayList<SchemeData> drmSchemeDatas, ArrayList<Descriptor> inbandEventStreams) {
this.format = format; this.format = format;
this.baseUrl = baseUrl; this.baseUrl = baseUrl;
this.segmentBase = segmentBase; this.segmentBase = segmentBase;

View file

@ -15,19 +15,37 @@
*/ */
package com.google.android.exoplayer2.source.dash.manifest; package com.google.android.exoplayer2.source.dash.manifest;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
/** /**
* A pair consisting of a scheme ID and value. * A descriptor, as defined by ISO 23009-1, 2nd edition, 5.8.2.
*/ */
public class SchemeValuePair { public final class Descriptor {
public final String schemeIdUri; /**
public final String value; * The scheme URI.
*/
@NonNull public final String schemeIdUri;
/**
* The value, or null.
*/
@Nullable public final String value;
/**
* The identifier, or null.
*/
@Nullable public final String id;
public SchemeValuePair(String schemeIdUri, String value) { /**
* @param schemeIdUri The scheme URI.
* @param value The value, or null.
* @param id The identifier, or null.
*/
public Descriptor(@NonNull String schemeIdUri, @Nullable String value, @Nullable String id) {
this.schemeIdUri = schemeIdUri; this.schemeIdUri = schemeIdUri;
this.value = value; this.value = value;
this.id = id;
} }
@Override @Override
@ -38,14 +56,17 @@ public class SchemeValuePair {
if (obj == null || getClass() != obj.getClass()) { if (obj == null || getClass() != obj.getClass()) {
return false; return false;
} }
SchemeValuePair other = (SchemeValuePair) obj; Descriptor other = (Descriptor) obj;
return Util.areEqual(schemeIdUri, other.schemeIdUri) && Util.areEqual(value, other.value); return Util.areEqual(schemeIdUri, other.schemeIdUri) && Util.areEqual(value, other.value)
&& Util.areEqual(id, other.id);
} }
@Override @Override
public int hashCode() { public int hashCode() {
return 31 * (schemeIdUri != null ? schemeIdUri.hashCode() : 0) int result = (schemeIdUri != null ? schemeIdUri.hashCode() : 0);
+ (value != null ? value.hashCode() : 0); result = 31 * result + (value != null ? value.hashCode() : 0);
result = 31 * result + (id != null ? id.hashCode() : 0);
return result;
} }
} }

View file

@ -65,7 +65,7 @@ public abstract class Representation {
/** /**
* The in-band event streams 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<SchemeValuePair> inbandEventStreams; public final List<Descriptor> inbandEventStreams;
private final RangedUri initializationUri; private final RangedUri initializationUri;
@ -96,7 +96,7 @@ public abstract class Representation {
* @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<SchemeValuePair> inbandEventStreams) { String baseUrl, SegmentBase segmentBase, List<Descriptor> inbandEventStreams) {
return newInstance(contentId, revisionId, format, baseUrl, segmentBase, inbandEventStreams, return newInstance(contentId, revisionId, format, baseUrl, segmentBase, inbandEventStreams,
null); null);
} }
@ -115,7 +115,7 @@ public abstract class Representation {
* @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<SchemeValuePair> inbandEventStreams, String baseUrl, SegmentBase segmentBase, List<Descriptor> 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,12 @@ 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<SchemeValuePair> inbandEventStreams) { SegmentBase segmentBase, List<Descriptor> 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.<Descriptor>emptyList()
? Collections.<SchemeValuePair>emptyList()
: Collections.unmodifiableList(inbandEventStreams); : Collections.unmodifiableList(inbandEventStreams);
initializationUri = segmentBase.getInitialization(this); initializationUri = segmentBase.getInitialization(this);
presentationTimeOffsetUs = segmentBase.getPresentationTimeOffsetUs(); presentationTimeOffsetUs = segmentBase.getPresentationTimeOffsetUs();
@ -201,8 +200,8 @@ public abstract class Representation {
*/ */
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<SchemeValuePair> inbandEventStreams, long indexStart, long indexEnd, List<Descriptor> inbandEventStreams, String customCacheKey,
String customCacheKey, long contentLength) { long contentLength) {
RangedUri rangedUri = new RangedUri(null, initializationStart, RangedUri rangedUri = new RangedUri(null, initializationStart,
initializationEnd - initializationStart + 1); initializationEnd - initializationStart + 1);
SingleSegmentBase segmentBase = new SingleSegmentBase(rangedUri, 1, 0, indexStart, SingleSegmentBase segmentBase = new SingleSegmentBase(rangedUri, 1, 0, indexStart,
@ -222,7 +221,7 @@ public abstract class Representation {
* @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<SchemeValuePair> inbandEventStreams, String baseUrl, SingleSegmentBase segmentBase, List<Descriptor> 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);
@ -270,7 +269,7 @@ public abstract class Representation {
* @param inbandEventStreams The in-band event streams 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<SchemeValuePair> inbandEventStreams) { String baseUrl, MultiSegmentBase segmentBase, List<Descriptor> inbandEventStreams) {
super(contentId, revisionId, format, baseUrl, segmentBase, inbandEventStreams); super(contentId, revisionId, format, baseUrl, segmentBase, inbandEventStreams);
this.segmentBase = segmentBase; this.segmentBase = segmentBase;
} }