Handle non-indexed representations.
These may occur in VOD streams where a representation's data is small enough not to require segmentation or an index. For example subtitle files. Issue: #268
This commit is contained in:
parent
d1fe33cdf8
commit
7b9b7c6e3b
@ -451,7 +451,7 @@ public class DashChunkSource implements ChunkSource {
|
||||
DataSpec dataSpec = new DataSpec(segmentUri.getUri(), segmentUri.start, segmentUri.length,
|
||||
representation.getCacheKey());
|
||||
|
||||
long presentationTimeOffsetUs = representation.presentationTimeOffsetMs * 1000;
|
||||
long presentationTimeOffsetUs = representation.presentationTimeOffsetUs;
|
||||
if (representation.format.mimeType.equals(MimeTypes.TEXT_VTT)) {
|
||||
if (representationHolder.vttHeaderOffsetUs != presentationTimeOffsetUs) {
|
||||
// Update the VTT header.
|
||||
|
@ -0,0 +1,60 @@
|
||||
package com.google.android.exoplayer.dash;
|
||||
|
||||
import com.google.android.exoplayer.dash.mpd.RangedUri;
|
||||
|
||||
/**
|
||||
* A {@link DashSegmentIndex} that defines a single segment.
|
||||
*/
|
||||
public class DashSingleSegmentIndex implements DashSegmentIndex {
|
||||
|
||||
private final long startTimeUs;
|
||||
private final long durationUs;
|
||||
private final RangedUri uri;
|
||||
|
||||
/**
|
||||
* @param startTimeUs The start time of the segment, in microseconds.
|
||||
* @param durationUs The duration of the segment, in microseconds.
|
||||
* @param uri A {@link RangedUri} defining the location of the segment data.
|
||||
*/
|
||||
public DashSingleSegmentIndex(long startTimeUs, long durationUs, RangedUri uri) {
|
||||
this.startTimeUs = startTimeUs;
|
||||
this.durationUs = durationUs;
|
||||
this.uri = uri;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSegmentNum(long timeUs) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTimeUs(int segmentNum) {
|
||||
return startTimeUs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDurationUs(int segmentNum) {
|
||||
return durationUs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RangedUri getSegmentUrl(int segmentNum) {
|
||||
return uri;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFirstSegmentNum() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLastSegmentNum() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExplicit() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -305,7 +305,7 @@ public class MediaPresentationDescriptionParser extends DefaultHandler
|
||||
Format format = buildFormat(id, mimeType, width, height, numChannels, audioSamplingRate,
|
||||
bandwidth, language, codecs);
|
||||
return buildRepresentation(periodStartMs, periodDurationMs, contentId, -1, format,
|
||||
segmentBase);
|
||||
segmentBase != null ? segmentBase : new SingleSegmentBase(baseUrl));
|
||||
}
|
||||
|
||||
protected Format buildFormat(String id, String mimeType, int width, int height, int numChannels,
|
||||
|
@ -17,6 +17,7 @@ package com.google.android.exoplayer.dash.mpd;
|
||||
|
||||
import com.google.android.exoplayer.chunk.Format;
|
||||
import com.google.android.exoplayer.dash.DashSegmentIndex;
|
||||
import com.google.android.exoplayer.dash.DashSingleSegmentIndex;
|
||||
import com.google.android.exoplayer.dash.mpd.SegmentBase.MultiSegmentBase;
|
||||
import com.google.android.exoplayer.dash.mpd.SegmentBase.SingleSegmentBase;
|
||||
|
||||
@ -63,7 +64,7 @@ public abstract class Representation {
|
||||
/**
|
||||
* The offset of the presentation timestamps in the media stream relative to media time.
|
||||
*/
|
||||
public final long presentationTimeOffsetMs;
|
||||
public final long presentationTimeOffsetUs;
|
||||
|
||||
private final RangedUri initializationUri;
|
||||
|
||||
@ -101,7 +102,7 @@ public abstract class Representation {
|
||||
this.revisionId = revisionId;
|
||||
this.format = format;
|
||||
initializationUri = segmentBase.getInitialization(this);
|
||||
presentationTimeOffsetMs = (segmentBase.presentationTimeOffset * 1000) / segmentBase.timescale;
|
||||
presentationTimeOffsetUs = segmentBase.getPresentationTimeOffsetUs();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -156,6 +157,7 @@ public abstract class Representation {
|
||||
public final long contentLength;
|
||||
|
||||
private final RangedUri indexUri;
|
||||
private final DashSingleSegmentIndex segmentIndex;
|
||||
|
||||
/**
|
||||
* @param periodStartMs The start time of the enclosing period in milliseconds.
|
||||
@ -198,6 +200,10 @@ public abstract class Representation {
|
||||
this.uri = segmentBase.uri;
|
||||
this.indexUri = segmentBase.getIndex();
|
||||
this.contentLength = contentLength;
|
||||
// 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 DashSingleSegmentIndex(periodStartMs * 1000,
|
||||
periodDurationMs * 1000, new RangedUri(uri, null, 0, -1));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -207,7 +213,7 @@ public abstract class Representation {
|
||||
|
||||
@Override
|
||||
public DashSegmentIndex getIndex() {
|
||||
return null;
|
||||
return segmentIndex;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -56,6 +56,15 @@ public abstract class SegmentBase {
|
||||
return initialization;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the presentation time offset, in microseconds.
|
||||
*
|
||||
* @return The presentation time offset, in microseconds.
|
||||
*/
|
||||
public long getPresentationTimeOffsetUs() {
|
||||
return Util.scaleLargeTimestamp(presentationTimeOffset, C.MICROS_PER_SECOND, timescale);
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link SegmentBase} that defines a single segment.
|
||||
*/
|
||||
@ -87,8 +96,15 @@ public abstract class SegmentBase {
|
||||
this.indexLength = indexLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param uri The uri of the segment.
|
||||
*/
|
||||
public SingleSegmentBase(Uri uri) {
|
||||
this(null, 1, 0, uri, 0, -1);
|
||||
}
|
||||
|
||||
public RangedUri getIndex() {
|
||||
return new RangedUri(uri, null, indexStart, indexLength);
|
||||
return indexLength <= 0 ? null : new RangedUri(uri, null, indexStart, indexLength);
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user