Remove some files from the nullness blacklist

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=205816544
This commit is contained in:
olly 2018-07-24 06:01:10 -07:00 committed by Oliver Woodman
parent 138b222457
commit 340d846d9b
19 changed files with 214 additions and 171 deletions

View File

@ -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'
} }

View File

@ -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) {
Assertions.checkNotNull(response.body()).close();
response = null; response = null;
}
responseByteStream = null; responseByteStream = null;
} }

View File

@ -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 =
new OkHttpDataSource(
callFactory,
userAgent,
/* contentTypePredicate= */ null,
cacheControl,
defaultRequestProperties); defaultRequestProperties);
if (listener != null) {
dataSource.addTransferListener(listener);
}
return dataSource;
} }
} }

View File

@ -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(

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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.

View File

@ -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(

View File

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

View File

@ -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,

View File

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

View File

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

View File

@ -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.
*/ */

View File

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

View File

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