mirror of
https://github.com/samsonjs/media.git
synced 2026-06-30 05:49:33 +00:00
Add support for the data URI scheme
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=165699328
This commit is contained in:
parent
cc9a93d9d9
commit
1e4f899548
4 changed files with 194 additions and 1 deletions
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.google.android.exoplayer2.upstream;
|
||||
|
||||
import android.net.Uri;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.testutil.TestUtil;
|
||||
import java.io.IOException;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link DataSchemeDataSource}.
|
||||
*/
|
||||
public final class DataSchemeDataSourceTest extends TestCase {
|
||||
|
||||
private DataSource schemeDataDataSource;
|
||||
|
||||
@Override
|
||||
public void setUp() {
|
||||
schemeDataDataSource = new DataSchemeDataSource();
|
||||
}
|
||||
|
||||
public void testBase64Data() throws IOException {
|
||||
DataSpec dataSpec = buildDataSpec("data:text/plain;base64,eyJwcm92aWRlciI6IndpZGV2aW5lX3Rlc3QiL"
|
||||
+ "CJjb250ZW50X2lkIjoiTWpBeE5WOTBaV0Z5Y3c9PSIsImtleV9pZHMiOlsiMDAwMDAwMDAwMDAwMDAwMDAwMDAwM"
|
||||
+ "DAwMDAwMDAwMDAiXX0=");
|
||||
TestUtil.assertDataSourceContent(schemeDataDataSource, dataSpec,
|
||||
("{\"provider\":\"widevine_test\",\"content_id\":\"MjAxNV90ZWFycw==\",\"key_ids\":"
|
||||
+ "[\"00000000000000000000000000000000\"]}").getBytes());
|
||||
}
|
||||
|
||||
public void testAsciiData() throws IOException {
|
||||
TestUtil.assertDataSourceContent(schemeDataDataSource, buildDataSpec("data:,A%20brief%20note"),
|
||||
"A brief note".getBytes());
|
||||
}
|
||||
|
||||
public void testPartialReads() throws IOException {
|
||||
byte[] buffer = new byte[18];
|
||||
DataSpec dataSpec = buildDataSpec("data:,012345678901234567");
|
||||
assertEquals(18, schemeDataDataSource.open(dataSpec));
|
||||
assertEquals(9, schemeDataDataSource.read(buffer, 0, 9));
|
||||
assertEquals(0, schemeDataDataSource.read(buffer, 3, 0));
|
||||
assertEquals(9, schemeDataDataSource.read(buffer, 9, 15));
|
||||
assertEquals(0, schemeDataDataSource.read(buffer, 1, 0));
|
||||
assertEquals(C.RESULT_END_OF_INPUT, schemeDataDataSource.read(buffer, 1, 1));
|
||||
assertEquals("012345678901234567", new String(buffer, 0, 18));
|
||||
}
|
||||
|
||||
public void testIncorrectScheme() {
|
||||
try {
|
||||
schemeDataDataSource.open(buildDataSpec("http://www.google.com"));
|
||||
fail();
|
||||
} catch (IOException e) {
|
||||
// Expected.
|
||||
}
|
||||
}
|
||||
|
||||
public void testMalformedData() {
|
||||
try {
|
||||
schemeDataDataSource.open(buildDataSpec("data:text/plain;base64,,This%20is%20Content"));
|
||||
fail();
|
||||
} catch (IOException e) {
|
||||
// Expected.
|
||||
}
|
||||
try {
|
||||
schemeDataDataSource.open(buildDataSpec("data:text/plain;base64,IncorrectPadding=="));
|
||||
fail();
|
||||
} catch (IOException e) {
|
||||
// Expected.
|
||||
}
|
||||
}
|
||||
|
||||
private static DataSpec buildDataSpec(String uriString) {
|
||||
return new DataSpec(Uri.parse(uriString));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -73,6 +73,10 @@ public final class C {
|
|||
*/
|
||||
public static final long NANOS_PER_SECOND = 1000000000L;
|
||||
|
||||
/**
|
||||
* The name of the ASCII charset.
|
||||
*/
|
||||
public static final String ASCII_NAME = "US-ASCII";
|
||||
/**
|
||||
* The name of the UTF-8 charset.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.google.android.exoplayer2.upstream;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.util.Base64;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.ParserException;
|
||||
import java.io.IOException;
|
||||
import java.net.URLDecoder;
|
||||
|
||||
/**
|
||||
* A {@link DataSource} for reading data URLs, as defined by RFC 2397.
|
||||
*/
|
||||
public final class DataSchemeDataSource implements DataSource {
|
||||
|
||||
public static final String SCHEME_DATA = "data";
|
||||
|
||||
private DataSpec dataSpec;
|
||||
private int bytesRead;
|
||||
private byte[] data;
|
||||
|
||||
@Override
|
||||
public long open(DataSpec dataSpec) throws IOException {
|
||||
this.dataSpec = dataSpec;
|
||||
Uri uri = dataSpec.uri;
|
||||
String scheme = uri.getScheme();
|
||||
if (!SCHEME_DATA.equals(scheme)) {
|
||||
throw new ParserException("Unsupported scheme: " + scheme);
|
||||
}
|
||||
String[] uriParts = uri.getSchemeSpecificPart().split(",");
|
||||
if (uriParts.length > 2) {
|
||||
throw new ParserException("Unexpected URI format: " + uri);
|
||||
}
|
||||
String dataString = uriParts[1];
|
||||
if (uriParts[0].contains(";base64")) {
|
||||
try {
|
||||
data = Base64.decode(dataString, 0);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new ParserException("Error while parsing Base64 encoded string: " + dataString, e);
|
||||
}
|
||||
} else {
|
||||
// TODO: Add support for other charsets.
|
||||
data = URLDecoder.decode(dataString, C.ASCII_NAME).getBytes();
|
||||
}
|
||||
return data.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] buffer, int offset, int readLength) {
|
||||
if (readLength == 0) {
|
||||
return 0;
|
||||
}
|
||||
int remainingBytes = data.length - bytesRead;
|
||||
if (remainingBytes == 0) {
|
||||
return C.RESULT_END_OF_INPUT;
|
||||
}
|
||||
readLength = Math.min(readLength, remainingBytes);
|
||||
System.arraycopy(data, bytesRead, buffer, offset, readLength);
|
||||
bytesRead += readLength;
|
||||
return readLength;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uri getUri() {
|
||||
return dataSpec != null ? dataSpec.uri : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
dataSpec = null;
|
||||
data = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -34,10 +34,11 @@ import java.lang.reflect.InvocationTargetException;
|
|||
* <li>content: For fetching data from a content URI (e.g. content://authority/path/123).
|
||||
* <li>rtmp: For fetching data over RTMP. Only supported if the project using ExoPlayer has an
|
||||
* explicit dependency on ExoPlayer's RTMP extension.</li>
|
||||
* <li>data: For parsing data inlined in the URI as defined in RFC 2397.</li>
|
||||
* <li>http(s): For fetching data over HTTP and HTTPS (e.g. https://www.something.com/media.mp4), if
|
||||
* constructed using {@link #DefaultDataSource(Context, TransferListener, String, boolean)}, or
|
||||
* any other schemes supported by a base data source if constructed using
|
||||
* {@link #DefaultDataSource(Context, TransferListener, DataSource)}.
|
||||
* {@link #DefaultDataSource(Context, TransferListener, DataSource)}.</li>
|
||||
* </ul>
|
||||
*/
|
||||
public final class DefaultDataSource implements DataSource {
|
||||
|
|
@ -58,6 +59,7 @@ public final class DefaultDataSource implements DataSource {
|
|||
private DataSource assetDataSource;
|
||||
private DataSource contentDataSource;
|
||||
private DataSource rtmpDataSource;
|
||||
private DataSource dataSchemeDataSource;
|
||||
|
||||
private DataSource dataSource;
|
||||
|
||||
|
|
@ -130,6 +132,8 @@ public final class DefaultDataSource implements DataSource {
|
|||
dataSource = getContentDataSource();
|
||||
} else if (SCHEME_RTMP.equals(scheme)) {
|
||||
dataSource = getRtmpDataSource();
|
||||
} else if (DataSchemeDataSource.SCHEME_DATA.equals(scheme)) {
|
||||
dataSource = getDataSchemeDataSource();
|
||||
} else {
|
||||
dataSource = baseDataSource;
|
||||
}
|
||||
|
|
@ -202,4 +206,11 @@ public final class DefaultDataSource implements DataSource {
|
|||
return rtmpDataSource;
|
||||
}
|
||||
|
||||
private DataSource getDataSchemeDataSource() {
|
||||
if (dataSchemeDataSource == null) {
|
||||
dataSchemeDataSource = new DataSchemeDataSource();
|
||||
}
|
||||
return dataSchemeDataSource;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue