Remove some more core classes from nullness blacklist

PiperOrigin-RevId: 283366568
This commit is contained in:
olly 2019-12-02 18:24:59 +00:00 committed by Oliver Woodman
parent ab1d54d0ac
commit 92566323da
11 changed files with 138 additions and 118 deletions

View File

@ -20,6 +20,7 @@ import com.google.android.exoplayer2.source.SampleStream;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.MediaClock; import com.google.android.exoplayer2.util.MediaClock;
import java.io.IOException; import java.io.IOException;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/** /**
* A {@link Renderer} implementation whose track type is {@link C#TRACK_TYPE_NONE} and does not * A {@link Renderer} implementation whose track type is {@link C#TRACK_TYPE_NONE} and does not
@ -27,10 +28,10 @@ import java.io.IOException;
*/ */
public abstract class NoSampleRenderer implements Renderer, RendererCapabilities { public abstract class NoSampleRenderer implements Renderer, RendererCapabilities {
private RendererConfiguration configuration; @MonotonicNonNull private RendererConfiguration configuration;
private int index; private int index;
private int state; private int state;
private SampleStream stream; @Nullable private SampleStream stream;
private boolean streamIsFinal; private boolean streamIsFinal;
@Override @Override
@ -285,8 +286,10 @@ public abstract class NoSampleRenderer implements Renderer, RendererCapabilities
// Methods to be called by subclasses. // Methods to be called by subclasses.
/** /**
* Returns the configuration set when the renderer was most recently enabled. * Returns the configuration set when the renderer was most recently enabled, or {@code null} if
* the renderer has never been enabled.
*/ */
@Nullable
protected final RendererConfiguration getConfiguration() { protected final RendererConfiguration getConfiguration() {
return configuration; return configuration;
} }

View File

@ -15,6 +15,8 @@
*/ */
package com.google.android.exoplayer2.audio; package com.google.android.exoplayer2.audio;
import static com.google.android.exoplayer2.util.Util.castNonNull;
import android.os.Handler; import android.os.Handler;
import android.os.SystemClock; import android.os.SystemClock;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
@ -105,8 +107,8 @@ public interface AudioRendererEventListener {
* Invokes {@link AudioRendererEventListener#onAudioEnabled(DecoderCounters)}. * Invokes {@link AudioRendererEventListener#onAudioEnabled(DecoderCounters)}.
*/ */
public void enabled(final DecoderCounters decoderCounters) { public void enabled(final DecoderCounters decoderCounters) {
if (listener != null) { if (handler != null) {
handler.post(() -> listener.onAudioEnabled(decoderCounters)); handler.post(() -> castNonNull(listener).onAudioEnabled(decoderCounters));
} }
} }
@ -115,10 +117,11 @@ public interface AudioRendererEventListener {
*/ */
public void decoderInitialized(final String decoderName, public void decoderInitialized(final String decoderName,
final long initializedTimestampMs, final long initializationDurationMs) { final long initializedTimestampMs, final long initializationDurationMs) {
if (listener != null) { if (handler != null) {
handler.post( handler.post(
() -> () ->
listener.onAudioDecoderInitialized( castNonNull(listener)
.onAudioDecoderInitialized(
decoderName, initializedTimestampMs, initializationDurationMs)); decoderName, initializedTimestampMs, initializationDurationMs));
} }
} }
@ -127,8 +130,8 @@ public interface AudioRendererEventListener {
* Invokes {@link AudioRendererEventListener#onAudioInputFormatChanged(Format)}. * Invokes {@link AudioRendererEventListener#onAudioInputFormatChanged(Format)}.
*/ */
public void inputFormatChanged(final Format format) { public void inputFormatChanged(final Format format) {
if (listener != null) { if (handler != null) {
handler.post(() -> listener.onAudioInputFormatChanged(format)); handler.post(() -> castNonNull(listener).onAudioInputFormatChanged(format));
} }
} }
@ -137,9 +140,11 @@ public interface AudioRendererEventListener {
*/ */
public void audioTrackUnderrun(final int bufferSize, final long bufferSizeMs, public void audioTrackUnderrun(final int bufferSize, final long bufferSizeMs,
final long elapsedSinceLastFeedMs) { final long elapsedSinceLastFeedMs) {
if (listener != null) { if (handler != null) {
handler.post( handler.post(
() -> listener.onAudioSinkUnderrun(bufferSize, bufferSizeMs, elapsedSinceLastFeedMs)); () ->
castNonNull(listener)
.onAudioSinkUnderrun(bufferSize, bufferSizeMs, elapsedSinceLastFeedMs));
} }
} }
@ -148,11 +153,11 @@ public interface AudioRendererEventListener {
*/ */
public void disabled(final DecoderCounters counters) { public void disabled(final DecoderCounters counters) {
counters.ensureUpdated(); counters.ensureUpdated();
if (listener != null) { if (handler != null) {
handler.post( handler.post(
() -> { () -> {
counters.ensureUpdated(); counters.ensureUpdated();
listener.onAudioDisabled(counters); castNonNull(listener).onAudioDisabled(counters);
}); });
} }
} }
@ -161,11 +166,9 @@ public interface AudioRendererEventListener {
* Invokes {@link AudioRendererEventListener#onAudioSessionId(int)}. * Invokes {@link AudioRendererEventListener#onAudioSessionId(int)}.
*/ */
public void audioSessionId(final int audioSessionId) { public void audioSessionId(final int audioSessionId) {
if (listener != null) { if (handler != null) {
handler.post(() -> listener.onAudioSessionId(audioSessionId)); handler.post(() -> castNonNull(listener).onAudioSessionId(audioSessionId));
} }
} }
} }
} }

View File

@ -17,6 +17,7 @@ package com.google.android.exoplayer2.extractor;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
import org.checkerframework.checker.nullness.qual.Nullable;
/** /**
* An MPEG audio frame header. * An MPEG audio frame header.
@ -195,7 +196,7 @@ public final class MpegAudioHeader {
/** MPEG audio header version. */ /** MPEG audio header version. */
public int version; public int version;
/** The mime type. */ /** The mime type. */
public String mimeType; @Nullable public String mimeType;
/** Size of the frame associated with this header, in bytes. */ /** Size of the frame associated with this header, in bytes. */
public int frameSize; public int frameSize;
/** Sample rate in samples per second. */ /** Sample rate in samples per second. */
@ -223,5 +224,4 @@ public final class MpegAudioHeader {
this.bitrate = bitrate; this.bitrate = bitrate;
this.samplesPerFrame = samplesPerFrame; this.samplesPerFrame = samplesPerFrame;
} }
} }

View File

@ -15,6 +15,7 @@
*/ */
package com.google.android.exoplayer2.extractor.wav; package com.google.android.exoplayer2.extractor.wav;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ParserException; import com.google.android.exoplayer2.ParserException;
import com.google.android.exoplayer2.audio.WavUtil; import com.google.android.exoplayer2.audio.WavUtil;
@ -39,6 +40,7 @@ import java.io.IOException;
* @return A new {@code WavHeader} peeked from {@code input}, or null if the input is not a * @return A new {@code WavHeader} peeked from {@code input}, or null if the input is not a
* supported WAV format. * supported WAV format.
*/ */
@Nullable
public static WavHeader peek(ExtractorInput input) throws IOException, InterruptedException { public static WavHeader peek(ExtractorInput input) throws IOException, InterruptedException {
Assertions.checkNotNull(input); Assertions.checkNotNull(input);

View File

@ -15,6 +15,7 @@
*/ */
package com.google.android.exoplayer2.metadata; package com.google.android.exoplayer2.metadata;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.metadata.emsg.EventMessageDecoder; import com.google.android.exoplayer2.metadata.emsg.EventMessageDecoder;
import com.google.android.exoplayer2.metadata.icy.IcyDecoder; import com.google.android.exoplayer2.metadata.icy.IcyDecoder;
@ -62,7 +63,7 @@ public interface MetadataDecoderFactory {
@Override @Override
public boolean supportsFormat(Format format) { public boolean supportsFormat(Format format) {
String mimeType = format.sampleMimeType; @Nullable String mimeType = format.sampleMimeType;
return MimeTypes.APPLICATION_ID3.equals(mimeType) return MimeTypes.APPLICATION_ID3.equals(mimeType)
|| MimeTypes.APPLICATION_EMSG.equals(mimeType) || MimeTypes.APPLICATION_EMSG.equals(mimeType)
|| MimeTypes.APPLICATION_SCTE35.equals(mimeType) || MimeTypes.APPLICATION_SCTE35.equals(mimeType)
@ -71,7 +72,9 @@ public interface MetadataDecoderFactory {
@Override @Override
public MetadataDecoder createDecoder(Format format) { public MetadataDecoder createDecoder(Format format) {
switch (format.sampleMimeType) { @Nullable String mimeType = format.sampleMimeType;
if (mimeType != null) {
switch (mimeType) {
case MimeTypes.APPLICATION_ID3: case MimeTypes.APPLICATION_ID3:
return new Id3Decoder(); return new Id3Decoder();
case MimeTypes.APPLICATION_EMSG: case MimeTypes.APPLICATION_EMSG:
@ -81,9 +84,11 @@ public interface MetadataDecoderFactory {
case MimeTypes.APPLICATION_ICY: case MimeTypes.APPLICATION_ICY:
return new IcyDecoder(); return new IcyDecoder();
default: default:
throw new IllegalArgumentException( break;
"Attempted to create decoder for unsupported format");
} }
} }
throw new IllegalArgumentException(
"Attempted to create decoder for unsupported MIME type: " + mimeType);
}
}; };
} }

View File

@ -15,6 +15,7 @@
*/ */
package com.google.android.exoplayer2.text; package com.google.android.exoplayer2.text;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.text.cea.Cea608Decoder; import com.google.android.exoplayer2.text.cea.Cea608Decoder;
import com.google.android.exoplayer2.text.cea.Cea708Decoder; import com.google.android.exoplayer2.text.cea.Cea708Decoder;
@ -74,7 +75,7 @@ public interface SubtitleDecoderFactory {
@Override @Override
public boolean supportsFormat(Format format) { public boolean supportsFormat(Format format) {
String mimeType = format.sampleMimeType; @Nullable String mimeType = format.sampleMimeType;
return MimeTypes.TEXT_VTT.equals(mimeType) return MimeTypes.TEXT_VTT.equals(mimeType)
|| MimeTypes.TEXT_SSA.equals(mimeType) || MimeTypes.TEXT_SSA.equals(mimeType)
|| MimeTypes.APPLICATION_TTML.equals(mimeType) || MimeTypes.APPLICATION_TTML.equals(mimeType)
@ -90,7 +91,9 @@ public interface SubtitleDecoderFactory {
@Override @Override
public SubtitleDecoder createDecoder(Format format) { public SubtitleDecoder createDecoder(Format format) {
switch (format.sampleMimeType) { @Nullable String mimeType = format.sampleMimeType;
if (mimeType != null) {
switch (mimeType) {
case MimeTypes.TEXT_VTT: case MimeTypes.TEXT_VTT:
return new WebvttDecoder(); return new WebvttDecoder();
case MimeTypes.TEXT_SSA: case MimeTypes.TEXT_SSA:
@ -105,7 +108,7 @@ public interface SubtitleDecoderFactory {
return new Tx3gDecoder(format.initializationData); return new Tx3gDecoder(format.initializationData);
case MimeTypes.APPLICATION_CEA608: case MimeTypes.APPLICATION_CEA608:
case MimeTypes.APPLICATION_MP4CEA608: case MimeTypes.APPLICATION_MP4CEA608:
return new Cea608Decoder(format.sampleMimeType, format.accessibilityChannel); return new Cea608Decoder(mimeType, format.accessibilityChannel);
case MimeTypes.APPLICATION_CEA708: case MimeTypes.APPLICATION_CEA708:
return new Cea708Decoder(format.accessibilityChannel, format.initializationData); return new Cea708Decoder(format.accessibilityChannel, format.initializationData);
case MimeTypes.APPLICATION_DVBSUBS: case MimeTypes.APPLICATION_DVBSUBS:
@ -113,9 +116,11 @@ public interface SubtitleDecoderFactory {
case MimeTypes.APPLICATION_PGS: case MimeTypes.APPLICATION_PGS:
return new PgsDecoder(); return new PgsDecoder();
default: default:
throw new IllegalArgumentException( break;
"Attempted to create decoder for unsupported format");
} }
} }
throw new IllegalArgumentException(
"Attempted to create decoder for unsupported MIME type: " + mimeType);
}
}; };
} }

View File

@ -190,8 +190,8 @@ public final class Loader implements LoaderErrorThrower {
private final ExecutorService downloadExecutorService; private final ExecutorService downloadExecutorService;
private LoadTask<? extends Loadable> currentTask; @Nullable private LoadTask<? extends Loadable> currentTask;
private IOException fatalError; @Nullable private IOException fatalError;
/** /**
* @param threadName A name for the loader's thread. * @param threadName A name for the loader's thread.
@ -242,39 +242,34 @@ public final class Loader implements LoaderErrorThrower {
*/ */
public <T extends Loadable> long startLoading( public <T extends Loadable> long startLoading(
T loadable, Callback<T> callback, int defaultMinRetryCount) { T loadable, Callback<T> callback, int defaultMinRetryCount) {
Looper looper = Looper.myLooper(); Looper looper = Assertions.checkStateNotNull(Looper.myLooper());
Assertions.checkState(looper != null);
fatalError = null; fatalError = null;
long startTimeMs = SystemClock.elapsedRealtime(); long startTimeMs = SystemClock.elapsedRealtime();
new LoadTask<>(looper, loadable, callback, defaultMinRetryCount, startTimeMs).start(0); new LoadTask<>(looper, loadable, callback, defaultMinRetryCount, startTimeMs).start(0);
return startTimeMs; return startTimeMs;
} }
/** /** Returns whether the loader is currently loading. */
* Returns whether the {@link Loader} is currently loading a {@link Loadable}.
*/
public boolean isLoading() { public boolean isLoading() {
return currentTask != null; return currentTask != null;
} }
/** /**
* Cancels the current load. This method should only be called when a load is in progress. * Cancels the current load.
*
* @throws IllegalStateException If the loader is not currently loading.
*/ */
public void cancelLoading() { public void cancelLoading() {
currentTask.cancel(false); Assertions.checkStateNotNull(currentTask).cancel(false);
} }
/** /** Releases the loader. This method should be called when the loader is no longer required. */
* Releases the {@link Loader}. This method should be called when the {@link Loader} is no longer
* required.
*/
public void release() { public void release() {
release(null); release(null);
} }
/** /**
* Releases the {@link Loader}. This method should be called when the {@link Loader} is no longer * Releases the loader. This method should be called when the loader is no longer required.
* required.
* *
* @param callback An optional callback to be called on the loading thread once the loader has * @param callback An optional callback to be called on the loading thread once the loader has
* been released. * been released.
@ -325,10 +320,10 @@ public final class Loader implements LoaderErrorThrower {
private final long startTimeMs; private final long startTimeMs;
@Nullable private Loader.Callback<T> callback; @Nullable private Loader.Callback<T> callback;
private IOException currentError; @Nullable private IOException currentError;
private int errorCount; private int errorCount;
private volatile Thread executorThread; @Nullable private volatile Thread executorThread;
private volatile boolean canceled; private volatile boolean canceled;
private volatile boolean released; private volatile boolean released;
@ -368,6 +363,7 @@ public final class Loader implements LoaderErrorThrower {
} else { } else {
canceled = true; canceled = true;
loadable.cancelLoad(); loadable.cancelLoad();
Thread executorThread = this.executorThread;
if (executorThread != null) { if (executorThread != null) {
executorThread.interrupt(); executorThread.interrupt();
} }
@ -375,7 +371,8 @@ public final class Loader implements LoaderErrorThrower {
if (released) { if (released) {
finish(); finish();
long nowMs = SystemClock.elapsedRealtime(); long nowMs = SystemClock.elapsedRealtime();
callback.onLoadCanceled(loadable, nowMs, nowMs - startTimeMs, true); Assertions.checkNotNull(callback)
.onLoadCanceled(loadable, nowMs, nowMs - startTimeMs, true);
// If loading, this task will be referenced from a GC root (the loading thread) until // If loading, this task will be referenced from a GC root (the loading thread) until
// cancellation completes. The time taken for cancellation to complete depends on the // cancellation completes. The time taken for cancellation to complete depends on the
// implementation of the Loadable that the task is loading. We null the callback reference // implementation of the Loadable that the task is loading. We null the callback reference
@ -450,6 +447,7 @@ public final class Loader implements LoaderErrorThrower {
finish(); finish();
long nowMs = SystemClock.elapsedRealtime(); long nowMs = SystemClock.elapsedRealtime();
long durationMs = nowMs - startTimeMs; long durationMs = nowMs - startTimeMs;
Loader.Callback<T> callback = Assertions.checkNotNull(this.callback);
if (canceled) { if (canceled) {
callback.onLoadCanceled(loadable, nowMs, durationMs, false); callback.onLoadCanceled(loadable, nowMs, durationMs, false);
return; return;
@ -492,7 +490,7 @@ public final class Loader implements LoaderErrorThrower {
private void execute() { private void execute() {
currentError = null; currentError = null;
downloadExecutorService.execute(currentTask); downloadExecutorService.execute(Assertions.checkNotNull(currentTask));
} }
private void finish() { private void finish() {

View File

@ -172,7 +172,7 @@ public final class CacheUtil {
@Nullable CacheKeyFactory cacheKeyFactory, @Nullable CacheKeyFactory cacheKeyFactory,
CacheDataSource dataSource, CacheDataSource dataSource,
byte[] buffer, byte[] buffer,
PriorityTaskManager priorityTaskManager, @Nullable PriorityTaskManager priorityTaskManager,
int priority, int priority,
@Nullable ProgressListener progressListener, @Nullable ProgressListener progressListener,
@Nullable AtomicBoolean isCanceled, @Nullable AtomicBoolean isCanceled,
@ -268,11 +268,11 @@ public final class CacheUtil {
long length, long length,
DataSource dataSource, DataSource dataSource,
byte[] buffer, byte[] buffer,
PriorityTaskManager priorityTaskManager, @Nullable PriorityTaskManager priorityTaskManager,
int priority, int priority,
@Nullable ProgressNotifier progressNotifier, @Nullable ProgressNotifier progressNotifier,
boolean isLastBlock, boolean isLastBlock,
AtomicBoolean isCanceled) @Nullable AtomicBoolean isCanceled)
throws IOException, InterruptedException { throws IOException, InterruptedException {
long positionOffset = absoluteStreamPosition - dataSpec.absoluteStreamPosition; long positionOffset = absoluteStreamPosition - dataSpec.absoluteStreamPosition;
long initialPositionOffset = positionOffset; long initialPositionOffset = positionOffset;
@ -392,7 +392,7 @@ public final class CacheUtil {
.buildCacheKey(dataSpec); .buildCacheKey(dataSpec);
} }
private static void throwExceptionIfInterruptedOrCancelled(AtomicBoolean isCanceled) private static void throwExceptionIfInterruptedOrCancelled(@Nullable AtomicBoolean isCanceled)
throws InterruptedException { throws InterruptedException {
if (Thread.interrupted() || (isCanceled != null && isCanceled.get())) { if (Thread.interrupted() || (isCanceled != null && isCanceled.get())) {
throw new InterruptedException(); throw new InterruptedException();

View File

@ -17,13 +17,10 @@ package com.google.android.exoplayer2.upstream.cache;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.upstream.cache.Cache.CacheException; import com.google.android.exoplayer2.upstream.cache.Cache.CacheException;
import java.util.Comparator;
import java.util.TreeSet; import java.util.TreeSet;
/** /** Evicts least recently used cache files first. */
* Evicts least recently used cache files first. public final class LeastRecentlyUsedCacheEvictor implements CacheEvictor {
*/
public final class LeastRecentlyUsedCacheEvictor implements CacheEvictor, Comparator<CacheSpan> {
private final long maxBytes; private final long maxBytes;
private final TreeSet<CacheSpan> leastRecentlyUsed; private final TreeSet<CacheSpan> leastRecentlyUsed;
@ -32,7 +29,7 @@ public final class LeastRecentlyUsedCacheEvictor implements CacheEvictor, Compar
public LeastRecentlyUsedCacheEvictor(long maxBytes) { public LeastRecentlyUsedCacheEvictor(long maxBytes) {
this.maxBytes = maxBytes; this.maxBytes = maxBytes;
this.leastRecentlyUsed = new TreeSet<>(this); this.leastRecentlyUsed = new TreeSet<>(LeastRecentlyUsedCacheEvictor::compare);
} }
@Override @Override
@ -71,16 +68,6 @@ public final class LeastRecentlyUsedCacheEvictor implements CacheEvictor, Compar
onSpanAdded(cache, newSpan); onSpanAdded(cache, newSpan);
} }
@Override
public int compare(CacheSpan lhs, CacheSpan rhs) {
long lastTouchTimestampDelta = lhs.lastTouchTimestamp - rhs.lastTouchTimestamp;
if (lastTouchTimestampDelta == 0) {
// Use the standard compareTo method as a tie-break.
return lhs.compareTo(rhs);
}
return lhs.lastTouchTimestamp < rhs.lastTouchTimestamp ? -1 : 1;
}
private void evictCache(Cache cache, long requiredSpace) { private void evictCache(Cache cache, long requiredSpace) {
while (currentSize + requiredSpace > maxBytes && !leastRecentlyUsed.isEmpty()) { while (currentSize + requiredSpace > maxBytes && !leastRecentlyUsed.isEmpty()) {
try { try {
@ -91,4 +78,12 @@ public final class LeastRecentlyUsedCacheEvictor implements CacheEvictor, Compar
} }
} }
private static int compare(CacheSpan lhs, CacheSpan rhs) {
long lastTouchTimestampDelta = lhs.lastTouchTimestamp - rhs.lastTouchTimestamp;
if (lastTouchTimestampDelta == 0) {
// Use the standard compareTo method as a tie-break.
return lhs.compareTo(rhs);
}
return lhs.lastTouchTimestamp < rhs.lastTouchTimestamp ? -1 : 1;
}
} }

View File

@ -116,10 +116,11 @@ import java.util.regex.Pattern;
File file, long length, long lastTouchTimestamp, CachedContentIndex index) { File file, long length, long lastTouchTimestamp, CachedContentIndex index) {
String name = file.getName(); String name = file.getName();
if (!name.endsWith(SUFFIX)) { if (!name.endsWith(SUFFIX)) {
file = upgradeFile(file, index); @Nullable File upgradedFile = upgradeFile(file, index);
if (file == null) { if (upgradedFile == null) {
return null; return null;
} }
file = upgradedFile;
name = file.getName(); name = file.getName();
} }
@ -174,8 +175,12 @@ import java.util.regex.Pattern;
key = matcher.group(1); // Keys were not escaped in version 1. key = matcher.group(1); // Keys were not escaped in version 1.
} }
File newCacheFile = getCacheFile(file.getParentFile(), index.assignIdForKey(key), File newCacheFile =
Long.parseLong(matcher.group(2)), Long.parseLong(matcher.group(3))); getCacheFile(
Assertions.checkStateNotNull(file.getParentFile()),
index.assignIdForKey(key),
Long.parseLong(matcher.group(2)),
Long.parseLong(matcher.group(3)));
if (!file.renameTo(newCacheFile)) { if (!file.renameTo(newCacheFile)) {
return null; return null;
} }

View File

@ -15,6 +15,8 @@
*/ */
package com.google.android.exoplayer2.video; package com.google.android.exoplayer2.video;
import static com.google.android.exoplayer2.util.Util.castNonNull;
import android.os.Handler; import android.os.Handler;
import android.os.SystemClock; import android.os.SystemClock;
import android.view.Surface; import android.view.Surface;
@ -126,33 +128,34 @@ public interface VideoRendererEventListener {
/** Invokes {@link VideoRendererEventListener#onVideoEnabled(DecoderCounters)}. */ /** Invokes {@link VideoRendererEventListener#onVideoEnabled(DecoderCounters)}. */
public void enabled(DecoderCounters decoderCounters) { public void enabled(DecoderCounters decoderCounters) {
if (listener != null) { if (handler != null) {
handler.post(() -> listener.onVideoEnabled(decoderCounters)); handler.post(() -> castNonNull(listener).onVideoEnabled(decoderCounters));
} }
} }
/** Invokes {@link VideoRendererEventListener#onVideoDecoderInitialized(String, long, long)}. */ /** Invokes {@link VideoRendererEventListener#onVideoDecoderInitialized(String, long, long)}. */
public void decoderInitialized( public void decoderInitialized(
String decoderName, long initializedTimestampMs, long initializationDurationMs) { String decoderName, long initializedTimestampMs, long initializationDurationMs) {
if (listener != null) { if (handler != null) {
handler.post( handler.post(
() -> () ->
listener.onVideoDecoderInitialized( castNonNull(listener)
.onVideoDecoderInitialized(
decoderName, initializedTimestampMs, initializationDurationMs)); decoderName, initializedTimestampMs, initializationDurationMs));
} }
} }
/** Invokes {@link VideoRendererEventListener#onVideoInputFormatChanged(Format)}. */ /** Invokes {@link VideoRendererEventListener#onVideoInputFormatChanged(Format)}. */
public void inputFormatChanged(Format format) { public void inputFormatChanged(Format format) {
if (listener != null) { if (handler != null) {
handler.post(() -> listener.onVideoInputFormatChanged(format)); handler.post(() -> castNonNull(listener).onVideoInputFormatChanged(format));
} }
} }
/** Invokes {@link VideoRendererEventListener#onDroppedFrames(int, long)}. */ /** Invokes {@link VideoRendererEventListener#onDroppedFrames(int, long)}. */
public void droppedFrames(int droppedFrameCount, long elapsedMs) { public void droppedFrames(int droppedFrameCount, long elapsedMs) {
if (listener != null) { if (handler != null) {
handler.post(() -> listener.onDroppedFrames(droppedFrameCount, elapsedMs)); handler.post(() -> castNonNull(listener).onDroppedFrames(droppedFrameCount, elapsedMs));
} }
} }
@ -162,29 +165,30 @@ public interface VideoRendererEventListener {
int height, int height,
final int unappliedRotationDegrees, final int unappliedRotationDegrees,
final float pixelWidthHeightRatio) { final float pixelWidthHeightRatio) {
if (listener != null) { if (handler != null) {
handler.post( handler.post(
() -> () ->
listener.onVideoSizeChanged( castNonNull(listener)
.onVideoSizeChanged(
width, height, unappliedRotationDegrees, pixelWidthHeightRatio)); width, height, unappliedRotationDegrees, pixelWidthHeightRatio));
} }
} }
/** Invokes {@link VideoRendererEventListener#onRenderedFirstFrame(Surface)}. */ /** Invokes {@link VideoRendererEventListener#onRenderedFirstFrame(Surface)}. */
public void renderedFirstFrame(@Nullable Surface surface) { public void renderedFirstFrame(@Nullable Surface surface) {
if (listener != null) { if (handler != null) {
handler.post(() -> listener.onRenderedFirstFrame(surface)); handler.post(() -> castNonNull(listener).onRenderedFirstFrame(surface));
} }
} }
/** Invokes {@link VideoRendererEventListener#onVideoDisabled(DecoderCounters)}. */ /** Invokes {@link VideoRendererEventListener#onVideoDisabled(DecoderCounters)}. */
public void disabled(DecoderCounters counters) { public void disabled(DecoderCounters counters) {
counters.ensureUpdated(); counters.ensureUpdated();
if (listener != null) { if (handler != null) {
handler.post( handler.post(
() -> { () -> {
counters.ensureUpdated(); counters.ensureUpdated();
listener.onVideoDisabled(counters); castNonNull(listener).onVideoDisabled(counters);
}); });
} }
} }