Commit e0773f70 by olly Committed by Oliver Woodman

Allow applications to specify the live edge offset.

Also allow use of suggestedPresentationDelay taken from the
manifest, and enable this by default.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=130409924
parent 76f7fffb
...@@ -58,22 +58,30 @@ public final class DashMediaSource implements MediaSource { ...@@ -58,22 +58,30 @@ public final class DashMediaSource implements MediaSource {
*/ */
public static final int DEFAULT_MIN_LOADABLE_RETRY_COUNT = 3; public static final int DEFAULT_MIN_LOADABLE_RETRY_COUNT = 3;
/** /**
* A constant indicating that the live edge offset (the offset subtracted from the live edge
* when calculating the default position returned by {@link #getDefaultStartPosition(int)}) should
* be set to {@link DashManifest#suggestedPresentationDelay} if specified by the manifest, or
* {@link #DEFAULT_LIVE_EDGE_OFFSET_FIXED_MS} otherwise.
*/
public static final long DEFAULT_LIVE_EDGE_OFFSET_PREFER_MANIFEST_MS = -1;
/**
* A fixed default live edge offset (the offset subtracted from the live edge when calculating the
* default position returned by {@link #getDefaultStartPosition(int)}).
*/
public static final long DEFAULT_LIVE_EDGE_OFFSET_FIXED_MS = 30000;
/**
* The interval in milliseconds between invocations of * The interval in milliseconds between invocations of
* {@link MediaSource.Listener#onSourceInfoRefreshed(Timeline, Object)} when the source's * {@link MediaSource.Listener#onSourceInfoRefreshed(Timeline, Object)} when the source's
* {@link Window} is changing dynamically (for example, for incomplete live streams). * {@link Window} is changing dynamically (for example, for incomplete live streams).
*/ */
private static final int NOTIFY_MANIFEST_INTERVAL_MS = 5000; private static final int NOTIFY_MANIFEST_INTERVAL_MS = 5000;
/**
* The offset in milliseconds subtracted from the live edge position when calculating the default
* position returned by {@link #getDefaultStartPosition(int)}.
*/
private static final long LIVE_EDGE_OFFSET_MS = 30000;
private static final String TAG = "DashMediaSource"; private static final String TAG = "DashMediaSource";
private final DataSource.Factory manifestDataSourceFactory; private final DataSource.Factory manifestDataSourceFactory;
private final DashChunkSource.Factory chunkSourceFactory; private final DashChunkSource.Factory chunkSourceFactory;
private final int minLoadableRetryCount; private final int minLoadableRetryCount;
private final long liveEdgeOffsetMs;
private final EventDispatcher eventDispatcher; private final EventDispatcher eventDispatcher;
private final DashManifestParser manifestParser; private final DashManifestParser manifestParser;
private final ManifestCallback manifestCallback; private final ManifestCallback manifestCallback;
...@@ -99,16 +107,18 @@ public final class DashMediaSource implements MediaSource { ...@@ -99,16 +107,18 @@ public final class DashMediaSource implements MediaSource {
DashChunkSource.Factory chunkSourceFactory, Handler eventHandler, DashChunkSource.Factory chunkSourceFactory, Handler eventHandler,
AdaptiveMediaSourceEventListener eventListener) { AdaptiveMediaSourceEventListener eventListener) {
this(manifestUri, manifestDataSourceFactory, chunkSourceFactory, this(manifestUri, manifestDataSourceFactory, chunkSourceFactory,
DEFAULT_MIN_LOADABLE_RETRY_COUNT, eventHandler, eventListener); DEFAULT_MIN_LOADABLE_RETRY_COUNT, DEFAULT_LIVE_EDGE_OFFSET_PREFER_MANIFEST_MS, eventHandler,
eventListener);
} }
public DashMediaSource(Uri manifestUri, DataSource.Factory manifestDataSourceFactory, public DashMediaSource(Uri manifestUri, DataSource.Factory manifestDataSourceFactory,
DashChunkSource.Factory chunkSourceFactory, int minLoadableRetryCount, DashChunkSource.Factory chunkSourceFactory, int minLoadableRetryCount, long liveEdgeOffsetMs,
Handler eventHandler, AdaptiveMediaSourceEventListener eventListener) { Handler eventHandler, AdaptiveMediaSourceEventListener eventListener) {
this.manifestUri = manifestUri; this.manifestUri = manifestUri;
this.manifestDataSourceFactory = manifestDataSourceFactory; this.manifestDataSourceFactory = manifestDataSourceFactory;
this.chunkSourceFactory = chunkSourceFactory; this.chunkSourceFactory = chunkSourceFactory;
this.minLoadableRetryCount = minLoadableRetryCount; this.minLoadableRetryCount = minLoadableRetryCount;
this.liveEdgeOffsetMs = liveEdgeOffsetMs;
eventDispatcher = new EventDispatcher(eventHandler, eventListener); eventDispatcher = new EventDispatcher(eventHandler, eventListener);
manifestParser = new DashManifestParser(generateContentId()); manifestParser = new DashManifestParser(generateContentId());
manifestCallback = new ManifestCallback(); manifestCallback = new ManifestCallback();
...@@ -159,7 +169,12 @@ public final class DashMediaSource implements MediaSource { ...@@ -159,7 +169,12 @@ public final class DashMediaSource implements MediaSource {
if (index == 0 && manifest.dynamic) { if (index == 0 && manifest.dynamic) {
// The stream is live, so return a position a position offset from the live edge. // The stream is live, so return a position a position offset from the live edge.
int periodIndex = window.endPeriodIndex; int periodIndex = window.endPeriodIndex;
long positionMs = window.endTimeMs - LIVE_EDGE_OFFSET_MS; long liveEdgeOffsetForManifest = liveEdgeOffsetMs;
if (liveEdgeOffsetForManifest == DEFAULT_LIVE_EDGE_OFFSET_PREFER_MANIFEST_MS) {
liveEdgeOffsetForManifest = manifest.suggestedPresentationDelay != -1
? manifest.suggestedPresentationDelay : DEFAULT_LIVE_EDGE_OFFSET_FIXED_MS;
}
long positionMs = window.endTimeMs - liveEdgeOffsetForManifest;
while (positionMs < 0 && periodIndex > window.startPeriodIndex) { while (positionMs < 0 && periodIndex > window.startPeriodIndex) {
periodIndex--; periodIndex--;
positionMs += manifest.getPeriodDurationMs(periodIndex); positionMs += manifest.getPeriodDurationMs(periodIndex);
......
...@@ -37,6 +37,8 @@ public class DashManifest { ...@@ -37,6 +37,8 @@ public class DashManifest {
public final long timeShiftBufferDepth; public final long timeShiftBufferDepth;
public final long suggestedPresentationDelay;
public final UtcTimingElement utcTiming; public final UtcTimingElement utcTiming;
public final Uri location; public final Uri location;
...@@ -44,14 +46,16 @@ public class DashManifest { ...@@ -44,14 +46,16 @@ public class DashManifest {
private final List<Period> periods; private final List<Period> periods;
public DashManifest(long availabilityStartTime, long duration, long minBufferTime, public DashManifest(long availabilityStartTime, long duration, long minBufferTime,
boolean dynamic, long minUpdatePeriod, long timeShiftBufferDepth, UtcTimingElement utcTiming, boolean dynamic, long minUpdatePeriod, long timeShiftBufferDepth,
Uri location, List<Period> periods) { long suggestedPresentationDelay, UtcTimingElement utcTiming, Uri location,
List<Period> periods) {
this.availabilityStartTime = availabilityStartTime; this.availabilityStartTime = availabilityStartTime;
this.duration = duration; this.duration = duration;
this.minBufferTime = minBufferTime; this.minBufferTime = minBufferTime;
this.dynamic = dynamic; this.dynamic = dynamic;
this.minUpdatePeriod = minUpdatePeriod; this.minUpdatePeriod = minUpdatePeriod;
this.timeShiftBufferDepth = timeShiftBufferDepth; this.timeShiftBufferDepth = timeShiftBufferDepth;
this.suggestedPresentationDelay = suggestedPresentationDelay;
this.utcTiming = utcTiming; this.utcTiming = utcTiming;
this.location = location; this.location = location;
this.periods = periods == null ? Collections.<Period>emptyList() : periods; this.periods = periods == null ? Collections.<Period>emptyList() : periods;
......
...@@ -106,8 +106,10 @@ public class DashManifestParser extends DefaultHandler ...@@ -106,8 +106,10 @@ public class DashManifestParser extends DefaultHandler
long minBufferTimeMs = parseDuration(xpp, "minBufferTime", -1); long minBufferTimeMs = parseDuration(xpp, "minBufferTime", -1);
String typeString = xpp.getAttributeValue(null, "type"); String typeString = xpp.getAttributeValue(null, "type");
boolean dynamic = typeString != null && typeString.equals("dynamic"); boolean dynamic = typeString != null && typeString.equals("dynamic");
long minUpdateTimeMs = (dynamic) ? parseDuration(xpp, "minimumUpdatePeriod", -1) : -1; long minUpdateTimeMs = dynamic ? parseDuration(xpp, "minimumUpdatePeriod", -1) : -1;
long timeShiftBufferDepthMs = (dynamic) ? parseDuration(xpp, "timeShiftBufferDepth", -1) : -1; long timeShiftBufferDepthMs = dynamic ? parseDuration(xpp, "timeShiftBufferDepth", -1) : -1;
long suggestedPresentationDelayMs = dynamic
? parseDuration(xpp, "suggestedPresentationDelay", -1) : -1;
UtcTimingElement utcTiming = null; UtcTimingElement utcTiming = null;
Uri location = null; Uri location = null;
...@@ -159,14 +161,17 @@ public class DashManifestParser extends DefaultHandler ...@@ -159,14 +161,17 @@ public class DashManifestParser extends DefaultHandler
} }
return buildMediaPresentationDescription(availabilityStartTime, durationMs, minBufferTimeMs, return buildMediaPresentationDescription(availabilityStartTime, durationMs, minBufferTimeMs,
dynamic, minUpdateTimeMs, timeShiftBufferDepthMs, utcTiming, location, periods); dynamic, minUpdateTimeMs, timeShiftBufferDepthMs, suggestedPresentationDelayMs, utcTiming,
location, periods);
} }
protected DashManifest buildMediaPresentationDescription(long availabilityStartTime, protected DashManifest buildMediaPresentationDescription(long availabilityStartTime,
long durationMs, long minBufferTimeMs, boolean dynamic, long minUpdateTimeMs, long durationMs, long minBufferTimeMs, boolean dynamic, long minUpdateTimeMs,
long timeShiftBufferDepthMs, UtcTimingElement utcTiming, Uri location, List<Period> periods) { long timeShiftBufferDepthMs, long suggestedPresentationDelayMs, UtcTimingElement utcTiming,
Uri location, List<Period> periods) {
return new DashManifest(availabilityStartTime, durationMs, minBufferTimeMs, return new DashManifest(availabilityStartTime, durationMs, minBufferTimeMs,
dynamic, minUpdateTimeMs, timeShiftBufferDepthMs, utcTiming, location, periods); dynamic, minUpdateTimeMs, timeShiftBufferDepthMs, suggestedPresentationDelayMs, utcTiming,
location, periods);
} }
protected UtcTimingElement parseUtcTiming(XmlPullParser xpp) { protected UtcTimingElement parseUtcTiming(XmlPullParser xpp) {
......
...@@ -743,7 +743,8 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit ...@@ -743,7 +743,8 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit
DefaultDashChunkSource.Factory chunkSourceFactory = new DefaultDashChunkSource.Factory( DefaultDashChunkSource.Factory chunkSourceFactory = new DefaultDashChunkSource.Factory(
mediaDataSourceFactory); mediaDataSourceFactory);
return new DashMediaSource(manifestUri, manifestDataSourceFactory, chunkSourceFactory, return new DashMediaSource(manifestUri, manifestDataSourceFactory, chunkSourceFactory,
MIN_LOADABLE_RETRY_COUNT, null, null); MIN_LOADABLE_RETRY_COUNT, DashMediaSource.DEFAULT_LIVE_EDGE_OFFSET_PREFER_MANIFEST_MS,
null, null);
} }
@Override @Override
......
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