Remove some files from the nullness blacklist
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=205816544
This commit is contained in:
parent
138b222457
commit
340d846d9b
@ -33,6 +33,7 @@ android {
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation project(modulePrefix + 'library-core')
|
implementation project(modulePrefix + 'library-core')
|
||||||
implementation 'com.android.support:support-annotations:' + supportLibraryVersion
|
implementation 'com.android.support:support-annotations:' + supportLibraryVersion
|
||||||
|
compileOnly 'org.checkerframework:checker-qual:' + checkerframeworkVersion
|
||||||
api 'com.squareup.okhttp3:okhttp:3.10.0'
|
api 'com.squareup.okhttp3:okhttp:3.10.0'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,8 +15,9 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.ext.okhttp;
|
package com.google.android.exoplayer2.ext.okhttp;
|
||||||
|
|
||||||
|
import static org.checkerframework.checker.nullness.NullnessUtil.castNonNull;
|
||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
|
import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
|
||||||
@ -24,7 +25,6 @@ import com.google.android.exoplayer2.upstream.BaseDataSource;
|
|||||||
import com.google.android.exoplayer2.upstream.DataSourceException;
|
import com.google.android.exoplayer2.upstream.DataSourceException;
|
||||||
import com.google.android.exoplayer2.upstream.DataSpec;
|
import com.google.android.exoplayer2.upstream.DataSpec;
|
||||||
import com.google.android.exoplayer2.upstream.HttpDataSource;
|
import com.google.android.exoplayer2.upstream.HttpDataSource;
|
||||||
import com.google.android.exoplayer2.upstream.TransferListener;
|
|
||||||
import com.google.android.exoplayer2.util.Assertions;
|
import com.google.android.exoplayer2.util.Assertions;
|
||||||
import com.google.android.exoplayer2.util.Predicate;
|
import com.google.android.exoplayer2.util.Predicate;
|
||||||
import java.io.EOFException;
|
import java.io.EOFException;
|
||||||
@ -34,7 +34,6 @@ import java.io.InterruptedIOException;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
|
||||||
import okhttp3.CacheControl;
|
import okhttp3.CacheControl;
|
||||||
import okhttp3.Call;
|
import okhttp3.Call;
|
||||||
import okhttp3.HttpUrl;
|
import okhttp3.HttpUrl;
|
||||||
@ -42,6 +41,7 @@ import okhttp3.MediaType;
|
|||||||
import okhttp3.Request;
|
import okhttp3.Request;
|
||||||
import okhttp3.RequestBody;
|
import okhttp3.RequestBody;
|
||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
|
import okhttp3.ResponseBody;
|
||||||
|
|
||||||
/** An {@link HttpDataSource} that delegates to Square's {@link Call.Factory}. */
|
/** An {@link HttpDataSource} that delegates to Square's {@link Call.Factory}. */
|
||||||
public class OkHttpDataSource extends BaseDataSource implements HttpDataSource {
|
public class OkHttpDataSource extends BaseDataSource implements HttpDataSource {
|
||||||
@ -50,19 +50,19 @@ public class OkHttpDataSource extends BaseDataSource implements HttpDataSource {
|
|||||||
ExoPlayerLibraryInfo.registerModule("goog.exo.okhttp");
|
ExoPlayerLibraryInfo.registerModule("goog.exo.okhttp");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final AtomicReference<byte[]> skipBufferReference = new AtomicReference<>();
|
private static final byte[] SKIP_BUFFER = new byte[4096];
|
||||||
|
|
||||||
@NonNull private final Call.Factory callFactory;
|
private final Call.Factory callFactory;
|
||||||
@NonNull private final RequestProperties requestProperties;
|
private final RequestProperties requestProperties;
|
||||||
|
|
||||||
@Nullable private final String userAgent;
|
private final @Nullable String userAgent;
|
||||||
@Nullable private final Predicate<String> contentTypePredicate;
|
private final @Nullable Predicate<String> contentTypePredicate;
|
||||||
@Nullable private final CacheControl cacheControl;
|
private final @Nullable CacheControl cacheControl;
|
||||||
@Nullable private final RequestProperties defaultRequestProperties;
|
private final @Nullable RequestProperties defaultRequestProperties;
|
||||||
|
|
||||||
private DataSpec dataSpec;
|
private @Nullable DataSpec dataSpec;
|
||||||
private Response response;
|
private @Nullable Response response;
|
||||||
private InputStream responseByteStream;
|
private @Nullable InputStream responseByteStream;
|
||||||
private boolean opened;
|
private boolean opened;
|
||||||
|
|
||||||
private long bytesToSkip;
|
private long bytesToSkip;
|
||||||
@ -71,18 +71,6 @@ public class OkHttpDataSource extends BaseDataSource implements HttpDataSource {
|
|||||||
private long bytesSkipped;
|
private long bytesSkipped;
|
||||||
private long bytesRead;
|
private long bytesRead;
|
||||||
|
|
||||||
/**
|
|
||||||
* @param callFactory A {@link Call.Factory} (typically an {@link okhttp3.OkHttpClient}) for use
|
|
||||||
* by the source.
|
|
||||||
* @param userAgent An optional User-Agent string.
|
|
||||||
* @param contentTypePredicate An optional {@link Predicate}. If a content type is rejected by the
|
|
||||||
* predicate then a InvalidContentTypeException} is thrown from {@link #open(DataSpec)}.
|
|
||||||
*/
|
|
||||||
public OkHttpDataSource(@NonNull Call.Factory callFactory, @Nullable String userAgent,
|
|
||||||
@Nullable Predicate<String> contentTypePredicate) {
|
|
||||||
this(callFactory, userAgent, contentTypePredicate, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param callFactory A {@link Call.Factory} (typically an {@link okhttp3.OkHttpClient}) for use
|
* @param callFactory A {@link Call.Factory} (typically an {@link okhttp3.OkHttpClient}) for use
|
||||||
* by the source.
|
* by the source.
|
||||||
@ -90,14 +78,17 @@ public class OkHttpDataSource extends BaseDataSource implements HttpDataSource {
|
|||||||
* @param contentTypePredicate An optional {@link Predicate}. If a content type is rejected by the
|
* @param contentTypePredicate An optional {@link Predicate}. If a content type is rejected by the
|
||||||
* predicate then a {@link InvalidContentTypeException} is thrown from {@link
|
* predicate then a {@link InvalidContentTypeException} is thrown from {@link
|
||||||
* #open(DataSpec)}.
|
* #open(DataSpec)}.
|
||||||
* @param listener An optional listener.
|
|
||||||
*/
|
*/
|
||||||
public OkHttpDataSource(
|
public OkHttpDataSource(
|
||||||
@NonNull Call.Factory callFactory,
|
Call.Factory callFactory,
|
||||||
@Nullable String userAgent,
|
@Nullable String userAgent,
|
||||||
@Nullable Predicate<String> contentTypePredicate,
|
@Nullable Predicate<String> contentTypePredicate) {
|
||||||
@Nullable TransferListener listener) {
|
this(
|
||||||
this(callFactory, userAgent, contentTypePredicate, listener, null, null);
|
callFactory,
|
||||||
|
userAgent,
|
||||||
|
contentTypePredicate,
|
||||||
|
/* cacheControl= */ null,
|
||||||
|
/* defaultRequestProperties= */ null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -107,16 +98,14 @@ public class OkHttpDataSource extends BaseDataSource implements HttpDataSource {
|
|||||||
* @param contentTypePredicate An optional {@link Predicate}. If a content type is rejected by the
|
* @param contentTypePredicate An optional {@link Predicate}. If a content type is rejected by the
|
||||||
* predicate then a {@link InvalidContentTypeException} is thrown from {@link
|
* predicate then a {@link InvalidContentTypeException} is thrown from {@link
|
||||||
* #open(DataSpec)}.
|
* #open(DataSpec)}.
|
||||||
* @param listener An optional listener.
|
|
||||||
* @param cacheControl An optional {@link CacheControl} for setting the Cache-Control header.
|
* @param cacheControl An optional {@link CacheControl} for setting the Cache-Control header.
|
||||||
* @param defaultRequestProperties The optional default {@link RequestProperties} to be sent to
|
* @param defaultRequestProperties The optional default {@link RequestProperties} to be sent to
|
||||||
* the server as HTTP headers on every request.
|
* the server as HTTP headers on every request.
|
||||||
*/
|
*/
|
||||||
public OkHttpDataSource(
|
public OkHttpDataSource(
|
||||||
@NonNull Call.Factory callFactory,
|
Call.Factory callFactory,
|
||||||
@Nullable String userAgent,
|
@Nullable String userAgent,
|
||||||
@Nullable Predicate<String> contentTypePredicate,
|
@Nullable Predicate<String> contentTypePredicate,
|
||||||
@Nullable TransferListener listener,
|
|
||||||
@Nullable CacheControl cacheControl,
|
@Nullable CacheControl cacheControl,
|
||||||
@Nullable RequestProperties defaultRequestProperties) {
|
@Nullable RequestProperties defaultRequestProperties) {
|
||||||
super(/* isNetwork= */ true);
|
super(/* isNetwork= */ true);
|
||||||
@ -126,13 +115,10 @@ public class OkHttpDataSource extends BaseDataSource implements HttpDataSource {
|
|||||||
this.cacheControl = cacheControl;
|
this.cacheControl = cacheControl;
|
||||||
this.defaultRequestProperties = defaultRequestProperties;
|
this.defaultRequestProperties = defaultRequestProperties;
|
||||||
this.requestProperties = new RequestProperties();
|
this.requestProperties = new RequestProperties();
|
||||||
if (listener != null) {
|
|
||||||
addTransferListener(listener);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Uri getUri() {
|
public @Nullable Uri getUri() {
|
||||||
return response == null ? null : Uri.parse(response.request().url().toString());
|
return response == null ? null : Uri.parse(response.request().url().toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,10 +151,15 @@ public class OkHttpDataSource extends BaseDataSource implements HttpDataSource {
|
|||||||
this.bytesRead = 0;
|
this.bytesRead = 0;
|
||||||
this.bytesSkipped = 0;
|
this.bytesSkipped = 0;
|
||||||
transferInitializing(dataSpec);
|
transferInitializing(dataSpec);
|
||||||
|
|
||||||
Request request = makeRequest(dataSpec);
|
Request request = makeRequest(dataSpec);
|
||||||
|
Response response;
|
||||||
|
ResponseBody responseBody;
|
||||||
try {
|
try {
|
||||||
response = callFactory.newCall(request).execute();
|
this.response = callFactory.newCall(request).execute();
|
||||||
responseByteStream = response.body().byteStream();
|
response = this.response;
|
||||||
|
responseBody = Assertions.checkNotNull(response.body());
|
||||||
|
responseByteStream = responseBody.byteStream();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new HttpDataSourceException("Unable to connect to " + dataSpec.uri.toString(), e,
|
throw new HttpDataSourceException("Unable to connect to " + dataSpec.uri.toString(), e,
|
||||||
dataSpec, HttpDataSourceException.TYPE_OPEN);
|
dataSpec, HttpDataSourceException.TYPE_OPEN);
|
||||||
@ -189,8 +180,8 @@ public class OkHttpDataSource extends BaseDataSource implements HttpDataSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check for a valid content type.
|
// Check for a valid content type.
|
||||||
MediaType mediaType = response.body().contentType();
|
MediaType mediaType = responseBody.contentType();
|
||||||
String contentType = mediaType != null ? mediaType.toString() : null;
|
String contentType = mediaType != null ? mediaType.toString() : "";
|
||||||
if (contentTypePredicate != null && !contentTypePredicate.evaluate(contentType)) {
|
if (contentTypePredicate != null && !contentTypePredicate.evaluate(contentType)) {
|
||||||
closeConnectionQuietly();
|
closeConnectionQuietly();
|
||||||
throw new InvalidContentTypeException(contentType, dataSpec);
|
throw new InvalidContentTypeException(contentType, dataSpec);
|
||||||
@ -205,7 +196,7 @@ public class OkHttpDataSource extends BaseDataSource implements HttpDataSource {
|
|||||||
if (dataSpec.length != C.LENGTH_UNSET) {
|
if (dataSpec.length != C.LENGTH_UNSET) {
|
||||||
bytesToRead = dataSpec.length;
|
bytesToRead = dataSpec.length;
|
||||||
} else {
|
} else {
|
||||||
long contentLength = response.body().contentLength();
|
long contentLength = responseBody.contentLength();
|
||||||
bytesToRead = contentLength != -1 ? (contentLength - bytesToSkip) : C.LENGTH_UNSET;
|
bytesToRead = contentLength != -1 ? (contentLength - bytesToSkip) : C.LENGTH_UNSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,7 +212,8 @@ public class OkHttpDataSource extends BaseDataSource implements HttpDataSource {
|
|||||||
skipInternal();
|
skipInternal();
|
||||||
return readInternal(buffer, offset, readLength);
|
return readInternal(buffer, offset, readLength);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new HttpDataSourceException(e, dataSpec, HttpDataSourceException.TYPE_READ);
|
throw new HttpDataSourceException(
|
||||||
|
e, Assertions.checkNotNull(dataSpec), HttpDataSourceException.TYPE_READ);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,15 +258,18 @@ public class OkHttpDataSource extends BaseDataSource implements HttpDataSource {
|
|||||||
return bytesToRead == C.LENGTH_UNSET ? bytesToRead : bytesToRead - bytesRead;
|
return bytesToRead == C.LENGTH_UNSET ? bytesToRead : bytesToRead - bytesRead;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Establishes a connection. */
|
||||||
* Establishes a connection.
|
private Request makeRequest(DataSpec dataSpec) throws HttpDataSourceException {
|
||||||
*/
|
|
||||||
private Request makeRequest(DataSpec dataSpec) {
|
|
||||||
long position = dataSpec.position;
|
long position = dataSpec.position;
|
||||||
long length = dataSpec.length;
|
long length = dataSpec.length;
|
||||||
boolean allowGzip = dataSpec.isFlagSet(DataSpec.FLAG_ALLOW_GZIP);
|
boolean allowGzip = dataSpec.isFlagSet(DataSpec.FLAG_ALLOW_GZIP);
|
||||||
|
|
||||||
HttpUrl url = HttpUrl.parse(dataSpec.uri.toString());
|
HttpUrl url = HttpUrl.parse(dataSpec.uri.toString());
|
||||||
|
if (url == null) {
|
||||||
|
throw new HttpDataSourceException(
|
||||||
|
"Malformed URL", dataSpec, HttpDataSourceException.TYPE_OPEN);
|
||||||
|
}
|
||||||
|
|
||||||
Request.Builder builder = new Request.Builder().url(url);
|
Request.Builder builder = new Request.Builder().url(url);
|
||||||
if (cacheControl != null) {
|
if (cacheControl != null) {
|
||||||
builder.cacheControl(cacheControl);
|
builder.cacheControl(cacheControl);
|
||||||
@ -320,15 +315,9 @@ public class OkHttpDataSource extends BaseDataSource implements HttpDataSource {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Acquire the shared skip buffer.
|
|
||||||
byte[] skipBuffer = skipBufferReference.getAndSet(null);
|
|
||||||
if (skipBuffer == null) {
|
|
||||||
skipBuffer = new byte[4096];
|
|
||||||
}
|
|
||||||
|
|
||||||
while (bytesSkipped != bytesToSkip) {
|
while (bytesSkipped != bytesToSkip) {
|
||||||
int readLength = (int) Math.min(bytesToSkip - bytesSkipped, skipBuffer.length);
|
int readLength = (int) Math.min(bytesToSkip - bytesSkipped, SKIP_BUFFER.length);
|
||||||
int read = responseByteStream.read(skipBuffer, 0, readLength);
|
int read = castNonNull(responseByteStream).read(SKIP_BUFFER, 0, readLength);
|
||||||
if (Thread.currentThread().isInterrupted()) {
|
if (Thread.currentThread().isInterrupted()) {
|
||||||
throw new InterruptedIOException();
|
throw new InterruptedIOException();
|
||||||
}
|
}
|
||||||
@ -338,9 +327,6 @@ public class OkHttpDataSource extends BaseDataSource implements HttpDataSource {
|
|||||||
bytesSkipped += read;
|
bytesSkipped += read;
|
||||||
bytesTransferred(read);
|
bytesTransferred(read);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release the shared skip buffer.
|
|
||||||
skipBufferReference.set(skipBuffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -369,7 +355,7 @@ public class OkHttpDataSource extends BaseDataSource implements HttpDataSource {
|
|||||||
readLength = (int) Math.min(readLength, bytesRemaining);
|
readLength = (int) Math.min(readLength, bytesRemaining);
|
||||||
}
|
}
|
||||||
|
|
||||||
int read = responseByteStream.read(buffer, offset, readLength);
|
int read = castNonNull(responseByteStream).read(buffer, offset, readLength);
|
||||||
if (read == -1) {
|
if (read == -1) {
|
||||||
if (bytesToRead != C.LENGTH_UNSET) {
|
if (bytesToRead != C.LENGTH_UNSET) {
|
||||||
// End of stream reached having not read sufficient data.
|
// End of stream reached having not read sufficient data.
|
||||||
@ -387,8 +373,10 @@ public class OkHttpDataSource extends BaseDataSource implements HttpDataSource {
|
|||||||
* Closes the current connection quietly, if there is one.
|
* Closes the current connection quietly, if there is one.
|
||||||
*/
|
*/
|
||||||
private void closeConnectionQuietly() {
|
private void closeConnectionQuietly() {
|
||||||
response.body().close();
|
if (response != null) {
|
||||||
response = null;
|
Assertions.checkNotNull(response.body()).close();
|
||||||
|
response = null;
|
||||||
|
}
|
||||||
responseByteStream = null;
|
responseByteStream = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.ext.okhttp;
|
package com.google.android.exoplayer2.ext.okhttp;
|
||||||
|
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import com.google.android.exoplayer2.upstream.HttpDataSource;
|
import com.google.android.exoplayer2.upstream.HttpDataSource;
|
||||||
import com.google.android.exoplayer2.upstream.HttpDataSource.BaseFactory;
|
import com.google.android.exoplayer2.upstream.HttpDataSource.BaseFactory;
|
||||||
@ -29,17 +28,17 @@ import okhttp3.Call;
|
|||||||
*/
|
*/
|
||||||
public final class OkHttpDataSourceFactory extends BaseFactory {
|
public final class OkHttpDataSourceFactory extends BaseFactory {
|
||||||
|
|
||||||
@NonNull private final Call.Factory callFactory;
|
private final Call.Factory callFactory;
|
||||||
@Nullable private final String userAgent;
|
private final @Nullable String userAgent;
|
||||||
@Nullable private final TransferListener listener;
|
private final @Nullable TransferListener listener;
|
||||||
@Nullable private final CacheControl cacheControl;
|
private final @Nullable CacheControl cacheControl;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param callFactory A {@link Call.Factory} (typically an {@link okhttp3.OkHttpClient}) for use
|
* @param callFactory A {@link Call.Factory} (typically an {@link okhttp3.OkHttpClient}) for use
|
||||||
* by the sources created by the factory.
|
* by the sources created by the factory.
|
||||||
* @param userAgent An optional User-Agent string.
|
* @param userAgent An optional User-Agent string.
|
||||||
*/
|
*/
|
||||||
public OkHttpDataSourceFactory(@NonNull Call.Factory callFactory, @Nullable String userAgent) {
|
public OkHttpDataSourceFactory(Call.Factory callFactory, @Nullable String userAgent) {
|
||||||
this(callFactory, userAgent, /* listener= */ null, /* cacheControl= */ null);
|
this(callFactory, userAgent, /* listener= */ null, /* cacheControl= */ null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,9 +49,7 @@ public final class OkHttpDataSourceFactory extends BaseFactory {
|
|||||||
* @param cacheControl An optional {@link CacheControl} for setting the Cache-Control header.
|
* @param cacheControl An optional {@link CacheControl} for setting the Cache-Control header.
|
||||||
*/
|
*/
|
||||||
public OkHttpDataSourceFactory(
|
public OkHttpDataSourceFactory(
|
||||||
@NonNull Call.Factory callFactory,
|
Call.Factory callFactory, @Nullable String userAgent, @Nullable CacheControl cacheControl) {
|
||||||
@Nullable String userAgent,
|
|
||||||
@Nullable CacheControl cacheControl) {
|
|
||||||
this(callFactory, userAgent, /* listener= */ null, cacheControl);
|
this(callFactory, userAgent, /* listener= */ null, cacheControl);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,9 +60,7 @@ public final class OkHttpDataSourceFactory extends BaseFactory {
|
|||||||
* @param listener An optional listener.
|
* @param listener An optional listener.
|
||||||
*/
|
*/
|
||||||
public OkHttpDataSourceFactory(
|
public OkHttpDataSourceFactory(
|
||||||
@NonNull Call.Factory callFactory,
|
Call.Factory callFactory, @Nullable String userAgent, @Nullable TransferListener listener) {
|
||||||
@Nullable String userAgent,
|
|
||||||
@Nullable TransferListener listener) {
|
|
||||||
this(callFactory, userAgent, listener, /* cacheControl= */ null);
|
this(callFactory, userAgent, listener, /* cacheControl= */ null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,7 +72,7 @@ public final class OkHttpDataSourceFactory extends BaseFactory {
|
|||||||
* @param cacheControl An optional {@link CacheControl} for setting the Cache-Control header.
|
* @param cacheControl An optional {@link CacheControl} for setting the Cache-Control header.
|
||||||
*/
|
*/
|
||||||
public OkHttpDataSourceFactory(
|
public OkHttpDataSourceFactory(
|
||||||
@NonNull Call.Factory callFactory,
|
Call.Factory callFactory,
|
||||||
@Nullable String userAgent,
|
@Nullable String userAgent,
|
||||||
@Nullable TransferListener listener,
|
@Nullable TransferListener listener,
|
||||||
@Nullable CacheControl cacheControl) {
|
@Nullable CacheControl cacheControl) {
|
||||||
@ -90,7 +85,16 @@ public final class OkHttpDataSourceFactory extends BaseFactory {
|
|||||||
@Override
|
@Override
|
||||||
protected OkHttpDataSource createDataSourceInternal(
|
protected OkHttpDataSource createDataSourceInternal(
|
||||||
HttpDataSource.RequestProperties defaultRequestProperties) {
|
HttpDataSource.RequestProperties defaultRequestProperties) {
|
||||||
return new OkHttpDataSource(callFactory, userAgent, null, listener, cacheControl,
|
OkHttpDataSource dataSource =
|
||||||
defaultRequestProperties);
|
new OkHttpDataSource(
|
||||||
|
callFactory,
|
||||||
|
userAgent,
|
||||||
|
/* contentTypePredicate= */ null,
|
||||||
|
cacheControl,
|
||||||
|
defaultRequestProperties);
|
||||||
|
if (listener != null) {
|
||||||
|
dataSource.addTransferListener(listener);
|
||||||
|
}
|
||||||
|
return dataSource;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -182,7 +182,7 @@ public final class Format implements Parcelable {
|
|||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
float frameRate,
|
float frameRate,
|
||||||
List<byte[]> initializationData,
|
@Nullable List<byte[]> initializationData,
|
||||||
@C.SelectionFlags int selectionFlags) {
|
@C.SelectionFlags int selectionFlags) {
|
||||||
return createVideoContainerFormat(
|
return createVideoContainerFormat(
|
||||||
id,
|
id,
|
||||||
@ -208,7 +208,7 @@ public final class Format implements Parcelable {
|
|||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
float frameRate,
|
float frameRate,
|
||||||
List<byte[]> initializationData,
|
@Nullable List<byte[]> initializationData,
|
||||||
@C.SelectionFlags int selectionFlags) {
|
@C.SelectionFlags int selectionFlags) {
|
||||||
return new Format(
|
return new Format(
|
||||||
id,
|
id,
|
||||||
@ -249,7 +249,7 @@ public final class Format implements Parcelable {
|
|||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
float frameRate,
|
float frameRate,
|
||||||
List<byte[]> initializationData,
|
@Nullable List<byte[]> initializationData,
|
||||||
@Nullable DrmInitData drmInitData) {
|
@Nullable DrmInitData drmInitData) {
|
||||||
return createVideoSampleFormat(
|
return createVideoSampleFormat(
|
||||||
id,
|
id,
|
||||||
@ -275,7 +275,7 @@ public final class Format implements Parcelable {
|
|||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
float frameRate,
|
float frameRate,
|
||||||
List<byte[]> initializationData,
|
@Nullable List<byte[]> initializationData,
|
||||||
int rotationDegrees,
|
int rotationDegrees,
|
||||||
float pixelWidthHeightRatio,
|
float pixelWidthHeightRatio,
|
||||||
@Nullable DrmInitData drmInitData) {
|
@Nullable DrmInitData drmInitData) {
|
||||||
@ -306,7 +306,7 @@ public final class Format implements Parcelable {
|
|||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
float frameRate,
|
float frameRate,
|
||||||
List<byte[]> initializationData,
|
@Nullable List<byte[]> initializationData,
|
||||||
int rotationDegrees,
|
int rotationDegrees,
|
||||||
float pixelWidthHeightRatio,
|
float pixelWidthHeightRatio,
|
||||||
byte[] projectionData,
|
byte[] projectionData,
|
||||||
@ -354,7 +354,7 @@ public final class Format implements Parcelable {
|
|||||||
int bitrate,
|
int bitrate,
|
||||||
int channelCount,
|
int channelCount,
|
||||||
int sampleRate,
|
int sampleRate,
|
||||||
List<byte[]> initializationData,
|
@Nullable List<byte[]> initializationData,
|
||||||
@C.SelectionFlags int selectionFlags,
|
@C.SelectionFlags int selectionFlags,
|
||||||
@Nullable String language) {
|
@Nullable String language) {
|
||||||
return createAudioContainerFormat(
|
return createAudioContainerFormat(
|
||||||
@ -380,7 +380,7 @@ public final class Format implements Parcelable {
|
|||||||
int bitrate,
|
int bitrate,
|
||||||
int channelCount,
|
int channelCount,
|
||||||
int sampleRate,
|
int sampleRate,
|
||||||
List<byte[]> initializationData,
|
@Nullable List<byte[]> initializationData,
|
||||||
@C.SelectionFlags int selectionFlags,
|
@C.SelectionFlags int selectionFlags,
|
||||||
@Nullable String language) {
|
@Nullable String language) {
|
||||||
return new Format(
|
return new Format(
|
||||||
@ -421,7 +421,7 @@ public final class Format implements Parcelable {
|
|||||||
int maxInputSize,
|
int maxInputSize,
|
||||||
int channelCount,
|
int channelCount,
|
||||||
int sampleRate,
|
int sampleRate,
|
||||||
List<byte[]> initializationData,
|
@Nullable List<byte[]> initializationData,
|
||||||
@Nullable DrmInitData drmInitData,
|
@Nullable DrmInitData drmInitData,
|
||||||
@C.SelectionFlags int selectionFlags,
|
@C.SelectionFlags int selectionFlags,
|
||||||
@Nullable String language) {
|
@Nullable String language) {
|
||||||
@ -449,7 +449,7 @@ public final class Format implements Parcelable {
|
|||||||
int channelCount,
|
int channelCount,
|
||||||
int sampleRate,
|
int sampleRate,
|
||||||
@C.PcmEncoding int pcmEncoding,
|
@C.PcmEncoding int pcmEncoding,
|
||||||
List<byte[]> initializationData,
|
@Nullable List<byte[]> initializationData,
|
||||||
@Nullable DrmInitData drmInitData,
|
@Nullable DrmInitData drmInitData,
|
||||||
@C.SelectionFlags int selectionFlags,
|
@C.SelectionFlags int selectionFlags,
|
||||||
@Nullable String language) {
|
@Nullable String language) {
|
||||||
@ -482,7 +482,7 @@ public final class Format implements Parcelable {
|
|||||||
@C.PcmEncoding int pcmEncoding,
|
@C.PcmEncoding int pcmEncoding,
|
||||||
int encoderDelay,
|
int encoderDelay,
|
||||||
int encoderPadding,
|
int encoderPadding,
|
||||||
List<byte[]> initializationData,
|
@Nullable List<byte[]> initializationData,
|
||||||
@Nullable DrmInitData drmInitData,
|
@Nullable DrmInitData drmInitData,
|
||||||
@C.SelectionFlags int selectionFlags,
|
@C.SelectionFlags int selectionFlags,
|
||||||
@Nullable String language,
|
@Nullable String language,
|
||||||
@ -720,7 +720,7 @@ public final class Format implements Parcelable {
|
|||||||
@Nullable String codecs,
|
@Nullable String codecs,
|
||||||
int bitrate,
|
int bitrate,
|
||||||
@C.SelectionFlags int selectionFlags,
|
@C.SelectionFlags int selectionFlags,
|
||||||
List<byte[]> initializationData,
|
@Nullable List<byte[]> initializationData,
|
||||||
@Nullable String language,
|
@Nullable String language,
|
||||||
@Nullable DrmInitData drmInitData) {
|
@Nullable DrmInitData drmInitData) {
|
||||||
return new Format(
|
return new Format(
|
||||||
|
@ -15,14 +15,13 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2;
|
package com.google.android.exoplayer2;
|
||||||
|
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds a {@link Format}.
|
* Holds a {@link Format}.
|
||||||
*/
|
*/
|
||||||
public final class FormatHolder {
|
public final class FormatHolder {
|
||||||
|
|
||||||
/**
|
/** The held {@link Format}. */
|
||||||
* The held {@link Format}.
|
public @Nullable Format format;
|
||||||
*/
|
|
||||||
public Format format;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -137,17 +137,17 @@ public final class Ac3Util {
|
|||||||
121, 139, 174, 208, 243, 278, 348, 417, 487, 557, 696, 835, 975, 1114, 1253, 1393};
|
121, 139, 174, 208, 243, 278, 348, 417, 487, 557, 696, 835, 975, 1114, 1253, 1393};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the AC-3 format given {@code data} containing the AC3SpecificBox according to
|
* Returns the AC-3 format given {@code data} containing the AC3SpecificBox according to ETSI TS
|
||||||
* ETSI TS 102 366 Annex F. The reading position of {@code data} will be modified.
|
* 102 366 Annex F. The reading position of {@code data} will be modified.
|
||||||
*
|
*
|
||||||
* @param data The AC3SpecificBox to parse.
|
* @param data The AC3SpecificBox to parse.
|
||||||
* @param trackId The track identifier to set on the format, or null.
|
* @param trackId The track identifier to set on the format.
|
||||||
* @param language The language to set on the format.
|
* @param language The language to set on the format.
|
||||||
* @param drmInitData {@link DrmInitData} to be included in the format.
|
* @param drmInitData {@link DrmInitData} to be included in the format.
|
||||||
* @return The AC-3 format parsed from data in the header.
|
* @return The AC-3 format parsed from data in the header.
|
||||||
*/
|
*/
|
||||||
public static Format parseAc3AnnexFFormat(ParsableByteArray data, String trackId,
|
public static Format parseAc3AnnexFFormat(
|
||||||
String language, DrmInitData drmInitData) {
|
ParsableByteArray data, String trackId, String language, DrmInitData drmInitData) {
|
||||||
int fscod = (data.readUnsignedByte() & 0xC0) >> 6;
|
int fscod = (data.readUnsignedByte() & 0xC0) >> 6;
|
||||||
int sampleRate = SAMPLE_RATE_BY_FSCOD[fscod];
|
int sampleRate = SAMPLE_RATE_BY_FSCOD[fscod];
|
||||||
int nextByte = data.readUnsignedByte();
|
int nextByte = data.readUnsignedByte();
|
||||||
@ -155,22 +155,32 @@ public final class Ac3Util {
|
|||||||
if ((nextByte & 0x04) != 0) { // lfeon
|
if ((nextByte & 0x04) != 0) { // lfeon
|
||||||
channelCount++;
|
channelCount++;
|
||||||
}
|
}
|
||||||
return Format.createAudioSampleFormat(trackId, MimeTypes.AUDIO_AC3, null, Format.NO_VALUE,
|
return Format.createAudioSampleFormat(
|
||||||
Format.NO_VALUE, channelCount, sampleRate, null, drmInitData, 0, language);
|
trackId,
|
||||||
|
MimeTypes.AUDIO_AC3,
|
||||||
|
/* codecs= */ null,
|
||||||
|
Format.NO_VALUE,
|
||||||
|
Format.NO_VALUE,
|
||||||
|
channelCount,
|
||||||
|
sampleRate,
|
||||||
|
/* initializationData= */ null,
|
||||||
|
drmInitData,
|
||||||
|
/* selectionFlags= */ 0,
|
||||||
|
language);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the E-AC-3 format given {@code data} containing the EC3SpecificBox according to
|
* Returns the E-AC-3 format given {@code data} containing the EC3SpecificBox according to ETSI TS
|
||||||
* ETSI TS 102 366 Annex F. The reading position of {@code data} will be modified.
|
* 102 366 Annex F. The reading position of {@code data} will be modified.
|
||||||
*
|
*
|
||||||
* @param data The EC3SpecificBox to parse.
|
* @param data The EC3SpecificBox to parse.
|
||||||
* @param trackId The track identifier to set on the format, or null.
|
* @param trackId The track identifier to set on the format.
|
||||||
* @param language The language to set on the format.
|
* @param language The language to set on the format.
|
||||||
* @param drmInitData {@link DrmInitData} to be included in the format.
|
* @param drmInitData {@link DrmInitData} to be included in the format.
|
||||||
* @return The E-AC-3 format parsed from data in the header.
|
* @return The E-AC-3 format parsed from data in the header.
|
||||||
*/
|
*/
|
||||||
public static Format parseEAc3AnnexFFormat(ParsableByteArray data, String trackId,
|
public static Format parseEAc3AnnexFFormat(
|
||||||
String language, DrmInitData drmInitData) {
|
ParsableByteArray data, String trackId, String language, DrmInitData drmInitData) {
|
||||||
data.skipBytes(2); // data_rate, num_ind_sub
|
data.skipBytes(2); // data_rate, num_ind_sub
|
||||||
|
|
||||||
// Read the first independent substream.
|
// Read the first independent substream.
|
||||||
@ -200,8 +210,18 @@ public final class Ac3Util {
|
|||||||
mimeType = MimeTypes.AUDIO_E_AC3_JOC;
|
mimeType = MimeTypes.AUDIO_E_AC3_JOC;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Format.createAudioSampleFormat(trackId, mimeType, null, Format.NO_VALUE,
|
return Format.createAudioSampleFormat(
|
||||||
Format.NO_VALUE, channelCount, sampleRate, null, drmInitData, 0, language);
|
trackId,
|
||||||
|
mimeType,
|
||||||
|
/* codecs= */ null,
|
||||||
|
Format.NO_VALUE,
|
||||||
|
Format.NO_VALUE,
|
||||||
|
channelCount,
|
||||||
|
sampleRate,
|
||||||
|
/* initializationData= */ null,
|
||||||
|
drmInitData,
|
||||||
|
/* selectionFlags= */ 0,
|
||||||
|
language);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -74,13 +74,13 @@ public final class DtsUtil {
|
|||||||
* subsections 5.3/5.4.
|
* subsections 5.3/5.4.
|
||||||
*
|
*
|
||||||
* @param frame The DTS frame to parse.
|
* @param frame The DTS frame to parse.
|
||||||
* @param trackId The track identifier to set on the format, or null.
|
* @param trackId The track identifier to set on the format.
|
||||||
* @param language The language to set on the format.
|
* @param language The language to set on the format.
|
||||||
* @param drmInitData {@link DrmInitData} to be included in the format.
|
* @param drmInitData {@link DrmInitData} to be included in the format.
|
||||||
* @return The DTS format parsed from data in the header.
|
* @return The DTS format parsed from data in the header.
|
||||||
*/
|
*/
|
||||||
public static Format parseDtsFormat(byte[] frame, String trackId, String language,
|
public static Format parseDtsFormat(
|
||||||
DrmInitData drmInitData) {
|
byte[] frame, String trackId, String language, DrmInitData drmInitData) {
|
||||||
ParsableBitArray frameBits = getNormalizedFrameHeader(frame);
|
ParsableBitArray frameBits = getNormalizedFrameHeader(frame);
|
||||||
frameBits.skipBits(32 + 1 + 5 + 1 + 7 + 14); // SYNC, FTYPE, SHORT, CPF, NBLKS, FSIZE
|
frameBits.skipBits(32 + 1 + 5 + 1 + 7 + 14); // SYNC, FTYPE, SHORT, CPF, NBLKS, FSIZE
|
||||||
int amode = frameBits.readBits(6);
|
int amode = frameBits.readBits(6);
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.extractor.mp4;
|
package com.google.android.exoplayer2.extractor.mp4;
|
||||||
|
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import com.google.android.exoplayer2.util.ParsableByteArray;
|
import com.google.android.exoplayer2.util.ParsableByteArray;
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -214,14 +215,14 @@ import java.util.List;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the child leaf of the given type.
|
* Returns the child leaf of the given type.
|
||||||
* <p>
|
*
|
||||||
* If no child exists with the given type then null is returned. If multiple children exist with
|
* <p>If no child exists with the given type then null is returned. If multiple children exist
|
||||||
* the given type then the first one to have been added is returned.
|
* with the given type then the first one to have been added is returned.
|
||||||
*
|
*
|
||||||
* @param type The leaf type.
|
* @param type The leaf type.
|
||||||
* @return The child leaf of the given type, or null if no such child exists.
|
* @return The child leaf of the given type, or null if no such child exists.
|
||||||
*/
|
*/
|
||||||
public LeafAtom getLeafAtomOfType(int type) {
|
public @Nullable LeafAtom getLeafAtomOfType(int type) {
|
||||||
int childrenSize = leafChildren.size();
|
int childrenSize = leafChildren.size();
|
||||||
for (int i = 0; i < childrenSize; i++) {
|
for (int i = 0; i < childrenSize; i++) {
|
||||||
LeafAtom atom = leafChildren.get(i);
|
LeafAtom atom = leafChildren.get(i);
|
||||||
@ -234,14 +235,14 @@ import java.util.List;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the child container of the given type.
|
* Returns the child container of the given type.
|
||||||
* <p>
|
*
|
||||||
* If no child exists with the given type then null is returned. If multiple children exist with
|
* <p>If no child exists with the given type then null is returned. If multiple children exist
|
||||||
* the given type then the first one to have been added is returned.
|
* with the given type then the first one to have been added is returned.
|
||||||
*
|
*
|
||||||
* @param type The container type.
|
* @param type The container type.
|
||||||
* @return The child container of the given type, or null if no such child exists.
|
* @return The child container of the given type, or null if no such child exists.
|
||||||
*/
|
*/
|
||||||
public ContainerAtom getContainerAtomOfType(int type) {
|
public @Nullable ContainerAtom getContainerAtomOfType(int type) {
|
||||||
int childrenSize = containerChildren.size();
|
int childrenSize = containerChildren.size();
|
||||||
for (int i = 0; i < childrenSize; i++) {
|
for (int i = 0; i < childrenSize; i++) {
|
||||||
ContainerAtom atom = containerChildren.get(i);
|
ContainerAtom atom = containerChildren.get(i);
|
||||||
|
@ -681,7 +681,7 @@ import java.util.List;
|
|||||||
parent.setPosition(position + Atom.HEADER_SIZE + StsdData.STSD_HEADER_SIZE);
|
parent.setPosition(position + Atom.HEADER_SIZE + StsdData.STSD_HEADER_SIZE);
|
||||||
|
|
||||||
// Default values.
|
// Default values.
|
||||||
List<byte[]> initializationData = Collections.emptyList();
|
List<byte[]> initializationData = null;
|
||||||
long subsampleOffsetUs = Format.OFFSET_SAMPLE_RELATIVE;
|
long subsampleOffsetUs = Format.OFFSET_SAMPLE_RELATIVE;
|
||||||
|
|
||||||
String mimeType;
|
String mimeType;
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.extractor.mp4;
|
package com.google.android.exoplayer2.extractor.mp4;
|
||||||
|
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import com.google.android.exoplayer2.metadata.Metadata;
|
import com.google.android.exoplayer2.metadata.Metadata;
|
||||||
import com.google.android.exoplayer2.metadata.id3.ApicFrame;
|
import com.google.android.exoplayer2.metadata.id3.ApicFrame;
|
||||||
@ -69,6 +70,8 @@ import com.google.android.exoplayer2.util.Util;
|
|||||||
// Type for items that are intended for internal use by the player.
|
// Type for items that are intended for internal use by the player.
|
||||||
private static final int TYPE_INTERNAL = Util.getIntegerCodeForString("----");
|
private static final int TYPE_INTERNAL = Util.getIntegerCodeForString("----");
|
||||||
|
|
||||||
|
private static final int PICTURE_TYPE_FRONT_COVER = 3;
|
||||||
|
|
||||||
// Standard genres.
|
// Standard genres.
|
||||||
private static final String[] STANDARD_GENRES = new String[] {
|
private static final String[] STANDARD_GENRES = new String[] {
|
||||||
// These are the official ID3v1 genres.
|
// These are the official ID3v1 genres.
|
||||||
@ -104,13 +107,13 @@ import com.google.android.exoplayer2.util.Util;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses a single ilst element from a {@link ParsableByteArray}. The element is read starting
|
* Parses a single ilst element from a {@link ParsableByteArray}. The element is read starting
|
||||||
* from the current position of the {@link ParsableByteArray}, and the position is advanced by
|
* from the current position of the {@link ParsableByteArray}, and the position is advanced by the
|
||||||
* the size of the element. The position is advanced even if the element's type is unrecognized.
|
* size of the element. The position is advanced even if the element's type is unrecognized.
|
||||||
*
|
*
|
||||||
* @param ilst Holds the data to be parsed.
|
* @param ilst Holds the data to be parsed.
|
||||||
* @return The parsed element, or null if the element's type was not recognized.
|
* @return The parsed element, or null if the element's type was not recognized.
|
||||||
*/
|
*/
|
||||||
public static Metadata.Entry parseIlstElement(ParsableByteArray ilst) {
|
public static @Nullable Metadata.Entry parseIlstElement(ParsableByteArray ilst) {
|
||||||
int position = ilst.getPosition();
|
int position = ilst.getPosition();
|
||||||
int endPosition = position + ilst.readInt();
|
int endPosition = position + ilst.readInt();
|
||||||
int type = ilst.readInt();
|
int type = ilst.readInt();
|
||||||
@ -182,20 +185,20 @@ import com.google.android.exoplayer2.util.Util;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TextInformationFrame parseTextAttribute(int type, String id,
|
private static @Nullable TextInformationFrame parseTextAttribute(
|
||||||
ParsableByteArray data) {
|
int type, String id, ParsableByteArray data) {
|
||||||
int atomSize = data.readInt();
|
int atomSize = data.readInt();
|
||||||
int atomType = data.readInt();
|
int atomType = data.readInt();
|
||||||
if (atomType == Atom.TYPE_data) {
|
if (atomType == Atom.TYPE_data) {
|
||||||
data.skipBytes(8); // version (1), flags (3), empty (4)
|
data.skipBytes(8); // version (1), flags (3), empty (4)
|
||||||
String value = data.readNullTerminatedString(atomSize - 16);
|
String value = data.readNullTerminatedString(atomSize - 16);
|
||||||
return new TextInformationFrame(id, null, value);
|
return new TextInformationFrame(id, /* description= */ null, value);
|
||||||
}
|
}
|
||||||
Log.w(TAG, "Failed to parse text attribute: " + Atom.getAtomTypeString(type));
|
Log.w(TAG, "Failed to parse text attribute: " + Atom.getAtomTypeString(type));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static CommentFrame parseCommentAttribute(int type, ParsableByteArray data) {
|
private static @Nullable CommentFrame parseCommentAttribute(int type, ParsableByteArray data) {
|
||||||
int atomSize = data.readInt();
|
int atomSize = data.readInt();
|
||||||
int atomType = data.readInt();
|
int atomType = data.readInt();
|
||||||
if (atomType == Atom.TYPE_data) {
|
if (atomType == Atom.TYPE_data) {
|
||||||
@ -207,22 +210,27 @@ import com.google.android.exoplayer2.util.Util;
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Id3Frame parseUint8Attribute(int type, String id, ParsableByteArray data,
|
private static @Nullable Id3Frame parseUint8Attribute(
|
||||||
boolean isTextInformationFrame, boolean isBoolean) {
|
int type,
|
||||||
|
String id,
|
||||||
|
ParsableByteArray data,
|
||||||
|
boolean isTextInformationFrame,
|
||||||
|
boolean isBoolean) {
|
||||||
int value = parseUint8AttributeValue(data);
|
int value = parseUint8AttributeValue(data);
|
||||||
if (isBoolean) {
|
if (isBoolean) {
|
||||||
value = Math.min(1, value);
|
value = Math.min(1, value);
|
||||||
}
|
}
|
||||||
if (value >= 0) {
|
if (value >= 0) {
|
||||||
return isTextInformationFrame ? new TextInformationFrame(id, null, Integer.toString(value))
|
return isTextInformationFrame
|
||||||
|
? new TextInformationFrame(id, /* description= */ null, Integer.toString(value))
|
||||||
: new CommentFrame(LANGUAGE_UNDEFINED, id, Integer.toString(value));
|
: new CommentFrame(LANGUAGE_UNDEFINED, id, Integer.toString(value));
|
||||||
}
|
}
|
||||||
Log.w(TAG, "Failed to parse uint8 attribute: " + Atom.getAtomTypeString(type));
|
Log.w(TAG, "Failed to parse uint8 attribute: " + Atom.getAtomTypeString(type));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TextInformationFrame parseIndexAndCountAttribute(int type, String attributeName,
|
private static @Nullable TextInformationFrame parseIndexAndCountAttribute(
|
||||||
ParsableByteArray data) {
|
int type, String attributeName, ParsableByteArray data) {
|
||||||
int atomSize = data.readInt();
|
int atomSize = data.readInt();
|
||||||
int atomType = data.readInt();
|
int atomType = data.readInt();
|
||||||
if (atomType == Atom.TYPE_data && atomSize >= 22) {
|
if (atomType == Atom.TYPE_data && atomSize >= 22) {
|
||||||
@ -234,25 +242,26 @@ import com.google.android.exoplayer2.util.Util;
|
|||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
value += "/" + count;
|
value += "/" + count;
|
||||||
}
|
}
|
||||||
return new TextInformationFrame(attributeName, null, value);
|
return new TextInformationFrame(attributeName, /* description= */ null, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Log.w(TAG, "Failed to parse index/count attribute: " + Atom.getAtomTypeString(type));
|
Log.w(TAG, "Failed to parse index/count attribute: " + Atom.getAtomTypeString(type));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TextInformationFrame parseStandardGenreAttribute(ParsableByteArray data) {
|
private static @Nullable TextInformationFrame parseStandardGenreAttribute(
|
||||||
|
ParsableByteArray data) {
|
||||||
int genreCode = parseUint8AttributeValue(data);
|
int genreCode = parseUint8AttributeValue(data);
|
||||||
String genreString = (0 < genreCode && genreCode <= STANDARD_GENRES.length)
|
String genreString = (0 < genreCode && genreCode <= STANDARD_GENRES.length)
|
||||||
? STANDARD_GENRES[genreCode - 1] : null;
|
? STANDARD_GENRES[genreCode - 1] : null;
|
||||||
if (genreString != null) {
|
if (genreString != null) {
|
||||||
return new TextInformationFrame("TCON", null, genreString);
|
return new TextInformationFrame("TCON", /* description= */ null, genreString);
|
||||||
}
|
}
|
||||||
Log.w(TAG, "Failed to parse standard genre code");
|
Log.w(TAG, "Failed to parse standard genre code");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ApicFrame parseCoverArt(ParsableByteArray data) {
|
private static @Nullable ApicFrame parseCoverArt(ParsableByteArray data) {
|
||||||
int atomSize = data.readInt();
|
int atomSize = data.readInt();
|
||||||
int atomType = data.readInt();
|
int atomType = data.readInt();
|
||||||
if (atomType == Atom.TYPE_data) {
|
if (atomType == Atom.TYPE_data) {
|
||||||
@ -266,13 +275,18 @@ import com.google.android.exoplayer2.util.Util;
|
|||||||
data.skipBytes(4); // empty (4)
|
data.skipBytes(4); // empty (4)
|
||||||
byte[] pictureData = new byte[atomSize - 16];
|
byte[] pictureData = new byte[atomSize - 16];
|
||||||
data.readBytes(pictureData, 0, pictureData.length);
|
data.readBytes(pictureData, 0, pictureData.length);
|
||||||
return new ApicFrame(mimeType, null, 3 /* Cover (front) */, pictureData);
|
return new ApicFrame(
|
||||||
|
mimeType,
|
||||||
|
/* description= */ null,
|
||||||
|
/* pictureType= */ PICTURE_TYPE_FRONT_COVER,
|
||||||
|
pictureData);
|
||||||
}
|
}
|
||||||
Log.w(TAG, "Failed to parse cover art attribute");
|
Log.w(TAG, "Failed to parse cover art attribute");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Id3Frame parseInternalAttribute(ParsableByteArray data, int endPosition) {
|
private static @Nullable Id3Frame parseInternalAttribute(
|
||||||
|
ParsableByteArray data, int endPosition) {
|
||||||
String domain = null;
|
String domain = null;
|
||||||
String name = null;
|
String name = null;
|
||||||
int dataAtomPosition = -1;
|
int dataAtomPosition = -1;
|
||||||
|
@ -52,26 +52,25 @@ public final class PsshAtomUtil {
|
|||||||
@SuppressWarnings("ParameterNotNullable")
|
@SuppressWarnings("ParameterNotNullable")
|
||||||
public static byte[] buildPsshAtom(
|
public static byte[] buildPsshAtom(
|
||||||
UUID systemId, @Nullable UUID[] keyIds, @Nullable byte[] data) {
|
UUID systemId, @Nullable UUID[] keyIds, @Nullable byte[] data) {
|
||||||
boolean buildV1Atom = keyIds != null;
|
|
||||||
int dataLength = data != null ? data.length : 0;
|
int dataLength = data != null ? data.length : 0;
|
||||||
int psshBoxLength = Atom.FULL_HEADER_SIZE + 16 /* SystemId */ + 4 /* DataSize */ + dataLength;
|
int psshBoxLength = Atom.FULL_HEADER_SIZE + 16 /* SystemId */ + 4 /* DataSize */ + dataLength;
|
||||||
if (buildV1Atom) {
|
if (keyIds != null) {
|
||||||
psshBoxLength += 4 /* KID_count */ + (keyIds.length * 16) /* KIDs */;
|
psshBoxLength += 4 /* KID_count */ + (keyIds.length * 16) /* KIDs */;
|
||||||
}
|
}
|
||||||
ByteBuffer psshBox = ByteBuffer.allocate(psshBoxLength);
|
ByteBuffer psshBox = ByteBuffer.allocate(psshBoxLength);
|
||||||
psshBox.putInt(psshBoxLength);
|
psshBox.putInt(psshBoxLength);
|
||||||
psshBox.putInt(Atom.TYPE_pssh);
|
psshBox.putInt(Atom.TYPE_pssh);
|
||||||
psshBox.putInt(buildV1Atom ? 0x01000000 : 0 /* version=(buildV1Atom ? 1 : 0), flags=0 */);
|
psshBox.putInt(keyIds != null ? 0x01000000 : 0 /* version=(buildV1Atom ? 1 : 0), flags=0 */);
|
||||||
psshBox.putLong(systemId.getMostSignificantBits());
|
psshBox.putLong(systemId.getMostSignificantBits());
|
||||||
psshBox.putLong(systemId.getLeastSignificantBits());
|
psshBox.putLong(systemId.getLeastSignificantBits());
|
||||||
if (buildV1Atom) {
|
if (keyIds != null) {
|
||||||
psshBox.putInt(keyIds.length);
|
psshBox.putInt(keyIds.length);
|
||||||
for (UUID keyId : keyIds) {
|
for (UUID keyId : keyIds) {
|
||||||
psshBox.putLong(keyId.getMostSignificantBits());
|
psshBox.putLong(keyId.getMostSignificantBits());
|
||||||
psshBox.putLong(keyId.getLeastSignificantBits());
|
psshBox.putLong(keyId.getLeastSignificantBits());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (dataLength != 0) {
|
if (data != null && data.length != 0) {
|
||||||
psshBox.putInt(data.length);
|
psshBox.putInt(data.length);
|
||||||
psshBox.put(data);
|
psshBox.put(data);
|
||||||
} // Else the last 4 bytes are a 0 DataSize.
|
} // Else the last 4 bytes are a 0 DataSize.
|
||||||
|
@ -195,13 +195,11 @@ public final class DefaultTsPayloadReaderFactory implements TsPayloadReader.Fact
|
|||||||
// Skip reserved (8).
|
// Skip reserved (8).
|
||||||
scratchDescriptorData.skipBytes(1);
|
scratchDescriptorData.skipBytes(1);
|
||||||
|
|
||||||
List<byte[]> initializationData;
|
List<byte[]> initializationData = null;
|
||||||
// The wide_aspect_ratio flag only has meaning for CEA-708.
|
// The wide_aspect_ratio flag only has meaning for CEA-708.
|
||||||
if (isDigital) {
|
if (isDigital) {
|
||||||
boolean isWideAspectRatio = (flags & 0x40) != 0;
|
boolean isWideAspectRatio = (flags & 0x40) != 0;
|
||||||
initializationData = Cea708InitializationData.buildData(isWideAspectRatio);
|
initializationData = Cea708InitializationData.buildData(isWideAspectRatio);
|
||||||
} else {
|
|
||||||
initializationData = Collections.emptyList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
closedCaptionFormats.add(
|
closedCaptionFormats.add(
|
||||||
|
@ -29,11 +29,12 @@ public final class ApicFrame extends Id3Frame {
|
|||||||
public static final String ID = "APIC";
|
public static final String ID = "APIC";
|
||||||
|
|
||||||
public final String mimeType;
|
public final String mimeType;
|
||||||
public final String description;
|
public final @Nullable String description;
|
||||||
public final int pictureType;
|
public final int pictureType;
|
||||||
public final byte[] pictureData;
|
public final byte[] pictureData;
|
||||||
|
|
||||||
public ApicFrame(String mimeType, String description, int pictureType, byte[] pictureData) {
|
public ApicFrame(
|
||||||
|
String mimeType, @Nullable String description, int pictureType, byte[] pictureData) {
|
||||||
super(ID);
|
super(ID);
|
||||||
this.mimeType = mimeType;
|
this.mimeType = mimeType;
|
||||||
this.description = description;
|
this.description = description;
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.metadata.id3;
|
package com.google.android.exoplayer2.metadata.id3;
|
||||||
|
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.metadata.Metadata;
|
import com.google.android.exoplayer2.metadata.Metadata;
|
||||||
@ -88,7 +89,7 @@ public final class Id3Decoder implements MetadataDecoder {
|
|||||||
private static final int ID3_TEXT_ENCODING_UTF_16BE = 2;
|
private static final int ID3_TEXT_ENCODING_UTF_16BE = 2;
|
||||||
private static final int ID3_TEXT_ENCODING_UTF_8 = 3;
|
private static final int ID3_TEXT_ENCODING_UTF_8 = 3;
|
||||||
|
|
||||||
private final FramePredicate framePredicate;
|
private final @Nullable FramePredicate framePredicate;
|
||||||
|
|
||||||
public Id3Decoder() {
|
public Id3Decoder() {
|
||||||
this(null);
|
this(null);
|
||||||
@ -97,7 +98,7 @@ public final class Id3Decoder implements MetadataDecoder {
|
|||||||
/**
|
/**
|
||||||
* @param framePredicate Determines which frames are decoded. May be null to decode all frames.
|
* @param framePredicate Determines which frames are decoded. May be null to decode all frames.
|
||||||
*/
|
*/
|
||||||
public Id3Decoder(FramePredicate framePredicate) {
|
public Id3Decoder(@Nullable FramePredicate framePredicate) {
|
||||||
this.framePredicate = framePredicate;
|
this.framePredicate = framePredicate;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -270,8 +271,12 @@ public final class Id3Decoder implements MetadataDecoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Id3Frame decodeFrame(int majorVersion, ParsableByteArray id3Data,
|
private static Id3Frame decodeFrame(
|
||||||
boolean unsignedIntFrameSizeHack, int frameHeaderSize, FramePredicate framePredicate) {
|
int majorVersion,
|
||||||
|
ParsableByteArray id3Data,
|
||||||
|
boolean unsignedIntFrameSizeHack,
|
||||||
|
int frameHeaderSize,
|
||||||
|
@Nullable FramePredicate framePredicate) {
|
||||||
int frameId0 = id3Data.readUnsignedByte();
|
int frameId0 = id3Data.readUnsignedByte();
|
||||||
int frameId1 = id3Data.readUnsignedByte();
|
int frameId1 = id3Data.readUnsignedByte();
|
||||||
int frameId2 = id3Data.readUnsignedByte();
|
int frameId2 = id3Data.readUnsignedByte();
|
||||||
@ -579,9 +584,14 @@ public final class Id3Decoder implements MetadataDecoder {
|
|||||||
return new CommentFrame(language, description, text);
|
return new CommentFrame(language, description, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ChapterFrame decodeChapterFrame(ParsableByteArray id3Data, int frameSize,
|
private static ChapterFrame decodeChapterFrame(
|
||||||
int majorVersion, boolean unsignedIntFrameSizeHack, int frameHeaderSize,
|
ParsableByteArray id3Data,
|
||||||
FramePredicate framePredicate) throws UnsupportedEncodingException {
|
int frameSize,
|
||||||
|
int majorVersion,
|
||||||
|
boolean unsignedIntFrameSizeHack,
|
||||||
|
int frameHeaderSize,
|
||||||
|
@Nullable FramePredicate framePredicate)
|
||||||
|
throws UnsupportedEncodingException {
|
||||||
int framePosition = id3Data.getPosition();
|
int framePosition = id3Data.getPosition();
|
||||||
int chapterIdEndIndex = indexOfZeroByte(id3Data.data, framePosition);
|
int chapterIdEndIndex = indexOfZeroByte(id3Data.data, framePosition);
|
||||||
String chapterId = new String(id3Data.data, framePosition, chapterIdEndIndex - framePosition,
|
String chapterId = new String(id3Data.data, framePosition, chapterIdEndIndex - framePosition,
|
||||||
@ -614,9 +624,14 @@ public final class Id3Decoder implements MetadataDecoder {
|
|||||||
return new ChapterFrame(chapterId, startTime, endTime, startOffset, endOffset, subFrameArray);
|
return new ChapterFrame(chapterId, startTime, endTime, startOffset, endOffset, subFrameArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ChapterTocFrame decodeChapterTOCFrame(ParsableByteArray id3Data, int frameSize,
|
private static ChapterTocFrame decodeChapterTOCFrame(
|
||||||
int majorVersion, boolean unsignedIntFrameSizeHack, int frameHeaderSize,
|
ParsableByteArray id3Data,
|
||||||
FramePredicate framePredicate) throws UnsupportedEncodingException {
|
int frameSize,
|
||||||
|
int majorVersion,
|
||||||
|
boolean unsignedIntFrameSizeHack,
|
||||||
|
int frameHeaderSize,
|
||||||
|
@Nullable FramePredicate framePredicate)
|
||||||
|
throws UnsupportedEncodingException {
|
||||||
int framePosition = id3Data.getPosition();
|
int framePosition = id3Data.getPosition();
|
||||||
int elementIdEndIndex = indexOfZeroByte(id3Data.data, framePosition);
|
int elementIdEndIndex = indexOfZeroByte(id3Data.data, framePosition);
|
||||||
String elementId = new String(id3Data.data, framePosition, elementIdEndIndex - framePosition,
|
String elementId = new String(id3Data.data, framePosition, elementIdEndIndex - framePosition,
|
||||||
|
@ -25,10 +25,10 @@ import com.google.android.exoplayer2.util.Util;
|
|||||||
*/
|
*/
|
||||||
public final class TextInformationFrame extends Id3Frame {
|
public final class TextInformationFrame extends Id3Frame {
|
||||||
|
|
||||||
public final String description;
|
public final @Nullable String description;
|
||||||
public final String value;
|
public final String value;
|
||||||
|
|
||||||
public TextInformationFrame(String id, String description, String value) {
|
public TextInformationFrame(String id, @Nullable String description, String value) {
|
||||||
super(id);
|
super(id);
|
||||||
this.description = description;
|
this.description = description;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.util;
|
package com.google.android.exoplayer2.util;
|
||||||
|
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.ParserException;
|
import com.google.android.exoplayer2.ParserException;
|
||||||
@ -221,8 +222,8 @@ public final class CodecSpecificDataUtil {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Splits an array of NAL units.
|
* Splits an array of NAL units.
|
||||||
* <p>
|
*
|
||||||
* If the input consists of NAL start code delimited units, then the returned array consists of
|
* <p>If the input consists of NAL start code delimited units, then the returned array consists of
|
||||||
* the split NAL units, each of which is still prefixed with the NAL start code. For any other
|
* the split NAL units, each of which is still prefixed with the NAL start code. For any other
|
||||||
* input, null is returned.
|
* input, null is returned.
|
||||||
*
|
*
|
||||||
@ -230,7 +231,7 @@ public final class CodecSpecificDataUtil {
|
|||||||
* @return The individual NAL units, or null if the input did not consist of NAL start code
|
* @return The individual NAL units, or null if the input did not consist of NAL start code
|
||||||
* delimited units.
|
* delimited units.
|
||||||
*/
|
*/
|
||||||
public static byte[][] splitNalUnits(byte[] data) {
|
public static @Nullable byte[][] splitNalUnits(byte[] data) {
|
||||||
if (!isNalStartCode(data, 0)) {
|
if (!isNalStartCode(data, 0)) {
|
||||||
// data does not consist of NAL start code delimited units.
|
// data does not consist of NAL start code delimited units.
|
||||||
return null;
|
return null;
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
package com.google.android.exoplayer2.util;
|
package com.google.android.exoplayer2.util;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines a true of false value for a given input.
|
* Determines a true or false value for a given input.
|
||||||
*
|
*
|
||||||
* @param <T> The input type of the predicate.
|
* @param <T> The input type of the predicate.
|
||||||
*/
|
*/
|
||||||
|
@ -50,10 +50,8 @@ public final class ColorInfo implements Parcelable {
|
|||||||
@C.ColorTransfer
|
@C.ColorTransfer
|
||||||
public final int colorTransfer;
|
public final int colorTransfer;
|
||||||
|
|
||||||
/**
|
/** HdrStaticInfo as defined in CTA-861.3, or null if none specified. */
|
||||||
* HdrStaticInfo as defined in CTA-861.3.
|
public final @Nullable byte[] hdrStaticInfo;
|
||||||
*/
|
|
||||||
public final byte[] hdrStaticInfo;
|
|
||||||
|
|
||||||
// Lazily initialized hashcode.
|
// Lazily initialized hashcode.
|
||||||
private int hashCode;
|
private int hashCode;
|
||||||
@ -64,10 +62,13 @@ public final class ColorInfo implements Parcelable {
|
|||||||
* @param colorSpace The color space of the video.
|
* @param colorSpace The color space of the video.
|
||||||
* @param colorRange The color range of the video.
|
* @param colorRange The color range of the video.
|
||||||
* @param colorTransfer The color transfer characteristics of the video.
|
* @param colorTransfer The color transfer characteristics of the video.
|
||||||
* @param hdrStaticInfo HdrStaticInfo as defined in CTA-861.3.
|
* @param hdrStaticInfo HdrStaticInfo as defined in CTA-861.3, or null if none specified.
|
||||||
*/
|
*/
|
||||||
public ColorInfo(@C.ColorSpace int colorSpace, @C.ColorRange int colorRange,
|
public ColorInfo(
|
||||||
@C.ColorTransfer int colorTransfer, byte[] hdrStaticInfo) {
|
@C.ColorSpace int colorSpace,
|
||||||
|
@C.ColorRange int colorRange,
|
||||||
|
@C.ColorTransfer int colorTransfer,
|
||||||
|
@Nullable byte[] hdrStaticInfo) {
|
||||||
this.colorSpace = colorSpace;
|
this.colorSpace = colorSpace;
|
||||||
this.colorRange = colorRange;
|
this.colorRange = colorRange;
|
||||||
this.colorTransfer = colorTransfer;
|
this.colorTransfer = colorTransfer;
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.video;
|
package com.google.android.exoplayer2.video;
|
||||||
|
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import com.google.android.exoplayer2.ParserException;
|
import com.google.android.exoplayer2.ParserException;
|
||||||
import com.google.android.exoplayer2.util.NalUnitUtil;
|
import com.google.android.exoplayer2.util.NalUnitUtil;
|
||||||
import com.google.android.exoplayer2.util.ParsableByteArray;
|
import com.google.android.exoplayer2.util.ParsableByteArray;
|
||||||
@ -26,7 +27,7 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public final class HevcConfig {
|
public final class HevcConfig {
|
||||||
|
|
||||||
public final List<byte[]> initializationData;
|
public final @Nullable List<byte[]> initializationData;
|
||||||
public final int nalUnitLengthFieldLength;
|
public final int nalUnitLengthFieldLength;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -82,7 +83,7 @@ public final class HevcConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private HevcConfig(List<byte[]> initializationData, int nalUnitLengthFieldLength) {
|
private HevcConfig(@Nullable List<byte[]> initializationData, int nalUnitLengthFieldLength) {
|
||||||
this.initializationData = initializationData;
|
this.initializationData = initializationData;
|
||||||
this.nalUnitLengthFieldLength = nalUnitLengthFieldLength;
|
this.nalUnitLengthFieldLength = nalUnitLengthFieldLength;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user