From 340d846d9b12877def389bcfd7c272bc7a104b7d Mon Sep 17 00:00:00 2001 From: olly Date: Tue, 24 Jul 2018 06:01:10 -0700 Subject: [PATCH] Remove some files from the nullness blacklist ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=205816544 --- extensions/okhttp/build.gradle | 1 + .../ext/okhttp/OkHttpDataSource.java | 110 ++++++++---------- .../ext/okhttp/OkHttpDataSourceFactory.java | 34 +++--- .../com/google/android/exoplayer2/Format.java | 22 ++-- .../android/exoplayer2/FormatHolder.java | 9 +- .../android/exoplayer2/audio/Ac3Util.java | 48 +++++--- .../android/exoplayer2/audio/DtsUtil.java | 6 +- .../exoplayer2/extractor/mp4/Atom.java | 17 +-- .../exoplayer2/extractor/mp4/AtomParsers.java | 2 +- .../extractor/mp4/MetadataUtil.java | 50 +++++--- .../extractor/mp4/PsshAtomUtil.java | 9 +- .../ts/DefaultTsPayloadReaderFactory.java | 4 +- .../exoplayer2/metadata/id3/ApicFrame.java | 5 +- .../exoplayer2/metadata/id3/Id3Decoder.java | 35 ++++-- .../metadata/id3/TextInformationFrame.java | 4 +- .../util/CodecSpecificDataUtil.java | 7 +- .../android/exoplayer2/util/Predicate.java | 2 +- .../android/exoplayer2/video/ColorInfo.java | 15 +-- .../android/exoplayer2/video/HevcConfig.java | 5 +- 19 files changed, 214 insertions(+), 171 deletions(-) diff --git a/extensions/okhttp/build.gradle b/extensions/okhttp/build.gradle index d7351ced3e..fd1ebd28b5 100644 --- a/extensions/okhttp/build.gradle +++ b/extensions/okhttp/build.gradle @@ -33,6 +33,7 @@ android { dependencies { implementation project(modulePrefix + 'library-core') implementation 'com.android.support:support-annotations:' + supportLibraryVersion + compileOnly 'org.checkerframework:checker-qual:' + checkerframeworkVersion api 'com.squareup.okhttp3:okhttp:3.10.0' } diff --git a/extensions/okhttp/src/main/java/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSource.java b/extensions/okhttp/src/main/java/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSource.java index 97ca48bd14..e182e802fc 100644 --- a/extensions/okhttp/src/main/java/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSource.java +++ b/extensions/okhttp/src/main/java/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSource.java @@ -15,8 +15,9 @@ */ package com.google.android.exoplayer2.ext.okhttp; +import static org.checkerframework.checker.nullness.NullnessUtil.castNonNull; + import android.net.Uri; -import android.support.annotation.NonNull; import android.support.annotation.Nullable; import com.google.android.exoplayer2.C; 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.DataSpec; 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.Predicate; import java.io.EOFException; @@ -34,7 +34,6 @@ import java.io.InterruptedIOException; import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.concurrent.atomic.AtomicReference; import okhttp3.CacheControl; import okhttp3.Call; import okhttp3.HttpUrl; @@ -42,6 +41,7 @@ import okhttp3.MediaType; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; +import okhttp3.ResponseBody; /** An {@link HttpDataSource} that delegates to Square's {@link Call.Factory}. */ public class OkHttpDataSource extends BaseDataSource implements HttpDataSource { @@ -50,19 +50,19 @@ public class OkHttpDataSource extends BaseDataSource implements HttpDataSource { ExoPlayerLibraryInfo.registerModule("goog.exo.okhttp"); } - private static final AtomicReference skipBufferReference = new AtomicReference<>(); + private static final byte[] SKIP_BUFFER = new byte[4096]; - @NonNull private final Call.Factory callFactory; - @NonNull private final RequestProperties requestProperties; + private final Call.Factory callFactory; + private final RequestProperties requestProperties; - @Nullable private final String userAgent; - @Nullable private final Predicate contentTypePredicate; - @Nullable private final CacheControl cacheControl; - @Nullable private final RequestProperties defaultRequestProperties; + private final @Nullable String userAgent; + private final @Nullable Predicate contentTypePredicate; + private final @Nullable CacheControl cacheControl; + private final @Nullable RequestProperties defaultRequestProperties; - private DataSpec dataSpec; - private Response response; - private InputStream responseByteStream; + private @Nullable DataSpec dataSpec; + private @Nullable Response response; + private @Nullable InputStream responseByteStream; private boolean opened; private long bytesToSkip; @@ -71,18 +71,6 @@ public class OkHttpDataSource extends BaseDataSource implements HttpDataSource { private long bytesSkipped; 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 contentTypePredicate) { - this(callFactory, userAgent, contentTypePredicate, null); - } - /** * @param callFactory A {@link Call.Factory} (typically an {@link okhttp3.OkHttpClient}) for use * 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 * predicate then a {@link InvalidContentTypeException} is thrown from {@link * #open(DataSpec)}. - * @param listener An optional listener. */ public OkHttpDataSource( - @NonNull Call.Factory callFactory, + Call.Factory callFactory, @Nullable String userAgent, - @Nullable Predicate contentTypePredicate, - @Nullable TransferListener listener) { - this(callFactory, userAgent, contentTypePredicate, listener, null, null); + @Nullable Predicate contentTypePredicate) { + this( + 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 * predicate then a {@link InvalidContentTypeException} is thrown from {@link * #open(DataSpec)}. - * @param listener An optional listener. * @param cacheControl An optional {@link CacheControl} for setting the Cache-Control header. * @param defaultRequestProperties The optional default {@link RequestProperties} to be sent to * the server as HTTP headers on every request. */ public OkHttpDataSource( - @NonNull Call.Factory callFactory, + Call.Factory callFactory, @Nullable String userAgent, @Nullable Predicate contentTypePredicate, - @Nullable TransferListener listener, @Nullable CacheControl cacheControl, @Nullable RequestProperties defaultRequestProperties) { super(/* isNetwork= */ true); @@ -126,13 +115,10 @@ public class OkHttpDataSource extends BaseDataSource implements HttpDataSource { this.cacheControl = cacheControl; this.defaultRequestProperties = defaultRequestProperties; this.requestProperties = new RequestProperties(); - if (listener != null) { - addTransferListener(listener); - } } @Override - public Uri getUri() { + public @Nullable Uri getUri() { 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.bytesSkipped = 0; transferInitializing(dataSpec); + Request request = makeRequest(dataSpec); + Response response; + ResponseBody responseBody; try { - response = callFactory.newCall(request).execute(); - responseByteStream = response.body().byteStream(); + this.response = callFactory.newCall(request).execute(); + response = this.response; + responseBody = Assertions.checkNotNull(response.body()); + responseByteStream = responseBody.byteStream(); } catch (IOException e) { throw new HttpDataSourceException("Unable to connect to " + dataSpec.uri.toString(), e, dataSpec, HttpDataSourceException.TYPE_OPEN); @@ -189,8 +180,8 @@ public class OkHttpDataSource extends BaseDataSource implements HttpDataSource { } // Check for a valid content type. - MediaType mediaType = response.body().contentType(); - String contentType = mediaType != null ? mediaType.toString() : null; + MediaType mediaType = responseBody.contentType(); + String contentType = mediaType != null ? mediaType.toString() : ""; if (contentTypePredicate != null && !contentTypePredicate.evaluate(contentType)) { closeConnectionQuietly(); throw new InvalidContentTypeException(contentType, dataSpec); @@ -205,7 +196,7 @@ public class OkHttpDataSource extends BaseDataSource implements HttpDataSource { if (dataSpec.length != C.LENGTH_UNSET) { bytesToRead = dataSpec.length; } else { - long contentLength = response.body().contentLength(); + long contentLength = responseBody.contentLength(); bytesToRead = contentLength != -1 ? (contentLength - bytesToSkip) : C.LENGTH_UNSET; } @@ -221,7 +212,8 @@ public class OkHttpDataSource extends BaseDataSource implements HttpDataSource { skipInternal(); return readInternal(buffer, offset, readLength); } 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; } - /** - * Establishes a connection. - */ - private Request makeRequest(DataSpec dataSpec) { + /** Establishes a connection. */ + private Request makeRequest(DataSpec dataSpec) throws HttpDataSourceException { long position = dataSpec.position; long length = dataSpec.length; boolean allowGzip = dataSpec.isFlagSet(DataSpec.FLAG_ALLOW_GZIP); 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); if (cacheControl != null) { builder.cacheControl(cacheControl); @@ -320,15 +315,9 @@ public class OkHttpDataSource extends BaseDataSource implements HttpDataSource { return; } - // Acquire the shared skip buffer. - byte[] skipBuffer = skipBufferReference.getAndSet(null); - if (skipBuffer == null) { - skipBuffer = new byte[4096]; - } - while (bytesSkipped != bytesToSkip) { - int readLength = (int) Math.min(bytesToSkip - bytesSkipped, skipBuffer.length); - int read = responseByteStream.read(skipBuffer, 0, readLength); + int readLength = (int) Math.min(bytesToSkip - bytesSkipped, SKIP_BUFFER.length); + int read = castNonNull(responseByteStream).read(SKIP_BUFFER, 0, readLength); if (Thread.currentThread().isInterrupted()) { throw new InterruptedIOException(); } @@ -338,9 +327,6 @@ public class OkHttpDataSource extends BaseDataSource implements HttpDataSource { bytesSkipped += 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); } - int read = responseByteStream.read(buffer, offset, readLength); + int read = castNonNull(responseByteStream).read(buffer, offset, readLength); if (read == -1) { if (bytesToRead != C.LENGTH_UNSET) { // 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. */ private void closeConnectionQuietly() { - response.body().close(); - response = null; + if (response != null) { + Assertions.checkNotNull(response.body()).close(); + response = null; + } responseByteStream = null; } diff --git a/extensions/okhttp/src/main/java/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSourceFactory.java b/extensions/okhttp/src/main/java/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSourceFactory.java index b0f5b953db..09f4e0b61a 100644 --- a/extensions/okhttp/src/main/java/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSourceFactory.java +++ b/extensions/okhttp/src/main/java/com/google/android/exoplayer2/ext/okhttp/OkHttpDataSourceFactory.java @@ -15,7 +15,6 @@ */ package com.google.android.exoplayer2.ext.okhttp; -import android.support.annotation.NonNull; import android.support.annotation.Nullable; import com.google.android.exoplayer2.upstream.HttpDataSource; import com.google.android.exoplayer2.upstream.HttpDataSource.BaseFactory; @@ -29,17 +28,17 @@ import okhttp3.Call; */ public final class OkHttpDataSourceFactory extends BaseFactory { - @NonNull private final Call.Factory callFactory; - @Nullable private final String userAgent; - @Nullable private final TransferListener listener; - @Nullable private final CacheControl cacheControl; + private final Call.Factory callFactory; + private final @Nullable String userAgent; + private final @Nullable TransferListener listener; + private final @Nullable CacheControl cacheControl; /** * @param callFactory A {@link Call.Factory} (typically an {@link okhttp3.OkHttpClient}) for use * by the sources created by the factory. * @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); } @@ -50,9 +49,7 @@ public final class OkHttpDataSourceFactory extends BaseFactory { * @param cacheControl An optional {@link CacheControl} for setting the Cache-Control header. */ public OkHttpDataSourceFactory( - @NonNull Call.Factory callFactory, - @Nullable String userAgent, - @Nullable CacheControl cacheControl) { + Call.Factory callFactory, @Nullable String userAgent, @Nullable CacheControl cacheControl) { this(callFactory, userAgent, /* listener= */ null, cacheControl); } @@ -63,9 +60,7 @@ public final class OkHttpDataSourceFactory extends BaseFactory { * @param listener An optional listener. */ public OkHttpDataSourceFactory( - @NonNull Call.Factory callFactory, - @Nullable String userAgent, - @Nullable TransferListener listener) { + Call.Factory callFactory, @Nullable String userAgent, @Nullable TransferListener listener) { 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. */ public OkHttpDataSourceFactory( - @NonNull Call.Factory callFactory, + Call.Factory callFactory, @Nullable String userAgent, @Nullable TransferListener listener, @Nullable CacheControl cacheControl) { @@ -90,7 +85,16 @@ public final class OkHttpDataSourceFactory extends BaseFactory { @Override protected OkHttpDataSource createDataSourceInternal( HttpDataSource.RequestProperties defaultRequestProperties) { - return new OkHttpDataSource(callFactory, userAgent, null, listener, cacheControl, - defaultRequestProperties); + OkHttpDataSource dataSource = + new OkHttpDataSource( + callFactory, + userAgent, + /* contentTypePredicate= */ null, + cacheControl, + defaultRequestProperties); + if (listener != null) { + dataSource.addTransferListener(listener); + } + return dataSource; } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/Format.java b/library/core/src/main/java/com/google/android/exoplayer2/Format.java index 35566f4487..459c56ee0e 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/Format.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/Format.java @@ -182,7 +182,7 @@ public final class Format implements Parcelable { int width, int height, float frameRate, - List initializationData, + @Nullable List initializationData, @C.SelectionFlags int selectionFlags) { return createVideoContainerFormat( id, @@ -208,7 +208,7 @@ public final class Format implements Parcelable { int width, int height, float frameRate, - List initializationData, + @Nullable List initializationData, @C.SelectionFlags int selectionFlags) { return new Format( id, @@ -249,7 +249,7 @@ public final class Format implements Parcelable { int width, int height, float frameRate, - List initializationData, + @Nullable List initializationData, @Nullable DrmInitData drmInitData) { return createVideoSampleFormat( id, @@ -275,7 +275,7 @@ public final class Format implements Parcelable { int width, int height, float frameRate, - List initializationData, + @Nullable List initializationData, int rotationDegrees, float pixelWidthHeightRatio, @Nullable DrmInitData drmInitData) { @@ -306,7 +306,7 @@ public final class Format implements Parcelable { int width, int height, float frameRate, - List initializationData, + @Nullable List initializationData, int rotationDegrees, float pixelWidthHeightRatio, byte[] projectionData, @@ -354,7 +354,7 @@ public final class Format implements Parcelable { int bitrate, int channelCount, int sampleRate, - List initializationData, + @Nullable List initializationData, @C.SelectionFlags int selectionFlags, @Nullable String language) { return createAudioContainerFormat( @@ -380,7 +380,7 @@ public final class Format implements Parcelable { int bitrate, int channelCount, int sampleRate, - List initializationData, + @Nullable List initializationData, @C.SelectionFlags int selectionFlags, @Nullable String language) { return new Format( @@ -421,7 +421,7 @@ public final class Format implements Parcelable { int maxInputSize, int channelCount, int sampleRate, - List initializationData, + @Nullable List initializationData, @Nullable DrmInitData drmInitData, @C.SelectionFlags int selectionFlags, @Nullable String language) { @@ -449,7 +449,7 @@ public final class Format implements Parcelable { int channelCount, int sampleRate, @C.PcmEncoding int pcmEncoding, - List initializationData, + @Nullable List initializationData, @Nullable DrmInitData drmInitData, @C.SelectionFlags int selectionFlags, @Nullable String language) { @@ -482,7 +482,7 @@ public final class Format implements Parcelable { @C.PcmEncoding int pcmEncoding, int encoderDelay, int encoderPadding, - List initializationData, + @Nullable List initializationData, @Nullable DrmInitData drmInitData, @C.SelectionFlags int selectionFlags, @Nullable String language, @@ -720,7 +720,7 @@ public final class Format implements Parcelable { @Nullable String codecs, int bitrate, @C.SelectionFlags int selectionFlags, - List initializationData, + @Nullable List initializationData, @Nullable String language, @Nullable DrmInitData drmInitData) { return new Format( diff --git a/library/core/src/main/java/com/google/android/exoplayer2/FormatHolder.java b/library/core/src/main/java/com/google/android/exoplayer2/FormatHolder.java index b26787517e..8c7ba1eb91 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/FormatHolder.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/FormatHolder.java @@ -15,14 +15,13 @@ */ package com.google.android.exoplayer2; +import android.support.annotation.Nullable; + /** * Holds a {@link Format}. */ public final class FormatHolder { - /** - * The held {@link Format}. - */ - public Format format; - + /** The held {@link Format}. */ + public @Nullable Format format; } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/Ac3Util.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/Ac3Util.java index c61b8ff24c..94fe759a9b 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/Ac3Util.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/Ac3Util.java @@ -137,17 +137,17 @@ public final class Ac3Util { 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 - * ETSI TS 102 366 Annex F. The reading position of {@code data} will be modified. + * Returns the AC-3 format given {@code data} containing the AC3SpecificBox according to ETSI TS + * 102 366 Annex F. The reading position of {@code data} will be modified. * * @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 drmInitData {@link DrmInitData} to be included in the format. * @return The AC-3 format parsed from data in the header. */ - public static Format parseAc3AnnexFFormat(ParsableByteArray data, String trackId, - String language, DrmInitData drmInitData) { + public static Format parseAc3AnnexFFormat( + ParsableByteArray data, String trackId, String language, DrmInitData drmInitData) { int fscod = (data.readUnsignedByte() & 0xC0) >> 6; int sampleRate = SAMPLE_RATE_BY_FSCOD[fscod]; int nextByte = data.readUnsignedByte(); @@ -155,22 +155,32 @@ public final class Ac3Util { if ((nextByte & 0x04) != 0) { // lfeon channelCount++; } - return Format.createAudioSampleFormat(trackId, MimeTypes.AUDIO_AC3, null, Format.NO_VALUE, - Format.NO_VALUE, channelCount, sampleRate, null, drmInitData, 0, language); + return Format.createAudioSampleFormat( + 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 - * ETSI TS 102 366 Annex F. The reading position of {@code data} will be modified. + * Returns the E-AC-3 format given {@code data} containing the EC3SpecificBox according to ETSI TS + * 102 366 Annex F. The reading position of {@code data} will be modified. * * @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 drmInitData {@link DrmInitData} to be included in the format. * @return The E-AC-3 format parsed from data in the header. */ - public static Format parseEAc3AnnexFFormat(ParsableByteArray data, String trackId, - String language, DrmInitData drmInitData) { + public static Format parseEAc3AnnexFFormat( + ParsableByteArray data, String trackId, String language, DrmInitData drmInitData) { data.skipBytes(2); // data_rate, num_ind_sub // Read the first independent substream. @@ -200,8 +210,18 @@ public final class Ac3Util { mimeType = MimeTypes.AUDIO_E_AC3_JOC; } } - return Format.createAudioSampleFormat(trackId, mimeType, null, Format.NO_VALUE, - Format.NO_VALUE, channelCount, sampleRate, null, drmInitData, 0, language); + return Format.createAudioSampleFormat( + trackId, + mimeType, + /* codecs= */ null, + Format.NO_VALUE, + Format.NO_VALUE, + channelCount, + sampleRate, + /* initializationData= */ null, + drmInitData, + /* selectionFlags= */ 0, + language); } /** diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/DtsUtil.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/DtsUtil.java index dc07b1a646..f65dc3fc4e 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/DtsUtil.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/DtsUtil.java @@ -74,13 +74,13 @@ public final class DtsUtil { * subsections 5.3/5.4. * * @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 drmInitData {@link DrmInitData} to be included in the format. * @return The DTS format parsed from data in the header. */ - public static Format parseDtsFormat(byte[] frame, String trackId, String language, - DrmInitData drmInitData) { + public static Format parseDtsFormat( + byte[] frame, String trackId, String language, DrmInitData drmInitData) { ParsableBitArray frameBits = getNormalizedFrameHeader(frame); frameBits.skipBits(32 + 1 + 5 + 1 + 7 + 14); // SYNC, FTYPE, SHORT, CPF, NBLKS, FSIZE int amode = frameBits.readBits(6); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/Atom.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/Atom.java index 21d861af30..f59214fc37 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/Atom.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/Atom.java @@ -15,6 +15,7 @@ */ 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.Util; import java.util.ArrayList; @@ -214,14 +215,14 @@ import java.util.List; /** * Returns the child leaf of the given type. - *

- * If no child exists with the given type then null is returned. If multiple children exist with - * the given type then the first one to have been added is returned. + * + *

If no child exists with the given type then null is returned. If multiple children exist + * with the given type then the first one to have been added is returned. * * @param type The leaf type. * @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(); for (int i = 0; i < childrenSize; i++) { LeafAtom atom = leafChildren.get(i); @@ -234,14 +235,14 @@ import java.util.List; /** * Returns the child container of the given type. - *

- * If no child exists with the given type then null is returned. If multiple children exist with - * the given type then the first one to have been added is returned. + * + *

If no child exists with the given type then null is returned. If multiple children exist + * with the given type then the first one to have been added is returned. * * @param type The container type. * @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(); for (int i = 0; i < childrenSize; i++) { ContainerAtom atom = containerChildren.get(i); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java index 8e6928ee5c..fe79185697 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java @@ -681,7 +681,7 @@ import java.util.List; parent.setPosition(position + Atom.HEADER_SIZE + StsdData.STSD_HEADER_SIZE); // Default values. - List initializationData = Collections.emptyList(); + List initializationData = null; long subsampleOffsetUs = Format.OFFSET_SAMPLE_RELATIVE; String mimeType; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/MetadataUtil.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/MetadataUtil.java index 991f765d0d..ed7c539118 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/MetadataUtil.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/MetadataUtil.java @@ -15,6 +15,7 @@ */ package com.google.android.exoplayer2.extractor.mp4; +import android.support.annotation.Nullable; import android.util.Log; import com.google.android.exoplayer2.metadata.Metadata; 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. private static final int TYPE_INTERNAL = Util.getIntegerCodeForString("----"); + private static final int PICTURE_TYPE_FRONT_COVER = 3; + // Standard genres. private static final String[] STANDARD_GENRES = new String[] { // 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 - * from the current position of the {@link ParsableByteArray}, and the position is advanced by - * the size of the element. The position is advanced even if the element's type is unrecognized. + * from the current position of the {@link ParsableByteArray}, and the position is advanced by the + * size of the element. The position is advanced even if the element's type is unrecognized. * * @param ilst Holds the data to be parsed. * @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 endPosition = position + 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, - ParsableByteArray data) { + private static @Nullable TextInformationFrame parseTextAttribute( + int type, String id, ParsableByteArray data) { int atomSize = data.readInt(); int atomType = data.readInt(); if (atomType == Atom.TYPE_data) { data.skipBytes(8); // version (1), flags (3), empty (4) 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)); return null; } - private static CommentFrame parseCommentAttribute(int type, ParsableByteArray data) { + private static @Nullable CommentFrame parseCommentAttribute(int type, ParsableByteArray data) { int atomSize = data.readInt(); int atomType = data.readInt(); if (atomType == Atom.TYPE_data) { @@ -207,22 +210,27 @@ import com.google.android.exoplayer2.util.Util; return null; } - private static Id3Frame parseUint8Attribute(int type, String id, ParsableByteArray data, - boolean isTextInformationFrame, boolean isBoolean) { + private static @Nullable Id3Frame parseUint8Attribute( + int type, + String id, + ParsableByteArray data, + boolean isTextInformationFrame, + boolean isBoolean) { int value = parseUint8AttributeValue(data); if (isBoolean) { value = Math.min(1, value); } 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)); } Log.w(TAG, "Failed to parse uint8 attribute: " + Atom.getAtomTypeString(type)); return null; } - private static TextInformationFrame parseIndexAndCountAttribute(int type, String attributeName, - ParsableByteArray data) { + private static @Nullable TextInformationFrame parseIndexAndCountAttribute( + int type, String attributeName, ParsableByteArray data) { int atomSize = data.readInt(); int atomType = data.readInt(); if (atomType == Atom.TYPE_data && atomSize >= 22) { @@ -234,25 +242,26 @@ import com.google.android.exoplayer2.util.Util; if (count > 0) { 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)); return null; } - private static TextInformationFrame parseStandardGenreAttribute(ParsableByteArray data) { + private static @Nullable TextInformationFrame parseStandardGenreAttribute( + ParsableByteArray data) { int genreCode = parseUint8AttributeValue(data); String genreString = (0 < genreCode && genreCode <= STANDARD_GENRES.length) ? STANDARD_GENRES[genreCode - 1] : 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"); return null; } - private static ApicFrame parseCoverArt(ParsableByteArray data) { + private static @Nullable ApicFrame parseCoverArt(ParsableByteArray data) { int atomSize = data.readInt(); int atomType = data.readInt(); if (atomType == Atom.TYPE_data) { @@ -266,13 +275,18 @@ import com.google.android.exoplayer2.util.Util; data.skipBytes(4); // empty (4) byte[] pictureData = new byte[atomSize - 16]; 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"); return null; } - private static Id3Frame parseInternalAttribute(ParsableByteArray data, int endPosition) { + private static @Nullable Id3Frame parseInternalAttribute( + ParsableByteArray data, int endPosition) { String domain = null; String name = null; int dataAtomPosition = -1; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/PsshAtomUtil.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/PsshAtomUtil.java index a033f5c663..983c23dc3d 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/PsshAtomUtil.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/PsshAtomUtil.java @@ -52,26 +52,25 @@ public final class PsshAtomUtil { @SuppressWarnings("ParameterNotNullable") public static byte[] buildPsshAtom( UUID systemId, @Nullable UUID[] keyIds, @Nullable byte[] data) { - boolean buildV1Atom = keyIds != null; int dataLength = data != null ? data.length : 0; int psshBoxLength = Atom.FULL_HEADER_SIZE + 16 /* SystemId */ + 4 /* DataSize */ + dataLength; - if (buildV1Atom) { + if (keyIds != null) { psshBoxLength += 4 /* KID_count */ + (keyIds.length * 16) /* KIDs */; } ByteBuffer psshBox = ByteBuffer.allocate(psshBoxLength); psshBox.putInt(psshBoxLength); 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.getLeastSignificantBits()); - if (buildV1Atom) { + if (keyIds != null) { psshBox.putInt(keyIds.length); for (UUID keyId : keyIds) { psshBox.putLong(keyId.getMostSignificantBits()); psshBox.putLong(keyId.getLeastSignificantBits()); } } - if (dataLength != 0) { + if (data != null && data.length != 0) { psshBox.putInt(data.length); psshBox.put(data); } // Else the last 4 bytes are a 0 DataSize. diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/ts/DefaultTsPayloadReaderFactory.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/ts/DefaultTsPayloadReaderFactory.java index 93ffb69499..085e3443c1 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/ts/DefaultTsPayloadReaderFactory.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/ts/DefaultTsPayloadReaderFactory.java @@ -195,13 +195,11 @@ public final class DefaultTsPayloadReaderFactory implements TsPayloadReader.Fact // Skip reserved (8). scratchDescriptorData.skipBytes(1); - List initializationData; + List initializationData = null; // The wide_aspect_ratio flag only has meaning for CEA-708. if (isDigital) { boolean isWideAspectRatio = (flags & 0x40) != 0; initializationData = Cea708InitializationData.buildData(isWideAspectRatio); - } else { - initializationData = Collections.emptyList(); } closedCaptionFormats.add( diff --git a/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/ApicFrame.java b/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/ApicFrame.java index ae78f712c7..543d8c0d8f 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/ApicFrame.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/ApicFrame.java @@ -29,11 +29,12 @@ public final class ApicFrame extends Id3Frame { public static final String ID = "APIC"; public final String mimeType; - public final String description; + public final @Nullable String description; public final int pictureType; 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); this.mimeType = mimeType; this.description = description; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/Id3Decoder.java b/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/Id3Decoder.java index ad24bac6c4..cea3fbbdfc 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/Id3Decoder.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/Id3Decoder.java @@ -15,6 +15,7 @@ */ package com.google.android.exoplayer2.metadata.id3; +import android.support.annotation.Nullable; import android.util.Log; import com.google.android.exoplayer2.C; 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_8 = 3; - private final FramePredicate framePredicate; + private final @Nullable FramePredicate framePredicate; public Id3Decoder() { 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. */ - public Id3Decoder(FramePredicate framePredicate) { + public Id3Decoder(@Nullable FramePredicate framePredicate) { this.framePredicate = framePredicate; } @@ -270,8 +271,12 @@ public final class Id3Decoder implements MetadataDecoder { } } - private static Id3Frame decodeFrame(int majorVersion, ParsableByteArray id3Data, - boolean unsignedIntFrameSizeHack, int frameHeaderSize, FramePredicate framePredicate) { + private static Id3Frame decodeFrame( + int majorVersion, + ParsableByteArray id3Data, + boolean unsignedIntFrameSizeHack, + int frameHeaderSize, + @Nullable FramePredicate framePredicate) { int frameId0 = id3Data.readUnsignedByte(); int frameId1 = id3Data.readUnsignedByte(); int frameId2 = id3Data.readUnsignedByte(); @@ -579,9 +584,14 @@ public final class Id3Decoder implements MetadataDecoder { return new CommentFrame(language, description, text); } - private static ChapterFrame decodeChapterFrame(ParsableByteArray id3Data, int frameSize, - int majorVersion, boolean unsignedIntFrameSizeHack, int frameHeaderSize, - FramePredicate framePredicate) throws UnsupportedEncodingException { + private static ChapterFrame decodeChapterFrame( + ParsableByteArray id3Data, + int frameSize, + int majorVersion, + boolean unsignedIntFrameSizeHack, + int frameHeaderSize, + @Nullable FramePredicate framePredicate) + throws UnsupportedEncodingException { int framePosition = id3Data.getPosition(); int chapterIdEndIndex = indexOfZeroByte(id3Data.data, 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); } - private static ChapterTocFrame decodeChapterTOCFrame(ParsableByteArray id3Data, int frameSize, - int majorVersion, boolean unsignedIntFrameSizeHack, int frameHeaderSize, - FramePredicate framePredicate) throws UnsupportedEncodingException { + private static ChapterTocFrame decodeChapterTOCFrame( + ParsableByteArray id3Data, + int frameSize, + int majorVersion, + boolean unsignedIntFrameSizeHack, + int frameHeaderSize, + @Nullable FramePredicate framePredicate) + throws UnsupportedEncodingException { int framePosition = id3Data.getPosition(); int elementIdEndIndex = indexOfZeroByte(id3Data.data, framePosition); String elementId = new String(id3Data.data, framePosition, elementIdEndIndex - framePosition, diff --git a/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/TextInformationFrame.java b/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/TextInformationFrame.java index dbab4ca7a8..1328ef54b6 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/TextInformationFrame.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/metadata/id3/TextInformationFrame.java @@ -25,10 +25,10 @@ import com.google.android.exoplayer2.util.Util; */ public final class TextInformationFrame extends Id3Frame { - public final String description; + public final @Nullable String description; public final String value; - public TextInformationFrame(String id, String description, String value) { + public TextInformationFrame(String id, @Nullable String description, String value) { super(id); this.description = description; this.value = value; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/util/CodecSpecificDataUtil.java b/library/core/src/main/java/com/google/android/exoplayer2/util/CodecSpecificDataUtil.java index 0514d9dbdc..e1ffa1024d 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/util/CodecSpecificDataUtil.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/util/CodecSpecificDataUtil.java @@ -15,6 +15,7 @@ */ package com.google.android.exoplayer2.util; +import android.support.annotation.Nullable; import android.util.Pair; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ParserException; @@ -221,8 +222,8 @@ public final class CodecSpecificDataUtil { /** * Splits an array of NAL units. - *

- * If the input consists of NAL start code delimited units, then the returned array consists of + * + *

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 * 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 * delimited units. */ - public static byte[][] splitNalUnits(byte[] data) { + public static @Nullable byte[][] splitNalUnits(byte[] data) { if (!isNalStartCode(data, 0)) { // data does not consist of NAL start code delimited units. return null; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/util/Predicate.java b/library/core/src/main/java/com/google/android/exoplayer2/util/Predicate.java index 889b19f3c3..b582cf3f7c 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/util/Predicate.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/util/Predicate.java @@ -16,7 +16,7 @@ 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 The input type of the predicate. */ diff --git a/library/core/src/main/java/com/google/android/exoplayer2/video/ColorInfo.java b/library/core/src/main/java/com/google/android/exoplayer2/video/ColorInfo.java index faedaaf273..77ca936a90 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/video/ColorInfo.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/video/ColorInfo.java @@ -50,10 +50,8 @@ public final class ColorInfo implements Parcelable { @C.ColorTransfer public final int colorTransfer; - /** - * HdrStaticInfo as defined in CTA-861.3. - */ - public final byte[] hdrStaticInfo; + /** HdrStaticInfo as defined in CTA-861.3, or null if none specified. */ + public final @Nullable byte[] hdrStaticInfo; // Lazily initialized hashcode. private int hashCode; @@ -64,10 +62,13 @@ public final class ColorInfo implements Parcelable { * @param colorSpace The color space of the video. * @param colorRange The color range 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, - @C.ColorTransfer int colorTransfer, byte[] hdrStaticInfo) { + public ColorInfo( + @C.ColorSpace int colorSpace, + @C.ColorRange int colorRange, + @C.ColorTransfer int colorTransfer, + @Nullable byte[] hdrStaticInfo) { this.colorSpace = colorSpace; this.colorRange = colorRange; this.colorTransfer = colorTransfer; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/video/HevcConfig.java b/library/core/src/main/java/com/google/android/exoplayer2/video/HevcConfig.java index 0982589866..089ff6343f 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/video/HevcConfig.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/video/HevcConfig.java @@ -15,6 +15,7 @@ */ package com.google.android.exoplayer2.video; +import android.support.annotation.Nullable; import com.google.android.exoplayer2.ParserException; import com.google.android.exoplayer2.util.NalUnitUtil; import com.google.android.exoplayer2.util.ParsableByteArray; @@ -26,7 +27,7 @@ import java.util.List; */ public final class HevcConfig { - public final List initializationData; + public final @Nullable List initializationData; public final int nalUnitLengthFieldLength; /** @@ -82,7 +83,7 @@ public final class HevcConfig { } } - private HevcConfig(List initializationData, int nalUnitLengthFieldLength) { + private HevcConfig(@Nullable List initializationData, int nalUnitLengthFieldLength) { this.initializationData = initializationData; this.nalUnitLengthFieldLength = nalUnitLengthFieldLength; }