Content/Asset data sources - Handle >2^31 byte files correctly.
Issue #641
This commit is contained in:
parent
b57b80f723
commit
7ea199638e
@ -16,7 +16,6 @@
|
||||
package com.google.android.exoplayer.upstream;
|
||||
|
||||
import com.google.android.exoplayer.C;
|
||||
import com.google.android.exoplayer.util.Assertions;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.AssetManager;
|
||||
@ -79,12 +78,22 @@ public final class AssetDataSource implements UriDataSource {
|
||||
uriString = dataSpec.uri.toString();
|
||||
inputStream = assetManager.open(path, AssetManager.ACCESS_RANDOM);
|
||||
long skipped = inputStream.skip(dataSpec.position);
|
||||
Assertions.checkState(skipped == dataSpec.position);
|
||||
bytesRemaining = dataSpec.length == C.LENGTH_UNBOUNDED ? inputStream.available()
|
||||
: dataSpec.length;
|
||||
if (bytesRemaining < 0) {
|
||||
if (skipped < dataSpec.position) {
|
||||
// assetManager.open() returns an AssetInputStream, whose skip() implementation only skips
|
||||
// fewer bytes than requested if the skip is beyond the end of the asset's data.
|
||||
throw new EOFException();
|
||||
}
|
||||
if (dataSpec.length != C.LENGTH_UNBOUNDED) {
|
||||
bytesRemaining = dataSpec.length;
|
||||
} else {
|
||||
bytesRemaining = inputStream.available();
|
||||
if (bytesRemaining == Integer.MAX_VALUE) {
|
||||
// assetManager.open() returns an AssetInputStream, whose available() implementation
|
||||
// returns Integer.MAX_VALUE if the remaining length is greater than (or equal to)
|
||||
// Integer.MAX_VALUE. We don't know the true length in this case, so treat as unbounded.
|
||||
bytesRemaining = C.LENGTH_UNBOUNDED;
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new AssetDataSourceException(e);
|
||||
}
|
||||
@ -103,13 +112,17 @@ public final class AssetDataSource implements UriDataSource {
|
||||
} else {
|
||||
int bytesRead = 0;
|
||||
try {
|
||||
bytesRead = inputStream.read(buffer, offset, (int) Math.min(bytesRemaining, readLength));
|
||||
int bytesToRead = bytesRemaining == C.LENGTH_UNBOUNDED ? readLength
|
||||
: (int) Math.min(bytesRemaining, readLength);
|
||||
bytesRead = inputStream.read(buffer, offset, bytesToRead);
|
||||
} catch (IOException e) {
|
||||
throw new AssetDataSourceException(e);
|
||||
}
|
||||
|
||||
if (bytesRead > 0) {
|
||||
bytesRemaining -= bytesRead;
|
||||
if (bytesRemaining != C.LENGTH_UNBOUNDED) {
|
||||
bytesRemaining -= bytesRead;
|
||||
}
|
||||
if (listener != null) {
|
||||
listener.onBytesTransferred(bytesRead);
|
||||
}
|
||||
|
@ -16,7 +16,6 @@
|
||||
package com.google.android.exoplayer.upstream;
|
||||
|
||||
import com.google.android.exoplayer.C;
|
||||
import com.google.android.exoplayer.util.Assertions;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
@ -75,12 +74,22 @@ public final class ContentDataSource implements UriDataSource {
|
||||
AssetFileDescriptor assetFd = resolver.openAssetFileDescriptor(dataSpec.uri, "r");
|
||||
inputStream = new FileInputStream(assetFd.getFileDescriptor());
|
||||
long skipped = inputStream.skip(dataSpec.position);
|
||||
Assertions.checkState(skipped == dataSpec.position);
|
||||
bytesRemaining = dataSpec.length == C.LENGTH_UNBOUNDED ? inputStream.available()
|
||||
: dataSpec.length;
|
||||
if (bytesRemaining < 0) {
|
||||
if (skipped < dataSpec.position) {
|
||||
// We expect the skip to be satisfied in full. If it isn't then we're probably trying to
|
||||
// skip beyond the end of the data.
|
||||
throw new EOFException();
|
||||
}
|
||||
if (dataSpec.length != C.LENGTH_UNBOUNDED) {
|
||||
bytesRemaining = dataSpec.length;
|
||||
} else {
|
||||
bytesRemaining = inputStream.available();
|
||||
if (bytesRemaining == 0) {
|
||||
// FileInputStream.available() returns 0 if the remaining length cannot be determined, or
|
||||
// if it's greater than Integer.MAX_VALUE. We don't know the true length in either case,
|
||||
// so treat as unbounded.
|
||||
bytesRemaining = C.LENGTH_UNBOUNDED;
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new ContentDataSourceException(e);
|
||||
}
|
||||
@ -100,13 +109,17 @@ public final class ContentDataSource implements UriDataSource {
|
||||
} else {
|
||||
int bytesRead = 0;
|
||||
try {
|
||||
bytesRead = inputStream.read(buffer, offset, (int) Math.min(bytesRemaining, readLength));
|
||||
int bytesToRead = bytesRemaining == C.LENGTH_UNBOUNDED ? readLength
|
||||
: (int) Math.min(bytesRemaining, readLength);
|
||||
bytesRead = inputStream.read(buffer, offset, bytesToRead);
|
||||
} catch (IOException e) {
|
||||
throw new ContentDataSourceException(e);
|
||||
}
|
||||
|
||||
if (bytesRead > 0) {
|
||||
bytesRemaining -= bytesRead;
|
||||
if (bytesRemaining != C.LENGTH_UNBOUNDED) {
|
||||
bytesRemaining -= bytesRead;
|
||||
}
|
||||
if (listener != null) {
|
||||
listener.onBytesTransferred(bytesRead);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user