diff --git a/library/common/src/main/java/com/google/android/exoplayer2/decoder/CryptoInfo.java b/library/common/src/main/java/com/google/android/exoplayer2/decoder/CryptoInfo.java index c3cebb970d..1c52abc476 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/decoder/CryptoInfo.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/decoder/CryptoInfo.java @@ -15,11 +15,9 @@ */ 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.Util; -import java.util.Arrays; /** * Compatibility wrapper for {@link android.media.MediaCodec.CryptoInfo}. @@ -121,25 +119,6 @@ public final class CryptoInfo { return frameworkCryptoInfo; } - /** Performs a deep copy to {@code cryptoInfo}. */ - public void copyTo(android.media.MediaCodec.CryptoInfo cryptoInfo) { - // Update cryptoInfo fields directly because CryptoInfo.set performs an unnecessary - // object allocation on Android N. - cryptoInfo.numSubSamples = numSubSamples; - cryptoInfo.numBytesOfClearData = copyOrNull(numBytesOfClearData); - cryptoInfo.numBytesOfEncryptedData = copyOrNull(numBytesOfEncryptedData); - cryptoInfo.key = copyOrNull(key); - cryptoInfo.iv = copyOrNull(iv); - cryptoInfo.mode = mode; - if (Util.SDK_INT >= 24) { - android.media.MediaCodec.CryptoInfo.Pattern pattern = patternHolder.pattern; - android.media.MediaCodec.CryptoInfo.Pattern patternCopy = - new android.media.MediaCodec.CryptoInfo.Pattern( - pattern.getEncryptBlocks(), pattern.getSkipBlocks()); - cryptoInfo.setPattern(patternCopy); - } - } - /** @deprecated Use {@link #getFrameworkCryptoInfo()}. */ @Deprecated public android.media.MediaCodec.CryptoInfo getFrameworkCryptoInfoV16() { @@ -169,16 +148,6 @@ public final class CryptoInfo { numBytesOfClearData[0] += count; } - @Nullable - private static int[] copyOrNull(@Nullable int[] array) { - return array != null ? Arrays.copyOf(array, array.length) : null; - } - - @Nullable - private static byte[] copyOrNull(@Nullable byte[] array) { - return array != null ? Arrays.copyOf(array, array.length) : null; - } - @RequiresApi(24) private static final class PatternHolderV24 { diff --git a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecBufferEnqueuer.java b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecBufferEnqueuer.java index c5bfaf8f4d..48568fed8b 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecBufferEnqueuer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecBufferEnqueuer.java @@ -29,6 +29,7 @@ import com.google.android.exoplayer2.decoder.CryptoInfo; import com.google.android.exoplayer2.util.ConditionVariable; import com.google.android.exoplayer2.util.Util; import java.util.ArrayDeque; +import java.util.Arrays; import java.util.concurrent.atomic.AtomicReference; import org.checkerframework.checker.nullness.compatqual.NullableType; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; @@ -110,7 +111,7 @@ class AsynchronousMediaCodecBufferEnqueuer implements MediaCodecInputBufferEnque maybeThrowException(); MessageParams messageParams = getMessageParams(); messageParams.setQueueParams(index, offset, /* size= */ 0, presentationTimeUs, flags); - info.copyTo(messageParams.cryptoInfo); + copy(info, messageParams.cryptoInfo); Message message = Util.castNonNull(handler).obtainMessage(MSG_QUEUE_SECURE_INPUT_BUFFER, messageParams); message.sendToTarget(); @@ -271,4 +272,65 @@ class AsynchronousMediaCodecBufferEnqueuer implements MediaCodecInputBufferEnque } return labelBuilder.toString(); } + + /** Performs a deep copy of {@code cryptoInfo} to {@code frameworkCryptoInfo}. */ + private static void copy( + CryptoInfo cryptoInfo, android.media.MediaCodec.CryptoInfo frameworkCryptoInfo) { + // Update frameworkCryptoInfo fields directly because CryptoInfo.set performs an unnecessary + // object allocation on Android N. + frameworkCryptoInfo.numSubSamples = cryptoInfo.numSubSamples; + frameworkCryptoInfo.numBytesOfClearData = + 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.mode = cryptoInfo.mode; + if (Util.SDK_INT >= 24) { + android.media.MediaCodec.CryptoInfo.Pattern pattern = + new android.media.MediaCodec.CryptoInfo.Pattern( + cryptoInfo.encryptedBlocks, cryptoInfo.clearBlocks); + frameworkCryptoInfo.setPattern(pattern); + } + } + + /** + * Copies {@code src}, reusing {@code dst} if it's at least as long as {@code src}. + * + * @param src The source array. + * @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) { + if (src == null) { + return dst; + } + + if (dst == null || dst.length < src.length) { + return Arrays.copyOf(src, src.length); + } else { + System.arraycopy(src, 0, dst, 0, src.length); + return dst; + } + } + + /** + * Copies {@code src}, reusing {@code dst} if it's at least as long as {@code src}. + * + * @param src The source array. + * @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) { + if (src == null) { + return dst; + } + + if (dst == null || dst.length < src.length) { + return Arrays.copyOf(src, src.length); + } else { + System.arraycopy(src, 0, dst, 0, src.length); + return dst; + } + } }