Verified Commit 65f632f6 authored by Daniel Baker's avatar Daniel Baker Committed by ma1
Browse files

Bug 2039050 - Track largest observed output size to drive SamplePool sizing on...

Bug 2039050 - Track largest observed output size to drive SamplePool sizing on Android, and size-check obtain. r=padenot

Differential Revision: https://phabricator.services.mozilla.com/D299792
parent e41384f1
Loading
Loading
Loading
Loading
+14 −9
Original line number Diff line number Diff line
@@ -244,7 +244,12 @@ import org.mozilla.gecko.gfx.GeckoSurface;

  private class OutputProcessor {
    private final boolean mRenderToSurface;
    private boolean mHasOutputCapacitySet;
    // Tracks the largest output frame size observed so far. MediaCodec's
    // getOutputBuffer(idx).capacity() is not reliable as a max-buffer hint
    // on modern Android (it reports the valid data range of the current
    // frame, e.g. ~28 bytes for the first SPS/PPS), so we grow the
    // SamplePool's default monotonically from observed info.size instead.
    private int mMaxObservedOutputSize;
    private Queue<Output> mSentOutputs = new LinkedList<>();
    private boolean mStopped;

@@ -285,6 +290,14 @@ import org.mozilla.gecko.gfx.GeckoSurface;
    }

    private Sample obtainOutputSample(final int index, final MediaCodec.BufferInfo info) {
      // Grow the pool's minimum-useful capacity ahead of allocation so
      // setDefaultBufferSize sweeps any now-stranded recycled samples
      // before obtainOutput could hand one back.
      if (!mRenderToSurface && info.size > mMaxObservedOutputSize) {
        mMaxObservedOutputSize = info.size;
        mSamplePool.setOutputBufferSize(mMaxObservedOutputSize);
      }

      final Sample sample = mSamplePool.obtainOutput(info);

      if (mRenderToSurface) {
@@ -292,14 +305,6 @@ import org.mozilla.gecko.gfx.GeckoSurface;
      }

      final ByteBuffer output = mCodec.getOutputBuffer(index);
      if (!mHasOutputCapacitySet) {
        final int capacity = output.capacity();
        if (capacity > 0) {
          mSamplePool.setOutputBufferSize(capacity);
          mHasOutputCapacitySet = true;
        }
      }

      if (info.size > 0) {
        try {
          mSamplePool
+32 −7
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@ import android.media.MediaCodec;
import android.util.SparseArray;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.mozilla.gecko.mozglue.SharedMemory;

@@ -26,23 +27,47 @@ final class SamplePool {
      mBufferless = bufferless;
    }

    private void setDefaultBufferSize(final int size) {
    private synchronized void setDefaultBufferSize(final int size) {
      if (mBufferless) {
        throw new IllegalStateException("Setting buffer size of a bufferless pool is not allowed");
      }
      if (size <= mDefaultBufferSize) {
        return;
      }
      mDefaultBufferSize = size;
      // Sweep: any sample admitted under a smaller default is now stranded.
      final Iterator<Sample> it = mRecycledSamples.iterator();
      while (it.hasNext()) {
        final Sample s = it.next();
        final SampleBuffer buf = mBuffers.get(s.bufferId);
        if (buf == null || buf.capacity() < mDefaultBufferSize) {
          it.remove();
          disposeSample(s);
        }
      }
    }

    private synchronized Sample obtain(final int size) {
      if (mBufferless) {
        if (!mRecycledSamples.isEmpty()) {
          return mRecycledSamples.remove(0);
        }

      if (mBufferless) {
        return Sample.obtain();
      } else {
        return allocateSampleAndBuffer(size);
      }
      final Iterator<Sample> it = mRecycledSamples.iterator();
      while (it.hasNext()) {
        final Sample candidate = it.next();
        final SampleBuffer buf = mBuffers.get(candidate.bufferId);
        if (buf != null && buf.capacity() >= size) {
          it.remove();
          return candidate;
        }
        it.remove();
        if (buf != null) {
          disposeSample(candidate);
        }
      }
      return allocateSampleAndBuffer(size);
    }

    private Sample allocateSampleAndBuffer(final int size) {