diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/SamplePool.java | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/SamplePool.java | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/SamplePool.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/SamplePool.java new file mode 100644 index 0000000000..a2101b3aeb --- /dev/null +++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/SamplePool.java @@ -0,0 +1,154 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.gecko.media; + +import android.media.MediaCodec; +import android.util.SparseArray; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import org.mozilla.gecko.mozglue.SharedMemory; + +final class SamplePool { + private static final class Impl { + private final String mName; + private int mDefaultBufferSize = 4096; + private final List<Sample> mRecycledSamples = new ArrayList<>(); + private final boolean mBufferless; + + private int mNextBufferId = Sample.NO_BUFFER + 1; + private SparseArray<SampleBuffer> mBuffers = new SparseArray<>(); + + private Impl(final String name, final boolean bufferless) { + mName = name; + mBufferless = bufferless; + } + + private void setDefaultBufferSize(final int size) { + if (mBufferless) { + throw new IllegalStateException("Setting buffer size of a bufferless pool is not allowed"); + } + mDefaultBufferSize = size; + } + + private synchronized Sample obtain(final int size) { + if (!mRecycledSamples.isEmpty()) { + return mRecycledSamples.remove(0); + } + + if (mBufferless) { + return Sample.obtain(); + } else { + return allocateSampleAndBuffer(size); + } + } + + private Sample allocateSampleAndBuffer(final int size) { + final int id = mNextBufferId++; + try { + final SharedMemory shm = new SharedMemory(id, Math.max(size, mDefaultBufferSize)); + mBuffers.put((Integer) id, new SampleBuffer(shm)); + final Sample s = Sample.obtain(); + s.bufferId = id; + return s; + } catch (final NoSuchMethodException | IOException e) { + mBuffers.delete(id); + throw new UnsupportedOperationException(e); + } + } + + private synchronized SampleBuffer getBuffer(final int id) { + return mBuffers.get(id); + } + + private synchronized void recycle(final Sample recycled) { + if (mBufferless || isUsefulSample(recycled)) { + mRecycledSamples.add(recycled); + } else { + disposeSample(recycled); + } + } + + private boolean isUsefulSample(final Sample sample) { + return mBuffers.get(sample.bufferId).capacity() >= mDefaultBufferSize; + } + + private synchronized void clear() { + for (final Sample s : mRecycledSamples) { + disposeSample(s); + } + mRecycledSamples.clear(); + + for (int i = 0; i < mBuffers.size(); ++i) { + mBuffers.valueAt(i).dispose(); + } + mBuffers.clear(); + } + + private void disposeSample(final Sample sample) { + if (sample.bufferId != Sample.NO_BUFFER) { + mBuffers.get(sample.bufferId).dispose(); + mBuffers.delete(sample.bufferId); + } + sample.dispose(); + } + + @Override + protected void finalize() { + clear(); + } + } + + private final Impl mInputs; + private final Impl mOutputs; + + /* package */ SamplePool(final String name, final boolean renderToSurface) { + mInputs = new Impl(name + " input sample pool", false); + // Buffers are useless when rendering to surface. + mOutputs = new Impl(name + " output sample pool", renderToSurface); + } + + /* package */ void setInputBufferSize(final int size) { + mInputs.setDefaultBufferSize(size); + } + + /* package */ void setOutputBufferSize(final int size) { + mOutputs.setDefaultBufferSize(size); + } + + /* package */ Sample obtainInput(final int size) { + final Sample input = mInputs.obtain(size); + input.info.set(0, 0, 0, 0); + return input; + } + + /* package */ Sample obtainOutput(final MediaCodec.BufferInfo info) { + final Sample output = mOutputs.obtain(info.size); + output.info.set(0, info.size, info.presentationTimeUs, info.flags); + return output; + } + + /* package */ void recycleInput(final Sample sample) { + sample.cryptoInfo = null; + mInputs.recycle(sample); + } + + /* package */ void recycleOutput(final Sample sample) { + mOutputs.recycle(sample); + } + + /* package */ void reset() { + mInputs.clear(); + mOutputs.clear(); + } + + /* package */ SampleBuffer getInputBuffer(final int id) { + return mInputs.getBuffer(id); + } + + /* package */ SampleBuffer getOutputBuffer(final int id) { + return mOutputs.getBuffer(id); + } +} |