mirror of
https://github.com/samsonjs/media.git
synced 2026-04-02 10:45:51 +00:00
Fix DataSchemeDataSource re-opening and range requests
Issue:#6192 PiperOrigin-RevId: 258592902
This commit is contained in:
parent
bee35ed9d7
commit
80d5dabd52
3 changed files with 72 additions and 14 deletions
|
|
@ -25,6 +25,8 @@
|
|||
* Add `enable` and `disable` methods to `MediaSource` to improve resource
|
||||
management in playlists.
|
||||
* Fix issue where initial seek positions get ignored when playing a preroll ad.
|
||||
* Fix `DataSchemeDataSource` re-opening and range requests
|
||||
([#6192](https://github.com/google/ExoPlayer/issues/6192)).
|
||||
|
||||
### 2.10.3 ###
|
||||
|
||||
|
|
|
|||
|
|
@ -33,8 +33,8 @@ public final class DataSchemeDataSource extends BaseDataSource {
|
|||
|
||||
@Nullable private DataSpec dataSpec;
|
||||
@Nullable private byte[] data;
|
||||
private int dataLength;
|
||||
private int bytesRead;
|
||||
private int endPosition;
|
||||
private int readPosition;
|
||||
|
||||
public DataSchemeDataSource() {
|
||||
super(/* isNetwork= */ false);
|
||||
|
|
@ -44,6 +44,7 @@ public final class DataSchemeDataSource extends BaseDataSource {
|
|||
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)) {
|
||||
|
|
@ -57,17 +58,21 @@ public final class DataSchemeDataSource extends BaseDataSource {
|
|||
if (uriParts[0].contains(";base64")) {
|
||||
try {
|
||||
data = Base64.decode(dataString, 0);
|
||||
dataLength = data.length;
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new ParserException("Error while parsing Base64 encoded string: " + dataString, e);
|
||||
}
|
||||
} else {
|
||||
// TODO: Add support for other charsets.
|
||||
data = Util.getUtf8Bytes(URLDecoder.decode(dataString, C.ASCII_NAME));
|
||||
dataLength = data.length;
|
||||
}
|
||||
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 dataLength;
|
||||
return (long) endPosition - readPosition;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -75,13 +80,13 @@ public final class DataSchemeDataSource extends BaseDataSource {
|
|||
if (readLength == 0) {
|
||||
return 0;
|
||||
}
|
||||
int remainingBytes = dataLength - bytesRead;
|
||||
int remainingBytes = endPosition - readPosition;
|
||||
if (remainingBytes == 0) {
|
||||
return C.RESULT_END_OF_INPUT;
|
||||
}
|
||||
readLength = Math.min(readLength, remainingBytes);
|
||||
System.arraycopy(castNonNull(data), bytesRead, buffer, offset, readLength);
|
||||
bytesRead += readLength;
|
||||
System.arraycopy(castNonNull(data), readPosition, buffer, offset, readLength);
|
||||
readPosition += readLength;
|
||||
bytesTransferred(readLength);
|
||||
return readLength;
|
||||
}
|
||||
|
|
@ -93,12 +98,11 @@ public final class DataSchemeDataSource extends BaseDataSource {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
public void close() {
|
||||
if (data != null) {
|
||||
data = null;
|
||||
transferEnded();
|
||||
}
|
||||
dataSpec = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import static org.junit.Assert.fail;
|
|||
|
||||
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;
|
||||
|
|
@ -31,6 +32,9 @@ import org.junit.runner.RunWith;
|
|||
@RunWith(AndroidJUnit4.class)
|
||||
public final class DataSchemeDataSourceTest {
|
||||
|
||||
private static final String DATA_SCHEME_URI =
|
||||
"data:text/plain;base64,eyJwcm92aWRlciI6IndpZGV2aW5lX3Rlc3QiLCJjb250ZW50X2lkIjoiTWpBeE5WOTBaV"
|
||||
+ "0Z5Y3c9PSIsImtleV9pZHMiOlsiMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAiXX0=";
|
||||
private DataSource schemeDataDataSource;
|
||||
|
||||
@Before
|
||||
|
|
@ -40,9 +44,7 @@ public final class DataSchemeDataSourceTest {
|
|||
|
||||
@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,
|
||||
|
|
@ -72,6 +74,52 @@ public final class DataSchemeDataSourceTest {
|
|||
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 {
|
||||
|
|
@ -99,7 +147,11 @@ public final class DataSchemeDataSourceTest {
|
|||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue