- * A merge is successful if both instances define the same {@link Uri}, and if one starts the byte - * after the other ends, forming a contiguous region with no overlap. + * A merge is successful if both instances define the same {@link Uri} after resolution with the + * base uri, and if one starts the byte after the other ends, forming a contiguous region with + * no overlap. *
* If {@code other} is null then the merge is considered unsuccessful, and null is returned.
*
* @param other The {@link RangedUri} to merge.
+ * @param baseUri The optional base Uri.
* @return The merged {@link RangedUri} if the merge was successful. Null otherwise.
*/
- public RangedUri attemptMerge(RangedUri other) {
- if (other == null || !getUriString().equals(other.getUriString())) {
+ public RangedUri attemptMerge(RangedUri other, String baseUri) {
+ final String resolvedUri = resolveUriString(baseUri);
+ if (other == null || !resolvedUri.equals(other.resolveUriString(baseUri))) {
return null;
} else if (length != C.LENGTH_UNSET && start + length == other.start) {
- return new RangedUri(baseUri, referenceUri, start,
+ return new RangedUri(resolvedUri, start,
other.length == C.LENGTH_UNSET ? C.LENGTH_UNSET : length + other.length);
} else if (other.length != C.LENGTH_UNSET && other.start + other.length == start) {
- return new RangedUri(baseUri, referenceUri, other.start,
+ return new RangedUri(resolvedUri, other.start,
length == C.LENGTH_UNSET ? C.LENGTH_UNSET : other.length + length);
} else {
return null;
@@ -111,7 +106,7 @@ public final class RangedUri {
int result = 17;
result = 31 * result + (int) start;
result = 31 * result + (int) length;
- result = 31 * result + getUriString().hashCode();
+ result = 31 * result + referenceUri.hashCode();
hashCode = result;
}
return hashCode;
@@ -128,7 +123,7 @@ public final class RangedUri {
RangedUri other = (RangedUri) obj;
return this.start == other.start
&& this.length == other.length
- && getUriString().equals(other.getUriString());
+ && referenceUri.equals(other.referenceUri);
}
}
diff --git a/library/src/main/java/com/google/android/exoplayer2/source/dash/manifest/Representation.java b/library/src/main/java/com/google/android/exoplayer2/source/dash/manifest/Representation.java
index 6ebd69e29b..f52727c1a8 100644
--- a/library/src/main/java/com/google/android/exoplayer2/source/dash/manifest/Representation.java
+++ b/library/src/main/java/com/google/android/exoplayer2/source/dash/manifest/Representation.java
@@ -52,6 +52,10 @@ public abstract class Representation {
* The format of the representation.
*/
public final Format format;
+ /**
+ * The base URL of the representation.
+ */
+ public final String baseUrl;
/**
* The offset of the presentation timestamps in the media stream relative to media time.
*/
@@ -65,12 +69,13 @@ public abstract class Representation {
* @param contentId Identifies the piece of content to which this representation belongs.
* @param revisionId Identifies the revision of the content.
* @param format The format of the representation.
+ * @param baseUrl The base URL.
* @param segmentBase A segment base element for the representation.
* @return The constructed instance.
*/
public static Representation newInstance(String contentId, long revisionId, Format format,
- SegmentBase segmentBase) {
- return newInstance(contentId, revisionId, format, segmentBase, null);
+ String baseUrl, SegmentBase segmentBase) {
+ return newInstance(contentId, revisionId, format, baseUrl, segmentBase, null);
}
/**
@@ -79,18 +84,19 @@ public abstract class Representation {
* @param contentId Identifies the piece of content to which this representation belongs.
* @param revisionId Identifies the revision of the content.
* @param format The format of the representation.
+ * @param baseUrl The base URL of the representation.
* @param segmentBase A segment base element for the representation.
* @param customCacheKey A custom value to be returned from {@link #getCacheKey()}, or null. This
* parameter is ignored if {@code segmentBase} consists of multiple segments.
* @return The constructed instance.
*/
public static Representation newInstance(String contentId, long revisionId, Format format,
- SegmentBase segmentBase, String customCacheKey) {
+ String baseUrl, SegmentBase segmentBase, String customCacheKey) {
if (segmentBase instanceof SingleSegmentBase) {
- return new SingleSegmentRepresentation(contentId, revisionId, format,
+ return new SingleSegmentRepresentation(contentId, revisionId, format, baseUrl,
(SingleSegmentBase) segmentBase, customCacheKey, C.LENGTH_UNSET);
} else if (segmentBase instanceof MultiSegmentBase) {
- return new MultiSegmentRepresentation(contentId, revisionId, format,
+ return new MultiSegmentRepresentation(contentId, revisionId, format, baseUrl,
(MultiSegmentBase) segmentBase);
} else {
throw new IllegalArgumentException("segmentBase must be of type SingleSegmentBase or "
@@ -98,11 +104,12 @@ public abstract class Representation {
}
}
- private Representation(String contentId, long revisionId, Format format,
+ private Representation(String contentId, long revisionId, Format format, String baseUrl,
SegmentBase segmentBase) {
this.contentId = contentId;
this.revisionId = revisionId;
this.format = format;
+ this.baseUrl = baseUrl;
initializationUri = segmentBase.getInitialization(this);
presentationTimeOffsetUs = segmentBase.getPresentationTimeOffsetUs();
}
@@ -166,26 +173,27 @@ public abstract class Representation {
public static SingleSegmentRepresentation newInstance(String contentId, long revisionId,
Format format, String uri, long initializationStart, long initializationEnd,
long indexStart, long indexEnd, String customCacheKey, long contentLength) {
- RangedUri rangedUri = new RangedUri(uri, null, initializationStart,
+ RangedUri rangedUri = new RangedUri(null, initializationStart,
initializationEnd - initializationStart + 1);
- SingleSegmentBase segmentBase = new SingleSegmentBase(rangedUri, 1, 0, uri, indexStart,
+ SingleSegmentBase segmentBase = new SingleSegmentBase(rangedUri, 1, 0, indexStart,
indexEnd - indexStart + 1);
return new SingleSegmentRepresentation(contentId, revisionId,
- format, segmentBase, customCacheKey, contentLength);
+ format, uri, segmentBase, customCacheKey, contentLength);
}
/**
* @param contentId Identifies the piece of content to which this representation belongs.
* @param revisionId Identifies the revision of the content.
* @param format The format of the representation.
+ * @param baseUrl The base URL of the representation.
* @param segmentBase The segment base underlying the representation.
* @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.
*/
public SingleSegmentRepresentation(String contentId, long revisionId, Format format,
- SingleSegmentBase segmentBase, String customCacheKey, long contentLength) {
- super(contentId, revisionId, format, segmentBase);
- this.uri = Uri.parse(segmentBase.uri);
+ String baseUrl, SingleSegmentBase segmentBase, String customCacheKey, long contentLength) {
+ super(contentId, revisionId, format, baseUrl, segmentBase);
+ this.uri = Uri.parse(baseUrl);
this.indexUri = segmentBase.getIndex();
this.cacheKey = customCacheKey != null ? customCacheKey
: contentId != null ? contentId + "." + format.id + "." + revisionId : null;
@@ -193,7 +201,7 @@ public abstract class Representation {
// If we have an index uri then the index is defined externally, and we shouldn't return one
// directly. If we don't, then we can't do better than an index defining a single segment.
segmentIndex = indexUri != null ? null
- : new SingleSegmentIndex(new RangedUri(segmentBase.uri, null, 0, contentLength));
+ : new SingleSegmentIndex(new RangedUri(null, 0, contentLength));
}
@Override
@@ -225,11 +233,12 @@ public abstract class Representation {
* @param contentId Identifies the piece of content to which this representation belongs.
* @param revisionId Identifies the revision of the content.
* @param format The format of the representation.
+ * @param baseUrl The base URL of the representation.
* @param segmentBase The segment base underlying the representation.
*/
public MultiSegmentRepresentation(String contentId, long revisionId, Format format,
- MultiSegmentBase segmentBase) {
- super(contentId, revisionId, format, segmentBase);
+ String baseUrl, MultiSegmentBase segmentBase) {
+ super(contentId, revisionId, format, baseUrl, segmentBase);
this.segmentBase = segmentBase;
}
diff --git a/library/src/main/java/com/google/android/exoplayer2/source/dash/manifest/SegmentBase.java b/library/src/main/java/com/google/android/exoplayer2/source/dash/manifest/SegmentBase.java
index dec626c326..966f88e5bc 100644
--- a/library/src/main/java/com/google/android/exoplayer2/source/dash/manifest/SegmentBase.java
+++ b/library/src/main/java/com/google/android/exoplayer2/source/dash/manifest/SegmentBase.java
@@ -65,11 +65,6 @@ public abstract class SegmentBase {
*/
public static class SingleSegmentBase extends SegmentBase {
- /**
- * The uri of the segment.
- */
- public final String uri;
-
/* package */ final long indexStart;
/* package */ final long indexLength;
@@ -79,27 +74,22 @@ public abstract class SegmentBase {
* @param timescale The timescale in units per second.
* @param presentationTimeOffset The presentation time offset. The value in seconds is the
* division of this value and {@code timescale}.
- * @param uri The uri of the segment.
* @param indexStart The byte offset of the index data in the segment.
* @param indexLength The length of the index data in bytes.
*/
public SingleSegmentBase(RangedUri initialization, long timescale, long presentationTimeOffset,
- String uri, long indexStart, long indexLength) {
+ long indexStart, long indexLength) {
super(initialization, timescale, presentationTimeOffset);
- this.uri = uri;
this.indexStart = indexStart;
this.indexLength = indexLength;
}
- /**
- * @param uri The uri of the segment.
- */
public SingleSegmentBase(String uri) {
- this(null, 1, 0, uri, 0, 0);
+ this(null, 1, 0, 0, 0);
}
public RangedUri getIndex() {
- return indexLength <= 0 ? null : new RangedUri(uri, null, indexStart, indexLength);
+ return indexLength <= 0 ? null : new RangedUri(null, indexStart, indexLength);
}
}
@@ -279,8 +269,6 @@ public abstract class SegmentBase {
/* package */ final UrlTemplate initializationTemplate;
/* package */ final UrlTemplate mediaTemplate;
- private final String baseUrl;
-
/**
* @param initialization A {@link RangedUri} corresponding to initialization data, if such data
* exists. The value of this parameter is ignored if {@code initializationTemplate} is
@@ -299,16 +287,14 @@ public abstract class SegmentBase {
* such data exists. If non-null then the {@code initialization} parameter is ignored. If
* null then {@code initialization} will be used.
* @param mediaTemplate A template defining the location of each media segment.
- * @param baseUrl A url to use as the base for relative urls generated by the templates.
*/
public SegmentTemplate(RangedUri initialization, long timescale, long presentationTimeOffset,
int startNumber, long duration, List