Minor cleanup.

- Add constants class. Currently housing a single lonely variable,
which is used generally throughout the library, and so no longer
nicely fits into a specific class.

- Rename a few other constants to add clear units.

- Made minor tweak to ExoPlayer documentation.
This commit is contained in:
Oliver Woodman 2014-08-11 18:38:39 +01:00
parent 25a532656c
commit 8ec8840261
19 changed files with 84 additions and 78 deletions

View File

@ -98,12 +98,12 @@ import android.widget.TextView;
@Override
protected long getDurationUs() {
return TrackRenderer.MATCH_LONGEST;
return TrackRenderer.MATCH_LONGEST_US;
}
@Override
protected long getBufferedPositionUs() {
return TrackRenderer.END_OF_TRACK;
return TrackRenderer.END_OF_TRACK_US;
}
@Override

View File

@ -316,14 +316,16 @@ public interface ExoPlayer {
public void seekTo(int positionMs);
/**
* Stops playback.
* Stops playback. Use {@code setPlayWhenReady(false)} rather than this method if the intention
* is to pause playback.
* <p>
* Calling this method will cause the playback state to transition to
* {@link ExoPlayer#STATE_IDLE}. Note that the player instance can still be used, and that
* {@link ExoPlayer#release()} must still be called on the player should it no longer be required.
* {@link ExoPlayer#STATE_IDLE}. The player instance can still be used, and
* {@link ExoPlayer#release()} must still be called on the player if it's no longer required.
* <p>
* Use {@code setPlayWhenReady(false)} rather than this method if the intention is to pause
* playback.
* Calling this method does not reset the playback position. If this player instance will be used
* to play another video from its start, then {@code seekTo(0)} should be called after stopping
* the player and before preparing it for the next video.
*/
public void stop();

View File

@ -95,8 +95,8 @@ import java.util.List;
}
this.state = ExoPlayer.STATE_IDLE;
this.durationUs = TrackRenderer.UNKNOWN_TIME;
this.bufferedPositionUs = TrackRenderer.UNKNOWN_TIME;
this.durationUs = TrackRenderer.UNKNOWN_TIME_US;
this.bufferedPositionUs = TrackRenderer.UNKNOWN_TIME_US;
mediaClock = new MediaClock();
enabledRenderers = new ArrayList<TrackRenderer>(rendererEnabledFlags.length);
@ -122,12 +122,12 @@ import java.util.List;
}
public int getBufferedPosition() {
return bufferedPositionUs == TrackRenderer.UNKNOWN_TIME ? ExoPlayer.UNKNOWN_TIME
return bufferedPositionUs == TrackRenderer.UNKNOWN_TIME_US ? ExoPlayer.UNKNOWN_TIME
: (int) (bufferedPositionUs / 1000);
}
public int getDuration() {
return durationUs == TrackRenderer.UNKNOWN_TIME ? ExoPlayer.UNKNOWN_TIME
return durationUs == TrackRenderer.UNKNOWN_TIME_US ? ExoPlayer.UNKNOWN_TIME
: (int) (durationUs / 1000);
}
@ -287,14 +287,14 @@ import java.util.List;
enabledRenderers.add(renderer);
isEnded = isEnded && renderer.isEnded();
allRenderersReadyOrEnded = allRenderersReadyOrEnded && rendererReadyOrEnded(renderer);
if (durationUs == TrackRenderer.UNKNOWN_TIME) {
if (durationUs == TrackRenderer.UNKNOWN_TIME_US) {
// We've already encountered a track for which the duration is unknown, so the media
// duration is unknown regardless of the duration of this track.
} else {
long trackDurationUs = renderer.getDurationUs();
if (trackDurationUs == TrackRenderer.UNKNOWN_TIME) {
durationUs = TrackRenderer.UNKNOWN_TIME;
} else if (trackDurationUs == TrackRenderer.MATCH_LONGEST) {
if (trackDurationUs == TrackRenderer.UNKNOWN_TIME_US) {
durationUs = TrackRenderer.UNKNOWN_TIME_US;
} else if (trackDurationUs == TrackRenderer.MATCH_LONGEST_US) {
// Do nothing.
} else {
durationUs = Math.max(durationUs, trackDurationUs);
@ -331,11 +331,11 @@ import java.util.List;
long rendererBufferedPositionUs = renderer.getBufferedPositionUs();
long minBufferDurationUs = rebuffering ? minRebufferUs : minBufferUs;
return minBufferDurationUs <= 0
|| rendererBufferedPositionUs == TrackRenderer.UNKNOWN_TIME
|| rendererBufferedPositionUs == TrackRenderer.END_OF_TRACK
|| rendererBufferedPositionUs == TrackRenderer.UNKNOWN_TIME_US
|| rendererBufferedPositionUs == TrackRenderer.END_OF_TRACK_US
|| rendererBufferedPositionUs >= positionUs + minBufferDurationUs
|| (rendererDurationUs != TrackRenderer.UNKNOWN_TIME
&& rendererDurationUs != TrackRenderer.MATCH_LONGEST
|| (rendererDurationUs != TrackRenderer.UNKNOWN_TIME_US
&& rendererDurationUs != TrackRenderer.MATCH_LONGEST_US
&& rendererBufferedPositionUs >= rendererDurationUs);
}
@ -384,7 +384,7 @@ import java.util.List;
private void doSomeWork() throws ExoPlaybackException {
TraceUtil.beginSection("doSomeWork");
long operationStartTimeMs = SystemClock.elapsedRealtime();
long bufferedPositionUs = durationUs != TrackRenderer.UNKNOWN_TIME ? durationUs
long bufferedPositionUs = durationUs != TrackRenderer.UNKNOWN_TIME_US ? durationUs
: Long.MAX_VALUE;
boolean isEnded = true;
boolean allRenderersReadyOrEnded = true;
@ -398,17 +398,17 @@ import java.util.List;
isEnded = isEnded && renderer.isEnded();
allRenderersReadyOrEnded = allRenderersReadyOrEnded && rendererReadyOrEnded(renderer);
if (bufferedPositionUs == TrackRenderer.UNKNOWN_TIME) {
if (bufferedPositionUs == TrackRenderer.UNKNOWN_TIME_US) {
// We've already encountered a track for which the buffered position is unknown. Hence the
// media buffer position unknown regardless of the buffered position of this track.
} else {
long rendererDurationUs = renderer.getDurationUs();
long rendererBufferedPositionUs = renderer.getBufferedPositionUs();
if (rendererBufferedPositionUs == TrackRenderer.UNKNOWN_TIME) {
bufferedPositionUs = TrackRenderer.UNKNOWN_TIME;
} else if (rendererBufferedPositionUs == TrackRenderer.END_OF_TRACK
|| (rendererDurationUs != TrackRenderer.UNKNOWN_TIME
&& rendererDurationUs != TrackRenderer.MATCH_LONGEST
if (rendererBufferedPositionUs == TrackRenderer.UNKNOWN_TIME_US) {
bufferedPositionUs = TrackRenderer.UNKNOWN_TIME_US;
} else if (rendererBufferedPositionUs == TrackRenderer.END_OF_TRACK_US
|| (rendererDurationUs != TrackRenderer.UNKNOWN_TIME_US
&& rendererDurationUs != TrackRenderer.MATCH_LONGEST_US
&& rendererBufferedPositionUs >= rendererDurationUs)) {
// This track is fully buffered.
} else {

View File

@ -72,7 +72,7 @@ public final class FrameworkSampleSource implements SampleSource {
for (int i = 0; i < trackStates.length; i++) {
android.media.MediaFormat format = extractor.getTrackFormat(i);
long duration = format.containsKey(android.media.MediaFormat.KEY_DURATION) ?
format.getLong(android.media.MediaFormat.KEY_DURATION) : TrackRenderer.UNKNOWN_TIME;
format.getLong(android.media.MediaFormat.KEY_DURATION) : TrackRenderer.UNKNOWN_TIME_US;
String mime = format.getString(android.media.MediaFormat.KEY_MIME);
trackInfos[i] = new TrackInfo(mime, duration);
}
@ -188,7 +188,7 @@ public final class FrameworkSampleSource implements SampleSource {
Assertions.checkState(prepared);
long bufferedDurationUs = extractor.getCachedDuration();
if (bufferedDurationUs == -1) {
return TrackRenderer.UNKNOWN_TIME;
return TrackRenderer.UNKNOWN_TIME_US;
} else {
return extractor.getSampleTime() + bufferedDurationUs;
}

View File

@ -340,7 +340,7 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer {
@Override
protected long getBufferedPositionUs() {
long sourceBufferedPosition = source.getBufferedPositionUs();
return sourceBufferedPosition == UNKNOWN_TIME || sourceBufferedPosition == END_OF_TRACK
return sourceBufferedPosition == UNKNOWN_TIME_US || sourceBufferedPosition == END_OF_TRACK_US
? sourceBufferedPosition : Math.max(sourceBufferedPosition, getCurrentPositionUs());
}

View File

@ -147,8 +147,8 @@ public interface SampleSource {
* This method should not be called until after the source has been successfully prepared.
*
* @return An estimate of the absolute position in micro-seconds up to which data is buffered,
* or {@link TrackRenderer#END_OF_TRACK} if data is buffered to the end of the stream, or
* {@link TrackRenderer#UNKNOWN_TIME} if no estimate is available.
* or {@link TrackRenderer#END_OF_TRACK_US} if data is buffered to the end of the stream, or
* {@link TrackRenderer#UNKNOWN_TIME_US} if no estimate is available.
*/
public long getBufferedPositionUs();

View File

@ -67,16 +67,16 @@ public abstract class TrackRenderer implements ExoPlayerComponent {
/**
* Represents an unknown time or duration.
*/
public static final long UNKNOWN_TIME = -1;
public static final long UNKNOWN_TIME_US = -1;
/**
* Represents a time or duration that should match the duration of the longest track whose
* duration is known.
*/
public static final long MATCH_LONGEST = -2;
public static final long MATCH_LONGEST_US = -2;
/**
* Represents the time of the end of the track.
*/
public static final long END_OF_TRACK = -3;
public static final long END_OF_TRACK_US = -3;
private int state;
@ -301,9 +301,9 @@ public abstract class TrackRenderer implements ExoPlayerComponent {
* This method may be called when the renderer is in the following states:
* {@link #STATE_PREPARED}, {@link #STATE_ENABLED}, {@link #STATE_STARTED}
*
* @return The duration of the track in micro-seconds, or {@link #MATCH_LONGEST} if
* @return The duration of the track in micro-seconds, or {@link #MATCH_LONGEST_US} if
* the track's duration should match that of the longest track whose duration is known, or
* or {@link #UNKNOWN_TIME} if the duration is not known.
* or {@link #UNKNOWN_TIME_US} if the duration is not known.
*/
protected abstract long getDurationUs();
@ -324,8 +324,8 @@ public abstract class TrackRenderer implements ExoPlayerComponent {
* {@link #STATE_ENABLED}, {@link #STATE_STARTED}
*
* @return An estimate of the absolute position in micro-seconds up to which data is buffered,
* or {@link #END_OF_TRACK} if the track is fully buffered, or {@link #UNKNOWN_TIME} if no
* estimate is available.
* or {@link #END_OF_TRACK_US} if the track is fully buffered, or {@link #UNKNOWN_TIME_US} if
* no estimate is available.
*/
protected abstract long getBufferedPositionUs();

View File

@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer.chunk;
import com.google.android.exoplayer.C;
import com.google.android.exoplayer.upstream.Allocation;
import com.google.android.exoplayer.upstream.Allocator;
import com.google.android.exoplayer.upstream.DataSource;
@ -89,8 +90,8 @@ public abstract class Chunk implements Loadable {
/**
* Gets the length of the chunk in bytes.
*
* @return The length of the chunk in bytes, or {@value DataSpec#LENGTH_UNBOUNDED} if the length
* has yet to be determined.
* @return The length of the chunk in bytes, or {@link C#LENGTH_UNBOUNDED} if the length has yet
* to be determined.
*/
public final long getLength() {
return dataSourceStream.getLength();

View File

@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer.chunk;
import com.google.android.exoplayer.C;
import com.google.android.exoplayer.FormatHolder;
import com.google.android.exoplayer.LoadControl;
import com.google.android.exoplayer.MediaFormat;
@ -22,7 +23,6 @@ import com.google.android.exoplayer.SampleHolder;
import com.google.android.exoplayer.SampleSource;
import com.google.android.exoplayer.TrackInfo;
import com.google.android.exoplayer.TrackRenderer;
import com.google.android.exoplayer.upstream.DataSpec;
import com.google.android.exoplayer.upstream.Loader;
import com.google.android.exoplayer.util.Assertions;
@ -383,14 +383,14 @@ public class ChunkSampleSource implements SampleSource, Loader.Listener {
if (currentLoadable != null && mediaChunk == currentLoadable) {
// Linearly interpolate partially-fetched chunk times.
long chunkLength = mediaChunk.getLength();
if (chunkLength != DataSpec.LENGTH_UNBOUNDED) {
if (chunkLength != C.LENGTH_UNBOUNDED) {
return mediaChunk.startTimeUs + ((mediaChunk.endTimeUs - mediaChunk.startTimeUs) *
mediaChunk.bytesLoaded()) / chunkLength;
} else {
return mediaChunk.startTimeUs;
}
} else if (mediaChunk.isLastChunk()) {
return TrackRenderer.END_OF_TRACK;
return TrackRenderer.END_OF_TRACK_US;
} else {
return mediaChunk.endTimeUs;
}

View File

@ -230,7 +230,7 @@ public class TextTrackRenderer extends TrackRenderer implements Callback {
@Override
protected long getBufferedPositionUs() {
// Don't block playback whilst subtitles are loading.
return END_OF_TRACK;
return END_OF_TRACK_US;
}
@Override

View File

@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer.upstream;
import com.google.android.exoplayer.C;
import com.google.android.exoplayer.util.Assertions;
import java.io.ByteArrayOutputStream;
@ -29,7 +30,7 @@ public class ByteArrayDataSink implements DataSink {
@Override
public DataSink open(DataSpec dataSpec) throws IOException {
if (dataSpec.length == DataSpec.LENGTH_UNBOUNDED) {
if (dataSpec.length == C.LENGTH_UNBOUNDED) {
stream = new ByteArrayOutputStream();
} else {
Assertions.checkArgument(dataSpec.length <= Integer.MAX_VALUE);

View File

@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer.upstream;
import com.google.android.exoplayer.C;
import com.google.android.exoplayer.util.Assertions;
import java.io.IOException;
@ -36,14 +37,14 @@ public class ByteArrayDataSource implements DataSource {
@Override
public long open(DataSpec dataSpec) throws IOException {
if (dataSpec.length == DataSpec.LENGTH_UNBOUNDED) {
if (dataSpec.length == C.LENGTH_UNBOUNDED) {
Assertions.checkArgument(dataSpec.position < data.length);
} else {
Assertions.checkArgument(dataSpec.position + dataSpec.length <= data.length);
}
readPosition = (int) dataSpec.position;
return (dataSpec.length == DataSpec.LENGTH_UNBOUNDED)
? (data.length - dataSpec.position) : dataSpec.length;
return (dataSpec.length == C.LENGTH_UNBOUNDED) ? (data.length - dataSpec.position)
: dataSpec.length;
}
@Override

View File

@ -15,6 +15,8 @@
*/
package com.google.android.exoplayer.upstream;
import com.google.android.exoplayer.C;
import java.io.IOException;
/**
@ -34,9 +36,9 @@ public interface DataSource {
* @param dataSpec Defines the data to be read.
* @throws IOException If an error occurs opening the source.
* @return The number of bytes that can be read from the opened source. For unbounded requests
* (i.e. requests where {@link DataSpec#length} equals {@link DataSpec#LENGTH_UNBOUNDED})
* this value is the resolved length of the request. For all other requests, the value
* returned will be equal to the request's {@link DataSpec#length}.
* (i.e. requests where {@link DataSpec#length} equals {@link C#LENGTH_UNBOUNDED}) this value
* is the resolved length of the request. For all other requests, the value returned will be
* equal to the request's {@link DataSpec#length}.
*/
public long open(DataSpec dataSpec) throws IOException;

View File

@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer.upstream;
import com.google.android.exoplayer.C;
import com.google.android.exoplayer.upstream.Loader.Loadable;
import com.google.android.exoplayer.util.Assertions;
import com.google.android.exoplayer.util.Util;
@ -67,7 +68,7 @@ public final class DataSourceStream implements Loadable, NonBlockingInputStream
this.dataSource = dataSource;
this.dataSpec = dataSpec;
this.allocator = allocator;
resolvedLength = DataSpec.LENGTH_UNBOUNDED;
resolvedLength = C.LENGTH_UNBOUNDED;
readHead = new ReadHead();
}
@ -99,11 +100,11 @@ public final class DataSourceStream implements Loadable, NonBlockingInputStream
/**
* Returns the length of the streamin bytes.
*
* @return The length of the stream in bytes, or {@value DataSpec#LENGTH_UNBOUNDED} if the length
* has yet to be determined.
* @return The length of the stream in bytes, or {@value C#LENGTH_UNBOUNDED} if the length has
* yet to be determined.
*/
public long getLength() {
return resolvedLength != DataSpec.LENGTH_UNBOUNDED ? resolvedLength : dataSpec.length;
return resolvedLength != C.LENGTH_UNBOUNDED ? resolvedLength : dataSpec.length;
}
/**
@ -112,7 +113,7 @@ public final class DataSourceStream implements Loadable, NonBlockingInputStream
* @return True if the stream has finished loading. False otherwise.
*/
public boolean isLoadFinished() {
return resolvedLength != DataSpec.LENGTH_UNBOUNDED && loadPosition == resolvedLength;
return resolvedLength != C.LENGTH_UNBOUNDED && loadPosition == resolvedLength;
}
/**
@ -144,7 +145,7 @@ public final class DataSourceStream implements Loadable, NonBlockingInputStream
@Override
public boolean isEndOfStream() {
return resolvedLength != DataSpec.LENGTH_UNBOUNDED && readHead.position == resolvedLength;
return resolvedLength != C.LENGTH_UNBOUNDED && readHead.position == resolvedLength;
}
@Override
@ -233,7 +234,7 @@ public final class DataSourceStream implements Loadable, NonBlockingInputStream
}
try {
DataSpec loadDataSpec;
if (resolvedLength == DataSpec.LENGTH_UNBOUNDED) {
if (resolvedLength == C.LENGTH_UNBOUNDED) {
loadDataSpec = dataSpec;
resolvedLength = dataSource.open(loadDataSpec);
if (resolvedLength > Integer.MAX_VALUE) {

View File

@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer.upstream;
import com.google.android.exoplayer.C;
import com.google.android.exoplayer.util.Assertions;
import android.net.Uri;
@ -24,13 +25,6 @@ import android.net.Uri;
*/
public final class DataSpec {
/**
* A permitted value of {@link #length}. A {@link DataSpec} defined with this length represents
* the region of media data that starts at its {@link #position} and extends to the end of the
* data whose location is defined by its {@link #uri}.
*/
public static final int LENGTH_UNBOUNDED = -1;
/**
* Identifies the source from which data should be read.
*/
@ -50,7 +44,7 @@ public final class DataSpec {
*/
public final long position;
/**
* The length of the data. Greater than zero, or equal to {@link #LENGTH_UNBOUNDED}.
* The length of the data. Greater than zero, or equal to {@link C#LENGTH_UNBOUNDED}.
*/
public final long length;
/**
@ -98,7 +92,7 @@ public final class DataSpec {
boolean uriIsFullStream) {
Assertions.checkArgument(absoluteStreamPosition >= 0);
Assertions.checkArgument(position >= 0);
Assertions.checkArgument(length > 0 || length == LENGTH_UNBOUNDED);
Assertions.checkArgument(length > 0 || length == C.LENGTH_UNBOUNDED);
Assertions.checkArgument(absoluteStreamPosition == position || !uriIsFullStream);
this.uri = uri;
this.uriIsFullStream = uriIsFullStream;

View File

@ -15,6 +15,8 @@
*/
package com.google.android.exoplayer.upstream;
import com.google.android.exoplayer.C;
import java.io.IOException;
import java.io.RandomAccessFile;
@ -42,8 +44,7 @@ public final class FileDataSource implements DataSource {
try {
file = new RandomAccessFile(dataSpec.uri.getPath(), "r");
file.seek(dataSpec.position);
bytesRemaining = dataSpec.length == DataSpec.LENGTH_UNBOUNDED
? file.length() - dataSpec.position
bytesRemaining = dataSpec.length == C.LENGTH_UNBOUNDED ? file.length() - dataSpec.position
: dataSpec.length;
return bytesRemaining;
} catch (IOException e) {

View File

@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer.upstream;
import com.google.android.exoplayer.C;
import com.google.android.exoplayer.util.Assertions;
import com.google.android.exoplayer.util.Predicate;
import com.google.android.exoplayer.util.Util;
@ -258,16 +259,16 @@ public class HttpDataSource implements DataSource {
}
long contentLength = getContentLength(connection);
dataLength = dataSpec.length == DataSpec.LENGTH_UNBOUNDED ? contentLength : dataSpec.length;
if (dataLength == DataSpec.LENGTH_UNBOUNDED) {
dataLength = dataSpec.length == C.LENGTH_UNBOUNDED ? contentLength : dataSpec.length;
if (dataLength == C.LENGTH_UNBOUNDED) {
// The DataSpec specified unbounded length and we failed to resolve a length from the
// response headers.
throw new HttpDataSourceException(
new UnexpectedLengthException(DataSpec.LENGTH_UNBOUNDED, DataSpec.LENGTH_UNBOUNDED),
new UnexpectedLengthException(C.LENGTH_UNBOUNDED, C.LENGTH_UNBOUNDED),
dataSpec);
}
if (dataSpec.length != DataSpec.LENGTH_UNBOUNDED && contentLength != DataSpec.LENGTH_UNBOUNDED
if (dataSpec.length != C.LENGTH_UNBOUNDED && contentLength != C.LENGTH_UNBOUNDED
&& contentLength != dataSpec.length) {
// The DataSpec specified a length and we resolved a length from the response headers, but
// the two lengths do not match.
@ -394,14 +395,14 @@ public class HttpDataSource implements DataSource {
private String buildRangeHeader(DataSpec dataSpec) {
String rangeRequest = "bytes=" + dataSpec.position + "-";
if (dataSpec.length != DataSpec.LENGTH_UNBOUNDED) {
if (dataSpec.length != C.LENGTH_UNBOUNDED) {
rangeRequest += (dataSpec.position + dataSpec.length - 1);
}
return rangeRequest;
}
private long getContentLength(HttpURLConnection connection) {
long contentLength = DataSpec.LENGTH_UNBOUNDED;
long contentLength = C.LENGTH_UNBOUNDED;
String contentLengthHeader = connection.getHeaderField("Content-Length");
if (!TextUtils.isEmpty(contentLengthHeader)) {
try {
@ -435,7 +436,7 @@ public class HttpDataSource implements DataSource {
}
}
}
if (contentLength == DataSpec.LENGTH_UNBOUNDED) {
if (contentLength == C.LENGTH_UNBOUNDED) {
Log.w(TAG, "Unable to parse content length [" + contentLengthHeader + "] [" +
contentRangeHeader + "]");
}

View File

@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer.upstream;
import com.google.android.exoplayer.C;
import com.google.android.exoplayer.util.Assertions;
import java.io.IOException;
@ -39,7 +40,7 @@ public final class TeeDataSource implements DataSource {
@Override
public long open(DataSpec dataSpec) throws IOException {
long dataLength = upstream.open(dataSpec);
if (dataSpec.length == DataSpec.LENGTH_UNBOUNDED) {
if (dataSpec.length == C.LENGTH_UNBOUNDED) {
// Reconstruct dataSpec in order to provide the resolved length to the sink.
dataSpec = new DataSpec(dataSpec.uri, dataSpec.absoluteStreamPosition, dataLength,
dataSpec.key, dataSpec.position, dataSpec.uriIsFullStream);

View File

@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer.upstream.cache;
import com.google.android.exoplayer.C;
import com.google.android.exoplayer.upstream.DataSink;
import com.google.android.exoplayer.upstream.DataSource;
import com.google.android.exoplayer.upstream.DataSpec;
@ -124,7 +125,7 @@ public final class CacheDataSource implements DataSource {
Assertions.checkState(dataSpec.uriIsFullStream);
// TODO: Support caching for unbounded requests. This requires storing the source length
// into the cache (the simplest approach is to incorporate it into each cache file's name).
Assertions.checkState(dataSpec.length != DataSpec.LENGTH_UNBOUNDED);
Assertions.checkState(dataSpec.length != C.LENGTH_UNBOUNDED);
try {
uri = dataSpec.uri;
key = dataSpec.key;