Content/Asset data sources - Handle >2^31 byte files correctly.

Issue #641
This commit is contained in:
Oliver Woodman 2015-07-23 13:44:11 +01:00
parent b57b80f723
commit 7ea199638e
2 changed files with 40 additions and 14 deletions

View File

@ -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);
}

View File

@ -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);
}