Add RepresentationHolder.selectedBaseUrl and use it for new chunks
PiperOrigin-RevId: 384968532
This commit is contained in:
parent
99abb4e1e9
commit
78ecb10ac0
@ -46,6 +46,29 @@ public final class DashUtil {
|
|||||||
/**
|
/**
|
||||||
* Builds a {@link DataSpec} for a given {@link RangedUri} belonging to {@link Representation}.
|
* Builds a {@link DataSpec} for a given {@link RangedUri} belonging to {@link Representation}.
|
||||||
*
|
*
|
||||||
|
* @param baseUrl The base url with which to resolve the request URI.
|
||||||
|
* @param requestUri The {@link RangedUri} of the data to request.
|
||||||
|
* @param cacheKey An optional cache key.
|
||||||
|
* @param flags Flags to be set on the returned {@link DataSpec}. See {@link
|
||||||
|
* DataSpec.Builder#setFlags(int)}.
|
||||||
|
* @return The {@link DataSpec}.
|
||||||
|
*/
|
||||||
|
public static DataSpec buildDataSpec(
|
||||||
|
String baseUrl, RangedUri requestUri, @Nullable String cacheKey, int flags) {
|
||||||
|
return new DataSpec.Builder()
|
||||||
|
.setUri(requestUri.resolveUri(baseUrl))
|
||||||
|
.setPosition(requestUri.start)
|
||||||
|
.setLength(requestUri.length)
|
||||||
|
.setKey(cacheKey)
|
||||||
|
.setFlags(flags)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds a {@link DataSpec} for a given {@link RangedUri} belonging to {@link Representation}.
|
||||||
|
*
|
||||||
|
* <p>Uses the first base URL of the representation to build the data spec.
|
||||||
|
*
|
||||||
* @param representation The {@link Representation} to which the request belongs.
|
* @param representation The {@link Representation} to which the request belongs.
|
||||||
* @param requestUri The {@link RangedUri} of the data to request.
|
* @param requestUri The {@link RangedUri} of the data to request.
|
||||||
* @param flags Flags to be set on the returned {@link DataSpec}. See {@link
|
* @param flags Flags to be set on the returned {@link DataSpec}. See {@link
|
||||||
@ -54,13 +77,8 @@ public final class DashUtil {
|
|||||||
*/
|
*/
|
||||||
public static DataSpec buildDataSpec(
|
public static DataSpec buildDataSpec(
|
||||||
Representation representation, RangedUri requestUri, int flags) {
|
Representation representation, RangedUri requestUri, int flags) {
|
||||||
return new DataSpec.Builder()
|
return buildDataSpec(
|
||||||
.setUri(requestUri.resolveUri(representation.baseUrls.get(0).url))
|
representation.baseUrls.get(0).url, requestUri, representation.getCacheKey(), flags);
|
||||||
.setPosition(requestUri.start)
|
|
||||||
.setLength(requestUri.length)
|
|
||||||
.setKey(representation.getCacheKey())
|
|
||||||
.setFlags(flags)
|
|
||||||
.build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -96,6 +114,7 @@ public final class DashUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Format manifestFormat = representation.format;
|
Format manifestFormat = representation.format;
|
||||||
|
@Nullable
|
||||||
Format sampleFormat = DashUtil.loadSampleFormat(dataSource, primaryTrackType, representation);
|
Format sampleFormat = DashUtil.loadSampleFormat(dataSource, primaryTrackType, representation);
|
||||||
return sampleFormat == null
|
return sampleFormat == null
|
||||||
? manifestFormat
|
? manifestFormat
|
||||||
@ -109,24 +128,46 @@ public final class DashUtil {
|
|||||||
* @param trackType The type of the representation. Typically one of the {@link
|
* @param trackType The type of the representation. Typically one of the {@link
|
||||||
* com.google.android.exoplayer2.C} {@code TRACK_TYPE_*} constants.
|
* com.google.android.exoplayer2.C} {@code TRACK_TYPE_*} constants.
|
||||||
* @param representation The representation which initialization chunk belongs to.
|
* @param representation The representation which initialization chunk belongs to.
|
||||||
|
* @param baseUrlIndex The index of the base URL to be picked from the {@link
|
||||||
|
* Representation#baseUrls list of base URLs}.
|
||||||
* @return the sample {@link Format} of the given representation.
|
* @return the sample {@link Format} of the given representation.
|
||||||
* @throws IOException Thrown when there is an error while loading.
|
* @throws IOException Thrown when there is an error while loading.
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public static Format loadSampleFormat(
|
public static Format loadSampleFormat(
|
||||||
DataSource dataSource, int trackType, Representation representation) throws IOException {
|
DataSource dataSource, int trackType, Representation representation, int baseUrlIndex)
|
||||||
|
throws IOException {
|
||||||
if (representation.getInitializationUri() == null) {
|
if (representation.getInitializationUri() == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
ChunkExtractor chunkExtractor = newChunkExtractor(trackType, representation.format);
|
ChunkExtractor chunkExtractor = newChunkExtractor(trackType, representation.format);
|
||||||
try {
|
try {
|
||||||
loadInitializationData(chunkExtractor, dataSource, representation, /* loadIndex= */ false);
|
loadInitializationData(
|
||||||
|
chunkExtractor, dataSource, representation, baseUrlIndex, /* loadIndex= */ false);
|
||||||
} finally {
|
} finally {
|
||||||
chunkExtractor.release();
|
chunkExtractor.release();
|
||||||
}
|
}
|
||||||
return Assertions.checkStateNotNull(chunkExtractor.getSampleFormats())[0];
|
return Assertions.checkStateNotNull(chunkExtractor.getSampleFormats())[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads initialization data for the {@code representation} and returns the sample {@link Format}.
|
||||||
|
*
|
||||||
|
* <p>Uses the first base URL for loading the format.
|
||||||
|
*
|
||||||
|
* @param dataSource The source from which the data should be loaded.
|
||||||
|
* @param trackType The type of the representation. Typically one of the {@link
|
||||||
|
* com.google.android.exoplayer2.C} {@code TRACK_TYPE_*} constants.
|
||||||
|
* @param representation The representation which initialization chunk belongs to.
|
||||||
|
* @return the sample {@link Format} of the given representation.
|
||||||
|
* @throws IOException Thrown when there is an error while loading.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public static Format loadSampleFormat(
|
||||||
|
DataSource dataSource, int trackType, Representation representation) throws IOException {
|
||||||
|
return loadSampleFormat(dataSource, trackType, representation, /* baseUrlIndex= */ 0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads initialization and index data for the {@code representation} and returns the {@link
|
* Loads initialization and index data for the {@code representation} and returns the {@link
|
||||||
* ChunkIndex}.
|
* ChunkIndex}.
|
||||||
@ -135,6 +176,38 @@ public final class DashUtil {
|
|||||||
* @param trackType The type of the representation. Typically one of the {@link
|
* @param trackType The type of the representation. Typically one of the {@link
|
||||||
* com.google.android.exoplayer2.C} {@code TRACK_TYPE_*} constants.
|
* com.google.android.exoplayer2.C} {@code TRACK_TYPE_*} constants.
|
||||||
* @param representation The representation which initialization chunk belongs to.
|
* @param representation The representation which initialization chunk belongs to.
|
||||||
|
* @param baseUrlIndex The index of the base URL with which to resolve the request URI.
|
||||||
|
* @return The {@link ChunkIndex} of the given representation, or null if no initialization or
|
||||||
|
* index data exists.
|
||||||
|
* @throws IOException Thrown when there is an error while loading.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public static ChunkIndex loadChunkIndex(
|
||||||
|
DataSource dataSource, int trackType, Representation representation, int baseUrlIndex)
|
||||||
|
throws IOException {
|
||||||
|
if (representation.getInitializationUri() == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
ChunkExtractor chunkExtractor = newChunkExtractor(trackType, representation.format);
|
||||||
|
try {
|
||||||
|
loadInitializationData(
|
||||||
|
chunkExtractor, dataSource, representation, baseUrlIndex, /* loadIndex= */ true);
|
||||||
|
} finally {
|
||||||
|
chunkExtractor.release();
|
||||||
|
}
|
||||||
|
return chunkExtractor.getChunkIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads initialization and index data for the {@code representation} and returns the {@link
|
||||||
|
* ChunkIndex}.
|
||||||
|
*
|
||||||
|
* <p>Uses the first base URL for loading the index.
|
||||||
|
*
|
||||||
|
* @param dataSource The source from which the data should be loaded.
|
||||||
|
* @param trackType The type of the representation. Typically one of the {@link
|
||||||
|
* com.google.android.exoplayer2.C} {@code TRACK_TYPE_*} constants.
|
||||||
|
* @param representation The representation which initialization chunk belongs to.
|
||||||
* @return The {@link ChunkIndex} of the given representation, or null if no initialization or
|
* @return The {@link ChunkIndex} of the given representation, or null if no initialization or
|
||||||
* index data exists.
|
* index data exists.
|
||||||
* @throws IOException Thrown when there is an error while loading.
|
* @throws IOException Thrown when there is an error while loading.
|
||||||
@ -142,16 +215,7 @@ public final class DashUtil {
|
|||||||
@Nullable
|
@Nullable
|
||||||
public static ChunkIndex loadChunkIndex(
|
public static ChunkIndex loadChunkIndex(
|
||||||
DataSource dataSource, int trackType, Representation representation) throws IOException {
|
DataSource dataSource, int trackType, Representation representation) throws IOException {
|
||||||
if (representation.getInitializationUri() == null) {
|
return loadChunkIndex(dataSource, trackType, representation, /* baseUrlIndex= */ 0);
|
||||||
return null;
|
|
||||||
}
|
|
||||||
ChunkExtractor chunkExtractor = newChunkExtractor(trackType, representation.format);
|
|
||||||
try {
|
|
||||||
loadInitializationData(chunkExtractor, dataSource, representation, /* loadIndex= */ true);
|
|
||||||
} finally {
|
|
||||||
chunkExtractor.release();
|
|
||||||
}
|
|
||||||
return chunkExtractor.getChunkIndex();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -161,6 +225,7 @@ public final class DashUtil {
|
|||||||
* @param chunkExtractor The {@link ChunkExtractor} to use.
|
* @param chunkExtractor The {@link ChunkExtractor} to use.
|
||||||
* @param dataSource The source from which the data should be loaded.
|
* @param dataSource The source from which the data should be loaded.
|
||||||
* @param representation The representation which initialization chunk belongs to.
|
* @param representation The representation which initialization chunk belongs to.
|
||||||
|
* @param baseUrlIndex The index of the base URL with which to resolve the request URI.
|
||||||
* @param loadIndex Whether to load index data too.
|
* @param loadIndex Whether to load index data too.
|
||||||
* @throws IOException Thrown when there is an error while loading.
|
* @throws IOException Thrown when there is an error while loading.
|
||||||
*/
|
*/
|
||||||
@ -168,6 +233,7 @@ public final class DashUtil {
|
|||||||
ChunkExtractor chunkExtractor,
|
ChunkExtractor chunkExtractor,
|
||||||
DataSource dataSource,
|
DataSource dataSource,
|
||||||
Representation representation,
|
Representation representation,
|
||||||
|
int baseUrlIndex,
|
||||||
boolean loadIndex)
|
boolean loadIndex)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
RangedUri initializationUri = Assertions.checkNotNull(representation.getInitializationUri());
|
RangedUri initializationUri = Assertions.checkNotNull(representation.getInitializationUri());
|
||||||
@ -179,24 +245,54 @@ public final class DashUtil {
|
|||||||
}
|
}
|
||||||
// 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.
|
||||||
requestUri = initializationUri.attemptMerge(indexUri, representation.baseUrls.get(0).url);
|
requestUri =
|
||||||
|
initializationUri.attemptMerge(indexUri, representation.baseUrls.get(baseUrlIndex).url);
|
||||||
if (requestUri == null) {
|
if (requestUri == null) {
|
||||||
loadInitializationData(dataSource, representation, chunkExtractor, initializationUri);
|
loadInitializationData(
|
||||||
|
dataSource, representation, baseUrlIndex, chunkExtractor, initializationUri);
|
||||||
requestUri = indexUri;
|
requestUri = indexUri;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
requestUri = initializationUri;
|
requestUri = initializationUri;
|
||||||
}
|
}
|
||||||
loadInitializationData(dataSource, representation, chunkExtractor, requestUri);
|
loadInitializationData(dataSource, representation, baseUrlIndex, chunkExtractor, requestUri);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads initialization data for the {@code representation} and optionally index data then returns
|
||||||
|
* a {@link BundledChunkExtractor} which contains the output.
|
||||||
|
*
|
||||||
|
* <p>Uses the first base URL for loading the initialization data.
|
||||||
|
*
|
||||||
|
* @param chunkExtractor The {@link ChunkExtractor} to use.
|
||||||
|
* @param dataSource The source from which the data should be loaded.
|
||||||
|
* @param representation The representation which initialization chunk belongs to.
|
||||||
|
* @param loadIndex Whether to load index data too.
|
||||||
|
* @throws IOException Thrown when there is an error while loading.
|
||||||
|
*/
|
||||||
|
public static void loadInitializationData(
|
||||||
|
ChunkExtractor chunkExtractor,
|
||||||
|
DataSource dataSource,
|
||||||
|
Representation representation,
|
||||||
|
boolean loadIndex)
|
||||||
|
throws IOException {
|
||||||
|
loadInitializationData(
|
||||||
|
chunkExtractor, dataSource, representation, /* baseUrlIndex= */ 0, loadIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void loadInitializationData(
|
private static void loadInitializationData(
|
||||||
DataSource dataSource,
|
DataSource dataSource,
|
||||||
Representation representation,
|
Representation representation,
|
||||||
|
int baseUrlIndex,
|
||||||
ChunkExtractor chunkExtractor,
|
ChunkExtractor chunkExtractor,
|
||||||
RangedUri requestUri)
|
RangedUri requestUri)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
DataSpec dataSpec = DashUtil.buildDataSpec(representation, requestUri, /* flags= */ 0);
|
DataSpec dataSpec =
|
||||||
|
DashUtil.buildDataSpec(
|
||||||
|
representation.baseUrls.get(baseUrlIndex).url,
|
||||||
|
requestUri,
|
||||||
|
representation.getCacheKey(),
|
||||||
|
/* flags= */ 0);
|
||||||
InitializationChunk initializationChunk =
|
InitializationChunk initializationChunk =
|
||||||
new InitializationChunk(
|
new InitializationChunk(
|
||||||
dataSource,
|
dataSource,
|
||||||
|
@ -40,6 +40,7 @@ import com.google.android.exoplayer2.source.chunk.MediaChunkIterator;
|
|||||||
import com.google.android.exoplayer2.source.chunk.SingleSampleMediaChunk;
|
import com.google.android.exoplayer2.source.chunk.SingleSampleMediaChunk;
|
||||||
import com.google.android.exoplayer2.source.dash.PlayerEmsgHandler.PlayerTrackEmsgHandler;
|
import com.google.android.exoplayer2.source.dash.PlayerEmsgHandler.PlayerTrackEmsgHandler;
|
||||||
import com.google.android.exoplayer2.source.dash.manifest.AdaptationSet;
|
import com.google.android.exoplayer2.source.dash.manifest.AdaptationSet;
|
||||||
|
import com.google.android.exoplayer2.source.dash.manifest.BaseUrl;
|
||||||
import com.google.android.exoplayer2.source.dash.manifest.DashManifest;
|
import com.google.android.exoplayer2.source.dash.manifest.DashManifest;
|
||||||
import com.google.android.exoplayer2.source.dash.manifest.RangedUri;
|
import com.google.android.exoplayer2.source.dash.manifest.RangedUri;
|
||||||
import com.google.android.exoplayer2.source.dash.manifest.Representation;
|
import com.google.android.exoplayer2.source.dash.manifest.Representation;
|
||||||
@ -203,6 +204,7 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
|||||||
new RepresentationHolder(
|
new RepresentationHolder(
|
||||||
periodDurationUs,
|
periodDurationUs,
|
||||||
representation,
|
representation,
|
||||||
|
representation.baseUrls.get(0),
|
||||||
BundledChunkExtractor.FACTORY.createProgressiveMediaExtractor(
|
BundledChunkExtractor.FACTORY.createProgressiveMediaExtractor(
|
||||||
trackType,
|
trackType,
|
||||||
representation.format,
|
representation.format,
|
||||||
@ -562,14 +564,20 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
|||||||
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.
|
||||||
requestUri = initializationUri.attemptMerge(indexUri, representation.baseUrls.get(0).url);
|
requestUri =
|
||||||
|
initializationUri.attemptMerge(indexUri, representationHolder.selectedBaseUrl.url);
|
||||||
if (requestUri == null) {
|
if (requestUri == null) {
|
||||||
requestUri = initializationUri;
|
requestUri = initializationUri;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
requestUri = indexUri;
|
requestUri = indexUri;
|
||||||
}
|
}
|
||||||
DataSpec dataSpec = DashUtil.buildDataSpec(representation, requestUri, /* flags= */ 0);
|
DataSpec dataSpec =
|
||||||
|
DashUtil.buildDataSpec(
|
||||||
|
representationHolder.selectedBaseUrl.url,
|
||||||
|
requestUri,
|
||||||
|
representation.getCacheKey(),
|
||||||
|
/* flags= */ 0);
|
||||||
return new InitializationChunk(
|
return new InitializationChunk(
|
||||||
dataSource,
|
dataSource,
|
||||||
dataSpec,
|
dataSpec,
|
||||||
@ -593,7 +601,6 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
|||||||
Representation representation = representationHolder.representation;
|
Representation representation = representationHolder.representation;
|
||||||
long startTimeUs = representationHolder.getSegmentStartTimeUs(firstSegmentNum);
|
long startTimeUs = representationHolder.getSegmentStartTimeUs(firstSegmentNum);
|
||||||
RangedUri segmentUri = representationHolder.getSegmentUrl(firstSegmentNum);
|
RangedUri segmentUri = representationHolder.getSegmentUrl(firstSegmentNum);
|
||||||
String baseUrl = representation.baseUrls.get(0).url;
|
|
||||||
if (representationHolder.chunkExtractor == null) {
|
if (representationHolder.chunkExtractor == null) {
|
||||||
long endTimeUs = representationHolder.getSegmentEndTimeUs(firstSegmentNum);
|
long endTimeUs = representationHolder.getSegmentEndTimeUs(firstSegmentNum);
|
||||||
int flags =
|
int flags =
|
||||||
@ -601,7 +608,12 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
|||||||
firstSegmentNum, nowPeriodTimeUs)
|
firstSegmentNum, nowPeriodTimeUs)
|
||||||
? 0
|
? 0
|
||||||
: DataSpec.FLAG_MIGHT_NOT_USE_FULL_NETWORK_SPEED;
|
: DataSpec.FLAG_MIGHT_NOT_USE_FULL_NETWORK_SPEED;
|
||||||
DataSpec dataSpec = DashUtil.buildDataSpec(representation, segmentUri, flags);
|
DataSpec dataSpec =
|
||||||
|
DashUtil.buildDataSpec(
|
||||||
|
representationHolder.selectedBaseUrl.url,
|
||||||
|
segmentUri,
|
||||||
|
representation.getCacheKey(),
|
||||||
|
flags);
|
||||||
return new SingleSampleMediaChunk(
|
return new SingleSampleMediaChunk(
|
||||||
dataSource,
|
dataSource,
|
||||||
dataSpec,
|
dataSpec,
|
||||||
@ -617,7 +629,9 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
|||||||
int segmentCount = 1;
|
int segmentCount = 1;
|
||||||
for (int i = 1; i < maxSegmentCount; i++) {
|
for (int i = 1; i < maxSegmentCount; i++) {
|
||||||
RangedUri nextSegmentUri = representationHolder.getSegmentUrl(firstSegmentNum + i);
|
RangedUri nextSegmentUri = representationHolder.getSegmentUrl(firstSegmentNum + i);
|
||||||
@Nullable RangedUri mergedSegmentUri = segmentUri.attemptMerge(nextSegmentUri, baseUrl);
|
@Nullable
|
||||||
|
RangedUri mergedSegmentUri =
|
||||||
|
segmentUri.attemptMerge(nextSegmentUri, representationHolder.selectedBaseUrl.url);
|
||||||
if (mergedSegmentUri == null) {
|
if (mergedSegmentUri == null) {
|
||||||
// Unable to merge segment fetches because the URIs do not merge.
|
// Unable to merge segment fetches because the URIs do not merge.
|
||||||
break;
|
break;
|
||||||
@ -636,7 +650,12 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
|||||||
representationHolder.isSegmentAvailableAtFullNetworkSpeed(segmentNum, nowPeriodTimeUs)
|
representationHolder.isSegmentAvailableAtFullNetworkSpeed(segmentNum, nowPeriodTimeUs)
|
||||||
? 0
|
? 0
|
||||||
: DataSpec.FLAG_MIGHT_NOT_USE_FULL_NETWORK_SPEED;
|
: DataSpec.FLAG_MIGHT_NOT_USE_FULL_NETWORK_SPEED;
|
||||||
DataSpec dataSpec = DashUtil.buildDataSpec(representation, segmentUri, flags);
|
DataSpec dataSpec =
|
||||||
|
DashUtil.buildDataSpec(
|
||||||
|
representationHolder.selectedBaseUrl.url,
|
||||||
|
segmentUri,
|
||||||
|
representation.getCacheKey(),
|
||||||
|
flags);
|
||||||
long sampleOffsetUs = -representation.presentationTimeOffsetUs;
|
long sampleOffsetUs = -representation.presentationTimeOffsetUs;
|
||||||
return new ContainerMediaChunk(
|
return new ContainerMediaChunk(
|
||||||
dataSource,
|
dataSource,
|
||||||
@ -691,7 +710,11 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
|||||||
representationHolder.isSegmentAvailableAtFullNetworkSpeed(currentIndex, nowPeriodTimeUs)
|
representationHolder.isSegmentAvailableAtFullNetworkSpeed(currentIndex, nowPeriodTimeUs)
|
||||||
? 0
|
? 0
|
||||||
: DataSpec.FLAG_MIGHT_NOT_USE_FULL_NETWORK_SPEED;
|
: DataSpec.FLAG_MIGHT_NOT_USE_FULL_NETWORK_SPEED;
|
||||||
return DashUtil.buildDataSpec(representationHolder.representation, segmentUri, flags);
|
return DashUtil.buildDataSpec(
|
||||||
|
representationHolder.selectedBaseUrl.url,
|
||||||
|
segmentUri,
|
||||||
|
representationHolder.representation.getCacheKey(),
|
||||||
|
flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -713,6 +736,7 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
|||||||
@Nullable /* package */ final ChunkExtractor chunkExtractor;
|
@Nullable /* package */ final ChunkExtractor chunkExtractor;
|
||||||
|
|
||||||
public final Representation representation;
|
public final Representation representation;
|
||||||
|
public final BaseUrl selectedBaseUrl;
|
||||||
@Nullable public final DashSegmentIndex segmentIndex;
|
@Nullable public final DashSegmentIndex segmentIndex;
|
||||||
|
|
||||||
private final long periodDurationUs;
|
private final long periodDurationUs;
|
||||||
@ -721,11 +745,13 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
|||||||
/* package */ RepresentationHolder(
|
/* package */ RepresentationHolder(
|
||||||
long periodDurationUs,
|
long periodDurationUs,
|
||||||
Representation representation,
|
Representation representation,
|
||||||
|
BaseUrl selectedBaseUrl,
|
||||||
@Nullable ChunkExtractor chunkExtractor,
|
@Nullable ChunkExtractor chunkExtractor,
|
||||||
long segmentNumShift,
|
long segmentNumShift,
|
||||||
@Nullable DashSegmentIndex segmentIndex) {
|
@Nullable DashSegmentIndex segmentIndex) {
|
||||||
this.periodDurationUs = periodDurationUs;
|
this.periodDurationUs = periodDurationUs;
|
||||||
this.representation = representation;
|
this.representation = representation;
|
||||||
|
this.selectedBaseUrl = selectedBaseUrl;
|
||||||
this.segmentNumShift = segmentNumShift;
|
this.segmentNumShift = segmentNumShift;
|
||||||
this.chunkExtractor = chunkExtractor;
|
this.chunkExtractor = chunkExtractor;
|
||||||
this.segmentIndex = segmentIndex;
|
this.segmentIndex = segmentIndex;
|
||||||
@ -735,26 +761,41 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
|||||||
/* package */ RepresentationHolder copyWithNewRepresentation(
|
/* package */ RepresentationHolder copyWithNewRepresentation(
|
||||||
long newPeriodDurationUs, Representation newRepresentation)
|
long newPeriodDurationUs, Representation newRepresentation)
|
||||||
throws BehindLiveWindowException {
|
throws BehindLiveWindowException {
|
||||||
DashSegmentIndex oldIndex = representation.getIndex();
|
@Nullable DashSegmentIndex oldIndex = representation.getIndex();
|
||||||
DashSegmentIndex newIndex = newRepresentation.getIndex();
|
@Nullable DashSegmentIndex newIndex = newRepresentation.getIndex();
|
||||||
|
|
||||||
if (oldIndex == null) {
|
if (oldIndex == null) {
|
||||||
// Segment numbers cannot shift if the index isn't defined by the manifest.
|
// Segment numbers cannot shift if the index isn't defined by the manifest.
|
||||||
return new RepresentationHolder(
|
return new RepresentationHolder(
|
||||||
newPeriodDurationUs, newRepresentation, chunkExtractor, segmentNumShift, oldIndex);
|
newPeriodDurationUs,
|
||||||
|
newRepresentation,
|
||||||
|
selectedBaseUrl,
|
||||||
|
chunkExtractor,
|
||||||
|
segmentNumShift,
|
||||||
|
oldIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!oldIndex.isExplicit()) {
|
if (!oldIndex.isExplicit()) {
|
||||||
// Segment numbers cannot shift if the index isn't explicit.
|
// Segment numbers cannot shift if the index isn't explicit.
|
||||||
return new RepresentationHolder(
|
return new RepresentationHolder(
|
||||||
newPeriodDurationUs, newRepresentation, chunkExtractor, segmentNumShift, newIndex);
|
newPeriodDurationUs,
|
||||||
|
newRepresentation,
|
||||||
|
selectedBaseUrl,
|
||||||
|
chunkExtractor,
|
||||||
|
segmentNumShift,
|
||||||
|
newIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
long oldIndexSegmentCount = oldIndex.getSegmentCount(newPeriodDurationUs);
|
long oldIndexSegmentCount = oldIndex.getSegmentCount(newPeriodDurationUs);
|
||||||
if (oldIndexSegmentCount == 0) {
|
if (oldIndexSegmentCount == 0) {
|
||||||
// Segment numbers cannot shift if the old index was empty.
|
// Segment numbers cannot shift if the old index was empty.
|
||||||
return new RepresentationHolder(
|
return new RepresentationHolder(
|
||||||
newPeriodDurationUs, newRepresentation, chunkExtractor, segmentNumShift, newIndex);
|
newPeriodDurationUs,
|
||||||
|
newRepresentation,
|
||||||
|
selectedBaseUrl,
|
||||||
|
chunkExtractor,
|
||||||
|
segmentNumShift,
|
||||||
|
newIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
long oldIndexFirstSegmentNum = oldIndex.getFirstSegmentNum();
|
long oldIndexFirstSegmentNum = oldIndex.getFirstSegmentNum();
|
||||||
@ -786,13 +827,23 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
|||||||
- newIndexFirstSegmentNum;
|
- newIndexFirstSegmentNum;
|
||||||
}
|
}
|
||||||
return new RepresentationHolder(
|
return new RepresentationHolder(
|
||||||
newPeriodDurationUs, newRepresentation, chunkExtractor, newSegmentNumShift, newIndex);
|
newPeriodDurationUs,
|
||||||
|
newRepresentation,
|
||||||
|
selectedBaseUrl,
|
||||||
|
chunkExtractor,
|
||||||
|
newSegmentNumShift,
|
||||||
|
newIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@CheckResult
|
@CheckResult
|
||||||
/* package */ RepresentationHolder copyWithNewSegmentIndex(DashSegmentIndex segmentIndex) {
|
/* package */ RepresentationHolder copyWithNewSegmentIndex(DashSegmentIndex segmentIndex) {
|
||||||
return new RepresentationHolder(
|
return new RepresentationHolder(
|
||||||
periodDurationUs, representation, chunkExtractor, segmentNumShift, segmentIndex);
|
periodDurationUs,
|
||||||
|
representation,
|
||||||
|
selectedBaseUrl,
|
||||||
|
chunkExtractor,
|
||||||
|
segmentNumShift,
|
||||||
|
segmentIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getFirstSegmentNum() {
|
public long getFirstSegmentNum() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user