Create Util method for SparseArray.contains()

And fixed usages in Transformer and Effect.

PiperOrigin-RevId: 551484860
This commit is contained in:
claincly 2023-07-27 12:09:46 +01:00 committed by Rohit Singh
parent 17ee5277d5
commit e77c318d96
5 changed files with 36 additions and 29 deletions

View File

@ -69,6 +69,7 @@ import android.security.NetworkSecurityPolicy;
import android.telephony.TelephonyManager; import android.telephony.TelephonyManager;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Base64; import android.util.Base64;
import android.util.SparseArray;
import android.util.SparseLongArray; import android.util.SparseLongArray;
import android.view.Display; import android.view.Display;
import android.view.SurfaceView; import android.view.SurfaceView;
@ -516,6 +517,16 @@ public final class Util {
return false; return false;
} }
/**
* Tests whether a {@link SparseArray} contains a given {@code key}.
*
* <p>This implements {@code SparseArray#contains} for lower API versions.
*/
@UnstableApi
public static <T> boolean containsKey(SparseArray<T> sparseArray, int key) {
return sparseArray.indexOfKey(key) >= 0;
}
/** /**
* Removes an indexed range from a List. * Removes an indexed range from a List.
* *

View File

@ -20,6 +20,7 @@ package androidx.media3.effect;
import static androidx.media3.common.util.Assertions.checkNotNull; import static androidx.media3.common.util.Assertions.checkNotNull;
import static androidx.media3.common.util.Assertions.checkState; import static androidx.media3.common.util.Assertions.checkState;
import static androidx.media3.common.util.Assertions.checkStateNotNull; import static androidx.media3.common.util.Assertions.checkStateNotNull;
import static androidx.media3.common.util.Util.containsKey;
import android.content.Context; import android.content.Context;
import android.util.SparseArray; import android.util.SparseArray;
@ -147,7 +148,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
*/ */
public void switchToInput(@VideoFrameProcessor.InputType int newInputType) { public void switchToInput(@VideoFrameProcessor.InputType int newInputType) {
checkStateNotNull(downstreamShaderProgram); checkStateNotNull(downstreamShaderProgram);
checkState(inputs.indexOfKey(newInputType) >= 0, "Input type not registered: " + newInputType); checkState(containsKey(inputs, newInputType), "Input type not registered: " + newInputType);
for (int i = 0; i < inputs.size(); i++) { for (int i = 0; i < inputs.size(); i++) {
@VideoFrameProcessor.InputType int inputType = inputs.keyAt(i); @VideoFrameProcessor.InputType int inputType = inputs.keyAt(i);

View File

@ -18,7 +18,7 @@ package androidx.media3.transformer;
import static androidx.media3.common.audio.AudioProcessor.EMPTY_BUFFER; import static androidx.media3.common.audio.AudioProcessor.EMPTY_BUFFER;
import static androidx.media3.common.util.Assertions.checkArgument; import static androidx.media3.common.util.Assertions.checkArgument;
import static androidx.media3.common.util.Assertions.checkState; import static androidx.media3.common.util.Assertions.checkState;
import static androidx.media3.common.util.Assertions.checkStateNotNull; import static androidx.media3.common.util.Util.containsKey;
import static java.lang.Math.max; import static java.lang.Math.max;
import static java.lang.Math.min; import static java.lang.Math.min;
@ -153,7 +153,7 @@ import java.nio.ByteOrder;
public boolean hasSource(int sourceId) { public boolean hasSource(int sourceId) {
checkStateIsConfigured(); checkStateIsConfigured();
return sources.get(sourceId) != null; return containsKey(sources, sourceId);
} }
@Override @Override
@ -295,7 +295,8 @@ import java.nio.ByteOrder;
} }
private SourceInfo getSourceById(int sourceId) { private SourceInfo getSourceById(int sourceId) {
return checkStateNotNull(sources.get(sourceId), "Source not found."); checkState(containsKey(sources, sourceId), "Source not found.");
return sources.get(sourceId);
} }
/** A buffer holding partially-mixed audio within an interval. */ /** A buffer holding partially-mixed audio within an interval. */

View File

@ -19,6 +19,7 @@ package androidx.media3.transformer;
import static androidx.media3.common.util.Assertions.checkArgument; import static androidx.media3.common.util.Assertions.checkArgument;
import static androidx.media3.common.util.Assertions.checkNotNull; import static androidx.media3.common.util.Assertions.checkNotNull;
import static androidx.media3.common.util.Assertions.checkState; import static androidx.media3.common.util.Assertions.checkState;
import static androidx.media3.common.util.Util.containsKey;
import static java.lang.Math.max; import static java.lang.Math.max;
import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.MILLISECONDS;
@ -174,9 +175,8 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
trackType == C.TRACK_TYPE_AUDIO || trackType == C.TRACK_TYPE_VIDEO, trackType == C.TRACK_TYPE_AUDIO || trackType == C.TRACK_TYPE_VIDEO,
"Unsupported track format: " + sampleMimeType); "Unsupported track format: " + sampleMimeType);
// SparseArray.get() returns null by default if the value is not found.
checkState( checkState(
trackTypeToInfo.get(trackType) == null, "There is already a track of type " + trackType); !containsKey(trackTypeToInfo, trackType), "There is already a track of type " + trackType);
ensureMuxerInitialized(); ensureMuxerInitialized();
@ -218,10 +218,8 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
public boolean writeSample( public boolean writeSample(
@C.TrackType int trackType, ByteBuffer data, boolean isKeyFrame, long presentationTimeUs) @C.TrackType int trackType, ByteBuffer data, boolean isKeyFrame, long presentationTimeUs)
throws Muxer.MuxerException { throws Muxer.MuxerException {
@Nullable TrackInfo trackInfo = trackTypeToInfo.get(trackType); checkArgument(containsKey(trackTypeToInfo, trackType));
// SparseArray.get() returns null by default if the value is not found. TrackInfo trackInfo = trackTypeToInfo.get(trackType);
checkArgument(
trackInfo != null, "Could not write sample because there is no track of type " + trackType);
boolean canWriteSample = canWriteSample(trackType, presentationTimeUs); boolean canWriteSample = canWriteSample(trackType, presentationTimeUs);
if (trackType == C.TRACK_TYPE_VIDEO) { if (trackType == C.TRACK_TYPE_VIDEO) {
DebugTraceUtil.logEvent( DebugTraceUtil.logEvent(
@ -262,12 +260,11 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
* @param trackType The {@link C.TrackType}. * @param trackType The {@link C.TrackType}.
*/ */
public void endTrack(@C.TrackType int trackType) { public void endTrack(@C.TrackType int trackType) {
@Nullable TrackInfo trackInfo = trackTypeToInfo.get(trackType); if (!containsKey(trackTypeToInfo, trackType)) {
if (trackInfo == null) {
// SparseArray.get() returns null by default if the value is not found.
return; return;
} }
TrackInfo trackInfo = trackTypeToInfo.get(trackType);
maxEndedTrackTimeUs = max(maxEndedTrackTimeUs, trackInfo.timeUs); maxEndedTrackTimeUs = max(maxEndedTrackTimeUs, trackInfo.timeUs);
listener.onTrackEnded( listener.onTrackEnded(
trackType, trackInfo.format, trackInfo.getAverageBitrate(), trackInfo.sampleCount); trackType, trackInfo.format, trackInfo.getAverageBitrate(), trackInfo.sampleCount);

View File

@ -18,6 +18,7 @@ package androidx.media3.transformer;
import static androidx.media3.common.util.Assertions.checkArgument; import static androidx.media3.common.util.Assertions.checkArgument;
import static androidx.media3.common.util.Assertions.checkState; import static androidx.media3.common.util.Assertions.checkState;
import static androidx.media3.common.util.Util.containsKey;
import static androidx.media3.transformer.AssetLoader.SUPPORTED_OUTPUT_TYPE_DECODED; import static androidx.media3.transformer.AssetLoader.SUPPORTED_OUTPUT_TYPE_DECODED;
import static androidx.media3.transformer.AssetLoader.SUPPORTED_OUTPUT_TYPE_ENCODED; import static androidx.media3.transformer.AssetLoader.SUPPORTED_OUTPUT_TYPE_ENCODED;
import static androidx.media3.transformer.Composition.HDR_MODE_KEEP_HDR; import static androidx.media3.transformer.Composition.HDR_MODE_KEEP_HDR;
@ -792,7 +793,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
public Format getAssetLoaderInputFormat(int sequenceIndex, @C.TrackType int trackType) { public Format getAssetLoaderInputFormat(int sequenceIndex, @C.TrackType int trackType) {
SparseArray<Format> trackTypeToFirstAssetLoaderInputFormat = SparseArray<Format> trackTypeToFirstAssetLoaderInputFormat =
sequencesMetadata.get(sequenceIndex).trackTypeToFirstAssetLoaderInputFormat; sequencesMetadata.get(sequenceIndex).trackTypeToFirstAssetLoaderInputFormat;
checkState(contains(trackTypeToFirstAssetLoaderInputFormat, trackType)); checkState(containsKey(trackTypeToFirstAssetLoaderInputFormat, trackType));
return trackTypeToFirstAssetLoaderInputFormat.get(trackType); return trackTypeToFirstAssetLoaderInputFormat.get(trackType);
} }
@ -833,7 +834,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
@C.TrackType int trackType = getProcessedTrackType(assetLoaderInputFormat.sampleMimeType); @C.TrackType int trackType = getProcessedTrackType(assetLoaderInputFormat.sampleMimeType);
SparseArray<Format> trackTypeToFirstAssetLoaderInputFormat = SparseArray<Format> trackTypeToFirstAssetLoaderInputFormat =
sequencesMetadata.get(sequenceIndex).trackTypeToFirstAssetLoaderInputFormat; sequencesMetadata.get(sequenceIndex).trackTypeToFirstAssetLoaderInputFormat;
checkState(!contains(trackTypeToFirstAssetLoaderInputFormat, trackType)); checkState(!containsKey(trackTypeToFirstAssetLoaderInputFormat, trackType));
trackTypeToFirstAssetLoaderInputFormat.put(trackType, assetLoaderInputFormat); trackTypeToFirstAssetLoaderInputFormat.put(trackType, assetLoaderInputFormat);
} }
@ -841,7 +842,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
* Returns the index of the primary sequence for a given {@link C.TrackType trackType}. * Returns the index of the primary sequence for a given {@link C.TrackType trackType}.
* *
* <p>A primary sequence for a {@link C.TrackType trackType} is defined as the lowest indexed * <p>A primary sequence for a {@link C.TrackType trackType} is defined as the lowest indexed
* sequence that contains a track of the given {@code trackType}. * sequence that containsKey a track of the given {@code trackType}.
*/ */
public int getIndexForPrimarySequence(@C.TrackType int trackType) { public int getIndexForPrimarySequence(@C.TrackType int trackType) {
checkState( checkState(
@ -850,7 +851,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
for (int i = 0; i < sequencesMetadata.size(); i++) { for (int i = 0; i < sequencesMetadata.size(); i++) {
SparseArray<Format> trackTypeToFirstAssetLoaderInputFormat = SparseArray<Format> trackTypeToFirstAssetLoaderInputFormat =
sequencesMetadata.get(i).trackTypeToFirstAssetLoaderInputFormat; sequencesMetadata.get(i).trackTypeToFirstAssetLoaderInputFormat;
if (contains(trackTypeToFirstAssetLoaderInputFormat, trackType)) { if (containsKey(trackTypeToFirstAssetLoaderInputFormat, trackType)) {
return i; return i;
} }
} }
@ -881,7 +882,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
*/ */
public void registerGraphInput(@C.TrackType int trackType) { public void registerGraphInput(@C.TrackType int trackType) {
int numberOfGraphInputForTrackType = 1; int numberOfGraphInputForTrackType = 1;
if (contains(trackTypeToNumberOfRegisteredGraphInput, trackType)) { if (containsKey(trackTypeToNumberOfRegisteredGraphInput, trackType)) {
numberOfGraphInputForTrackType += trackTypeToNumberOfRegisteredGraphInput.get(trackType); numberOfGraphInputForTrackType += trackTypeToNumberOfRegisteredGraphInput.get(trackType);
} }
trackTypeToNumberOfRegisteredGraphInput.put(trackType, numberOfGraphInputForTrackType); trackTypeToNumberOfRegisteredGraphInput.put(trackType, numberOfGraphInputForTrackType);
@ -894,7 +895,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
public boolean hasAssociatedAllTracksWithGraphInput(@C.TrackType int trackType) { public boolean hasAssociatedAllTracksWithGraphInput(@C.TrackType int trackType) {
int numberOfTracksForTrackType = 0; int numberOfTracksForTrackType = 0;
for (int i = 0; i < sequencesMetadata.size(); i++) { for (int i = 0; i < sequencesMetadata.size(); i++) {
if (contains(sequencesMetadata.get(i).trackTypeToFirstAssetLoaderInputFormat, trackType)) { if (containsKey(
sequencesMetadata.get(i).trackTypeToFirstAssetLoaderInputFormat, trackType)) {
numberOfTracksForTrackType++; numberOfTracksForTrackType++;
} }
} }
@ -908,10 +910,10 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
for (int i = 0; i < sequencesMetadata.size(); i++) { for (int i = 0; i < sequencesMetadata.size(); i++) {
SparseArray<Format> trackTypeToFirstAssetLoaderInputFormat = SparseArray<Format> trackTypeToFirstAssetLoaderInputFormat =
sequencesMetadata.get(i).trackTypeToFirstAssetLoaderInputFormat; sequencesMetadata.get(i).trackTypeToFirstAssetLoaderInputFormat;
if (contains(trackTypeToFirstAssetLoaderInputFormat, C.TRACK_TYPE_AUDIO)) { if (containsKey(trackTypeToFirstAssetLoaderInputFormat, C.TRACK_TYPE_AUDIO)) {
outputHasAudio = true; outputHasAudio = true;
} }
if (contains(trackTypeToFirstAssetLoaderInputFormat, C.TRACK_TYPE_VIDEO)) { if (containsKey(trackTypeToFirstAssetLoaderInputFormat, C.TRACK_TYPE_VIDEO)) {
outputHasVideo = true; outputHasVideo = true;
} }
} }
@ -921,14 +923,14 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/** Registers a {@link SampleExporter} for the given {@link C.TrackType trackType}. */ /** Registers a {@link SampleExporter} for the given {@link C.TrackType trackType}. */
public void registerSampleExporter(int trackType, SampleExporter sampleExporter) { public void registerSampleExporter(int trackType, SampleExporter sampleExporter) {
checkState( checkState(
!contains(trackTypeToSampleExporter, trackType), !containsKey(trackTypeToSampleExporter, trackType),
"Exactly one SampleExporter can be added for each track type."); "Exactly one SampleExporter can be added for each track type.");
trackTypeToSampleExporter.put(trackType, sampleExporter); trackTypeToSampleExporter.put(trackType, sampleExporter);
} }
/** Sets whether a track should be transcoded. */ /** Sets whether a track should be transcoded. */
public void setShouldTranscode(@C.TrackType int trackType, boolean shouldTranscode) { public void setShouldTranscode(@C.TrackType int trackType, boolean shouldTranscode) {
if (contains(trackTypeToShouldTranscode, trackType)) { if (containsKey(trackTypeToShouldTranscode, trackType)) {
checkState(shouldTranscode == trackTypeToShouldTranscode.get(trackType)); checkState(shouldTranscode == trackTypeToShouldTranscode.get(trackType));
return; return;
} }
@ -937,7 +939,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/** Returns whether a track should be transcoded. */ /** Returns whether a track should be transcoded. */
public boolean shouldTranscode(@C.TrackType int trackType) { public boolean shouldTranscode(@C.TrackType int trackType) {
checkState(contains(trackTypeToShouldTranscode, trackType)); checkState(containsKey(trackTypeToShouldTranscode, trackType));
return trackTypeToShouldTranscode.get(trackType); return trackTypeToShouldTranscode.get(trackType);
} }
@ -962,10 +964,5 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
requiredTrackCount = C.LENGTH_UNSET; requiredTrackCount = C.LENGTH_UNSET;
} }
} }
/** Implements {@code SparseArray#contains} for lower API versions. */
private static <T> boolean contains(SparseArray<T> sparseArray, int key) {
return sparseArray.get(key) != null;
}
} }
} }