Add nullness annotations to DefaultDashChunkSource

#fixit

PiperOrigin-RevId: 559405572
This commit is contained in:
rohks 2023-08-23 14:27:43 +01:00 committed by Ian Baker
parent 2ad37d2e37
commit e2ee8ae1b0

View File

@ -15,6 +15,8 @@
*/ */
package androidx.media3.exoplayer.dash; package androidx.media3.exoplayer.dash;
import static androidx.media3.common.util.Assertions.checkNotNull;
import static androidx.media3.common.util.Assertions.checkStateNotNull;
import static java.lang.Math.max; import static java.lang.Math.max;
import static java.lang.Math.min; import static java.lang.Math.min;
@ -62,6 +64,8 @@ import com.google.common.collect.ImmutableMap;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.checkerframework.checker.initialization.qual.UnknownInitialization;
import org.checkerframework.checker.nullness.qual.RequiresNonNull;
/** A default {@link DashChunkSource} implementation. */ /** A default {@link DashChunkSource} implementation. */
@UnstableApi @UnstableApi
@ -510,7 +514,9 @@ public class DefaultDashChunkSource implements DashChunkSource {
// from the stream. If the manifest defines an index then the stream shouldn't, but in cases // from the stream. If the manifest defines an index then the stream shouldn't, but in cases
// where it does we should ignore it. // where it does we should ignore it.
if (representationHolder.segmentIndex == null) { if (representationHolder.segmentIndex == null) {
@Nullable ChunkIndex chunkIndex = representationHolder.chunkExtractor.getChunkIndex(); @Nullable
ChunkIndex chunkIndex =
checkStateNotNull(representationHolder.chunkExtractor).getChunkIndex();
if (chunkIndex != null) { if (chunkIndex != null) {
representationHolders[trackIndex] = representationHolders[trackIndex] =
representationHolder.copyWithNewSegmentIndex( representationHolder.copyWithNewSegmentIndex(
@ -636,7 +642,9 @@ public class DefaultDashChunkSource implements DashChunkSource {
lastAvailableSegmentNum); lastAvailableSegmentNum);
} }
private ArrayList<Representation> getRepresentations() { @RequiresNonNull({"manifest", "adaptationSetIndices"})
private ArrayList<Representation> getRepresentations(
@UnknownInitialization DefaultDashChunkSource this) {
List<AdaptationSet> manifestAdaptationSets = manifest.getPeriod(periodIndex).adaptationSets; List<AdaptationSet> manifestAdaptationSets = manifest.getPeriod(periodIndex).adaptationSets;
ArrayList<Representation> representations = new ArrayList<>(); ArrayList<Representation> representations = new ArrayList<>();
for (int adaptationSetIndex : adaptationSetIndices) { for (int adaptationSetIndex : adaptationSetIndices) {
@ -664,6 +672,21 @@ public class DefaultDashChunkSource implements DashChunkSource {
manifest.availabilityStartTimeMs + manifest.getPeriod(periodIndex).startMs); manifest.availabilityStartTimeMs + manifest.getPeriod(periodIndex).startMs);
} }
/**
* Creates a new {@link Chunk} for initialization.
*
* @param representationHolder The {@link Representation} holder for initialization.
* @param dataSource The source from which the data should be loaded.
* @param trackFormat The format of the track to which this chunk belongs.
* @param trackSelectionReason One of the {@link C.SelectionReason selection reasons}.
* @param trackSelectionData Additional data related to track selection.
* @param initializationUri The URI pointing to initialization data. Can be {@code null} if {@code
* indexUri} is not {@code null}.
* @param indexUri The URI pointing to index data. Can be {@code null} if {@code
* initializationUri} is not {@code null}.
* @param cmcdHeadersFactory The {@link CmcdHeadersFactory} for generating CMCD data.
*/
@RequiresNonNull("#1.chunkExtractor")
protected Chunk newInitializationChunk( protected Chunk newInitializationChunk(
RepresentationHolder representationHolder, RepresentationHolder representationHolder,
DataSource dataSource, DataSource dataSource,
@ -674,7 +697,7 @@ public class DefaultDashChunkSource implements DashChunkSource {
@Nullable RangedUri indexUri, @Nullable RangedUri indexUri,
@Nullable CmcdHeadersFactory cmcdHeadersFactory) { @Nullable CmcdHeadersFactory cmcdHeadersFactory) {
Representation representation = representationHolder.representation; Representation representation = representationHolder.representation;
@Nullable RangedUri requestUri; RangedUri requestUri;
if (initializationUri != null) { if (initializationUri != null) {
// It's common for initialization and index data to be stored adjacently. Attempt to merge // It's common for initialization and index data to be stored adjacently. Attempt to merge
// the two requests together to request both at once. // the two requests together to request both at once.
@ -684,7 +707,7 @@ public class DefaultDashChunkSource implements DashChunkSource {
requestUri = initializationUri; requestUri = initializationUri;
} }
} else { } else {
requestUri = indexUri; requestUri = checkNotNull(indexUri);
} }
ImmutableMap<@CmcdConfiguration.HeaderKey String, String> httpRequestHeaders = ImmutableMap<@CmcdConfiguration.HeaderKey String, String> httpRequestHeaders =
cmcdHeadersFactory == null cmcdHeadersFactory == null
@ -714,7 +737,7 @@ public class DefaultDashChunkSource implements DashChunkSource {
@C.TrackType int trackType, @C.TrackType int trackType,
Format trackFormat, Format trackFormat,
@C.SelectionReason int trackSelectionReason, @C.SelectionReason int trackSelectionReason,
Object trackSelectionData, @Nullable Object trackSelectionData,
long firstSegmentNum, long firstSegmentNum,
int maxSegmentCount, int maxSegmentCount,
long seekTimeUs, long seekTimeUs,
@ -733,13 +756,17 @@ public class DefaultDashChunkSource implements DashChunkSource {
ImmutableMap<@CmcdConfiguration.HeaderKey String, String> httpRequestHeaders = ImmutableMap<@CmcdConfiguration.HeaderKey String, String> httpRequestHeaders =
ImmutableMap.of(); ImmutableMap.of();
if (cmcdHeadersFactory != null) { if (cmcdHeadersFactory != null) {
Pair<String, String> nextObjectAndRangeRequest =
getNextObjectAndRangeRequest(firstSegmentNum, segmentUri, representationHolder);
cmcdHeadersFactory cmcdHeadersFactory
.setChunkDurationUs(endTimeUs - startTimeUs) .setChunkDurationUs(endTimeUs - startTimeUs)
.setObjectType(CmcdHeadersFactory.getObjectType(trackSelection)) .setObjectType(CmcdHeadersFactory.getObjectType(trackSelection));
.setNextObjectRequest(nextObjectAndRangeRequest.first) @Nullable
.setNextRangeRequest(nextObjectAndRangeRequest.second); Pair<String, String> nextObjectAndRangeRequest =
getNextObjectAndRangeRequest(firstSegmentNum, segmentUri, representationHolder);
if (nextObjectAndRangeRequest != null) {
cmcdHeadersFactory
.setNextObjectRequest(nextObjectAndRangeRequest.first)
.setNextRangeRequest(nextObjectAndRangeRequest.second);
}
httpRequestHeaders = cmcdHeadersFactory.createHttpRequestHeaders(); httpRequestHeaders = cmcdHeadersFactory.createHttpRequestHeaders();
} }
DataSpec dataSpec = DataSpec dataSpec =
@ -788,13 +815,17 @@ public class DefaultDashChunkSource implements DashChunkSource {
ImmutableMap<@CmcdConfiguration.HeaderKey String, String> httpRequestHeaders = ImmutableMap<@CmcdConfiguration.HeaderKey String, String> httpRequestHeaders =
ImmutableMap.of(); ImmutableMap.of();
if (cmcdHeadersFactory != null) { if (cmcdHeadersFactory != null) {
Pair<String, String> nextObjectAndRangeRequest =
getNextObjectAndRangeRequest(segmentNum, segmentUri, representationHolder);
cmcdHeadersFactory cmcdHeadersFactory
.setChunkDurationUs(endTimeUs - startTimeUs) .setChunkDurationUs(endTimeUs - startTimeUs)
.setObjectType(CmcdHeadersFactory.getObjectType(trackSelection)) .setObjectType(CmcdHeadersFactory.getObjectType(trackSelection));
.setNextObjectRequest(nextObjectAndRangeRequest.first) @Nullable
.setNextRangeRequest(nextObjectAndRangeRequest.second); Pair<String, String> nextObjectAndRangeRequest =
getNextObjectAndRangeRequest(firstSegmentNum, segmentUri, representationHolder);
if (nextObjectAndRangeRequest != null) {
cmcdHeadersFactory
.setNextObjectRequest(nextObjectAndRangeRequest.first)
.setNextRangeRequest(nextObjectAndRangeRequest.second);
}
httpRequestHeaders = cmcdHeadersFactory.createHttpRequestHeaders(); httpRequestHeaders = cmcdHeadersFactory.createHttpRequestHeaders();
} }
DataSpec dataSpec = DataSpec dataSpec =
@ -822,21 +853,22 @@ public class DefaultDashChunkSource implements DashChunkSource {
} }
} }
@Nullable
private Pair<String, String> getNextObjectAndRangeRequest( private Pair<String, String> getNextObjectAndRangeRequest(
long segmentNum, RangedUri segmentUri, RepresentationHolder representationHolder) { long segmentNum, RangedUri segmentUri, RepresentationHolder representationHolder) {
if (segmentNum + 1 < representationHolder.getSegmentCount()) { if (segmentNum + 1 >= representationHolder.getSegmentCount()) {
RangedUri nextSegmentUri = representationHolder.getSegmentUrl(segmentNum + 1); return null;
Uri uri = segmentUri.resolveUri(representationHolder.selectedBaseUrl.url);
Uri nextUri = nextSegmentUri.resolveUri(representationHolder.selectedBaseUrl.url);
String nextObjectRequest = UriUtil.getRelativePath(uri, nextUri);
String nextRangeRequest = nextSegmentUri.start + "-";
if (nextSegmentUri.length != C.LENGTH_UNSET) {
nextRangeRequest += (nextSegmentUri.start + nextSegmentUri.length);
}
return new Pair<>(nextObjectRequest, nextRangeRequest);
} }
return new Pair<>(null, null); RangedUri nextSegmentUri = representationHolder.getSegmentUrl(segmentNum + 1);
Uri uri = segmentUri.resolveUri(representationHolder.selectedBaseUrl.url);
Uri nextUri = nextSegmentUri.resolveUri(representationHolder.selectedBaseUrl.url);
String nextObjectRequest = UriUtil.getRelativePath(uri, nextUri);
String nextRangeRequest = nextSegmentUri.start + "-";
if (nextSegmentUri.length != C.LENGTH_UNSET) {
nextRangeRequest += (nextSegmentUri.start + nextSegmentUri.length);
}
return new Pair<>(nextObjectRequest, nextRangeRequest);
} }
private RepresentationHolder updateSelectedBaseUrl(int trackIndex) { private RepresentationHolder updateSelectedBaseUrl(int trackIndex) {
@ -976,6 +1008,8 @@ public class DefaultDashChunkSource implements DashChunkSource {
newIndex); newIndex);
} }
checkStateNotNull(newIndex);
long oldIndexFirstSegmentNum = oldIndex.getFirstSegmentNum(); long oldIndexFirstSegmentNum = oldIndex.getFirstSegmentNum();
long oldIndexStartTimeUs = oldIndex.getTimeUs(oldIndexFirstSegmentNum); long oldIndexStartTimeUs = oldIndex.getTimeUs(oldIndexFirstSegmentNum);
long oldIndexLastSegmentNum = oldIndexFirstSegmentNum + oldIndexSegmentCount - 1; long oldIndexLastSegmentNum = oldIndexFirstSegmentNum + oldIndexSegmentCount - 1;
@ -1036,43 +1070,47 @@ public class DefaultDashChunkSource implements DashChunkSource {
} }
public long getFirstSegmentNum() { public long getFirstSegmentNum() {
return segmentIndex.getFirstSegmentNum() + segmentNumShift; return checkStateNotNull(segmentIndex).getFirstSegmentNum() + segmentNumShift;
} }
public long getFirstAvailableSegmentNum(long nowUnixTimeUs) { public long getFirstAvailableSegmentNum(long nowUnixTimeUs) {
return segmentIndex.getFirstAvailableSegmentNum(periodDurationUs, nowUnixTimeUs) return checkStateNotNull(segmentIndex)
.getFirstAvailableSegmentNum(periodDurationUs, nowUnixTimeUs)
+ segmentNumShift; + segmentNumShift;
} }
public long getSegmentCount() { public long getSegmentCount() {
return segmentIndex.getSegmentCount(periodDurationUs); return checkStateNotNull(segmentIndex).getSegmentCount(periodDurationUs);
} }
public long getSegmentStartTimeUs(long segmentNum) { public long getSegmentStartTimeUs(long segmentNum) {
return segmentIndex.getTimeUs(segmentNum - segmentNumShift); return checkStateNotNull(segmentIndex).getTimeUs(segmentNum - segmentNumShift);
} }
public long getSegmentEndTimeUs(long segmentNum) { public long getSegmentEndTimeUs(long segmentNum) {
return getSegmentStartTimeUs(segmentNum) return getSegmentStartTimeUs(segmentNum)
+ segmentIndex.getDurationUs(segmentNum - segmentNumShift, periodDurationUs); + checkStateNotNull(segmentIndex)
.getDurationUs(segmentNum - segmentNumShift, periodDurationUs);
} }
public long getSegmentNum(long positionUs) { public long getSegmentNum(long positionUs) {
return segmentIndex.getSegmentNum(positionUs, periodDurationUs) + segmentNumShift; return checkStateNotNull(segmentIndex).getSegmentNum(positionUs, periodDurationUs)
+ segmentNumShift;
} }
public RangedUri getSegmentUrl(long segmentNum) { public RangedUri getSegmentUrl(long segmentNum) {
return segmentIndex.getSegmentUrl(segmentNum - segmentNumShift); return checkStateNotNull(segmentIndex).getSegmentUrl(segmentNum - segmentNumShift);
} }
public long getLastAvailableSegmentNum(long nowUnixTimeUs) { public long getLastAvailableSegmentNum(long nowUnixTimeUs) {
return getFirstAvailableSegmentNum(nowUnixTimeUs) return getFirstAvailableSegmentNum(nowUnixTimeUs)
+ segmentIndex.getAvailableSegmentCount(periodDurationUs, nowUnixTimeUs) + checkStateNotNull(segmentIndex)
.getAvailableSegmentCount(periodDurationUs, nowUnixTimeUs)
- 1; - 1;
} }
public boolean isSegmentAvailableAtFullNetworkSpeed(long segmentNum, long nowPeriodTimeUs) { public boolean isSegmentAvailableAtFullNetworkSpeed(long segmentNum, long nowPeriodTimeUs) {
if (segmentIndex.isExplicit()) { if (checkStateNotNull(segmentIndex).isExplicit()) {
// We don't support segment availability for explicit indices (internal ref: b/172894901). // We don't support segment availability for explicit indices (internal ref: b/172894901).
// Hence, also assume all segments in explicit indices are always available at full network // Hence, also assume all segments in explicit indices are always available at full network
// speed even if they end in the future. // speed even if they end in the future.