mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Select base URL on demand when a new chunk is created
Instead of selecting the base URL initially or when a load error occurs, it is now selected when a chunk or initialization chunk is created. The selected base URL is then assigned to `RepresentationHolder.lastUsedBaseUrl` that is excluded in case of a load error. For a next chunk another base URL will be selected by using the `BaseUrlExclusionList`. #minor-release #exo-fixit PiperOrigin-RevId: 395721221
This commit is contained in:
parent
0c4bb23dd3
commit
9e3ef8180f
2 changed files with 32 additions and 20 deletions
|
|
@ -51,6 +51,8 @@
|
||||||
* DASH
|
* DASH
|
||||||
* Use identical cache keys for downloading and playing DASH segments
|
* Use identical cache keys for downloading and playing DASH segments
|
||||||
([#9370](https://github.com/google/ExoPlayer/issues/9370)).
|
([#9370](https://github.com/google/ExoPlayer/issues/9370)).
|
||||||
|
* Fix base URL selection and load error handling when base URLs are shared
|
||||||
|
across adaptation sets.
|
||||||
* Remove deprecated symbols:
|
* Remove deprecated symbols:
|
||||||
* Remove `Renderer.VIDEO_SCALING_MODE_*` constants. Use identically named
|
* Remove `Renderer.VIDEO_SCALING_MODE_*` constants. Use identically named
|
||||||
constants in `C` instead.
|
constants in `C` instead.
|
||||||
|
|
|
||||||
|
|
@ -338,6 +338,7 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
||||||
if (segmentNum < firstAvailableSegmentNum) {
|
if (segmentNum < firstAvailableSegmentNum) {
|
||||||
chunkIterators[i] = MediaChunkIterator.EMPTY;
|
chunkIterators[i] = MediaChunkIterator.EMPTY;
|
||||||
} else {
|
} else {
|
||||||
|
representationHolder = updateSelectedBaseUrl(/* trackIndex= */ i);
|
||||||
chunkIterators[i] =
|
chunkIterators[i] =
|
||||||
new RepresentationSegmentIterator(
|
new RepresentationSegmentIterator(
|
||||||
representationHolder, segmentNum, lastAvailableSegmentNum, nowPeriodTimeUs);
|
representationHolder, segmentNum, lastAvailableSegmentNum, nowPeriodTimeUs);
|
||||||
|
|
@ -350,12 +351,11 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
||||||
playbackPositionUs, bufferedDurationUs, availableLiveDurationUs, queue, chunkIterators);
|
playbackPositionUs, bufferedDurationUs, availableLiveDurationUs, queue, chunkIterators);
|
||||||
|
|
||||||
RepresentationHolder representationHolder =
|
RepresentationHolder representationHolder =
|
||||||
representationHolders[trackSelection.getSelectedIndex()];
|
updateSelectedBaseUrl(trackSelection.getSelectedIndex());
|
||||||
|
|
||||||
if (representationHolder.chunkExtractor != null) {
|
if (representationHolder.chunkExtractor != null) {
|
||||||
Representation selectedRepresentation = representationHolder.representation;
|
Representation selectedRepresentation = representationHolder.representation;
|
||||||
RangedUri pendingInitializationUri = null;
|
@Nullable RangedUri pendingInitializationUri = null;
|
||||||
RangedUri pendingIndexUri = null;
|
@Nullable RangedUri pendingIndexUri = null;
|
||||||
if (representationHolder.chunkExtractor.getSampleFormats() == null) {
|
if (representationHolder.chunkExtractor.getSampleFormats() == null) {
|
||||||
pendingInitializationUri = selectedRepresentation.getInitializationUri();
|
pendingInitializationUri = selectedRepresentation.getInitializationUri();
|
||||||
}
|
}
|
||||||
|
|
@ -495,18 +495,26 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
||||||
|
|
||||||
int trackIndex = trackSelection.indexOf(chunk.trackFormat);
|
int trackIndex = trackSelection.indexOf(chunk.trackFormat);
|
||||||
RepresentationHolder representationHolder = representationHolders[trackIndex];
|
RepresentationHolder representationHolder = representationHolders[trackIndex];
|
||||||
|
@Nullable
|
||||||
|
BaseUrl newBaseUrl =
|
||||||
|
baseUrlExclusionList.selectBaseUrl(representationHolder.representation.baseUrls);
|
||||||
|
if (newBaseUrl != null && !representationHolder.selectedBaseUrl.equals(newBaseUrl)) {
|
||||||
|
// The base URL has changed since the failing chunk was created. Request a replacement chunk,
|
||||||
|
// which will use the new base URL.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
LoadErrorHandlingPolicy.FallbackOptions fallbackOptions =
|
LoadErrorHandlingPolicy.FallbackOptions fallbackOptions =
|
||||||
createFallbackOptions(trackSelection, representationHolder.representation.baseUrls);
|
createFallbackOptions(trackSelection, representationHolder.representation.baseUrls);
|
||||||
if (!fallbackOptions.isFallbackAvailable(LoadErrorHandlingPolicy.FALLBACK_TYPE_TRACK)
|
if (!fallbackOptions.isFallbackAvailable(LoadErrorHandlingPolicy.FALLBACK_TYPE_TRACK)
|
||||||
&& !fallbackOptions.isFallbackAvailable(LoadErrorHandlingPolicy.FALLBACK_TYPE_LOCATION)) {
|
&& !fallbackOptions.isFallbackAvailable(LoadErrorHandlingPolicy.FALLBACK_TYPE_LOCATION)) {
|
||||||
// No more alternatives remaining.
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@Nullable
|
@Nullable
|
||||||
LoadErrorHandlingPolicy.FallbackSelection fallbackSelection =
|
LoadErrorHandlingPolicy.FallbackSelection fallbackSelection =
|
||||||
loadErrorHandlingPolicy.getFallbackSelectionFor(fallbackOptions, loadErrorInfo);
|
loadErrorHandlingPolicy.getFallbackSelectionFor(fallbackOptions, loadErrorInfo);
|
||||||
if (fallbackSelection == null) {
|
if (fallbackSelection == null || !fallbackOptions.isFallbackAvailable(fallbackSelection.type)) {
|
||||||
// Policy indicated to not use any fallback.
|
// Policy indicated to not use any fallback or a fallback type that is not available.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -518,17 +526,7 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
||||||
} else if (fallbackSelection.type == LoadErrorHandlingPolicy.FALLBACK_TYPE_LOCATION) {
|
} else if (fallbackSelection.type == LoadErrorHandlingPolicy.FALLBACK_TYPE_LOCATION) {
|
||||||
baseUrlExclusionList.exclude(
|
baseUrlExclusionList.exclude(
|
||||||
representationHolder.selectedBaseUrl, fallbackSelection.exclusionDurationMs);
|
representationHolder.selectedBaseUrl, fallbackSelection.exclusionDurationMs);
|
||||||
for (int i = 0; i < representationHolders.length; i++) {
|
cancelLoad = true;
|
||||||
@Nullable
|
|
||||||
BaseUrl baseUrl =
|
|
||||||
baseUrlExclusionList.selectBaseUrl(representationHolders[i].representation.baseUrls);
|
|
||||||
if (baseUrl != null) {
|
|
||||||
if (i == trackIndex) {
|
|
||||||
cancelLoad = true;
|
|
||||||
}
|
|
||||||
representationHolders[i] = representationHolders[i].copyWithNewSelectedBaseUrl(baseUrl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return cancelLoad;
|
return cancelLoad;
|
||||||
}
|
}
|
||||||
|
|
@ -610,9 +608,9 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
||||||
DataSource dataSource,
|
DataSource dataSource,
|
||||||
Format trackFormat,
|
Format trackFormat,
|
||||||
@C.SelectionReason int trackSelectionReason,
|
@C.SelectionReason int trackSelectionReason,
|
||||||
Object trackSelectionData,
|
@Nullable Object trackSelectionData,
|
||||||
@Nullable RangedUri initializationUri,
|
@Nullable RangedUri initializationUri,
|
||||||
RangedUri indexUri) {
|
@Nullable RangedUri indexUri) {
|
||||||
Representation representation = representationHolder.representation;
|
Representation representation = representationHolder.representation;
|
||||||
@Nullable RangedUri requestUri;
|
@Nullable RangedUri requestUri;
|
||||||
if (initializationUri != null) {
|
if (initializationUri != null) {
|
||||||
|
|
@ -719,6 +717,18 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private RepresentationHolder updateSelectedBaseUrl(int trackIndex) {
|
||||||
|
RepresentationHolder representationHolder = representationHolders[trackIndex];
|
||||||
|
@Nullable
|
||||||
|
BaseUrl selectedBaseUrl =
|
||||||
|
baseUrlExclusionList.selectBaseUrl(representationHolder.representation.baseUrls);
|
||||||
|
if (selectedBaseUrl != null && !selectedBaseUrl.equals(representationHolder.selectedBaseUrl)) {
|
||||||
|
representationHolder = representationHolder.copyWithNewSelectedBaseUrl(selectedBaseUrl);
|
||||||
|
representationHolders[trackIndex] = representationHolder;
|
||||||
|
}
|
||||||
|
return representationHolder;
|
||||||
|
}
|
||||||
|
|
||||||
// Protected classes.
|
// Protected classes.
|
||||||
|
|
||||||
/** {@link MediaChunkIterator} wrapping a {@link RepresentationHolder}. */
|
/** {@link MediaChunkIterator} wrapping a {@link RepresentationHolder}. */
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue