mirror of
https://github.com/androidx/media.git
synced 2025-05-17 04:29:55 +08:00
Add nullness annotations to DefaultDashChunkSource
#fixit PiperOrigin-RevId: 559405572
This commit is contained in:
parent
2ad37d2e37
commit
e2ee8ae1b0
@ -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));
|
||||||
|
@Nullable
|
||||||
|
Pair<String, String> nextObjectAndRangeRequest =
|
||||||
|
getNextObjectAndRangeRequest(firstSegmentNum, segmentUri, representationHolder);
|
||||||
|
if (nextObjectAndRangeRequest != null) {
|
||||||
|
cmcdHeadersFactory
|
||||||
.setNextObjectRequest(nextObjectAndRangeRequest.first)
|
.setNextObjectRequest(nextObjectAndRangeRequest.first)
|
||||||
.setNextRangeRequest(nextObjectAndRangeRequest.second);
|
.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));
|
||||||
|
@Nullable
|
||||||
|
Pair<String, String> nextObjectAndRangeRequest =
|
||||||
|
getNextObjectAndRangeRequest(firstSegmentNum, segmentUri, representationHolder);
|
||||||
|
if (nextObjectAndRangeRequest != null) {
|
||||||
|
cmcdHeadersFactory
|
||||||
.setNextObjectRequest(nextObjectAndRangeRequest.first)
|
.setNextObjectRequest(nextObjectAndRangeRequest.first)
|
||||||
.setNextRangeRequest(nextObjectAndRangeRequest.second);
|
.setNextRangeRequest(nextObjectAndRangeRequest.second);
|
||||||
|
}
|
||||||
httpRequestHeaders = cmcdHeadersFactory.createHttpRequestHeaders();
|
httpRequestHeaders = cmcdHeadersFactory.createHttpRequestHeaders();
|
||||||
}
|
}
|
||||||
DataSpec dataSpec =
|
DataSpec dataSpec =
|
||||||
@ -822,9 +853,12 @@ 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()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
RangedUri nextSegmentUri = representationHolder.getSegmentUrl(segmentNum + 1);
|
RangedUri nextSegmentUri = representationHolder.getSegmentUrl(segmentNum + 1);
|
||||||
Uri uri = segmentUri.resolveUri(representationHolder.selectedBaseUrl.url);
|
Uri uri = segmentUri.resolveUri(representationHolder.selectedBaseUrl.url);
|
||||||
Uri nextUri = nextSegmentUri.resolveUri(representationHolder.selectedBaseUrl.url);
|
Uri nextUri = nextSegmentUri.resolveUri(representationHolder.selectedBaseUrl.url);
|
||||||
@ -836,8 +870,6 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
|||||||
}
|
}
|
||||||
return new Pair<>(nextObjectRequest, nextRangeRequest);
|
return new Pair<>(nextObjectRequest, nextRangeRequest);
|
||||||
}
|
}
|
||||||
return new Pair<>(null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private RepresentationHolder updateSelectedBaseUrl(int trackIndex) {
|
private RepresentationHolder updateSelectedBaseUrl(int trackIndex) {
|
||||||
RepresentationHolder representationHolder = representationHolders[trackIndex];
|
RepresentationHolder representationHolder = representationHolders[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.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user