Commit 3c682610 by tonihei Committed by Oliver Woodman

Fix calculation of available duration in DefaultDashChunkSource

The available duration used a "live edge" that was calculated in
the previous iteration and was thus quite old. Also it also used
the end of the last available segment, but the actually available
duration for buffering needs to be clamped to the current live edge
for low-latency streams.

Issue: #4904
PiperOrigin-RevId: 337812621
parent 68cbf6dd
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
*/ */
package com.google.android.exoplayer2.source.dash; package com.google.android.exoplayer2.source.dash;
import static java.lang.Math.max;
import static java.lang.Math.min; import static java.lang.Math.min;
import android.net.Uri; import android.net.Uri;
...@@ -124,9 +125,8 @@ public class DefaultDashChunkSource implements DashChunkSource { ...@@ -124,9 +125,8 @@ public class DefaultDashChunkSource implements DashChunkSource {
private TrackSelection trackSelection; private TrackSelection trackSelection;
private DashManifest manifest; private DashManifest manifest;
private int periodIndex; private int periodIndex;
private IOException fatalError; @Nullable private IOException fatalError;
private boolean missingLastSegment; private boolean missingLastSegment;
private long liveEdgeTimeUs;
/** /**
* @param manifestLoaderErrorThrower Throws errors affecting loading of manifests. * @param manifestLoaderErrorThrower Throws errors affecting loading of manifests.
...@@ -172,7 +172,6 @@ public class DefaultDashChunkSource implements DashChunkSource { ...@@ -172,7 +172,6 @@ public class DefaultDashChunkSource implements DashChunkSource {
this.playerTrackEmsgHandler = playerTrackEmsgHandler; this.playerTrackEmsgHandler = playerTrackEmsgHandler;
long periodDurationUs = manifest.getPeriodDurationUs(periodIndex); long periodDurationUs = manifest.getPeriodDurationUs(periodIndex);
liveEdgeTimeUs = C.TIME_UNSET;
List<Representation> representations = getRepresentations(); List<Representation> representations = getRepresentations();
representationHolders = new RepresentationHolder[trackSelection.length()]; representationHolders = new RepresentationHolder[trackSelection.length()];
...@@ -266,7 +265,6 @@ public class DefaultDashChunkSource implements DashChunkSource { ...@@ -266,7 +265,6 @@ public class DefaultDashChunkSource implements DashChunkSource {
} }
long bufferedDurationUs = loadPositionUs - playbackPositionUs; long bufferedDurationUs = loadPositionUs - playbackPositionUs;
long timeToLiveEdgeUs = resolveTimeToLiveEdgeUs(playbackPositionUs);
long presentationPositionUs = long presentationPositionUs =
C.msToUs(manifest.availabilityStartTimeMs) C.msToUs(manifest.availabilityStartTimeMs)
+ C.msToUs(manifest.getPeriod(periodIndex).startMs) + C.msToUs(manifest.getPeriod(periodIndex).startMs)
...@@ -307,8 +305,9 @@ public class DefaultDashChunkSource implements DashChunkSource { ...@@ -307,8 +305,9 @@ public class DefaultDashChunkSource implements DashChunkSource {
} }
} }
long availableLiveDurationUs = getAvailableLiveDurationUs(nowUnixTimeUs, playbackPositionUs);
trackSelection.updateSelectedTrack( trackSelection.updateSelectedTrack(
playbackPositionUs, bufferedDurationUs, timeToLiveEdgeUs, queue, chunkIterators); playbackPositionUs, bufferedDurationUs, availableLiveDurationUs, queue, chunkIterators);
RepresentationHolder representationHolder = RepresentationHolder representationHolder =
representationHolders[trackSelection.getSelectedIndex()]; representationHolders[trackSelection.getSelectedIndex()];
...@@ -343,9 +342,6 @@ public class DefaultDashChunkSource implements DashChunkSource { ...@@ -343,9 +342,6 @@ public class DefaultDashChunkSource implements DashChunkSource {
long firstAvailableSegmentNum = representationHolder.getFirstAvailableSegmentNum(nowUnixTimeUs); long firstAvailableSegmentNum = representationHolder.getFirstAvailableSegmentNum(nowUnixTimeUs);
long lastAvailableSegmentNum = representationHolder.getLastAvailableSegmentNum(nowUnixTimeUs); long lastAvailableSegmentNum = representationHolder.getLastAvailableSegmentNum(nowUnixTimeUs);
updateLiveEdgeTimeUs(representationHolder, lastAvailableSegmentNum);
long segmentNum = long segmentNum =
getSegmentNum( getSegmentNum(
representationHolder, representationHolder,
...@@ -486,15 +482,17 @@ public class DefaultDashChunkSource implements DashChunkSource { ...@@ -486,15 +482,17 @@ public class DefaultDashChunkSource implements DashChunkSource {
return representations; return representations;
} }
private void updateLiveEdgeTimeUs( private long getAvailableLiveDurationUs(long nowUnixTimeUs, long playbackPositionUs) {
RepresentationHolder representationHolder, long lastAvailableSegmentNum) { if (!manifest.dynamic) {
liveEdgeTimeUs = manifest.dynamic return C.TIME_UNSET;
? representationHolder.getSegmentEndTimeUs(lastAvailableSegmentNum) : C.TIME_UNSET;
} }
long lastSegmentNum = representationHolders[0].getLastAvailableSegmentNum(nowUnixTimeUs);
private long resolveTimeToLiveEdgeUs(long playbackPositionUs) { long lastSegmentEndTimeUs = representationHolders[0].getSegmentEndTimeUs(lastSegmentNum);
boolean resolveTimeToLiveEdgePossible = manifest.dynamic && liveEdgeTimeUs != C.TIME_UNSET; long nowPeriodTimeUs =
return resolveTimeToLiveEdgePossible ? liveEdgeTimeUs - playbackPositionUs : C.TIME_UNSET; nowUnixTimeUs
- C.msToUs(manifest.availabilityStartTimeMs + manifest.getPeriod(periodIndex).startMs);
long availabilityEndTimeUs = min(nowPeriodTimeUs, lastSegmentEndTimeUs);
return max(0, availabilityEndTimeUs - playbackPositionUs);
} }
protected Chunk newInitializationChunk( protected Chunk newInitializationChunk(
......
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