diff options
Diffstat (limited to 'mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/decoder/DecoderInputBuffer.java')
-rw-r--r-- | mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/decoder/DecoderInputBuffer.java | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/decoder/DecoderInputBuffer.java b/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/decoder/DecoderInputBuffer.java new file mode 100644 index 0000000000..254ecfdec8 --- /dev/null +++ b/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/decoder/DecoderInputBuffer.java @@ -0,0 +1,209 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mozilla.thirdparty.com.google.android.exoplayer2.decoder; + +import androidx.annotation.IntDef; +import androidx.annotation.Nullable; +import org.mozilla.thirdparty.com.google.android.exoplayer2.C; +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.nio.ByteBuffer; +import org.checkerframework.checker.nullness.qual.EnsuresNonNull; + +/** + * Holds input for a decoder. + */ +public class DecoderInputBuffer extends Buffer { + + /** + * The buffer replacement mode, which may disable replacement. One of {@link + * #BUFFER_REPLACEMENT_MODE_DISABLED}, {@link #BUFFER_REPLACEMENT_MODE_NORMAL} or {@link + * #BUFFER_REPLACEMENT_MODE_DIRECT}. + */ + @Documented + @Retention(RetentionPolicy.SOURCE) + @IntDef({ + BUFFER_REPLACEMENT_MODE_DISABLED, + BUFFER_REPLACEMENT_MODE_NORMAL, + BUFFER_REPLACEMENT_MODE_DIRECT + }) + public @interface BufferReplacementMode {} + /** + * Disallows buffer replacement. + */ + public static final int BUFFER_REPLACEMENT_MODE_DISABLED = 0; + /** + * Allows buffer replacement using {@link ByteBuffer#allocate(int)}. + */ + public static final int BUFFER_REPLACEMENT_MODE_NORMAL = 1; + /** + * Allows buffer replacement using {@link ByteBuffer#allocateDirect(int)}. + */ + public static final int BUFFER_REPLACEMENT_MODE_DIRECT = 2; + + /** + * {@link CryptoInfo} for encrypted data. + */ + public final CryptoInfo cryptoInfo; + + /** The buffer's data, or {@code null} if no data has been set. */ + @Nullable public ByteBuffer data; + + // TODO: Remove this temporary signaling once end-of-stream propagation for clips using content + // protection is fixed. See [Internal: b/153326944] for details. + /** + * Whether the last attempt to read a sample into this buffer failed due to not yet having the DRM + * keys associated with the next sample. + */ + public boolean waitingForKeys; + + /** + * The time at which the sample should be presented. + */ + public long timeUs; + + /** + * Supplemental data related to the buffer, if {@link #hasSupplementalData()} returns true. If + * present, the buffer is populated with supplemental data from position 0 to its limit. + */ + @Nullable public ByteBuffer supplementalData; + + @BufferReplacementMode private final int bufferReplacementMode; + + /** + * Creates a new instance for which {@link #isFlagsOnly()} will return true. + * + * @return A new flags only input buffer. + */ + public static DecoderInputBuffer newFlagsOnlyInstance() { + return new DecoderInputBuffer(BUFFER_REPLACEMENT_MODE_DISABLED); + } + + /** + * @param bufferReplacementMode Determines the behavior of {@link #ensureSpaceForWrite(int)}. One + * of {@link #BUFFER_REPLACEMENT_MODE_DISABLED}, {@link #BUFFER_REPLACEMENT_MODE_NORMAL} and + * {@link #BUFFER_REPLACEMENT_MODE_DIRECT}. + */ + public DecoderInputBuffer(@BufferReplacementMode int bufferReplacementMode) { + this.cryptoInfo = new CryptoInfo(); + this.bufferReplacementMode = bufferReplacementMode; + } + + /** + * Clears {@link #supplementalData} and ensures that it's large enough to accommodate {@code + * length} bytes. + * + * @param length The length of the supplemental data that must be accommodated, in bytes. + */ + @EnsuresNonNull("supplementalData") + public void resetSupplementalData(int length) { + if (supplementalData == null || supplementalData.capacity() < length) { + supplementalData = ByteBuffer.allocate(length); + } else { + supplementalData.clear(); + } + } + + /** + * Ensures that {@link #data} is large enough to accommodate a write of a given length at its + * current position. + * + * <p>If the capacity of {@link #data} is sufficient this method does nothing. If the capacity is + * insufficient then an attempt is made to replace {@link #data} with a new {@link ByteBuffer} + * whose capacity is sufficient. Data up to the current position is copied to the new buffer. + * + * @param length The length of the write that must be accommodated, in bytes. + * @throws IllegalStateException If there is insufficient capacity to accommodate the write and + * the buffer replacement mode of the holder is {@link #BUFFER_REPLACEMENT_MODE_DISABLED}. + */ + @EnsuresNonNull("data") + public void ensureSpaceForWrite(int length) { + if (data == null) { + data = createReplacementByteBuffer(length); + return; + } + // Check whether the current buffer is sufficient. + int capacity = data.capacity(); + int position = data.position(); + int requiredCapacity = position + length; + if (capacity >= requiredCapacity) { + return; + } + // Instantiate a new buffer if possible. + ByteBuffer newData = createReplacementByteBuffer(requiredCapacity); + newData.order(data.order()); + // Copy data up to the current position from the old buffer to the new one. + if (position > 0) { + data.flip(); + newData.put(data); + } + // Set the new buffer. + data = newData; + } + + /** + * Returns whether the buffer is only able to hold flags, meaning {@link #data} is null and + * its replacement mode is {@link #BUFFER_REPLACEMENT_MODE_DISABLED}. + */ + public final boolean isFlagsOnly() { + return data == null && bufferReplacementMode == BUFFER_REPLACEMENT_MODE_DISABLED; + } + + /** + * Returns whether the {@link C#BUFFER_FLAG_ENCRYPTED} flag is set. + */ + public final boolean isEncrypted() { + return getFlag(C.BUFFER_FLAG_ENCRYPTED); + } + + /** + * Flips {@link #data} and {@link #supplementalData} in preparation for being queued to a decoder. + * + * @see java.nio.Buffer#flip() + */ + public final void flip() { + data.flip(); + if (supplementalData != null) { + supplementalData.flip(); + } + } + + @Override + public void clear() { + super.clear(); + if (data != null) { + data.clear(); + } + if (supplementalData != null) { + supplementalData.clear(); + } + waitingForKeys = false; + } + + private ByteBuffer createReplacementByteBuffer(int requiredCapacity) { + if (bufferReplacementMode == BUFFER_REPLACEMENT_MODE_NORMAL) { + return ByteBuffer.allocate(requiredCapacity); + } else if (bufferReplacementMode == BUFFER_REPLACEMENT_MODE_DIRECT) { + return ByteBuffer.allocateDirect(requiredCapacity); + } else { + int currentCapacity = data == null ? 0 : data.capacity(); + throw new IllegalStateException("Buffer too small (" + currentCapacity + " < " + + requiredCapacity + ")"); + } + } + +} |