Add NonNull annotations to metadata packages

Also remove MetadataRenderer and SpliceInfoDecoder from the
nullness blacklist

PiperOrigin-RevId: 283744417
This commit is contained in:
olly 2019-12-04 14:28:18 +00:00 committed by Ian Baker
parent b7666df2b3
commit 3930a539e0
12 changed files with 158 additions and 36 deletions

View File

@ -22,7 +22,6 @@ import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.util.Util;
import java.util.Arrays;
import java.util.List;
import org.checkerframework.checker.nullness.compatqual.NullableType;
/**
* A collection of metadata entries.
@ -57,19 +56,15 @@ public final class Metadata implements Parcelable {
* @param entries The metadata entries.
*/
public Metadata(Entry... entries) {
this.entries = entries == null ? new Entry[0] : entries;
this.entries = entries;
}
/**
* @param entries The metadata entries.
*/
public Metadata(List<? extends Entry> entries) {
if (entries != null) {
this.entries = new Entry[entries.size()];
entries.toArray(this.entries);
} else {
this.entries = new Entry[0];
}
}
/* package */ Metadata(Parcel in) {
@ -118,9 +113,10 @@ public final class Metadata implements Parcelable {
* @return The metadata instance with the appended entries.
*/
public Metadata copyWithAppendedEntries(Entry... entriesToAppend) {
@NullableType Entry[] merged = Arrays.copyOf(entries, entries.length + entriesToAppend.length);
System.arraycopy(entriesToAppend, 0, merged, entries.length, entriesToAppend.length);
return new Metadata(Util.castNonNullTypeArray(merged));
if (entriesToAppend.length == 0) {
return this;
}
return new Metadata(Util.nullSafeArrayConcatenation(entries, entriesToAppend));
}
@Override

View File

@ -15,6 +15,8 @@
*/
package com.google.android.exoplayer2.metadata;
import static com.google.android.exoplayer2.util.Util.castNonNull;
import android.os.Handler;
import android.os.Handler.Callback;
import android.os.Looper;
@ -22,7 +24,6 @@ import android.os.Message;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.BaseRenderer;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.FormatHolder;
import com.google.android.exoplayer2.util.Assertions;
@ -30,6 +31,7 @@ import com.google.android.exoplayer2.util.Util;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.checkerframework.checker.nullness.compatqual.NullableType;
/**
* A renderer for metadata.
@ -46,12 +48,12 @@ public final class MetadataRenderer extends BaseRenderer implements Callback {
private final MetadataOutput output;
@Nullable private final Handler outputHandler;
private final MetadataInputBuffer buffer;
private final Metadata[] pendingMetadata;
private final @NullableType Metadata[] pendingMetadata;
private final long[] pendingMetadataTimestamps;
private int pendingMetadataIndex;
private int pendingMetadataCount;
private MetadataDecoder decoder;
@Nullable private MetadataDecoder decoder;
private boolean inputStreamEnded;
private long subsampleOffsetUs;
@ -98,7 +100,7 @@ public final class MetadataRenderer extends BaseRenderer implements Callback {
}
@Override
protected void onStreamChanged(Format[] formats, long offsetUs) throws ExoPlaybackException {
protected void onStreamChanged(Format[] formats, long offsetUs) {
decoder = decoderFactory.createDecoder(formats[0]);
}
@ -109,7 +111,7 @@ public final class MetadataRenderer extends BaseRenderer implements Callback {
}
@Override
public void render(long positionUs, long elapsedRealtimeUs) throws ExoPlaybackException {
public void render(long positionUs, long elapsedRealtimeUs) {
if (!inputStreamEnded && pendingMetadataCount < MAX_PENDING_METADATA_COUNT) {
buffer.clear();
FormatHolder formatHolder = getFormatHolder();
@ -124,7 +126,7 @@ public final class MetadataRenderer extends BaseRenderer implements Callback {
} else {
buffer.subsampleOffsetUs = subsampleOffsetUs;
buffer.flip();
Metadata metadata = decoder.decode(buffer);
@Nullable Metadata metadata = castNonNull(decoder).decode(buffer);
if (metadata != null) {
List<Metadata.Entry> entries = new ArrayList<>(metadata.length());
decodeWrappedMetadata(metadata, entries);
@ -139,12 +141,13 @@ public final class MetadataRenderer extends BaseRenderer implements Callback {
}
}
} else if (result == C.RESULT_FORMAT_READ) {
subsampleOffsetUs = formatHolder.format.subsampleOffsetUs;
subsampleOffsetUs = Assertions.checkNotNull(formatHolder.format).subsampleOffsetUs;
}
}
if (pendingMetadataCount > 0 && pendingMetadataTimestamps[pendingMetadataIndex] <= positionUs) {
invokeRenderer(pendingMetadata[pendingMetadataIndex]);
Metadata metadata = castNonNull(pendingMetadata[pendingMetadataIndex]);
invokeRenderer(metadata);
pendingMetadata[pendingMetadataIndex] = null;
pendingMetadataIndex = (pendingMetadataIndex + 1) % MAX_PENDING_METADATA_COUNT;
pendingMetadataCount--;
@ -158,7 +161,7 @@ public final class MetadataRenderer extends BaseRenderer implements Callback {
*/
private void decodeWrappedMetadata(Metadata metadata, List<Metadata.Entry> decodedEntries) {
for (int i = 0; i < metadata.length(); i++) {
Format wrappedMetadataFormat = metadata.get(i).getWrappedMetadataFormat();
@Nullable Format wrappedMetadataFormat = metadata.get(i).getWrappedMetadataFormat();
if (wrappedMetadataFormat != null && decoderFactory.supportsFormat(wrappedMetadataFormat)) {
MetadataDecoder wrappedMetadataDecoder =
decoderFactory.createDecoder(wrappedMetadataFormat);
@ -167,7 +170,7 @@ public final class MetadataRenderer extends BaseRenderer implements Callback {
Assertions.checkNotNull(metadata.get(i).getWrappedMetadataBytes());
buffer.clear();
buffer.ensureSpaceForWrite(wrappedMetadataBytes.length);
buffer.data.put(wrappedMetadataBytes);
castNonNull(buffer.data).put(wrappedMetadataBytes);
buffer.flip();
@Nullable Metadata innerMetadata = wrappedMetadataDecoder.decode(buffer);
if (innerMetadata != null) {

View File

@ -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.metadata.emsg;
import com.google.android.exoplayer2.util.NonNullApi;

View File

@ -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.metadata.flac;
import com.google.android.exoplayer2.util.NonNullApi;

View File

@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer2.metadata.icy;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.metadata.MetadataDecoder;
@ -28,8 +29,6 @@ import java.util.regex.Pattern;
/** Decodes ICY stream information. */
public final class IcyDecoder implements MetadataDecoder {
private static final String TAG = "IcyDecoder";
private static final Pattern METADATA_ELEMENT = Pattern.compile("(.+?)='(.*?)';", Pattern.DOTALL);
private static final String STREAM_KEY_NAME = "streamtitle";
private static final String STREAM_KEY_URL = "streamurl";
@ -45,8 +44,8 @@ public final class IcyDecoder implements MetadataDecoder {
@VisibleForTesting
/* package */ Metadata decode(String metadata) {
String name = null;
String url = null;
@Nullable String name = null;
@Nullable String url = null;
int index = 0;
Matcher matcher = METADATA_ELEMENT.matcher(metadata);
while (matcher.find(index)) {

View File

@ -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.metadata.icy;
import com.google.android.exoplayer2.util.NonNullApi;

View File

@ -47,7 +47,7 @@ public final class ApicFrame extends Id3Frame {
/* package */ ApicFrame(Parcel in) {
super(ID);
mimeType = castNonNull(in.readString());
description = castNonNull(in.readString());
description = in.readString();
pictureType = in.readInt();
pictureData = castNonNull(in.createByteArray());
}

View File

@ -155,7 +155,8 @@ public final class Id3Decoder implements MetadataDecoder {
* @param data A {@link ParsableByteArray} from which the header should be read.
* @return The parsed header, or null if the ID3 tag is unsupported.
*/
private static @Nullable Id3Header decodeHeader(ParsableByteArray data) {
@Nullable
private static Id3Header decodeHeader(ParsableByteArray data) {
if (data.bytesLeft() < ID3_HEADER_LENGTH) {
Log.w(TAG, "Data too short to be an ID3 tag");
return null;
@ -269,7 +270,8 @@ public final class Id3Decoder implements MetadataDecoder {
}
}
private static @Nullable Id3Frame decodeFrame(
@Nullable
private static Id3Frame decodeFrame(
int majorVersion,
ParsableByteArray id3Data,
boolean unsignedIntFrameSizeHack,
@ -404,8 +406,9 @@ public final class Id3Decoder implements MetadataDecoder {
}
}
private static @Nullable TextInformationFrame decodeTxxxFrame(
ParsableByteArray id3Data, int frameSize) throws UnsupportedEncodingException {
@Nullable
private static TextInformationFrame decodeTxxxFrame(ParsableByteArray id3Data, int frameSize)
throws UnsupportedEncodingException {
if (frameSize < 1) {
// Frame is malformed.
return null;
@ -427,7 +430,8 @@ public final class Id3Decoder implements MetadataDecoder {
return new TextInformationFrame("TXXX", description, value);
}
private static @Nullable TextInformationFrame decodeTextInformationFrame(
@Nullable
private static TextInformationFrame decodeTextInformationFrame(
ParsableByteArray id3Data, int frameSize, String id) throws UnsupportedEncodingException {
if (frameSize < 1) {
// Frame is malformed.
@ -446,7 +450,8 @@ public final class Id3Decoder implements MetadataDecoder {
return new TextInformationFrame(id, null, value);
}
private static @Nullable UrlLinkFrame decodeWxxxFrame(ParsableByteArray id3Data, int frameSize)
@Nullable
private static UrlLinkFrame decodeWxxxFrame(ParsableByteArray id3Data, int frameSize)
throws UnsupportedEncodingException {
if (frameSize < 1) {
// Frame is malformed.
@ -557,7 +562,8 @@ public final class Id3Decoder implements MetadataDecoder {
return new ApicFrame(mimeType, description, pictureType, pictureData);
}
private static @Nullable CommentFrame decodeCommentFrame(ParsableByteArray id3Data, int frameSize)
@Nullable
private static CommentFrame decodeCommentFrame(ParsableByteArray id3Data, int frameSize)
throws UnsupportedEncodingException {
if (frameSize < 4) {
// Frame is malformed.

View File

@ -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.metadata.id3;
import com.google.android.exoplayer2.util.NonNullApi;

View File

@ -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.metadata;
import com.google.android.exoplayer2.util.NonNullApi;

View File

@ -15,13 +15,16 @@
*/
package com.google.android.exoplayer2.metadata.scte35;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.metadata.MetadataDecoder;
import com.google.android.exoplayer2.metadata.MetadataInputBuffer;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.ParsableBitArray;
import com.google.android.exoplayer2.util.ParsableByteArray;
import com.google.android.exoplayer2.util.TimestampAdjuster;
import java.nio.ByteBuffer;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/**
* Decodes splice info sections and produces splice commands.
@ -37,7 +40,7 @@ public final class SpliceInfoDecoder implements MetadataDecoder {
private final ParsableByteArray sectionData;
private final ParsableBitArray sectionHeader;
private TimestampAdjuster timestampAdjuster;
@MonotonicNonNull private TimestampAdjuster timestampAdjuster;
public SpliceInfoDecoder() {
sectionData = new ParsableByteArray();
@ -47,6 +50,8 @@ public final class SpliceInfoDecoder implements MetadataDecoder {
@SuppressWarnings("ByteBufferBackingArray")
@Override
public Metadata decode(MetadataInputBuffer inputBuffer) {
ByteBuffer buffer = Assertions.checkNotNull(inputBuffer.data);
// Internal timestamps adjustment.
if (timestampAdjuster == null
|| inputBuffer.subsampleOffsetUs != timestampAdjuster.getTimestampOffsetUs()) {
@ -54,7 +59,6 @@ public final class SpliceInfoDecoder implements MetadataDecoder {
timestampAdjuster.adjustSampleTimestamp(inputBuffer.timeUs - inputBuffer.subsampleOffsetUs);
}
ByteBuffer buffer = inputBuffer.data;
byte[] data = buffer.array();
int size = buffer.limit();
sectionData.reset(data, size);
@ -68,7 +72,7 @@ public final class SpliceInfoDecoder implements MetadataDecoder {
sectionHeader.skipBits(20);
int spliceCommandLength = sectionHeader.readBits(12);
int spliceCommandType = sectionHeader.readBits(8);
SpliceCommand command = null;
@Nullable SpliceCommand command = null;
// Go to the start of the command by skipping all fields up to command_type.
sectionData.skipBytes(14);
switch (spliceCommandType) {

View File

@ -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.metadata.scte35;
import com.google.android.exoplayer2.util.NonNullApi;