mirror of
https://github.com/androidx/media.git
synced 2025-05-17 12:39:52 +08:00
Remove some more core classes from nullness blacklist
PiperOrigin-RevId: 283366568
This commit is contained in:
parent
ab1d54d0ac
commit
92566323da
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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,11 +117,12 @@ 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)
|
||||||
decoderName, initializedTimestampMs, initializationDurationMs));
|
.onAudioDecoderInitialized(
|
||||||
|
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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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,19 +72,23 @@ public interface MetadataDecoderFactory {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MetadataDecoder createDecoder(Format format) {
|
public MetadataDecoder createDecoder(Format format) {
|
||||||
switch (format.sampleMimeType) {
|
@Nullable String mimeType = format.sampleMimeType;
|
||||||
case MimeTypes.APPLICATION_ID3:
|
if (mimeType != null) {
|
||||||
return new Id3Decoder();
|
switch (mimeType) {
|
||||||
case MimeTypes.APPLICATION_EMSG:
|
case MimeTypes.APPLICATION_ID3:
|
||||||
return new EventMessageDecoder();
|
return new Id3Decoder();
|
||||||
case MimeTypes.APPLICATION_SCTE35:
|
case MimeTypes.APPLICATION_EMSG:
|
||||||
return new SpliceInfoDecoder();
|
return new EventMessageDecoder();
|
||||||
case MimeTypes.APPLICATION_ICY:
|
case MimeTypes.APPLICATION_SCTE35:
|
||||||
return new IcyDecoder();
|
return new SpliceInfoDecoder();
|
||||||
default:
|
case MimeTypes.APPLICATION_ICY:
|
||||||
throw new IllegalArgumentException(
|
return new IcyDecoder();
|
||||||
"Attempted to create decoder for unsupported format");
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Attempted to create decoder for unsupported MIME type: " + mimeType);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -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,32 +91,36 @@ public interface SubtitleDecoderFactory {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SubtitleDecoder createDecoder(Format format) {
|
public SubtitleDecoder createDecoder(Format format) {
|
||||||
switch (format.sampleMimeType) {
|
@Nullable String mimeType = format.sampleMimeType;
|
||||||
case MimeTypes.TEXT_VTT:
|
if (mimeType != null) {
|
||||||
return new WebvttDecoder();
|
switch (mimeType) {
|
||||||
case MimeTypes.TEXT_SSA:
|
case MimeTypes.TEXT_VTT:
|
||||||
return new SsaDecoder(format.initializationData);
|
return new WebvttDecoder();
|
||||||
case MimeTypes.APPLICATION_MP4VTT:
|
case MimeTypes.TEXT_SSA:
|
||||||
return new Mp4WebvttDecoder();
|
return new SsaDecoder(format.initializationData);
|
||||||
case MimeTypes.APPLICATION_TTML:
|
case MimeTypes.APPLICATION_MP4VTT:
|
||||||
return new TtmlDecoder();
|
return new Mp4WebvttDecoder();
|
||||||
case MimeTypes.APPLICATION_SUBRIP:
|
case MimeTypes.APPLICATION_TTML:
|
||||||
return new SubripDecoder();
|
return new TtmlDecoder();
|
||||||
case MimeTypes.APPLICATION_TX3G:
|
case MimeTypes.APPLICATION_SUBRIP:
|
||||||
return new Tx3gDecoder(format.initializationData);
|
return new SubripDecoder();
|
||||||
case MimeTypes.APPLICATION_CEA608:
|
case MimeTypes.APPLICATION_TX3G:
|
||||||
case MimeTypes.APPLICATION_MP4CEA608:
|
return new Tx3gDecoder(format.initializationData);
|
||||||
return new Cea608Decoder(format.sampleMimeType, format.accessibilityChannel);
|
case MimeTypes.APPLICATION_CEA608:
|
||||||
case MimeTypes.APPLICATION_CEA708:
|
case MimeTypes.APPLICATION_MP4CEA608:
|
||||||
return new Cea708Decoder(format.accessibilityChannel, format.initializationData);
|
return new Cea608Decoder(mimeType, format.accessibilityChannel);
|
||||||
case MimeTypes.APPLICATION_DVBSUBS:
|
case MimeTypes.APPLICATION_CEA708:
|
||||||
return new DvbDecoder(format.initializationData);
|
return new Cea708Decoder(format.accessibilityChannel, format.initializationData);
|
||||||
case MimeTypes.APPLICATION_PGS:
|
case MimeTypes.APPLICATION_DVBSUBS:
|
||||||
return new PgsDecoder();
|
return new DvbDecoder(format.initializationData);
|
||||||
default:
|
case MimeTypes.APPLICATION_PGS:
|
||||||
throw new IllegalArgumentException(
|
return new PgsDecoder();
|
||||||
"Attempted to create decoder for unsupported format");
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Attempted to create decoder for unsupported MIME type: " + mimeType);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -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() {
|
||||||
|
@ -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();
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
decoderName, initializedTimestampMs, initializationDurationMs));
|
.onVideoDecoderInitialized(
|
||||||
|
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)
|
||||||
width, height, unappliedRotationDegrees, pixelWidthHeightRatio));
|
.onVideoSizeChanged(
|
||||||
|
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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user