use of com.google.android.exoplayer2.upstream.DataSourceException in project ExoPlayer by google.
the class CronetDataSource method open.
@Override
public long open(DataSpec dataSpec) throws HttpDataSourceException {
Assertions.checkNotNull(dataSpec);
Assertions.checkState(!opened);
operation.close();
resetConnectTimeout();
currentDataSpec = dataSpec;
currentUrlRequest = buildRequest(dataSpec);
currentUrlRequest.start();
boolean requestStarted = blockUntilConnectTimeout();
if (exception != null) {
throw new OpenException(exception, currentDataSpec, getStatus(currentUrlRequest));
} else if (!requestStarted) {
// The timeout was reached before the connection was opened.
throw new OpenException(new SocketTimeoutException(), dataSpec, getStatus(currentUrlRequest));
}
// Check for a valid response code.
int responseCode = responseInfo.getHttpStatusCode();
if (responseCode < 200 || responseCode > 299) {
InvalidResponseCodeException exception = new InvalidResponseCodeException(responseCode, responseInfo.getAllHeaders(), currentDataSpec);
if (responseCode == 416) {
exception.initCause(new DataSourceException(DataSourceException.POSITION_OUT_OF_RANGE));
}
throw exception;
}
// Check for a valid content type.
if (contentTypePredicate != null) {
List<String> contentTypeHeaders = responseInfo.getAllHeaders().get(CONTENT_TYPE);
String contentType = isEmpty(contentTypeHeaders) ? null : contentTypeHeaders.get(0);
if (!contentTypePredicate.evaluate(contentType)) {
throw new InvalidContentTypeException(contentType, currentDataSpec);
}
}
// If we requested a range starting from a non-zero position and received a 200 rather than a
// 206, then the server does not support partial requests. We'll need to manually skip to the
// requested position.
bytesToSkip = responseCode == 200 && dataSpec.position != 0 ? dataSpec.position : 0;
// Calculate the content length.
if (!getIsCompressed(responseInfo)) {
if (dataSpec.length != C.LENGTH_UNSET) {
bytesRemaining = dataSpec.length;
} else {
bytesRemaining = getContentLength(responseInfo);
}
} else {
// If the response is compressed then the content length will be that of the compressed data
// which isn't what we want. Always use the dataSpec length in this case.
bytesRemaining = currentDataSpec.length;
}
opened = true;
if (listener != null) {
listener.onTransferStart(this, dataSpec);
}
return bytesRemaining;
}
use of com.google.android.exoplayer2.upstream.DataSourceException in project ExoPlayer by google.
the class OkHttpDataSource method open.
@Override
public long open(DataSpec dataSpec) throws HttpDataSourceException {
this.dataSpec = dataSpec;
this.bytesRead = 0;
this.bytesSkipped = 0;
Request request = makeRequest(dataSpec);
try {
response = callFactory.newCall(request).execute();
responseByteStream = response.body().byteStream();
} catch (IOException e) {
throw new HttpDataSourceException("Unable to connect to " + dataSpec.uri.toString(), e, dataSpec, HttpDataSourceException.TYPE_OPEN);
}
int responseCode = response.code();
// Check for a valid response code.
if (!response.isSuccessful()) {
Map<String, List<String>> headers = request.headers().toMultimap();
closeConnectionQuietly();
InvalidResponseCodeException exception = new InvalidResponseCodeException(responseCode, headers, dataSpec);
if (responseCode == 416) {
exception.initCause(new DataSourceException(DataSourceException.POSITION_OUT_OF_RANGE));
}
throw exception;
}
// Check for a valid content type.
MediaType mediaType = response.body().contentType();
String contentType = mediaType != null ? mediaType.toString() : null;
if (contentTypePredicate != null && !contentTypePredicate.evaluate(contentType)) {
closeConnectionQuietly();
throw new InvalidContentTypeException(contentType, dataSpec);
}
// If we requested a range starting from a non-zero position and received a 200 rather than a
// 206, then the server does not support partial requests. We'll need to manually skip to the
// requested position.
bytesToSkip = responseCode == 200 && dataSpec.position != 0 ? dataSpec.position : 0;
// Determine the length of the data to be read, after skipping.
if (dataSpec.length != C.LENGTH_UNSET) {
bytesToRead = dataSpec.length;
} else {
long contentLength = response.body().contentLength();
bytesToRead = contentLength != -1 ? (contentLength - bytesToSkip) : C.LENGTH_UNSET;
}
opened = true;
if (listener != null) {
listener.onTransferStart(this, dataSpec);
}
return bytesToRead;
}
use of com.google.android.exoplayer2.upstream.DataSourceException in project ExoPlayer by google.
the class CacheDataSource method openNextSource.
/**
* Opens the next source. If the cache contains data spanning the current read position then
* {@link #cacheReadDataSource} is opened to read from it. Else {@link #upstreamDataSource} is
* opened to read from the upstream source and write into the cache.
* @param initial Whether it is the initial open call.
*/
private boolean openNextSource(boolean initial) throws IOException {
DataSpec dataSpec;
CacheSpan span;
if (currentRequestIgnoresCache) {
span = null;
} else if (blockOnCache) {
try {
span = cache.startReadWrite(key, readPosition);
} catch (InterruptedException e) {
throw new InterruptedIOException();
}
} else {
span = cache.startReadWriteNonBlocking(key, readPosition);
}
if (span == null) {
// The data is locked in the cache, or we're ignoring the cache. Bypass the cache and read
// from upstream.
currentDataSource = upstreamDataSource;
dataSpec = new DataSpec(uri, readPosition, bytesRemaining, key, flags);
} else if (span.isCached) {
// Data is cached, read from cache.
Uri fileUri = Uri.fromFile(span.file);
long filePosition = readPosition - span.position;
long length = span.length - filePosition;
if (bytesRemaining != C.LENGTH_UNSET) {
length = Math.min(length, bytesRemaining);
}
dataSpec = new DataSpec(fileUri, readPosition, filePosition, length, key, flags);
currentDataSource = cacheReadDataSource;
} else {
// Data is not cached, and data is not locked, read from upstream with cache backing.
long length;
if (span.isOpenEnded()) {
length = bytesRemaining;
} else {
length = span.length;
if (bytesRemaining != C.LENGTH_UNSET) {
length = Math.min(length, bytesRemaining);
}
}
dataSpec = new DataSpec(uri, readPosition, length, key, flags);
if (cacheWriteDataSource != null) {
currentDataSource = cacheWriteDataSource;
lockedSpan = span;
} else {
currentDataSource = upstreamDataSource;
cache.releaseHoleSpan(span);
}
}
currentRequestUnbounded = dataSpec.length == C.LENGTH_UNSET;
boolean successful = false;
long currentBytesRemaining = 0;
try {
currentBytesRemaining = currentDataSource.open(dataSpec);
successful = true;
} catch (IOException e) {
// end of the stream.
if (!initial && currentRequestUnbounded) {
Throwable cause = e;
while (cause != null) {
if (cause instanceof DataSourceException) {
int reason = ((DataSourceException) cause).reason;
if (reason == DataSourceException.POSITION_OUT_OF_RANGE) {
e = null;
break;
}
}
cause = cause.getCause();
}
}
if (e != null) {
throw e;
}
}
// bytesRemaining == C.LENGTH_UNSET) and got a resolved length from open() request
if (currentRequestUnbounded && currentBytesRemaining != C.LENGTH_UNSET) {
bytesRemaining = currentBytesRemaining;
setContentLength(dataSpec.position + bytesRemaining);
}
return successful;
}
Aggregations