mirror of
https://github.com/samsonjs/media.git
synced 2026-03-28 09:55:48 +00:00
Fix remaining common module nullness issues.
PiperOrigin-RevId: 319183621
This commit is contained in:
parent
7d46be5564
commit
e4e743a35f
9 changed files with 100 additions and 62 deletions
|
|
@ -23,6 +23,7 @@ import com.google.android.exoplayer2.decoder.SimpleDecoder;
|
|||
import com.google.android.exoplayer2.decoder.SimpleOutputBuffer;
|
||||
import com.google.android.exoplayer2.drm.DecryptionException;
|
||||
import com.google.android.exoplayer2.drm.ExoMediaCrypto;
|
||||
import com.google.android.exoplayer2.util.Assertions;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
|
@ -166,13 +167,28 @@ import java.util.List;
|
|||
}
|
||||
ByteBuffer inputData = Util.castNonNull(inputBuffer.data);
|
||||
CryptoInfo cryptoInfo = inputBuffer.cryptoInfo;
|
||||
int result = inputBuffer.isEncrypted()
|
||||
? opusSecureDecode(nativeDecoderContext, inputBuffer.timeUs, inputData, inputData.limit(),
|
||||
outputBuffer, SAMPLE_RATE, exoMediaCrypto, cryptoInfo.mode,
|
||||
cryptoInfo.key, cryptoInfo.iv, cryptoInfo.numSubSamples,
|
||||
cryptoInfo.numBytesOfClearData, cryptoInfo.numBytesOfEncryptedData)
|
||||
: opusDecode(nativeDecoderContext, inputBuffer.timeUs, inputData, inputData.limit(),
|
||||
outputBuffer);
|
||||
int result =
|
||||
inputBuffer.isEncrypted()
|
||||
? opusSecureDecode(
|
||||
nativeDecoderContext,
|
||||
inputBuffer.timeUs,
|
||||
inputData,
|
||||
inputData.limit(),
|
||||
outputBuffer,
|
||||
SAMPLE_RATE,
|
||||
exoMediaCrypto,
|
||||
cryptoInfo.mode,
|
||||
Assertions.checkNotNull(cryptoInfo.key),
|
||||
Assertions.checkNotNull(cryptoInfo.iv),
|
||||
cryptoInfo.numSubSamples,
|
||||
cryptoInfo.numBytesOfClearData,
|
||||
cryptoInfo.numBytesOfEncryptedData)
|
||||
: opusDecode(
|
||||
nativeDecoderContext,
|
||||
inputBuffer.timeUs,
|
||||
inputData,
|
||||
inputData.limit(),
|
||||
outputBuffer);
|
||||
if (result < 0) {
|
||||
if (result == DRM_ERROR) {
|
||||
String message = "Drm error: " + opusGetErrorMessage(nativeDecoderContext);
|
||||
|
|
@ -253,8 +269,8 @@ import java.util.List;
|
|||
byte[] key,
|
||||
byte[] iv,
|
||||
int numSubSamples,
|
||||
int[] numBytesOfClearData,
|
||||
int[] numBytesOfEncryptedData);
|
||||
@Nullable int[] numBytesOfClearData,
|
||||
@Nullable int[] numBytesOfEncryptedData);
|
||||
|
||||
private native void opusClose(long decoder);
|
||||
private native void opusReset(long decoder);
|
||||
|
|
|
|||
|
|
@ -124,11 +124,20 @@ import java.nio.ByteBuffer;
|
|||
ByteBuffer inputData = Util.castNonNull(inputBuffer.data);
|
||||
int inputSize = inputData.limit();
|
||||
CryptoInfo cryptoInfo = inputBuffer.cryptoInfo;
|
||||
final long result = inputBuffer.isEncrypted()
|
||||
? vpxSecureDecode(vpxDecContext, inputData, inputSize, exoMediaCrypto,
|
||||
cryptoInfo.mode, cryptoInfo.key, cryptoInfo.iv, cryptoInfo.numSubSamples,
|
||||
cryptoInfo.numBytesOfClearData, cryptoInfo.numBytesOfEncryptedData)
|
||||
: vpxDecode(vpxDecContext, inputData, inputSize);
|
||||
final long result =
|
||||
inputBuffer.isEncrypted()
|
||||
? vpxSecureDecode(
|
||||
vpxDecContext,
|
||||
inputData,
|
||||
inputSize,
|
||||
exoMediaCrypto,
|
||||
cryptoInfo.mode,
|
||||
Assertions.checkNotNull(cryptoInfo.key),
|
||||
Assertions.checkNotNull(cryptoInfo.iv),
|
||||
cryptoInfo.numSubSamples,
|
||||
cryptoInfo.numBytesOfClearData,
|
||||
cryptoInfo.numBytesOfEncryptedData)
|
||||
: vpxDecode(vpxDecContext, inputData, inputSize);
|
||||
if (result != NO_ERROR) {
|
||||
if (result == DRM_ERROR) {
|
||||
String message = "Drm error: " + vpxGetErrorMessage(vpxDecContext);
|
||||
|
|
@ -207,8 +216,8 @@ import java.nio.ByteBuffer;
|
|||
byte[] key,
|
||||
byte[] iv,
|
||||
int numSubSamples,
|
||||
int[] numBytesOfClearData,
|
||||
int[] numBytesOfEncryptedData);
|
||||
@Nullable int[] numBytesOfClearData,
|
||||
@Nullable int[] numBytesOfEncryptedData);
|
||||
|
||||
private native int vpxGetFrame(long context, VideoDecoderOutputBuffer outputBuffer);
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import androidx.annotation.Nullable;
|
|||
import com.google.android.exoplayer2.drm.DrmInitData;
|
||||
import com.google.android.exoplayer2.drm.ExoMediaCrypto;
|
||||
import com.google.android.exoplayer2.metadata.Metadata;
|
||||
import com.google.android.exoplayer2.util.Assertions;
|
||||
import com.google.android.exoplayer2.util.MimeTypes;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
import com.google.android.exoplayer2.video.ColorInfo;
|
||||
|
|
@ -1309,7 +1310,7 @@ public final class Format implements Parcelable {
|
|||
int initializationDataSize = in.readInt();
|
||||
initializationData = new ArrayList<>(initializationDataSize);
|
||||
for (int i = 0; i < initializationDataSize; i++) {
|
||||
initializationData.add(in.createByteArray());
|
||||
initializationData.add(Assertions.checkNotNull(in.createByteArray()));
|
||||
}
|
||||
drmInitData = in.readParcelable(DrmInitData.class.getClassLoader());
|
||||
subsampleOffsetUs = in.readLong();
|
||||
|
|
|
|||
|
|
@ -15,8 +15,10 @@
|
|||
*/
|
||||
package com.google.android.exoplayer2.decoder;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.util.Assertions;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
|
||||
/**
|
||||
|
|
@ -30,13 +32,13 @@ public final class CryptoInfo {
|
|||
*
|
||||
* @see android.media.MediaCodec.CryptoInfo#iv
|
||||
*/
|
||||
public byte[] iv;
|
||||
@Nullable public byte[] iv;
|
||||
/**
|
||||
* The 16 byte key id.
|
||||
*
|
||||
* @see android.media.MediaCodec.CryptoInfo#key
|
||||
*/
|
||||
public byte[] key;
|
||||
@Nullable public byte[] key;
|
||||
/**
|
||||
* The type of encryption that has been applied. Must be one of the {@link C.CryptoMode} values.
|
||||
*
|
||||
|
|
@ -49,14 +51,14 @@ public final class CryptoInfo {
|
|||
*
|
||||
* @see android.media.MediaCodec.CryptoInfo#numBytesOfClearData
|
||||
*/
|
||||
public int[] numBytesOfClearData;
|
||||
@Nullable public int[] numBytesOfClearData;
|
||||
/**
|
||||
* The number of trailing encrypted bytes in each sub-sample. If null, all bytes are treated as
|
||||
* clear and {@link #numBytesOfClearData} must be specified.
|
||||
*
|
||||
* @see android.media.MediaCodec.CryptoInfo#numBytesOfEncryptedData
|
||||
*/
|
||||
public int[] numBytesOfEncryptedData;
|
||||
@Nullable public int[] numBytesOfEncryptedData;
|
||||
/**
|
||||
* The number of subSamples that make up the buffer's contents.
|
||||
*
|
||||
|
|
@ -73,7 +75,7 @@ public final class CryptoInfo {
|
|||
public int clearBlocks;
|
||||
|
||||
private final android.media.MediaCodec.CryptoInfo frameworkCryptoInfo;
|
||||
private final PatternHolderV24 patternHolder;
|
||||
@Nullable private final PatternHolderV24 patternHolder;
|
||||
|
||||
public CryptoInfo() {
|
||||
frameworkCryptoInfo = new android.media.MediaCodec.CryptoInfo();
|
||||
|
|
@ -102,7 +104,7 @@ public final class CryptoInfo {
|
|||
frameworkCryptoInfo.iv = iv;
|
||||
frameworkCryptoInfo.mode = mode;
|
||||
if (Util.SDK_INT >= 24) {
|
||||
patternHolder.set(encryptedBlocks, clearBlocks);
|
||||
Assertions.checkNotNull(patternHolder).set(encryptedBlocks, clearBlocks);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,9 @@ import java.util.Set;
|
|||
*
|
||||
* @param <E> The type of element being stored.
|
||||
*/
|
||||
public final class CopyOnWriteMultiset<E> implements Iterable<E> {
|
||||
// Intentionally extending @NonNull-by-default Object to disallow @Nullable E types.
|
||||
@SuppressWarnings("TypeParameterExplicitlyExtendsObject")
|
||||
public final class CopyOnWriteMultiset<E extends Object> implements Iterable<E> {
|
||||
|
||||
private final Object lock;
|
||||
|
||||
|
|
|
|||
|
|
@ -431,18 +431,18 @@ public final class NalUnitUtil {
|
|||
return endOffset;
|
||||
}
|
||||
|
||||
if (prefixFlags != null) {
|
||||
if (prefixFlags[0]) {
|
||||
clearPrefixFlags(prefixFlags);
|
||||
return startOffset - 3;
|
||||
} else if (length > 1 && prefixFlags[1] && data[startOffset] == 1) {
|
||||
clearPrefixFlags(prefixFlags);
|
||||
return startOffset - 2;
|
||||
} else if (length > 2 && prefixFlags[2] && data[startOffset] == 0
|
||||
&& data[startOffset + 1] == 1) {
|
||||
clearPrefixFlags(prefixFlags);
|
||||
return startOffset - 1;
|
||||
}
|
||||
if (prefixFlags[0]) {
|
||||
clearPrefixFlags(prefixFlags);
|
||||
return startOffset - 3;
|
||||
} else if (length > 1 && prefixFlags[1] && data[startOffset] == 1) {
|
||||
clearPrefixFlags(prefixFlags);
|
||||
return startOffset - 2;
|
||||
} else if (length > 2
|
||||
&& prefixFlags[2]
|
||||
&& data[startOffset] == 0
|
||||
&& data[startOffset + 1] == 1) {
|
||||
clearPrefixFlags(prefixFlags);
|
||||
return startOffset - 1;
|
||||
}
|
||||
|
||||
int limit = endOffset - 1;
|
||||
|
|
@ -453,9 +453,7 @@ public final class NalUnitUtil {
|
|||
// There isn't a NAL prefix here, or at the next two positions. Do nothing and let the
|
||||
// loop advance the index by three.
|
||||
} else if (data[i - 2] == 0 && data[i - 1] == 0 && data[i] == 1) {
|
||||
if (prefixFlags != null) {
|
||||
clearPrefixFlags(prefixFlags);
|
||||
}
|
||||
clearPrefixFlags(prefixFlags);
|
||||
return i - 2;
|
||||
} else {
|
||||
// There isn't a NAL prefix here, but there might be at the next position. We should
|
||||
|
|
@ -464,18 +462,20 @@ public final class NalUnitUtil {
|
|||
}
|
||||
}
|
||||
|
||||
if (prefixFlags != null) {
|
||||
// True if the last three bytes in the data seen so far are {0,0,1}.
|
||||
prefixFlags[0] = length > 2
|
||||
? (data[endOffset - 3] == 0 && data[endOffset - 2] == 0 && data[endOffset - 1] == 1)
|
||||
: length == 2 ? (prefixFlags[2] && data[endOffset - 2] == 0 && data[endOffset - 1] == 1)
|
||||
: (prefixFlags[1] && data[endOffset - 1] == 1);
|
||||
// True if the last two bytes in the data seen so far are {0,0}.
|
||||
prefixFlags[1] = length > 1 ? data[endOffset - 2] == 0 && data[endOffset - 1] == 0
|
||||
: prefixFlags[2] && data[endOffset - 1] == 0;
|
||||
// True if the last byte in the data seen so far is {0}.
|
||||
prefixFlags[2] = data[endOffset - 1] == 0;
|
||||
}
|
||||
// True if the last three bytes in the data seen so far are {0,0,1}.
|
||||
prefixFlags[0] =
|
||||
length > 2
|
||||
? (data[endOffset - 3] == 0 && data[endOffset - 2] == 0 && data[endOffset - 1] == 1)
|
||||
: length == 2
|
||||
? (prefixFlags[2] && data[endOffset - 2] == 0 && data[endOffset - 1] == 1)
|
||||
: (prefixFlags[1] && data[endOffset - 1] == 1);
|
||||
// True if the last two bytes in the data seen so far are {0,0}.
|
||||
prefixFlags[1] =
|
||||
length > 1
|
||||
? data[endOffset - 2] == 0 && data[endOffset - 1] == 0
|
||||
: prefixFlags[2] && data[endOffset - 1] == 0;
|
||||
// True if the last byte in the data seen so far is {0}.
|
||||
prefixFlags[2] = data[endOffset - 1] == 0;
|
||||
|
||||
return endOffset;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1937,6 +1937,8 @@ public final class Util {
|
|||
* @param context A context to access the connectivity manager.
|
||||
* @return The {@link C.NetworkType} of the current network connection.
|
||||
*/
|
||||
// Intentional null check to guard against user input.
|
||||
@SuppressWarnings("known.nonnull")
|
||||
@C.NetworkType
|
||||
public static int getNetworkType(Context context) {
|
||||
if (context == null) {
|
||||
|
|
@ -1944,6 +1946,7 @@ public final class Util {
|
|||
return C.NETWORK_TYPE_UNKNOWN;
|
||||
}
|
||||
NetworkInfo networkInfo;
|
||||
@Nullable
|
||||
ConnectivityManager connectivityManager =
|
||||
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
if (connectivityManager == null) {
|
||||
|
|
@ -1983,6 +1986,7 @@ public final class Util {
|
|||
*/
|
||||
public static String getCountryCode(@Nullable Context context) {
|
||||
if (context != null) {
|
||||
@Nullable
|
||||
TelephonyManager telephonyManager =
|
||||
(TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
|
||||
if (telephonyManager != null) {
|
||||
|
|
@ -2062,6 +2066,7 @@ public final class Util {
|
|||
*/
|
||||
public static boolean isTv(Context context) {
|
||||
// See https://developer.android.com/training/tv/start/hardware.html#runtime-check.
|
||||
@Nullable
|
||||
UiModeManager uiModeManager =
|
||||
(UiModeManager) context.getApplicationContext().getSystemService(UI_MODE_SERVICE);
|
||||
return uiModeManager != null
|
||||
|
|
|
|||
|
|
@ -40,19 +40,19 @@ public final class NalUnitUtilTest {
|
|||
byte[] data = buildTestData();
|
||||
|
||||
// Should find NAL unit.
|
||||
int result = NalUnitUtil.findNalUnit(data, 0, data.length, null);
|
||||
int result = NalUnitUtil.findNalUnit(data, 0, data.length, new boolean[3]);
|
||||
assertThat(result).isEqualTo(TEST_NAL_POSITION);
|
||||
// Should find NAL unit whose prefix ends one byte before the limit.
|
||||
result = NalUnitUtil.findNalUnit(data, 0, TEST_NAL_POSITION + 4, null);
|
||||
result = NalUnitUtil.findNalUnit(data, 0, TEST_NAL_POSITION + 4, new boolean[3]);
|
||||
assertThat(result).isEqualTo(TEST_NAL_POSITION);
|
||||
// Shouldn't find NAL unit whose prefix ends at the limit (since the limit is exclusive).
|
||||
result = NalUnitUtil.findNalUnit(data, 0, TEST_NAL_POSITION + 3, null);
|
||||
result = NalUnitUtil.findNalUnit(data, 0, TEST_NAL_POSITION + 3, new boolean[3]);
|
||||
assertThat(result).isEqualTo(TEST_NAL_POSITION + 3);
|
||||
// Should find NAL unit whose prefix starts at the offset.
|
||||
result = NalUnitUtil.findNalUnit(data, TEST_NAL_POSITION, data.length, null);
|
||||
result = NalUnitUtil.findNalUnit(data, TEST_NAL_POSITION, data.length, new boolean[3]);
|
||||
assertThat(result).isEqualTo(TEST_NAL_POSITION);
|
||||
// Shouldn't find NAL unit whose prefix starts one byte past the offset.
|
||||
result = NalUnitUtil.findNalUnit(data, TEST_NAL_POSITION + 1, data.length, null);
|
||||
result = NalUnitUtil.findNalUnit(data, TEST_NAL_POSITION + 1, data.length, new boolean[3]);
|
||||
assertThat(result).isEqualTo(data.length);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,11 +16,14 @@
|
|||
|
||||
package com.google.android.exoplayer2.mediacodec;
|
||||
|
||||
import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
|
||||
|
||||
import android.media.MediaCodec;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.Message;
|
||||
import androidx.annotation.GuardedBy;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import com.google.android.exoplayer2.C;
|
||||
|
|
@ -292,8 +295,6 @@ class AsynchronousMediaCodecBufferEnqueuer implements MediaCodecInputBufferEnque
|
|||
}
|
||||
|
||||
/** Performs a deep copy of {@code cryptoInfo} to {@code frameworkCryptoInfo}. */
|
||||
// TODO: Remove suppression [internal b/78934030].
|
||||
@SuppressWarnings("nullness:argument.type.incompatible")
|
||||
private static void copy(
|
||||
CryptoInfo cryptoInfo, android.media.MediaCodec.CryptoInfo frameworkCryptoInfo) {
|
||||
// Update frameworkCryptoInfo fields directly because CryptoInfo.set performs an unnecessary
|
||||
|
|
@ -303,8 +304,8 @@ class AsynchronousMediaCodecBufferEnqueuer implements MediaCodecInputBufferEnque
|
|||
copy(cryptoInfo.numBytesOfClearData, frameworkCryptoInfo.numBytesOfClearData);
|
||||
frameworkCryptoInfo.numBytesOfEncryptedData =
|
||||
copy(cryptoInfo.numBytesOfEncryptedData, frameworkCryptoInfo.numBytesOfEncryptedData);
|
||||
frameworkCryptoInfo.key = copy(cryptoInfo.key, frameworkCryptoInfo.key);
|
||||
frameworkCryptoInfo.iv = copy(cryptoInfo.iv, frameworkCryptoInfo.iv);
|
||||
frameworkCryptoInfo.key = checkNotNull(copy(cryptoInfo.key, frameworkCryptoInfo.key));
|
||||
frameworkCryptoInfo.iv = checkNotNull(copy(cryptoInfo.iv, frameworkCryptoInfo.iv));
|
||||
frameworkCryptoInfo.mode = cryptoInfo.mode;
|
||||
if (Util.SDK_INT >= 24) {
|
||||
android.media.MediaCodec.CryptoInfo.Pattern pattern =
|
||||
|
|
@ -321,7 +322,8 @@ class AsynchronousMediaCodecBufferEnqueuer implements MediaCodecInputBufferEnque
|
|||
* @param dst The destination array, which will be reused if it's at least as long as {@code src}.
|
||||
* @return The copy, which may be {@code dst} if it was reused.
|
||||
*/
|
||||
private static int[] copy(int[] src, int[] dst) {
|
||||
@Nullable
|
||||
private static int[] copy(@Nullable int[] src, @Nullable int[] dst) {
|
||||
if (src == null) {
|
||||
return dst;
|
||||
}
|
||||
|
|
@ -341,7 +343,8 @@ class AsynchronousMediaCodecBufferEnqueuer implements MediaCodecInputBufferEnque
|
|||
* @param dst The destination array, which will be reused if it's at least as long as {@code src}.
|
||||
* @return The copy, which may be {@code dst} if it was reused.
|
||||
*/
|
||||
private static byte[] copy(byte[] src, byte[] dst) {
|
||||
@Nullable
|
||||
private static byte[] copy(@Nullable byte[] src, @Nullable byte[] dst) {
|
||||
if (src == null) {
|
||||
return dst;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue