Replace PeriodSeekInfo by static methods.

The inner class was only used to obtain 3 distinct pieces of
information which is better handled by static methods.

#exofixit

PiperOrigin-RevId: 344767661
This commit is contained in:
tonihei 2020-11-30 09:27:31 +00:00 committed by Ian Baker
parent 538445572d
commit 9f6ff55c0f

View file

@ -891,15 +891,12 @@ public final class DashMediaSource extends BaseMediaSource {
Period lastPeriod = manifest.getPeriod(lastPeriodIndex);
long lastPeriodDurationUs = manifest.getPeriodDurationUs(lastPeriodIndex);
long nowUnixTimeUs = C.msToUs(Util.getNowUnixTimeMs(elapsedRealtimeOffsetMs));
PeriodSeekInfo firstPeriodSeekInfo =
PeriodSeekInfo.createPeriodSeekInfo(
manifest.getPeriod(0), manifest.getPeriodDurationUs(0), nowUnixTimeUs);
PeriodSeekInfo lastPeriodSeekInfo =
PeriodSeekInfo.createPeriodSeekInfo(lastPeriod, lastPeriodDurationUs, nowUnixTimeUs);
// Get the period-relative start/end times.
long currentStartTimeUs = firstPeriodSeekInfo.availableStartTimeUs;
long currentEndTimeUs = lastPeriodSeekInfo.availableEndTimeUs;
if (manifest.dynamic && !lastPeriodSeekInfo.isIndexExplicit) {
long currentStartTimeUs =
getAvailableStartTimeUs(
manifest.getPeriod(0), manifest.getPeriodDurationUs(0), nowUnixTimeUs);
long currentEndTimeUs = getAvailableEndTimeUs(lastPeriod, lastPeriodDurationUs, nowUnixTimeUs);
if (manifest.dynamic && !isIndexExplicit(lastPeriod)) {
// 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 liveStreamEndPositionInLastPeriodUs = currentEndTimeUs - C.msToUs(lastPeriod.startMs);
@ -1141,74 +1138,86 @@ public final class DashMediaSource extends BaseMediaSource {
return LongMath.divide(intervalUs, 1000, RoundingMode.CEILING);
}
private static final class PeriodSeekInfo {
public static PeriodSeekInfo createPeriodSeekInfo(
Period period, long periodDurationUs, long nowUnixTimeUs) {
int adaptationSetCount = period.adaptationSets.size();
long availableStartTimeUs = 0;
long availableEndTimeUs = Long.MAX_VALUE;
boolean isIndexExplicit = false;
boolean seenEmptyIndex = false;
boolean haveAudioVideoAdaptationSets = false;
for (int i = 0; i < adaptationSetCount; i++) {
int type = period.adaptationSets.get(i).type;
if (type == C.TRACK_TYPE_AUDIO || type == C.TRACK_TYPE_VIDEO) {
haveAudioVideoAdaptationSets = true;
break;
}
private static long getAvailableStartTimeUs(
Period period, long periodDurationUs, long nowUnixTimeUs) {
long availableStartTimeUs = 0;
boolean haveAudioVideoAdaptationSets = hasVideoOrAudioAdaptationSets(period);
for (int i = 0; i < period.adaptationSets.size(); i++) {
AdaptationSet adaptationSet = period.adaptationSets.get(i);
List<Representation> representations = adaptationSet.representations;
// Exclude text adaptation sets from duration calculations, if we have at least one audio
// or video adaptation set. See: https://github.com/google/ExoPlayer/issues/4029
if ((haveAudioVideoAdaptationSets && adaptationSet.type == C.TRACK_TYPE_TEXT)
|| representations.isEmpty()) {
continue;
}
for (int i = 0; i < adaptationSetCount; i++) {
AdaptationSet adaptationSet = period.adaptationSets.get(i);
List<Representation> representations = adaptationSet.representations;
// Exclude text adaptation sets from duration calculations, if we have at least one audio
// or video adaptation set. See: https://github.com/google/ExoPlayer/issues/4029
if ((haveAudioVideoAdaptationSets && adaptationSet.type == C.TRACK_TYPE_TEXT)
|| representations.isEmpty()) {
continue;
}
@Nullable DashSegmentIndex index = representations.get(0).getIndex();
if (index == null) {
return new PeriodSeekInfo(
/* isIndexExplicit= */ true,
/* availableStartTimeUs= */ 0,
/* availableEndTimeUs= */ periodDurationUs);
}
isIndexExplicit |= index.isExplicit();
int availableSegmentCount = index.getAvailableSegmentCount(periodDurationUs, nowUnixTimeUs);
if (availableSegmentCount == 0) {
seenEmptyIndex = true;
availableStartTimeUs = 0;
availableEndTimeUs = 0;
} else if (!seenEmptyIndex) {
long firstAvailableSegmentNum =
index.getFirstAvailableSegmentNum(periodDurationUs, nowUnixTimeUs);
long adaptationSetAvailableStartTimeUs = index.getTimeUs(firstAvailableSegmentNum);
availableStartTimeUs = max(availableStartTimeUs, adaptationSetAvailableStartTimeUs);
long lastAvailableSegmentNum = firstAvailableSegmentNum + availableSegmentCount - 1;
long adaptationSetAvailableEndTimeUs =
index.getTimeUs(lastAvailableSegmentNum)
+ index.getDurationUs(lastAvailableSegmentNum, periodDurationUs);
availableEndTimeUs = min(availableEndTimeUs, adaptationSetAvailableEndTimeUs);
}
@Nullable DashSegmentIndex index = representations.get(0).getIndex();
if (index == null) {
return 0;
}
return new PeriodSeekInfo(isIndexExplicit, availableStartTimeUs, availableEndTimeUs);
int availableSegmentCount = index.getAvailableSegmentCount(periodDurationUs, nowUnixTimeUs);
if (availableSegmentCount == 0) {
return 0;
}
long firstAvailableSegmentNum =
index.getFirstAvailableSegmentNum(periodDurationUs, nowUnixTimeUs);
long adaptationSetAvailableStartTimeUs = index.getTimeUs(firstAvailableSegmentNum);
availableStartTimeUs = max(availableStartTimeUs, adaptationSetAvailableStartTimeUs);
}
return availableStartTimeUs;
}
public final boolean isIndexExplicit;
public final long availableStartTimeUs;
public final long availableEndTimeUs;
private PeriodSeekInfo(boolean isIndexExplicit, long availableStartTimeUs,
long availableEndTimeUs) {
this.isIndexExplicit = isIndexExplicit;
this.availableStartTimeUs = availableStartTimeUs;
this.availableEndTimeUs = availableEndTimeUs;
private static long getAvailableEndTimeUs(
Period period, long periodDurationUs, long nowUnixTimeUs) {
long availableEndTimeUs = Long.MAX_VALUE;
boolean haveAudioVideoAdaptationSets = hasVideoOrAudioAdaptationSets(period);
for (int i = 0; i < period.adaptationSets.size(); i++) {
AdaptationSet adaptationSet = period.adaptationSets.get(i);
List<Representation> representations = adaptationSet.representations;
// Exclude text adaptation sets from duration calculations, if we have at least one audio
// or video adaptation set. See: https://github.com/google/ExoPlayer/issues/4029
if ((haveAudioVideoAdaptationSets && adaptationSet.type == C.TRACK_TYPE_TEXT)
|| representations.isEmpty()) {
continue;
}
@Nullable DashSegmentIndex index = representations.get(0).getIndex();
if (index == null) {
return periodDurationUs;
}
int availableSegmentCount = index.getAvailableSegmentCount(periodDurationUs, nowUnixTimeUs);
if (availableSegmentCount == 0) {
return 0;
}
long firstAvailableSegmentNum =
index.getFirstAvailableSegmentNum(periodDurationUs, nowUnixTimeUs);
long lastAvailableSegmentNum = firstAvailableSegmentNum + availableSegmentCount - 1;
long adaptationSetAvailableEndTimeUs =
index.getTimeUs(lastAvailableSegmentNum)
+ index.getDurationUs(lastAvailableSegmentNum, periodDurationUs);
availableEndTimeUs = min(availableEndTimeUs, adaptationSetAvailableEndTimeUs);
}
return availableEndTimeUs;
}
private static boolean isIndexExplicit(Period period) {
for (int i = 0; i < period.adaptationSets.size(); i++) {
@Nullable
DashSegmentIndex index = period.adaptationSets.get(i).representations.get(0).getIndex();
if (index == null || index.isExplicit()) {
return true;
}
}
return false;
}
private static boolean hasVideoOrAudioAdaptationSets(Period period) {
for (int i = 0; i < period.adaptationSets.size(); i++) {
int type = period.adaptationSets.get(i).type;
if (type == C.TRACK_TYPE_AUDIO || type == C.TRACK_TYPE_VIDEO) {
return true;
}
}
return false;
}
private static final class DashTimeline extends Timeline {