Fix live window calculation and transition from VOD.
Fix the calculation of the seek window for multi-period DASH. Snap the default initial position back to the start of its segment, to ensure that the first sample provided when transitioning to a DASH live source is a key-frame. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=131052912
This commit is contained in:
parent
458c7bfc05
commit
85915f2ac1
@ -354,22 +354,33 @@ public final class DashMediaSource implements MediaSource {
|
||||
manifest.getPeriodDurationUs(0));
|
||||
PeriodSeekInfo lastPeriodSeekInfo = PeriodSeekInfo.createPeriodSeekInfo(
|
||||
manifest.getPeriod(lastPeriodIndex), manifest.getPeriodDurationUs(lastPeriodIndex));
|
||||
long currentStartTimeUs;
|
||||
long currentEndTimeUs;
|
||||
// Get the period-relative start/end times.
|
||||
long currentStartTimeUs = firstPeriodSeekInfo.availableStartTimeUs;
|
||||
long currentEndTimeUs = lastPeriodSeekInfo.availableEndTimeUs;
|
||||
if (manifest.dynamic && !lastPeriodSeekInfo.isIndexExplicit) {
|
||||
long minStartPositionUs = firstPeriodSeekInfo.availableStartTimeUs;
|
||||
long maxEndPositionUs = lastPeriodSeekInfo.availableEndTimeUs;
|
||||
long timeShiftBufferDepthUs = manifest.timeShiftBufferDepth == C.TIME_UNSET
|
||||
? C.TIME_UNSET : (manifest.timeShiftBufferDepth * 1000);
|
||||
currentEndTimeUs = Math.min(maxEndPositionUs,
|
||||
getNowUnixTimeUs() - manifest.availabilityStartTime * 1000);
|
||||
currentStartTimeUs = timeShiftBufferDepthUs == C.TIME_UNSET ? minStartPositionUs
|
||||
: Math.max(minStartPositionUs, currentEndTimeUs - timeShiftBufferDepthUs);
|
||||
// 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.
|
||||
long liveStreamDurationUs = getNowUnixTimeUs() - manifest.availabilityStartTime * 1000;
|
||||
long liveStreamEndPositionInLastPeriodUs =
|
||||
liveStreamDurationUs - manifest.getPeriod(lastPeriodIndex).startMs * 1000;
|
||||
currentEndTimeUs = Math.min(liveStreamEndPositionInLastPeriodUs, currentEndTimeUs);
|
||||
if (manifest.timeShiftBufferDepth != C.TIME_UNSET) {
|
||||
long timeShiftBufferDepthUs = manifest.timeShiftBufferDepth * 1000;
|
||||
long offsetInPeriodUs = currentEndTimeUs - timeShiftBufferDepthUs;
|
||||
int periodIndex = lastPeriodIndex;
|
||||
while (offsetInPeriodUs < 0 && periodIndex > 0) {
|
||||
offsetInPeriodUs += manifest.getPeriodDurationUs(--periodIndex);
|
||||
}
|
||||
if (periodIndex == 0) {
|
||||
currentStartTimeUs = Math.max(currentStartTimeUs, offsetInPeriodUs);
|
||||
} else {
|
||||
// The time shift buffer starts after the earliest period.
|
||||
// TODO: Does this ever happen?
|
||||
currentStartTimeUs = manifest.getPeriodDurationUs(0);
|
||||
}
|
||||
}
|
||||
// The window is changing implicitly. Post a simulated manifest refresh to update it.
|
||||
handler.postDelayed(simulateManifestRefreshRunnable, NOTIFY_MANIFEST_INTERVAL_MS);
|
||||
} else {
|
||||
currentStartTimeUs = firstPeriodSeekInfo.availableStartTimeUs;
|
||||
currentEndTimeUs = lastPeriodSeekInfo.availableEndTimeUs;
|
||||
}
|
||||
long windowDurationUs = currentEndTimeUs - currentStartTimeUs;
|
||||
for (int i = 0; i < manifest.getPeriodCount() - 1; i++) {
|
||||
@ -382,7 +393,31 @@ public final class DashMediaSource implements MediaSource {
|
||||
liveEdgeOffsetForManifestMs = manifest.suggestedPresentationDelay != C.TIME_UNSET
|
||||
? manifest.suggestedPresentationDelay : DEFAULT_LIVE_EDGE_OFFSET_FIXED_MS;
|
||||
}
|
||||
defaultInitialTimeUs = Math.max(0, windowDurationUs - (liveEdgeOffsetForManifestMs * 1000));
|
||||
// Snap the default position to the start of the segment containing it.
|
||||
long initialTimeOffsetInWindowUs =
|
||||
Math.max(0, windowDurationUs - (liveEdgeOffsetForManifestMs * 1000));
|
||||
int periodIndex = 0;
|
||||
long initialTimeOffsetInPeriodUs = currentStartTimeUs + initialTimeOffsetInWindowUs;
|
||||
long periodDurationUs = manifest.getPeriodDurationUs(periodIndex);
|
||||
while (periodIndex < manifest.getPeriodCount() - 1
|
||||
&& initialTimeOffsetInPeriodUs >= periodDurationUs) {
|
||||
initialTimeOffsetInPeriodUs -= periodDurationUs;
|
||||
periodIndex++;
|
||||
periodDurationUs = manifest.getPeriodDurationUs(periodIndex);
|
||||
}
|
||||
Period period = manifest.getPeriod(periodIndex);
|
||||
int videoAdaptationSetIndex = period.getAdaptationSetIndex(C.TRACK_TYPE_VIDEO);
|
||||
if (videoAdaptationSetIndex != C.INDEX_UNSET) {
|
||||
// If there are multiple video adaptation sets with unaligned segments, the initial time may
|
||||
// not correspond to the start of a segment in both, but this is an edge case.
|
||||
DashSegmentIndex index =
|
||||
period.adaptationSets.get(videoAdaptationSetIndex).representations.get(0).getIndex();
|
||||
int segmentNum = index.getSegmentNum(initialTimeOffsetInPeriodUs, periodDurationUs);
|
||||
defaultInitialTimeUs =
|
||||
initialTimeOffsetInWindowUs - initialTimeOffsetInPeriodUs + index.getTimeUs(segmentNum);
|
||||
} else {
|
||||
defaultInitialTimeUs = initialTimeOffsetInWindowUs;
|
||||
}
|
||||
}
|
||||
window = new MediaWindow(windowDurationUs, true /* isSeekable */, manifest.dynamic,
|
||||
defaultInitialTimeUs);
|
||||
|
@ -186,15 +186,17 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
||||
if (indexUnbounded) {
|
||||
// The index is itself unbounded. We need to use the current time to calculate the range of
|
||||
// available segments.
|
||||
long liveEdgeTimestampUs = nowUs - manifest.availabilityStartTime * 1000;
|
||||
long liveEdgeTimeUs = nowUs - manifest.availabilityStartTime * 1000;
|
||||
long periodStartUs = manifest.getPeriod(periodIndex).startMs * 1000;
|
||||
long liveEdgeTimeInPeriodUs = liveEdgeTimeUs - periodStartUs;
|
||||
if (manifest.timeShiftBufferDepth != C.TIME_UNSET) {
|
||||
long bufferDepthUs = manifest.timeShiftBufferDepth * 1000;
|
||||
firstAvailableSegmentNum = Math.max(firstAvailableSegmentNum,
|
||||
representationHolder.getSegmentNum(liveEdgeTimestampUs - bufferDepthUs));
|
||||
representationHolder.getSegmentNum(liveEdgeTimeInPeriodUs - bufferDepthUs));
|
||||
}
|
||||
// getSegmentNum(liveEdgeTimestampUs) will not be completed yet, so subtract one to get the
|
||||
// index of the last completed segment.
|
||||
lastAvailableSegmentNum = representationHolder.getSegmentNum(liveEdgeTimestampUs) - 1;
|
||||
lastAvailableSegmentNum = representationHolder.getSegmentNum(liveEdgeTimeInPeriodUs) - 1;
|
||||
}
|
||||
|
||||
int segmentNum;
|
||||
|
Loading…
x
Reference in New Issue
Block a user