Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit abba82cd authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "RELAND MediaCodec: don't cache buffers until requested" into tm-qpr-dev

parents e4611ad6 4a114c2f
Loading
Loading
Loading
Loading
+90 −41
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ import java.nio.ByteOrder;
import java.nio.ReadOnlyBufferException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -1803,7 +1804,7 @@ final public class MediaCodec {
                    synchronized(mBufferLock) {
                        switch (mBufferMode) {
                            case BUFFER_MODE_LEGACY:
                                validateInputByteBuffer(mCachedInputBuffers, index);
                                validateInputByteBufferLocked(mCachedInputBuffers, index);
                                break;
                            case BUFFER_MODE_BLOCK:
                                while (mQueueRequests.size() <= index) {
@@ -1832,7 +1833,7 @@ final public class MediaCodec {
                    synchronized(mBufferLock) {
                        switch (mBufferMode) {
                            case BUFFER_MODE_LEGACY:
                                validateOutputByteBuffer(mCachedOutputBuffers, index, info);
                                validateOutputByteBufferLocked(mCachedOutputBuffers, index, info);
                                break;
                            case BUFFER_MODE_BLOCK:
                                while (mOutputFrames.size() <= index) {
@@ -2320,10 +2321,6 @@ final public class MediaCodec {
     */
    public final void start() {
        native_start();
        synchronized(mBufferLock) {
            cacheBuffers(true /* input */);
            cacheBuffers(false /* input */);
        }
    }
    private native final void native_start();

@@ -2380,8 +2377,10 @@ final public class MediaCodec {
     */
    public final void flush() {
        synchronized(mBufferLock) {
            invalidateByteBuffers(mCachedInputBuffers);
            invalidateByteBuffers(mCachedOutputBuffers);
            invalidateByteBuffersLocked(mCachedInputBuffers);
            invalidateByteBuffersLocked(mCachedOutputBuffers);
            mValidInputIndices.clear();
            mValidOutputIndices.clear();
            mDequeuedInputBuffers.clear();
            mDequeuedOutputBuffers.clear();
        }
@@ -2665,14 +2664,14 @@ final public class MediaCodec {
                        + "is not compatible with CONFIGURE_FLAG_USE_BLOCK_MODEL. "
                        + "Please use getQueueRequest() to queue buffers");
            }
            invalidateByteBuffer(mCachedInputBuffers, index);
            invalidateByteBufferLocked(mCachedInputBuffers, index, true /* input */);
            mDequeuedInputBuffers.remove(index);
        }
        try {
            native_queueInputBuffer(
                    index, offset, size, presentationTimeUs, flags);
        } catch (CryptoException | IllegalStateException e) {
            revalidateByteBuffer(mCachedInputBuffers, index);
            revalidateByteBuffer(mCachedInputBuffers, index, true /* input */);
            throw e;
        }
    }
@@ -2935,14 +2934,14 @@ final public class MediaCodec {
                        + "is not compatible with CONFIGURE_FLAG_USE_BLOCK_MODEL. "
                        + "Please use getQueueRequest() to queue buffers");
            }
            invalidateByteBuffer(mCachedInputBuffers, index);
            invalidateByteBufferLocked(mCachedInputBuffers, index, true /* input */);
            mDequeuedInputBuffers.remove(index);
        }
        try {
            native_queueSecureInputBuffer(
                    index, offset, info, presentationTimeUs, flags);
        } catch (CryptoException | IllegalStateException e) {
            revalidateByteBuffer(mCachedInputBuffers, index);
            revalidateByteBuffer(mCachedInputBuffers, index, true /* input */);
            throw e;
        }
    }
@@ -2976,7 +2975,7 @@ final public class MediaCodec {
        int res = native_dequeueInputBuffer(timeoutUs);
        if (res >= 0) {
            synchronized(mBufferLock) {
                validateInputByteBuffer(mCachedInputBuffers, res);
                validateInputByteBufferLocked(mCachedInputBuffers, res);
            }
        }
        return res;
@@ -3573,10 +3572,10 @@ final public class MediaCodec {
        int res = native_dequeueOutputBuffer(info, timeoutUs);
        synchronized (mBufferLock) {
            if (res == INFO_OUTPUT_BUFFERS_CHANGED) {
                cacheBuffers(false /* input */);
                cacheBuffersLocked(false /* input */);
            } else if (res >= 0) {
                validateOutputByteBuffer(mCachedOutputBuffers, res, info);
                if (mHasSurface) {
                validateOutputByteBufferLocked(mCachedOutputBuffers, res, info);
                if (mHasSurface || mCachedOutputBuffers == null) {
                    mDequeuedOutputInfos.put(res, info.dup());
                }
            }
@@ -3670,9 +3669,9 @@ final public class MediaCodec {
        synchronized(mBufferLock) {
            switch (mBufferMode) {
                case BUFFER_MODE_LEGACY:
                    invalidateByteBuffer(mCachedOutputBuffers, index);
                    invalidateByteBufferLocked(mCachedOutputBuffers, index, false /* input */);
                    mDequeuedOutputBuffers.remove(index);
                    if (mHasSurface) {
                    if (mHasSurface || mCachedOutputBuffers == null) {
                        info = mDequeuedOutputInfos.remove(index);
                    }
                    break;
@@ -3824,15 +3823,24 @@ final public class MediaCodec {

    private ByteBuffer[] mCachedInputBuffers;
    private ByteBuffer[] mCachedOutputBuffers;
    private BitSet mValidInputIndices = new BitSet();
    private BitSet mValidOutputIndices = new BitSet();

    private final BufferMap mDequeuedInputBuffers = new BufferMap();
    private final BufferMap mDequeuedOutputBuffers = new BufferMap();
    private final Map<Integer, BufferInfo> mDequeuedOutputInfos =
        new HashMap<Integer, BufferInfo>();
    final private Object mBufferLock;

    private final void invalidateByteBuffer(
            @Nullable ByteBuffer[] buffers, int index) {
        if (buffers != null && index >= 0 && index < buffers.length) {
    private void invalidateByteBufferLocked(
            @Nullable ByteBuffer[] buffers, int index, boolean input) {
        if (buffers == null) {
            if (index < 0) {
                throw new IllegalStateException("index is negative (" + index + ")");
            }
            BitSet indices = input ? mValidInputIndices : mValidOutputIndices;
            indices.clear(index);
        } else if (index >= 0 && index < buffers.length) {
            ByteBuffer buffer = buffers[index];
            if (buffer != null) {
                buffer.setAccessible(false);
@@ -3840,9 +3848,14 @@ final public class MediaCodec {
        }
    }

    private final void validateInputByteBuffer(
    private void validateInputByteBufferLocked(
            @Nullable ByteBuffer[] buffers, int index) {
        if (buffers != null && index >= 0 && index < buffers.length) {
        if (buffers == null) {
            if (index < 0) {
                throw new IllegalStateException("index is negative (" + index + ")");
            }
            mValidInputIndices.set(index);
        } else if (index >= 0 && index < buffers.length) {
            ByteBuffer buffer = buffers[index];
            if (buffer != null) {
                buffer.setAccessible(true);
@@ -3851,10 +3864,16 @@ final public class MediaCodec {
        }
    }

    private final void revalidateByteBuffer(
            @Nullable ByteBuffer[] buffers, int index) {
    private void revalidateByteBuffer(
            @Nullable ByteBuffer[] buffers, int index, boolean input) {
        synchronized(mBufferLock) {
            if (buffers != null && index >= 0 && index < buffers.length) {
            if (buffers == null) {
                if (index < 0) {
                    throw new IllegalStateException("index is negative (" + index + ")");
                }
                BitSet indices = input ? mValidInputIndices : mValidOutputIndices;
                indices.set(index);
            } else if (index >= 0 && index < buffers.length) {
                ByteBuffer buffer = buffers[index];
                if (buffer != null) {
                    buffer.setAccessible(true);
@@ -3863,9 +3882,14 @@ final public class MediaCodec {
        }
    }

    private final void validateOutputByteBuffer(
    private void validateOutputByteBufferLocked(
            @Nullable ByteBuffer[] buffers, int index, @NonNull BufferInfo info) {
        if (buffers != null && index >= 0 && index < buffers.length) {
        if (buffers == null) {
            if (index < 0) {
                throw new IllegalStateException("index is negative (" + index + ")");
            }
            mValidOutputIndices.set(index);
        } else if (index >= 0 && index < buffers.length) {
            ByteBuffer buffer = buffers[index];
            if (buffer != null) {
                buffer.setAccessible(true);
@@ -3874,7 +3898,7 @@ final public class MediaCodec {
        }
    }

    private final void invalidateByteBuffers(@Nullable ByteBuffer[] buffers) {
    private void invalidateByteBuffersLocked(@Nullable ByteBuffer[] buffers) {
        if (buffers != null) {
            for (ByteBuffer buffer: buffers) {
                if (buffer != null) {
@@ -3884,27 +3908,29 @@ final public class MediaCodec {
        }
    }

    private final void freeByteBuffer(@Nullable ByteBuffer buffer) {
    private void freeByteBufferLocked(@Nullable ByteBuffer buffer) {
        if (buffer != null /* && buffer.isDirect() */) {
            // all of our ByteBuffers are direct
            java.nio.NioUtils.freeDirectBuffer(buffer);
        }
    }

    private final void freeByteBuffers(@Nullable ByteBuffer[] buffers) {
    private void freeByteBuffersLocked(@Nullable ByteBuffer[] buffers) {
        if (buffers != null) {
            for (ByteBuffer buffer: buffers) {
                freeByteBuffer(buffer);
                freeByteBufferLocked(buffer);
            }
        }
    }

    private final void freeAllTrackedBuffers() {
    private void freeAllTrackedBuffers() {
        synchronized(mBufferLock) {
            freeByteBuffers(mCachedInputBuffers);
            freeByteBuffers(mCachedOutputBuffers);
            freeByteBuffersLocked(mCachedInputBuffers);
            freeByteBuffersLocked(mCachedOutputBuffers);
            mCachedInputBuffers = null;
            mCachedOutputBuffers = null;
            mValidInputIndices.clear();
            mValidOutputIndices.clear();
            mDequeuedInputBuffers.clear();
            mDequeuedOutputBuffers.clear();
            mQueueRequests.clear();
@@ -3912,14 +3938,31 @@ final public class MediaCodec {
        }
    }

    private final void cacheBuffers(boolean input) {
    private void cacheBuffersLocked(boolean input) {
        ByteBuffer[] buffers = null;
        try {
            buffers = getBuffers(input);
            invalidateByteBuffers(buffers);
            invalidateByteBuffersLocked(buffers);
        } catch (IllegalStateException e) {
            // we don't get buffers in async mode
        }
        if (buffers != null) {
            BitSet indices = input ? mValidInputIndices : mValidOutputIndices;
            for (int i = 0; i < buffers.length; ++i) {
                ByteBuffer buffer = buffers[i];
                if (buffer == null || !indices.get(i)) {
                    continue;
                }
                buffer.setAccessible(true);
                if (!input) {
                    BufferInfo info = mDequeuedOutputInfos.get(i);
                    if (info != null) {
                        buffer.limit(info.offset + info.size).position(info.offset);
                    }
                }
            }
            indices.clear();
        }
        if (input) {
            mCachedInputBuffers = buffers;
        } else {
@@ -3954,6 +3997,9 @@ final public class MediaCodec {
                        + "Please obtain MediaCodec.LinearBlock or HardwareBuffer "
                        + "objects and attach to QueueRequest objects.");
            }
            if (mCachedInputBuffers == null) {
                cacheBuffersLocked(true /* input */);
            }
            if (mCachedInputBuffers == null) {
                throw new IllegalStateException();
            }
@@ -3992,6 +4038,9 @@ final public class MediaCodec {
                        + "is not compatible with CONFIGURE_FLAG_USE_BLOCK_MODEL. "
                        + "Please use getOutputFrame to get output frames.");
            }
            if (mCachedOutputBuffers == null) {
                cacheBuffersLocked(false /* input */);
            }
            if (mCachedOutputBuffers == null) {
                throw new IllegalStateException();
            }
@@ -4030,7 +4079,7 @@ final public class MediaCodec {
        }
        ByteBuffer newBuffer = getBuffer(true /* input */, index);
        synchronized (mBufferLock) {
            invalidateByteBuffer(mCachedInputBuffers, index);
            invalidateByteBufferLocked(mCachedInputBuffers, index, true /* input */);
            mDequeuedInputBuffers.put(index, newBuffer);
        }
        return newBuffer;
@@ -4067,7 +4116,7 @@ final public class MediaCodec {
        }
        Image newImage = getImage(true /* input */, index);
        synchronized (mBufferLock) {
            invalidateByteBuffer(mCachedInputBuffers, index);
            invalidateByteBufferLocked(mCachedInputBuffers, index, true /* input */);
            mDequeuedInputBuffers.put(index, newImage);
        }
        return newImage;
@@ -4103,7 +4152,7 @@ final public class MediaCodec {
        }
        ByteBuffer newBuffer = getBuffer(false /* input */, index);
        synchronized (mBufferLock) {
            invalidateByteBuffer(mCachedOutputBuffers, index);
            invalidateByteBufferLocked(mCachedOutputBuffers, index, false /* input */);
            mDequeuedOutputBuffers.put(index, newBuffer);
        }
        return newBuffer;
@@ -4138,7 +4187,7 @@ final public class MediaCodec {
        }
        Image newImage = getImage(false /* input */, index);
        synchronized (mBufferLock) {
            invalidateByteBuffer(mCachedOutputBuffers, index);
            invalidateByteBufferLocked(mCachedOutputBuffers, index, false /* input */);
            mDequeuedOutputBuffers.put(index, newImage);
        }
        return newImage;