Skip to content

Commit

Permalink
Fix DataSchemeDataSource re-opening and range requests
Browse files Browse the repository at this point in the history
Issue:#6192
PiperOrigin-RevId: 258592902
  • Loading branch information
AquilesCanta authored and ojw28 committed Jul 26, 2019
1 parent 962d5e7 commit e181d4b
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 14 deletions.
2 changes: 2 additions & 0 deletions RELEASENOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
* Flac extension: Parse `VORBIS_COMMENT` metadata
([#5527](https:/google/ExoPlayer/issues/5527)).
* Fix issue where initial seek positions get ignored when playing a preroll ad.
* Fix `DataSchemeDataSource` re-opening and range requests
([#6192](https:/google/ExoPlayer/issues/6192)).

### 2.10.3 ###

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
*/
package com.google.android.exoplayer2.upstream;

import static com.google.android.exoplayer2.util.Util.castNonNull;

import android.net.Uri;
import androidx.annotation.Nullable;
import android.util.Base64;
Expand All @@ -29,9 +31,10 @@ public final class DataSchemeDataSource extends BaseDataSource {

public static final String SCHEME_DATA = "data";

private @Nullable DataSpec dataSpec;
private int bytesRead;
private @Nullable byte[] data;
@Nullable private DataSpec dataSpec;
@Nullable private byte[] data;
private int endPosition;
private int readPosition;

public DataSchemeDataSource() {
super(/* isNetwork= */ false);
Expand All @@ -41,6 +44,7 @@ public DataSchemeDataSource() {
public long open(DataSpec dataSpec) throws IOException {
transferInitializing(dataSpec);
this.dataSpec = dataSpec;
readPosition = (int) dataSpec.position;
Uri uri = dataSpec.uri;
String scheme = uri.getScheme();
if (!SCHEME_DATA.equals(scheme)) {
Expand All @@ -61,38 +65,44 @@ public long open(DataSpec dataSpec) throws IOException {
// TODO: Add support for other charsets.
data = Util.getUtf8Bytes(URLDecoder.decode(dataString, C.ASCII_NAME));
}
endPosition =
dataSpec.length != C.LENGTH_UNSET ? (int) dataSpec.length + readPosition : data.length;
if (endPosition > data.length || readPosition > endPosition) {
data = null;
throw new DataSourceException(DataSourceException.POSITION_OUT_OF_RANGE);
}
transferStarted(dataSpec);
return data.length;
return (long) endPosition - readPosition;
}

@Override
public int read(byte[] buffer, int offset, int readLength) {
if (readLength == 0) {
return 0;
}
int remainingBytes = data.length - bytesRead;
int remainingBytes = endPosition - readPosition;
if (remainingBytes == 0) {
return C.RESULT_END_OF_INPUT;
}
readLength = Math.min(readLength, remainingBytes);
System.arraycopy(data, bytesRead, buffer, offset, readLength);
bytesRead += readLength;
System.arraycopy(castNonNull(data), readPosition, buffer, offset, readLength);
readPosition += readLength;
bytesTransferred(readLength);
return readLength;
}

@Override
public @Nullable Uri getUri() {
@Nullable
public Uri getUri() {
return dataSpec != null ? dataSpec.uri : null;
}

@Override
public void close() throws IOException {
public void close() {
if (data != null) {
data = null;
transferEnded();
}
dataSpec = null;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import android.net.Uri;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.util.Util;
import java.io.IOException;
import org.junit.Before;
Expand All @@ -31,6 +32,9 @@
@RunWith(AndroidJUnit4.class)
public final class DataSchemeDataSourceTest {

private static final String DATA_SCHEME_URI =
"data:text/plain;base64,eyJwcm92aWRlciI6IndpZGV2aW5lX3Rlc3QiLCJjb250ZW50X2lkIjoiTWpBeE5WOTBaV"
+ "0Z5Y3c9PSIsImtleV9pZHMiOlsiMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAiXX0=";
private DataSource schemeDataDataSource;

@Before
Expand All @@ -40,9 +44,7 @@ public void setUp() {

@Test
public void testBase64Data() throws IOException {
DataSpec dataSpec = buildDataSpec("data:text/plain;base64,eyJwcm92aWRlciI6IndpZGV2aW5lX3Rlc3QiL"
+ "CJjb250ZW50X2lkIjoiTWpBeE5WOTBaV0Z5Y3c9PSIsImtleV9pZHMiOlsiMDAwMDAwMDAwMDAwMDAwMDAwMDAwM"
+ "DAwMDAwMDAwMDAiXX0=");
DataSpec dataSpec = buildDataSpec(DATA_SCHEME_URI);
DataSourceAsserts.assertDataSourceContent(
schemeDataDataSource,
dataSpec,
Expand Down Expand Up @@ -72,6 +74,52 @@ public void testPartialReads() throws IOException {
assertThat(Util.fromUtf8Bytes(buffer, 0, 18)).isEqualTo("012345678901234567");
}

@Test
public void testSequentialRangeRequests() throws IOException {
DataSpec dataSpec =
buildDataSpec(DATA_SCHEME_URI, /* position= */ 1, /* length= */ C.LENGTH_UNSET);
DataSourceAsserts.assertDataSourceContent(
schemeDataDataSource,
dataSpec,
Util.getUtf8Bytes(
"\"provider\":\"widevine_test\",\"content_id\":\"MjAxNV90ZWFycw==\",\"key_ids\":"
+ "[\"00000000000000000000000000000000\"]}"));
dataSpec = buildDataSpec(DATA_SCHEME_URI, /* position= */ 10, /* length= */ C.LENGTH_UNSET);
DataSourceAsserts.assertDataSourceContent(
schemeDataDataSource,
dataSpec,
Util.getUtf8Bytes(
"\":\"widevine_test\",\"content_id\":\"MjAxNV90ZWFycw==\",\"key_ids\":"
+ "[\"00000000000000000000000000000000\"]}"));
dataSpec = buildDataSpec(DATA_SCHEME_URI, /* position= */ 15, /* length= */ 5);
DataSourceAsserts.assertDataSourceContent(
schemeDataDataSource, dataSpec, Util.getUtf8Bytes("devin"));
}

@Test
public void testInvalidStartPositionRequest() throws IOException {
try {
// Try to open a range starting one byte beyond the resource's length.
schemeDataDataSource.open(
buildDataSpec(DATA_SCHEME_URI, /* position= */ 108, /* length= */ C.LENGTH_UNSET));
fail();
} catch (DataSourceException e) {
assertThat(e.reason).isEqualTo(DataSourceException.POSITION_OUT_OF_RANGE);
}
}

@Test
public void testRangeExceedingResourceLengthRequest() throws IOException {
try {
// Try to open a range exceeding the resource's length.
schemeDataDataSource.open(
buildDataSpec(DATA_SCHEME_URI, /* position= */ 97, /* length= */ 11));
fail();
} catch (DataSourceException e) {
assertThat(e.reason).isEqualTo(DataSourceException.POSITION_OUT_OF_RANGE);
}
}

@Test
public void testIncorrectScheme() {
try {
Expand Down Expand Up @@ -99,7 +147,11 @@ public void testMalformedData() {
}

private static DataSpec buildDataSpec(String uriString) {
return new DataSpec(Uri.parse(uriString));
return buildDataSpec(uriString, /* position= */ 0, /* length= */ C.LENGTH_UNSET);
}

private static DataSpec buildDataSpec(String uriString, int position, int length) {
return new DataSpec(Uri.parse(uriString), position, length, /* key= */ null);
}

}

0 comments on commit e181d4b

Please sign in to comment.