mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Add server-client time offset to Window.
This offset allows to improve the calculated live offset because it can take known client-server time offsets into account. PiperOrigin-RevId: 285970738
This commit is contained in:
parent
a035c2e20a
commit
021291b38f
12 changed files with 77 additions and 30 deletions
|
|
@ -130,6 +130,7 @@ import java.util.Arrays;
|
||||||
/* manifest= */ null,
|
/* manifest= */ null,
|
||||||
/* presentationStartTimeMs= */ C.TIME_UNSET,
|
/* presentationStartTimeMs= */ C.TIME_UNSET,
|
||||||
/* windowStartTimeMs= */ C.TIME_UNSET,
|
/* windowStartTimeMs= */ C.TIME_UNSET,
|
||||||
|
/* elapsedRealtimeEpochOffsetMs= */ C.TIME_UNSET,
|
||||||
/* isSeekable= */ !isDynamic,
|
/* isSeekable= */ !isDynamic,
|
||||||
isDynamic,
|
isDynamic,
|
||||||
isLive[windowIndex],
|
isLive[windowIndex],
|
||||||
|
|
|
||||||
|
|
@ -153,7 +153,7 @@ public abstract class BasePlayer implements Player {
|
||||||
if (windowStartTimeMs == C.TIME_UNSET) {
|
if (windowStartTimeMs == C.TIME_UNSET) {
|
||||||
return C.TIME_UNSET;
|
return C.TIME_UNSET;
|
||||||
}
|
}
|
||||||
return System.currentTimeMillis() - window.windowStartTimeMs - getContentPosition();
|
return window.getCurrentUnixTimeMs() - window.windowStartTimeMs - getContentPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2;
|
package com.google.android.exoplayer2;
|
||||||
|
|
||||||
|
import android.os.SystemClock;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import com.google.android.exoplayer2.source.ads.AdPlaybackState;
|
import com.google.android.exoplayer2.source.ads.AdPlaybackState;
|
||||||
|
|
@ -136,19 +137,28 @@ public abstract class Timeline {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The start time of the presentation to which this window belongs in milliseconds since the
|
* The start time of the presentation to which this window belongs in milliseconds since the
|
||||||
* epoch, or {@link C#TIME_UNSET} if unknown or not applicable. For informational purposes only.
|
* Unix epoch, or {@link C#TIME_UNSET} if unknown or not applicable. For informational purposes
|
||||||
|
* only.
|
||||||
*/
|
*/
|
||||||
public long presentationStartTimeMs;
|
public long presentationStartTimeMs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The window's start time in milliseconds since the epoch, or {@link C#TIME_UNSET} if unknown
|
* The window's start time in milliseconds since the Unix epoch, or {@link C#TIME_UNSET} if
|
||||||
* or not applicable. For informational purposes only.
|
* unknown or not applicable. For informational purposes only.
|
||||||
*/
|
*/
|
||||||
public long windowStartTimeMs;
|
public long windowStartTimeMs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether it's possible to seek within this window.
|
* The offset between {@link SystemClock#elapsedRealtime()} and the time since the Unix epoch
|
||||||
|
* according to the clock of the media origin server, or {@link C#TIME_UNSET} if unknown or not
|
||||||
|
* applicable.
|
||||||
|
*
|
||||||
|
* <p>Note that the current Unix time can be retrieved using {@link #getCurrentUnixTimeMs()} and
|
||||||
|
* is calculated as {@code SystemClock.elapsedRealtime() + elapsedRealtimeEpochOffsetMs}.
|
||||||
*/
|
*/
|
||||||
|
public long elapsedRealtimeEpochOffsetMs;
|
||||||
|
|
||||||
|
/** Whether it's possible to seek within this window. */
|
||||||
public boolean isSeekable;
|
public boolean isSeekable;
|
||||||
|
|
||||||
// TODO: Split this to better describe which parts of the window might change. For example it
|
// TODO: Split this to better describe which parts of the window might change. For example it
|
||||||
|
|
@ -205,6 +215,7 @@ public abstract class Timeline {
|
||||||
@Nullable Object manifest,
|
@Nullable Object manifest,
|
||||||
long presentationStartTimeMs,
|
long presentationStartTimeMs,
|
||||||
long windowStartTimeMs,
|
long windowStartTimeMs,
|
||||||
|
long elapsedRealtimeEpochOffsetMs,
|
||||||
boolean isSeekable,
|
boolean isSeekable,
|
||||||
boolean isDynamic,
|
boolean isDynamic,
|
||||||
boolean isLive,
|
boolean isLive,
|
||||||
|
|
@ -218,6 +229,7 @@ public abstract class Timeline {
|
||||||
this.manifest = manifest;
|
this.manifest = manifest;
|
||||||
this.presentationStartTimeMs = presentationStartTimeMs;
|
this.presentationStartTimeMs = presentationStartTimeMs;
|
||||||
this.windowStartTimeMs = windowStartTimeMs;
|
this.windowStartTimeMs = windowStartTimeMs;
|
||||||
|
this.elapsedRealtimeEpochOffsetMs = elapsedRealtimeEpochOffsetMs;
|
||||||
this.isSeekable = isSeekable;
|
this.isSeekable = isSeekable;
|
||||||
this.isDynamic = isDynamic;
|
this.isDynamic = isDynamic;
|
||||||
this.isLive = isLive;
|
this.isLive = isLive;
|
||||||
|
|
@ -279,6 +291,16 @@ public abstract class Timeline {
|
||||||
return positionInFirstPeriodUs;
|
return positionInFirstPeriodUs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current time in milliseconds since the Unix epoch.
|
||||||
|
*
|
||||||
|
* <p>This method applies {@link #elapsedRealtimeEpochOffsetMs known corrections} made available
|
||||||
|
* by the media such that this time corresponds to the clock of the media origin server.
|
||||||
|
*/
|
||||||
|
public long getCurrentUnixTimeMs() {
|
||||||
|
return Util.getNowUnixTimeMs(elapsedRealtimeEpochOffsetMs);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(@Nullable Object obj) {
|
public boolean equals(@Nullable Object obj) {
|
||||||
if (this == obj) {
|
if (this == obj) {
|
||||||
|
|
@ -293,6 +315,7 @@ public abstract class Timeline {
|
||||||
&& Util.areEqual(manifest, that.manifest)
|
&& Util.areEqual(manifest, that.manifest)
|
||||||
&& presentationStartTimeMs == that.presentationStartTimeMs
|
&& presentationStartTimeMs == that.presentationStartTimeMs
|
||||||
&& windowStartTimeMs == that.windowStartTimeMs
|
&& windowStartTimeMs == that.windowStartTimeMs
|
||||||
|
&& elapsedRealtimeEpochOffsetMs == that.elapsedRealtimeEpochOffsetMs
|
||||||
&& isSeekable == that.isSeekable
|
&& isSeekable == that.isSeekable
|
||||||
&& isDynamic == that.isDynamic
|
&& isDynamic == that.isDynamic
|
||||||
&& isLive == that.isLive
|
&& isLive == that.isLive
|
||||||
|
|
@ -311,6 +334,9 @@ public abstract class Timeline {
|
||||||
result = 31 * result + (manifest == null ? 0 : manifest.hashCode());
|
result = 31 * result + (manifest == null ? 0 : manifest.hashCode());
|
||||||
result = 31 * result + (int) (presentationStartTimeMs ^ (presentationStartTimeMs >>> 32));
|
result = 31 * result + (int) (presentationStartTimeMs ^ (presentationStartTimeMs >>> 32));
|
||||||
result = 31 * result + (int) (windowStartTimeMs ^ (windowStartTimeMs >>> 32));
|
result = 31 * result + (int) (windowStartTimeMs ^ (windowStartTimeMs >>> 32));
|
||||||
|
result =
|
||||||
|
31 * result
|
||||||
|
+ (int) (elapsedRealtimeEpochOffsetMs ^ (elapsedRealtimeEpochOffsetMs >>> 32));
|
||||||
result = 31 * result + (isSeekable ? 1 : 0);
|
result = 31 * result + (isSeekable ? 1 : 0);
|
||||||
result = 31 * result + (isDynamic ? 1 : 0);
|
result = 31 * result + (isDynamic ? 1 : 0);
|
||||||
result = 31 * result + (isLive ? 1 : 0);
|
result = 31 * result + (isLive ? 1 : 0);
|
||||||
|
|
|
||||||
|
|
@ -337,6 +337,7 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> {
|
||||||
/* manifest= */ null,
|
/* manifest= */ null,
|
||||||
/* presentationStartTimeMs= */ C.TIME_UNSET,
|
/* presentationStartTimeMs= */ C.TIME_UNSET,
|
||||||
/* windowStartTimeMs= */ C.TIME_UNSET,
|
/* windowStartTimeMs= */ C.TIME_UNSET,
|
||||||
|
/* elapsedRealtimeEpochOffsetMs= */ C.TIME_UNSET,
|
||||||
/* isSeekable= */ false,
|
/* isSeekable= */ false,
|
||||||
// Dynamic window to indicate pending timeline updates.
|
// Dynamic window to indicate pending timeline updates.
|
||||||
/* isDynamic= */ true,
|
/* isDynamic= */ true,
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ public final class SinglePeriodTimeline extends Timeline {
|
||||||
|
|
||||||
private final long presentationStartTimeMs;
|
private final long presentationStartTimeMs;
|
||||||
private final long windowStartTimeMs;
|
private final long windowStartTimeMs;
|
||||||
|
private final long elapsedRealtimeEpochOffsetMs;
|
||||||
private final long periodDurationUs;
|
private final long periodDurationUs;
|
||||||
private final long windowDurationUs;
|
private final long windowDurationUs;
|
||||||
private final long windowPositionInPeriodUs;
|
private final long windowPositionInPeriodUs;
|
||||||
|
|
@ -110,6 +111,7 @@ public final class SinglePeriodTimeline extends Timeline {
|
||||||
this(
|
this(
|
||||||
/* presentationStartTimeMs= */ C.TIME_UNSET,
|
/* presentationStartTimeMs= */ C.TIME_UNSET,
|
||||||
/* windowStartTimeMs= */ C.TIME_UNSET,
|
/* windowStartTimeMs= */ C.TIME_UNSET,
|
||||||
|
/* elapsedRealtimeEpochOffsetMs= */ C.TIME_UNSET,
|
||||||
periodDurationUs,
|
periodDurationUs,
|
||||||
windowDurationUs,
|
windowDurationUs,
|
||||||
windowPositionInPeriodUs,
|
windowPositionInPeriodUs,
|
||||||
|
|
@ -126,8 +128,12 @@ public final class SinglePeriodTimeline extends Timeline {
|
||||||
* position in the period.
|
* position in the period.
|
||||||
*
|
*
|
||||||
* @param presentationStartTimeMs The start time of the presentation in milliseconds since the
|
* @param presentationStartTimeMs The start time of the presentation in milliseconds since the
|
||||||
* epoch.
|
* epoch, or {@link C#TIME_UNSET} if unknown or not applicable.
|
||||||
* @param windowStartTimeMs The window's start time in milliseconds since the epoch.
|
* @param windowStartTimeMs The window's start time in milliseconds since the epoch, or {@link
|
||||||
|
* C#TIME_UNSET} if unknown or not applicable.
|
||||||
|
* @param elapsedRealtimeEpochOffsetMs The offset between {@link
|
||||||
|
* android.os.SystemClock#elapsedRealtime()} and the time since the Unix epoch according to
|
||||||
|
* the clock of the media origin server, or {@link C#TIME_UNSET} if unknown or not applicable.
|
||||||
* @param periodDurationUs The duration of the period in microseconds.
|
* @param periodDurationUs The duration of the period in microseconds.
|
||||||
* @param windowDurationUs The duration of the window in microseconds.
|
* @param windowDurationUs The duration of the window in microseconds.
|
||||||
* @param windowPositionInPeriodUs The position of the start of the window in the period, in
|
* @param windowPositionInPeriodUs The position of the start of the window in the period, in
|
||||||
|
|
@ -143,6 +149,7 @@ public final class SinglePeriodTimeline extends Timeline {
|
||||||
public SinglePeriodTimeline(
|
public SinglePeriodTimeline(
|
||||||
long presentationStartTimeMs,
|
long presentationStartTimeMs,
|
||||||
long windowStartTimeMs,
|
long windowStartTimeMs,
|
||||||
|
long elapsedRealtimeEpochOffsetMs,
|
||||||
long periodDurationUs,
|
long periodDurationUs,
|
||||||
long windowDurationUs,
|
long windowDurationUs,
|
||||||
long windowPositionInPeriodUs,
|
long windowPositionInPeriodUs,
|
||||||
|
|
@ -154,6 +161,7 @@ public final class SinglePeriodTimeline extends Timeline {
|
||||||
@Nullable Object tag) {
|
@Nullable Object tag) {
|
||||||
this.presentationStartTimeMs = presentationStartTimeMs;
|
this.presentationStartTimeMs = presentationStartTimeMs;
|
||||||
this.windowStartTimeMs = windowStartTimeMs;
|
this.windowStartTimeMs = windowStartTimeMs;
|
||||||
|
this.elapsedRealtimeEpochOffsetMs = elapsedRealtimeEpochOffsetMs;
|
||||||
this.periodDurationUs = periodDurationUs;
|
this.periodDurationUs = periodDurationUs;
|
||||||
this.windowDurationUs = windowDurationUs;
|
this.windowDurationUs = windowDurationUs;
|
||||||
this.windowPositionInPeriodUs = windowPositionInPeriodUs;
|
this.windowPositionInPeriodUs = windowPositionInPeriodUs;
|
||||||
|
|
@ -192,13 +200,14 @@ public final class SinglePeriodTimeline extends Timeline {
|
||||||
manifest,
|
manifest,
|
||||||
presentationStartTimeMs,
|
presentationStartTimeMs,
|
||||||
windowStartTimeMs,
|
windowStartTimeMs,
|
||||||
|
elapsedRealtimeEpochOffsetMs,
|
||||||
isSeekable,
|
isSeekable,
|
||||||
isDynamic,
|
isDynamic,
|
||||||
isLive,
|
isLive,
|
||||||
windowDefaultStartPositionUs,
|
windowDefaultStartPositionUs,
|
||||||
windowDurationUs,
|
windowDurationUs,
|
||||||
0,
|
/* firstPeriodIndex= */ 0,
|
||||||
0,
|
/* lastPeriodIndex= */ 0,
|
||||||
windowPositionInPeriodUs);
|
windowPositionInPeriodUs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ import android.os.Build;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
|
import android.os.SystemClock;
|
||||||
import android.security.NetworkSecurityPolicy;
|
import android.security.NetworkSecurityPolicy;
|
||||||
import android.telephony.TelephonyManager;
|
import android.telephony.TelephonyManager;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
@ -2045,6 +2046,19 @@ public final class Util {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current time in milliseconds since the epoch.
|
||||||
|
*
|
||||||
|
* @param elapsedRealtimeEpochOffsetMs The offset between {@link SystemClock#elapsedRealtime()}
|
||||||
|
* and the time since the Unix epoch, or {@link C#TIME_UNSET} if unknown.
|
||||||
|
* @return The Unix time in milliseconds since the epoch.
|
||||||
|
*/
|
||||||
|
public static long getNowUnixTimeMs(long elapsedRealtimeEpochOffsetMs) {
|
||||||
|
return elapsedRealtimeEpochOffsetMs == C.TIME_UNSET
|
||||||
|
? System.currentTimeMillis()
|
||||||
|
: SystemClock.elapsedRealtime() + elapsedRealtimeEpochOffsetMs;
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private static String getSystemProperty(String name) {
|
private static String getSystemProperty(String name) {
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -134,6 +134,7 @@ public class TimelineTest {
|
||||||
window.manifest,
|
window.manifest,
|
||||||
window.presentationStartTimeMs,
|
window.presentationStartTimeMs,
|
||||||
window.windowStartTimeMs,
|
window.windowStartTimeMs,
|
||||||
|
window.elapsedRealtimeEpochOffsetMs,
|
||||||
window.isSeekable,
|
window.isSeekable,
|
||||||
window.isDynamic,
|
window.isDynamic,
|
||||||
window.isLive,
|
window.isLive,
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,8 @@ public interface DashChunkSource extends ChunkSource {
|
||||||
* @param trackSelection The track selection.
|
* @param trackSelection The track selection.
|
||||||
* @param elapsedRealtimeOffsetMs If known, an estimate of the instantaneous difference between
|
* @param elapsedRealtimeOffsetMs If known, an estimate of the instantaneous difference between
|
||||||
* server-side unix time and {@link SystemClock#elapsedRealtime()} in milliseconds,
|
* server-side unix time and {@link SystemClock#elapsedRealtime()} in milliseconds,
|
||||||
* specified as the server's unix time minus the local elapsed time. If unknown, set to 0.
|
* specified as the server's unix time minus the local elapsed time. Or {@link
|
||||||
|
* com.google.android.exoplayer2.C#TIME_UNSET} if unknown.
|
||||||
* @param enableEventMessageTrack Whether to output an event message track.
|
* @param enableEventMessageTrack Whether to output an event message track.
|
||||||
* @param closedCaptionFormats The {@link Format Formats} of closed caption tracks to be output.
|
* @param closedCaptionFormats The {@link Format Formats} of closed caption tracks to be output.
|
||||||
* @param transferListener The transfer listener which should be informed of any data transfers.
|
* @param transferListener The transfer listener which should be informed of any data transfers.
|
||||||
|
|
|
||||||
|
|
@ -621,6 +621,7 @@ public final class DashMediaSource extends BaseMediaSource {
|
||||||
periodsById = new SparseArray<>();
|
periodsById = new SparseArray<>();
|
||||||
playerEmsgCallback = new DefaultPlayerEmsgCallback();
|
playerEmsgCallback = new DefaultPlayerEmsgCallback();
|
||||||
expiredManifestPublishTimeUs = C.TIME_UNSET;
|
expiredManifestPublishTimeUs = C.TIME_UNSET;
|
||||||
|
elapsedRealtimeOffsetMs = C.TIME_UNSET;
|
||||||
if (sideloadedManifest) {
|
if (sideloadedManifest) {
|
||||||
Assertions.checkState(!manifest.dynamic);
|
Assertions.checkState(!manifest.dynamic);
|
||||||
manifestCallback = null;
|
manifestCallback = null;
|
||||||
|
|
@ -723,7 +724,7 @@ public final class DashMediaSource extends BaseMediaSource {
|
||||||
handler.removeCallbacksAndMessages(null);
|
handler.removeCallbacksAndMessages(null);
|
||||||
handler = null;
|
handler = null;
|
||||||
}
|
}
|
||||||
elapsedRealtimeOffsetMs = 0;
|
elapsedRealtimeOffsetMs = C.TIME_UNSET;
|
||||||
staleManifestReloadAttempt = 0;
|
staleManifestReloadAttempt = 0;
|
||||||
expiredManifestPublishTimeUs = C.TIME_UNSET;
|
expiredManifestPublishTimeUs = C.TIME_UNSET;
|
||||||
firstPeriodId = 0;
|
firstPeriodId = 0;
|
||||||
|
|
@ -969,7 +970,8 @@ public final class DashMediaSource extends BaseMediaSource {
|
||||||
if (manifest.dynamic && !lastPeriodSeekInfo.isIndexExplicit) {
|
if (manifest.dynamic && !lastPeriodSeekInfo.isIndexExplicit) {
|
||||||
// The manifest describes an incomplete live stream. Update the start/end times to reflect the
|
// The manifest describes an incomplete live stream. Update the start/end times to reflect the
|
||||||
// live stream duration and the manifest's time shift buffer depth.
|
// live stream duration and the manifest's time shift buffer depth.
|
||||||
long liveStreamDurationUs = getNowUnixTimeUs() - C.msToUs(manifest.availabilityStartTimeMs);
|
long nowUnixTimeUs = C.msToUs(Util.getNowUnixTimeMs(elapsedRealtimeOffsetMs));
|
||||||
|
long liveStreamDurationUs = nowUnixTimeUs - C.msToUs(manifest.availabilityStartTimeMs);
|
||||||
long liveStreamEndPositionInLastPeriodUs = liveStreamDurationUs
|
long liveStreamEndPositionInLastPeriodUs = liveStreamDurationUs
|
||||||
- C.msToUs(manifest.getPeriod(lastPeriodIndex).startMs);
|
- C.msToUs(manifest.getPeriod(lastPeriodIndex).startMs);
|
||||||
currentEndTimeUs = Math.min(liveStreamEndPositionInLastPeriodUs, currentEndTimeUs);
|
currentEndTimeUs = Math.min(liveStreamEndPositionInLastPeriodUs, currentEndTimeUs);
|
||||||
|
|
@ -1022,6 +1024,7 @@ public final class DashMediaSource extends BaseMediaSource {
|
||||||
new DashTimeline(
|
new DashTimeline(
|
||||||
manifest.availabilityStartTimeMs,
|
manifest.availabilityStartTimeMs,
|
||||||
windowStartTimeMs,
|
windowStartTimeMs,
|
||||||
|
elapsedRealtimeOffsetMs,
|
||||||
firstPeriodId,
|
firstPeriodId,
|
||||||
currentStartTimeUs,
|
currentStartTimeUs,
|
||||||
windowDurationUs,
|
windowDurationUs,
|
||||||
|
|
@ -1093,14 +1096,6 @@ public final class DashMediaSource extends BaseMediaSource {
|
||||||
manifestEventDispatcher.loadStarted(loadable.dataSpec, loadable.type, elapsedRealtimeMs);
|
manifestEventDispatcher.loadStarted(loadable.dataSpec, loadable.type, elapsedRealtimeMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
private long getNowUnixTimeUs() {
|
|
||||||
if (elapsedRealtimeOffsetMs != 0) {
|
|
||||||
return C.msToUs(SystemClock.elapsedRealtime() + elapsedRealtimeOffsetMs);
|
|
||||||
} else {
|
|
||||||
return C.msToUs(System.currentTimeMillis());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class PeriodSeekInfo {
|
private static final class PeriodSeekInfo {
|
||||||
|
|
||||||
public static PeriodSeekInfo createPeriodSeekInfo(
|
public static PeriodSeekInfo createPeriodSeekInfo(
|
||||||
|
|
@ -1170,6 +1165,7 @@ public final class DashMediaSource extends BaseMediaSource {
|
||||||
|
|
||||||
private final long presentationStartTimeMs;
|
private final long presentationStartTimeMs;
|
||||||
private final long windowStartTimeMs;
|
private final long windowStartTimeMs;
|
||||||
|
private final long elapsedRealtimeEpochOffsetMs;
|
||||||
|
|
||||||
private final int firstPeriodId;
|
private final int firstPeriodId;
|
||||||
private final long offsetInFirstPeriodUs;
|
private final long offsetInFirstPeriodUs;
|
||||||
|
|
@ -1181,6 +1177,7 @@ public final class DashMediaSource extends BaseMediaSource {
|
||||||
public DashTimeline(
|
public DashTimeline(
|
||||||
long presentationStartTimeMs,
|
long presentationStartTimeMs,
|
||||||
long windowStartTimeMs,
|
long windowStartTimeMs,
|
||||||
|
long elapsedRealtimeEpochOffsetMs,
|
||||||
int firstPeriodId,
|
int firstPeriodId,
|
||||||
long offsetInFirstPeriodUs,
|
long offsetInFirstPeriodUs,
|
||||||
long windowDurationUs,
|
long windowDurationUs,
|
||||||
|
|
@ -1189,6 +1186,7 @@ public final class DashMediaSource extends BaseMediaSource {
|
||||||
@Nullable Object windowTag) {
|
@Nullable Object windowTag) {
|
||||||
this.presentationStartTimeMs = presentationStartTimeMs;
|
this.presentationStartTimeMs = presentationStartTimeMs;
|
||||||
this.windowStartTimeMs = windowStartTimeMs;
|
this.windowStartTimeMs = windowStartTimeMs;
|
||||||
|
this.elapsedRealtimeEpochOffsetMs = elapsedRealtimeEpochOffsetMs;
|
||||||
this.firstPeriodId = firstPeriodId;
|
this.firstPeriodId = firstPeriodId;
|
||||||
this.offsetInFirstPeriodUs = offsetInFirstPeriodUs;
|
this.offsetInFirstPeriodUs = offsetInFirstPeriodUs;
|
||||||
this.windowDurationUs = windowDurationUs;
|
this.windowDurationUs = windowDurationUs;
|
||||||
|
|
@ -1228,6 +1226,7 @@ public final class DashMediaSource extends BaseMediaSource {
|
||||||
manifest,
|
manifest,
|
||||||
presentationStartTimeMs,
|
presentationStartTimeMs,
|
||||||
windowStartTimeMs,
|
windowStartTimeMs,
|
||||||
|
elapsedRealtimeEpochOffsetMs,
|
||||||
/* isSeekable= */ true,
|
/* isSeekable= */ true,
|
||||||
/* isDynamic= */ isMovingLiveWindow(manifest),
|
/* isDynamic= */ isMovingLiveWindow(manifest),
|
||||||
/* isLive= */ manifest.dynamic,
|
/* isLive= */ manifest.dynamic,
|
||||||
|
|
|
||||||
|
|
@ -136,7 +136,7 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
||||||
* @param dataSource A {@link DataSource} suitable for loading the media data.
|
* @param dataSource A {@link DataSource} suitable for loading the media data.
|
||||||
* @param elapsedRealtimeOffsetMs If known, an estimate of the instantaneous difference between
|
* @param elapsedRealtimeOffsetMs If known, an estimate of the instantaneous difference between
|
||||||
* server-side unix time and {@link SystemClock#elapsedRealtime()} in milliseconds, specified
|
* server-side unix time and {@link SystemClock#elapsedRealtime()} in milliseconds, specified
|
||||||
* as the server's unix time minus the local elapsed time. If unknown, set to 0.
|
* as the server's unix time minus the local elapsed time. Or {@link C#TIME_UNSET} if unknown.
|
||||||
* @param maxSegmentsPerLoad The maximum number of segments to combine into a single request. Note
|
* @param maxSegmentsPerLoad The maximum number of segments to combine into a single request. Note
|
||||||
* that segments will only be combined if their {@link Uri}s are the same and if their data
|
* that segments will only be combined if their {@link Uri}s are the same and if their data
|
||||||
* ranges are adjacent.
|
* ranges are adjacent.
|
||||||
|
|
@ -267,7 +267,7 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
long nowUnixTimeUs = getNowUnixTimeUs();
|
long nowUnixTimeUs = C.msToUs(Util.getNowUnixTimeMs(elapsedRealtimeOffsetMs));
|
||||||
MediaChunk previous = queue.isEmpty() ? null : queue.get(queue.size() - 1);
|
MediaChunk previous = queue.isEmpty() ? null : queue.get(queue.size() - 1);
|
||||||
MediaChunkIterator[] chunkIterators = new MediaChunkIterator[trackSelection.length()];
|
MediaChunkIterator[] chunkIterators = new MediaChunkIterator[trackSelection.length()];
|
||||||
for (int i = 0; i < chunkIterators.length; i++) {
|
for (int i = 0; i < chunkIterators.length; i++) {
|
||||||
|
|
@ -474,14 +474,6 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
||||||
? representationHolder.getSegmentEndTimeUs(lastAvailableSegmentNum) : C.TIME_UNSET;
|
? representationHolder.getSegmentEndTimeUs(lastAvailableSegmentNum) : C.TIME_UNSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
private long getNowUnixTimeUs() {
|
|
||||||
if (elapsedRealtimeOffsetMs != 0) {
|
|
||||||
return (SystemClock.elapsedRealtime() + elapsedRealtimeOffsetMs) * 1000;
|
|
||||||
} else {
|
|
||||||
return System.currentTimeMillis() * 1000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private long resolveTimeToLiveEdgeUs(long playbackPositionUs) {
|
private long resolveTimeToLiveEdgeUs(long playbackPositionUs) {
|
||||||
boolean resolveTimeToLiveEdgePossible = manifest.dynamic && liveEdgeTimeUs != C.TIME_UNSET;
|
boolean resolveTimeToLiveEdgePossible = manifest.dynamic && liveEdgeTimeUs != C.TIME_UNSET;
|
||||||
return resolveTimeToLiveEdgePossible ? liveEdgeTimeUs - playbackPositionUs : C.TIME_UNSET;
|
return resolveTimeToLiveEdgePossible ? liveEdgeTimeUs - playbackPositionUs : C.TIME_UNSET;
|
||||||
|
|
|
||||||
|
|
@ -468,6 +468,7 @@ public final class HlsMediaSource extends BaseMediaSource
|
||||||
new SinglePeriodTimeline(
|
new SinglePeriodTimeline(
|
||||||
presentationStartTimeMs,
|
presentationStartTimeMs,
|
||||||
windowStartTimeMs,
|
windowStartTimeMs,
|
||||||
|
/* elapsedRealtimeEpochOffsetMs= */ C.TIME_UNSET,
|
||||||
periodDurationUs,
|
periodDurationUs,
|
||||||
/* windowDurationUs= */ playlist.durationUs,
|
/* windowDurationUs= */ playlist.durationUs,
|
||||||
/* windowPositionInPeriodUs= */ offsetFromInitialStartTimeUs,
|
/* windowPositionInPeriodUs= */ offsetFromInitialStartTimeUs,
|
||||||
|
|
@ -485,6 +486,7 @@ public final class HlsMediaSource extends BaseMediaSource
|
||||||
new SinglePeriodTimeline(
|
new SinglePeriodTimeline(
|
||||||
presentationStartTimeMs,
|
presentationStartTimeMs,
|
||||||
windowStartTimeMs,
|
windowStartTimeMs,
|
||||||
|
/* elapsedRealtimeEpochOffsetMs= */ C.TIME_UNSET,
|
||||||
/* periodDurationUs= */ playlist.durationUs,
|
/* periodDurationUs= */ playlist.durationUs,
|
||||||
/* windowDurationUs= */ playlist.durationUs,
|
/* windowDurationUs= */ playlist.durationUs,
|
||||||
/* windowPositionInPeriodUs= */ 0,
|
/* windowPositionInPeriodUs= */ 0,
|
||||||
|
|
|
||||||
|
|
@ -219,6 +219,7 @@ public final class FakeTimeline extends Timeline {
|
||||||
manifests[windowIndex],
|
manifests[windowIndex],
|
||||||
/* presentationStartTimeMs= */ C.TIME_UNSET,
|
/* presentationStartTimeMs= */ C.TIME_UNSET,
|
||||||
/* windowStartTimeMs= */ C.TIME_UNSET,
|
/* windowStartTimeMs= */ C.TIME_UNSET,
|
||||||
|
/* elapsedRealtimeEpochOffsetMs= */ C.TIME_UNSET,
|
||||||
windowDefinition.isSeekable,
|
windowDefinition.isSeekable,
|
||||||
windowDefinition.isDynamic,
|
windowDefinition.isDynamic,
|
||||||
windowDefinition.isLive,
|
windowDefinition.isLive,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue