From dfc15733d2bba16f10bcce6bf8b9395357d90fd2 Mon Sep 17 00:00:00 2001 From: olly Date: Tue, 17 Dec 2019 13:34:33 +0000 Subject: [PATCH] Add NonNull annotations to the most extractor packages PiperOrigin-RevId: 285961788 --- .../extractor/amr/AmrExtractor.java | 21 +++++++++++--- .../extractor/amr/package-info.java | 19 ++++++++++++ .../extractor/flac/package-info.java | 19 ++++++++++++ .../extractor/flv/FlvExtractor.java | 13 +++++++-- .../extractor/flv/package-info.java | 19 ++++++++++++ .../extractor/mkv/DefaultEbmlReader.java | 14 +++++---- .../extractor/mkv/MatroskaExtractor.java | 23 ++++++++------- .../extractor/mkv/package-info.java | 19 ++++++++++++ .../extractor/mp3/Mp3Extractor.java | 29 ++++++++++++++----- .../exoplayer2/extractor/mp3/VbriSeeker.java | 3 +- .../exoplayer2/extractor/mp3/XingSeeker.java | 3 +- .../extractor/mp3/package-info.java | 19 ++++++++++++ .../extractor/ogg/DefaultOggSeeker.java | 5 +++- .../exoplayer2/extractor/ogg/FlacReader.java | 5 ++-- .../extractor/ogg/OggExtractor.java | 9 ++++-- .../exoplayer2/extractor/ogg/OggSeeker.java | 6 ++-- .../extractor/ogg/StreamReader.java | 7 +++-- .../extractor/ogg/VorbisReader.java | 2 +- .../extractor/ogg/package-info.java | 19 ++++++++++++ .../extractor/rawcc/RawCcExtractor.java | 10 ++++--- .../extractor/rawcc/package-info.java | 19 ++++++++++++ .../extractor/wav/package-info.java | 19 ++++++++++++ 22 files changed, 255 insertions(+), 47 deletions(-) create mode 100644 library/core/src/main/java/com/google/android/exoplayer2/extractor/amr/package-info.java create mode 100644 library/core/src/main/java/com/google/android/exoplayer2/extractor/flac/package-info.java create mode 100644 library/core/src/main/java/com/google/android/exoplayer2/extractor/flv/package-info.java create mode 100644 library/core/src/main/java/com/google/android/exoplayer2/extractor/mkv/package-info.java create mode 100644 library/core/src/main/java/com/google/android/exoplayer2/extractor/mp3/package-info.java create mode 100644 library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/package-info.java create mode 100644 library/core/src/main/java/com/google/android/exoplayer2/extractor/rawcc/package-info.java create mode 100644 library/core/src/main/java/com/google/android/exoplayer2/extractor/wav/package-info.java diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/amr/AmrExtractor.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/amr/AmrExtractor.java index f6b64245fc..6a31c941d2 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/amr/AmrExtractor.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/amr/AmrExtractor.java @@ -16,7 +16,6 @@ package com.google.android.exoplayer2.extractor.amr; import androidx.annotation.IntDef; -import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.ParserException; @@ -28,6 +27,7 @@ import com.google.android.exoplayer2.extractor.ExtractorsFactory; import com.google.android.exoplayer2.extractor.PositionHolder; import com.google.android.exoplayer2.extractor.SeekMap; import com.google.android.exoplayer2.extractor.TrackOutput; +import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.Util; import java.io.EOFException; @@ -36,6 +36,9 @@ import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Arrays; +import org.checkerframework.checker.nullness.qual.EnsuresNonNull; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; +import org.checkerframework.checker.nullness.qual.RequiresNonNull; /** * Extracts data from the AMR containers format (either AMR or AMR-WB). This follows RFC-4867, @@ -138,9 +141,9 @@ public final class AmrExtractor implements Extractor { private int numSamplesWithSameSize; private long timeOffsetUs; - private ExtractorOutput extractorOutput; - private TrackOutput trackOutput; - @Nullable private SeekMap seekMap; + @MonotonicNonNull private ExtractorOutput extractorOutput; + @MonotonicNonNull private TrackOutput trackOutput; + @MonotonicNonNull private SeekMap seekMap; private boolean hasOutputFormat; public AmrExtractor() { @@ -171,6 +174,7 @@ public final class AmrExtractor implements Extractor { @Override public int read(ExtractorInput input, PositionHolder seekPosition) throws IOException, InterruptedException { + assertInitialized(); if (input.getPosition() == 0) { if (!readAmrHeader(input)) { throw new ParserException("Could not find AMR header."); @@ -245,6 +249,7 @@ public final class AmrExtractor implements Extractor { return Arrays.equals(header, amrSignature); } + @RequiresNonNull("trackOutput") private void maybeOutputFormat() { if (!hasOutputFormat) { hasOutputFormat = true; @@ -267,6 +272,7 @@ public final class AmrExtractor implements Extractor { } } + @RequiresNonNull("trackOutput") private int readSample(ExtractorInput extractorInput) throws IOException, InterruptedException { if (currentSampleBytesRemaining == 0) { try { @@ -346,6 +352,7 @@ public final class AmrExtractor implements Extractor { return !isWideBand && (frameType < 12 || frameType > 14); } + @RequiresNonNull("extractorOutput") private void maybeOutputSeekMap(long inputLength, int sampleReadResult) { if (hasOutputSeekMap) { return; @@ -370,6 +377,12 @@ public final class AmrExtractor implements Extractor { return new ConstantBitrateSeekMap(inputLength, firstSamplePosition, bitrate, firstSampleSize); } + @EnsuresNonNull({"extractorOutput", "trackOutput"}) + private void assertInitialized() { + Assertions.checkStateNotNull(trackOutput); + Util.castNonNull(extractorOutput); + } + /** * Returns the stream bitrate, given a frame size and the duration of that frame in microseconds. * diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/amr/package-info.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/amr/package-info.java new file mode 100644 index 0000000000..31d58fadc9 --- /dev/null +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/amr/package-info.java @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +@NonNullApi +package com.google.android.exoplayer2.extractor.amr; + +import com.google.android.exoplayer2.util.NonNullApi; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/flac/package-info.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/flac/package-info.java new file mode 100644 index 0000000000..44d3427910 --- /dev/null +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/flac/package-info.java @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +@NonNullApi +package com.google.android.exoplayer2.extractor.flac; + +import com.google.android.exoplayer2.util.NonNullApi; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/flv/FlvExtractor.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/flv/FlvExtractor.java index f6835558f2..0ec98f9653 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/flv/FlvExtractor.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/flv/FlvExtractor.java @@ -23,11 +23,14 @@ import com.google.android.exoplayer2.extractor.ExtractorOutput; import com.google.android.exoplayer2.extractor.ExtractorsFactory; import com.google.android.exoplayer2.extractor.PositionHolder; import com.google.android.exoplayer2.extractor.SeekMap; +import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.ParsableByteArray; import java.io.IOException; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; +import org.checkerframework.checker.nullness.qual.RequiresNonNull; /** * Extracts data from the FLV container format. @@ -71,7 +74,7 @@ public final class FlvExtractor implements Extractor { private final ParsableByteArray tagData; private final ScriptTagPayloadReader metadataReader; - private ExtractorOutput extractorOutput; + @MonotonicNonNull private ExtractorOutput extractorOutput; private @States int state; private boolean outputFirstSample; private long mediaTagTimestampOffsetUs; @@ -80,8 +83,8 @@ public final class FlvExtractor implements Extractor { private int tagDataSize; private long tagTimestampUs; private boolean outputSeekMap; - private AudioTagPayloadReader audioReader; - private VideoTagPayloadReader videoReader; + @MonotonicNonNull private AudioTagPayloadReader audioReader; + @MonotonicNonNull private VideoTagPayloadReader videoReader; public FlvExtractor() { scratch = new ParsableByteArray(4); @@ -143,6 +146,7 @@ public final class FlvExtractor implements Extractor { @Override public int read(ExtractorInput input, PositionHolder seekPosition) throws IOException, InterruptedException { + Assertions.checkStateNotNull(extractorOutput); // Asserts that init has been called. while (true) { switch (state) { case STATE_READING_FLV_HEADER: @@ -178,6 +182,7 @@ public final class FlvExtractor implements Extractor { * @throws IOException If an error occurred reading or parsing data from the source. * @throws InterruptedException If the thread was interrupted. */ + @RequiresNonNull("extractorOutput") private boolean readFlvHeader(ExtractorInput input) throws IOException, InterruptedException { if (!input.readFully(headerBuffer.data, 0, FLV_HEADER_SIZE, true)) { // We've reached the end of the stream. @@ -250,6 +255,7 @@ public final class FlvExtractor implements Extractor { * @throws IOException If an error occurred reading or parsing data from the source. * @throws InterruptedException If the thread was interrupted. */ + @RequiresNonNull("extractorOutput") private boolean readTagData(ExtractorInput input) throws IOException, InterruptedException { boolean wasConsumed = true; boolean wasSampleOutput = false; @@ -293,6 +299,7 @@ public final class FlvExtractor implements Extractor { return tagData; } + @RequiresNonNull("extractorOutput") private void ensureReadyForMediaOutput() { if (!outputSeekMap) { extractorOutput.seekMap(new SeekMap.Unseekable(C.TIME_UNSET)); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/flv/package-info.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/flv/package-info.java new file mode 100644 index 0000000000..e726bb50e2 --- /dev/null +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/flv/package-info.java @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +@NonNullApi +package com.google.android.exoplayer2.extractor.flv; + +import com.google.android.exoplayer2.util.NonNullApi; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mkv/DefaultEbmlReader.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mkv/DefaultEbmlReader.java index b5da6dbf2f..5e6164249b 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mkv/DefaultEbmlReader.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mkv/DefaultEbmlReader.java @@ -15,6 +15,7 @@ */ package com.google.android.exoplayer2.extractor.mkv; + import androidx.annotation.IntDef; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ParserException; @@ -26,6 +27,8 @@ import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayDeque; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; +import org.checkerframework.checker.nullness.qual.RequiresNonNull; /** * Default implementation of {@link EbmlReader}. @@ -52,7 +55,7 @@ import java.util.ArrayDeque; private final ArrayDeque masterElementsStack; private final VarintReader varintReader; - private EbmlProcessor processor; + @MonotonicNonNull private EbmlProcessor processor; private @ElementState int elementState; private int elementId; private long elementContentSize; @@ -79,8 +82,8 @@ import java.util.ArrayDeque; public boolean read(ExtractorInput input) throws IOException, InterruptedException { Assertions.checkNotNull(processor); while (true) { - if (!masterElementsStack.isEmpty() - && input.getPosition() >= masterElementsStack.peek().elementEndPosition) { + MasterElement head = masterElementsStack.peek(); + if (head != null && input.getPosition() >= head.elementEndPosition) { processor.endMasterElement(masterElementsStack.pop().elementId); return true; } @@ -159,8 +162,9 @@ import java.util.ArrayDeque; * @throws IOException If an error occurs reading from the input. * @throws InterruptedException If the thread is interrupted. */ - private long maybeResyncToNextLevel1Element(ExtractorInput input) throws IOException, - InterruptedException { + @RequiresNonNull("processor") + private long maybeResyncToNextLevel1Element(ExtractorInput input) + throws IOException, InterruptedException { input.resetPeekPosition(); while (true) { input.peekFully(scratch, 0, MAX_ID_BYTES); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java index b30fbf105e..ed2acc5898 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java @@ -57,6 +57,8 @@ import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.UUID; +import org.checkerframework.checker.nullness.compatqual.NullableType; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; /** Extracts data from the Matroska and WebM container formats. */ public class MatroskaExtractor implements Extractor { @@ -342,7 +344,7 @@ public class MatroskaExtractor implements Extractor { private long durationUs = C.TIME_UNSET; // The track corresponding to the current TrackEntry element, or null. - private Track currentTrack; + @Nullable private Track currentTrack; // Whether a seek map has been sent to the output. private boolean sentSeekMap; @@ -356,8 +358,8 @@ public class MatroskaExtractor implements Extractor { private long cuesContentPosition = C.POSITION_UNSET; private long seekPositionAfterBuildingCues = C.POSITION_UNSET; private long clusterTimecodeUs = C.TIME_UNSET; - private LongArray cueTimesUs; - private LongArray cueClusterPositions; + @Nullable private LongArray cueTimesUs; + @Nullable private LongArray cueClusterPositions; private boolean seenClusterPositionForCurrentCuePoint; // Reading state. @@ -372,8 +374,7 @@ public class MatroskaExtractor implements Extractor { private int[] blockSampleSizes; private int blockTrackNumber; private int blockTrackNumberLength; - @C.BufferFlags - private int blockFlags; + @C.BufferFlags private int blockFlags; private int blockAdditionalId; private boolean blockHasReferenceBlock; @@ -389,7 +390,7 @@ public class MatroskaExtractor implements Extractor { private boolean sampleInitializationVectorRead; // Extractor outputs. - private ExtractorOutput extractorOutput; + @MonotonicNonNull private ExtractorOutput extractorOutput; public MatroskaExtractor() { this(0); @@ -415,6 +416,7 @@ public class MatroskaExtractor implements Extractor { encryptionInitializationVector = new ParsableByteArray(ENCRYPTION_IV_SIZE); encryptionSubsampleData = new ParsableByteArray(); blockAdditionalData = new ParsableByteArray(); + blockSampleSizes = new int[1]; } @Override @@ -1924,7 +1926,7 @@ public class MatroskaExtractor implements Extractor { String mimeType; int maxInputSize = Format.NO_VALUE; @C.PcmEncoding int pcmEncoding = Format.NO_VALUE; - List initializationData = null; + @Nullable List initializationData = null; switch (codecId) { case CODEC_ID_VP8: mimeType = MimeTypes.VIDEO_VP8; @@ -1958,7 +1960,8 @@ public class MatroskaExtractor implements Extractor { nalUnitLengthFieldLength = hevcConfig.nalUnitLengthFieldLength; break; case CODEC_ID_FOURCC: - Pair> pair = parseFourCcPrivate(new ParsableByteArray(codecPrivate)); + Pair> pair = + parseFourCcPrivate(new ParsableByteArray(codecPrivate)); mimeType = pair.first; initializationData = pair.second; break; @@ -2220,8 +2223,8 @@ public class MatroskaExtractor implements Extractor { * is {@code null}. * @throws ParserException If the initialization data could not be built. */ - private static Pair> parseFourCcPrivate(ParsableByteArray buffer) - throws ParserException { + private static Pair> parseFourCcPrivate( + ParsableByteArray buffer) throws ParserException { try { buffer.skipBytes(16); // size(4), width(4), height(4), planes(2), bitcount(2). long compression = buffer.readLittleEndianUnsignedInt(); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mkv/package-info.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mkv/package-info.java new file mode 100644 index 0000000000..15629ba584 --- /dev/null +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mkv/package-info.java @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +@NonNullApi +package com.google.android.exoplayer2.extractor.mkv; + +import com.google.android.exoplayer2.util.NonNullApi; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp3/Mp3Extractor.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp3/Mp3Extractor.java index 7a25677c55..c69cdac1e9 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp3/Mp3Extractor.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp3/Mp3Extractor.java @@ -34,12 +34,17 @@ import com.google.android.exoplayer2.metadata.Metadata; import com.google.android.exoplayer2.metadata.id3.Id3Decoder; import com.google.android.exoplayer2.metadata.id3.Id3Decoder.FramePredicate; import com.google.android.exoplayer2.metadata.id3.MlltFrame; +import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.ParsableByteArray; +import com.google.android.exoplayer2.util.Util; import java.io.EOFException; import java.io.IOException; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import org.checkerframework.checker.nullness.qual.EnsuresNonNull; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; +import org.checkerframework.checker.nullness.qual.RequiresNonNull; /** * Extracts data from the MP3 container format. @@ -107,13 +112,13 @@ public final class Mp3Extractor implements Extractor { private final Id3Peeker id3Peeker; // Extractor outputs. - private ExtractorOutput extractorOutput; - private TrackOutput trackOutput; + @MonotonicNonNull private ExtractorOutput extractorOutput; + @MonotonicNonNull private TrackOutput trackOutput; private int synchronizedHeaderData; - private Metadata metadata; - @Nullable private Seeker seeker; + @Nullable private Metadata metadata; + @MonotonicNonNull private Seeker seeker; private boolean disableSeeking; private long basisTimeUs; private long samplesRead; @@ -176,6 +181,7 @@ public final class Mp3Extractor implements Extractor { @Override public int read(ExtractorInput input, PositionHolder seekPosition) throws IOException, InterruptedException { + assertInitialized(); if (synchronizedHeaderData == 0) { try { synchronize(input, false); @@ -242,6 +248,7 @@ public final class Mp3Extractor implements Extractor { // Internal methods. + @RequiresNonNull({"trackOutput", "seeker"}) private int readSample(ExtractorInput extractorInput) throws IOException, InterruptedException { if (sampleBytesRemaining == 0) { extractorInput.resetPeekPosition(); @@ -390,6 +397,7 @@ public final class Mp3Extractor implements Extractor { * @throws InterruptedException Thrown if reading from the stream was interrupted. Not expected if * the next two frames were already peeked during synchronization. */ + @Nullable private Seeker maybeReadSeekFrame(ExtractorInput input) throws IOException, InterruptedException { ParsableByteArray frame = new ParsableByteArray(synchronizedHeader.frameSize); input.peekFully(frame.data, 0, synchronizedHeader.frameSize); @@ -397,7 +405,7 @@ public final class Mp3Extractor implements Extractor { ? (synchronizedHeader.channels != 1 ? 36 : 21) // MPEG 1 : (synchronizedHeader.channels != 1 ? 21 : 13); // MPEG 2 or 2.5 int seekHeader = getSeekFrameHeader(frame, xingBase); - Seeker seeker; + @Nullable Seeker seeker; if (seekHeader == SEEK_HEADER_XING || seekHeader == SEEK_HEADER_INFO) { seeker = XingSeeker.create(input.getLength(), input.getPosition(), synchronizedHeader, frame); if (seeker != null && !gaplessInfoHolder.hasGaplessInfo()) { @@ -435,6 +443,12 @@ public final class Mp3Extractor implements Extractor { return new ConstantBitrateSeeker(input.getLength(), input.getPosition(), synchronizedHeader); } + @EnsuresNonNull({"extractorOutput", "trackOutput"}) + private void assertInitialized() { + Assertions.checkStateNotNull(trackOutput); + Util.castNonNull(extractorOutput); + } + /** * Returns whether the headers match in those bits masked by {@link #MPEG_AUDIO_HEADER_MASK}. */ @@ -465,7 +479,8 @@ public final class Mp3Extractor implements Extractor { } @Nullable - private static MlltSeeker maybeHandleSeekMetadata(Metadata metadata, long firstFramePosition) { + private static MlltSeeker maybeHandleSeekMetadata( + @Nullable Metadata metadata, long firstFramePosition) { if (metadata != null) { int length = metadata.length(); for (int i = 0; i < length; i++) { @@ -477,6 +492,4 @@ public final class Mp3Extractor implements Extractor { } return null; } - - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp3/VbriSeeker.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp3/VbriSeeker.java index 86551319e1..dcccc675ed 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp3/VbriSeeker.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp3/VbriSeeker.java @@ -41,7 +41,8 @@ import com.google.android.exoplayer2.util.Util; * @return A {@link VbriSeeker} for seeking in the stream, or {@code null} if the required * information is not present. */ - public static @Nullable VbriSeeker create( + @Nullable + public static VbriSeeker create( long inputLength, long position, MpegAudioHeader mpegAudioHeader, ParsableByteArray frame) { frame.skipBytes(10); int numFrames = frame.readInt(); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp3/XingSeeker.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp3/XingSeeker.java index db1a0199ac..aa1d8be316 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp3/XingSeeker.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp3/XingSeeker.java @@ -42,7 +42,8 @@ import com.google.android.exoplayer2.util.Util; * @return A {@link XingSeeker} for seeking in the stream, or {@code null} if the required * information is not present. */ - public static @Nullable XingSeeker create( + @Nullable + public static XingSeeker create( long inputLength, long position, MpegAudioHeader mpegAudioHeader, ParsableByteArray frame) { int samplesPerFrame = mpegAudioHeader.samplesPerFrame; int sampleRate = mpegAudioHeader.sampleRate; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp3/package-info.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp3/package-info.java new file mode 100644 index 0000000000..3483b26b47 --- /dev/null +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp3/package-info.java @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +@NonNullApi +package com.google.android.exoplayer2.extractor.mp3; + +import com.google.android.exoplayer2.util.NonNullApi; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/DefaultOggSeeker.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/DefaultOggSeeker.java index 51ab94ba0e..ecbaaeb143 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/DefaultOggSeeker.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/DefaultOggSeeker.java @@ -15,6 +15,7 @@ */ package com.google.android.exoplayer2.extractor.ogg; +import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ParserException; @@ -39,7 +40,7 @@ import java.io.IOException; private static final int STATE_SKIP = 3; private static final int STATE_IDLE = 4; - private final OggPageHeader pageHeader = new OggPageHeader(); + private final OggPageHeader pageHeader; private final long payloadStartPosition; private final long payloadEndPosition; private final StreamReader streamReader; @@ -83,6 +84,7 @@ import java.io.IOException; } else { state = STATE_SEEK_TO_END; } + pageHeader = new OggPageHeader(); } @Override @@ -121,6 +123,7 @@ import java.io.IOException; } @Override + @Nullable public OggSeekMap createSeekMap() { return totalGranules != 0 ? new OggSeekMap() : null; } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/FlacReader.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/FlacReader.java index f99b2420cc..258390d21d 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/FlacReader.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/FlacReader.java @@ -15,6 +15,7 @@ */ package com.google.android.exoplayer2.extractor.ogg; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.extractor.ExtractorInput; import com.google.android.exoplayer2.extractor.FlacFrameReader; import com.google.android.exoplayer2.extractor.FlacMetadataReader; @@ -37,8 +38,8 @@ import java.util.Arrays; private static final int FRAME_HEADER_SAMPLE_NUMBER_OFFSET = 4; - private FlacStreamMetadata streamMetadata; - private FlacOggSeeker flacOggSeeker; + @Nullable private FlacStreamMetadata streamMetadata; + @Nullable private FlacOggSeeker flacOggSeeker; public static boolean verifyBitstreamType(ParsableByteArray data) { return data.bytesLeft() >= 5 && data.readUnsignedByte() == 0x7F && // packet type diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/OggExtractor.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/OggExtractor.java index 5e74eab8d4..4c13cc946c 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/OggExtractor.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/OggExtractor.java @@ -23,8 +23,11 @@ import com.google.android.exoplayer2.extractor.ExtractorOutput; import com.google.android.exoplayer2.extractor.ExtractorsFactory; import com.google.android.exoplayer2.extractor.PositionHolder; import com.google.android.exoplayer2.extractor.TrackOutput; +import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.ParsableByteArray; import java.io.IOException; +import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; /** * Extracts data from the Ogg container format. @@ -36,8 +39,8 @@ public class OggExtractor implements Extractor { private static final int MAX_VERIFICATION_BYTES = 8; - private ExtractorOutput output; - private StreamReader streamReader; + @MonotonicNonNull private ExtractorOutput output; + @MonotonicNonNull private StreamReader streamReader; private boolean streamReaderInitialized; @Override @@ -69,6 +72,7 @@ public class OggExtractor implements Extractor { @Override public int read(ExtractorInput input, PositionHolder seekPosition) throws IOException, InterruptedException { + Assertions.checkStateNotNull(output); // Asserts that init has been called. if (streamReader == null) { if (!sniffInternal(input)) { throw new ParserException("Failed to determine bitstream type"); @@ -84,6 +88,7 @@ public class OggExtractor implements Extractor { return streamReader.read(input, seekPosition); } + @EnsuresNonNullIf(expression = "streamReader", result = true) private boolean sniffInternal(ExtractorInput input) throws IOException, InterruptedException { OggPageHeader header = new OggPageHeader(); if (!header.populate(input, true) || (header.type & 0x02) != 0x02) { diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/OggSeeker.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/OggSeeker.java index e4c3a163e6..1fa7478488 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/OggSeeker.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/OggSeeker.java @@ -15,6 +15,7 @@ */ package com.google.android.exoplayer2.extractor.ogg; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.extractor.ExtractorInput; import com.google.android.exoplayer2.extractor.SeekMap; import java.io.IOException; @@ -27,9 +28,10 @@ import java.io.IOException; /* package */ interface OggSeeker { /** - * Returns a {@link SeekMap} that returns an initial estimated position for progressive seeking - * or the final position for direct seeking. Returns null if {@link #read} has yet to return -1. + * Returns a {@link SeekMap} that returns an initial estimated position for progressive seeking or + * the final position for direct seeking. Returns null if {@link #read} has yet to return -1. */ + @Nullable SeekMap createSeekMap(); /** diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/StreamReader.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/StreamReader.java index d2671125e4..2aec9cdd59 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/StreamReader.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/StreamReader.java @@ -25,6 +25,7 @@ import com.google.android.exoplayer2.extractor.SeekMap; import com.google.android.exoplayer2.extractor.TrackOutput; import com.google.android.exoplayer2.util.ParsableByteArray; import java.io.IOException; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; /** StreamReader abstract class. */ @SuppressWarnings("UngroupedOverloads") @@ -42,9 +43,9 @@ import java.io.IOException; private final OggPacket oggPacket; - private TrackOutput trackOutput; - private ExtractorOutput extractorOutput; - private OggSeeker oggSeeker; + @MonotonicNonNull private TrackOutput trackOutput; + @MonotonicNonNull private ExtractorOutput extractorOutput; + @MonotonicNonNull private OggSeeker oggSeeker; private long targetGranule; private long payloadStartPosition; private long currentGranule; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/VorbisReader.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/VorbisReader.java index b57678266a..71c6c3b73e 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/VorbisReader.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/VorbisReader.java @@ -88,7 +88,7 @@ import java.util.ArrayList; @Override protected boolean readHeaders(ParsableByteArray packet, long position, SetupData setupData) - throws IOException, InterruptedException { + throws IOException { if (vorbisSetup != null) { return false; } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/package-info.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/package-info.java new file mode 100644 index 0000000000..ef8ed054a4 --- /dev/null +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/ogg/package-info.java @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +@NonNullApi +package com.google.android.exoplayer2.extractor.ogg; + +import com.google.android.exoplayer2.util.NonNullApi; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/rawcc/RawCcExtractor.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/rawcc/RawCcExtractor.java index 3d76276240..accdd89795 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/rawcc/RawCcExtractor.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/rawcc/RawCcExtractor.java @@ -24,8 +24,11 @@ import com.google.android.exoplayer2.extractor.ExtractorOutput; import com.google.android.exoplayer2.extractor.PositionHolder; import com.google.android.exoplayer2.extractor.SeekMap; import com.google.android.exoplayer2.extractor.TrackOutput; +import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.ParsableByteArray; import java.io.IOException; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; +import org.checkerframework.checker.nullness.qual.RequiresNonNull; /** * Extracts data from the RawCC container format. @@ -44,11 +47,9 @@ public final class RawCcExtractor implements Extractor { private static final int STATE_READING_SAMPLES = 2; private final Format format; - private final ParsableByteArray dataScratch; - private TrackOutput trackOutput; - + @MonotonicNonNull private TrackOutput trackOutput; private int parserState; private int version; private long timestampUs; @@ -79,6 +80,7 @@ public final class RawCcExtractor implements Extractor { @Override public int read(ExtractorInput input, PositionHolder seekPosition) throws IOException, InterruptedException { + Assertions.checkStateNotNull(trackOutput); // Asserts that init has been called. while (true) { switch (parserState) { case STATE_READING_HEADER: @@ -153,6 +155,7 @@ public final class RawCcExtractor implements Extractor { return true; } + @RequiresNonNull("trackOutput") private void parseSamples(ExtractorInput input) throws IOException, InterruptedException { for (; remainingSampleCount > 0; remainingSampleCount--) { dataScratch.reset(); @@ -166,5 +169,4 @@ public final class RawCcExtractor implements Extractor { trackOutput.sampleMetadata(timestampUs, C.BUFFER_FLAG_KEY_FRAME, sampleBytesWritten, 0, null); } } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/rawcc/package-info.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/rawcc/package-info.java new file mode 100644 index 0000000000..b01e56b8dd --- /dev/null +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/rawcc/package-info.java @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +@NonNullApi +package com.google.android.exoplayer2.extractor.rawcc; + +import com.google.android.exoplayer2.util.NonNullApi; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/wav/package-info.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/wav/package-info.java new file mode 100644 index 0000000000..4769ea693a --- /dev/null +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/wav/package-info.java @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +@NonNullApi +package com.google.android.exoplayer2.extractor.wav; + +import com.google.android.exoplayer2.util.NonNullApi;