diff options
| -rw-r--r-- | media/java/android/media/MediaCodec.java | 125 |
1 files changed, 86 insertions, 39 deletions
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java index 3dc927c6442f..102d89b03b7c 100644 --- a/media/java/android/media/MediaCodec.java +++ b/media/java/android/media/MediaCodec.java @@ -42,6 +42,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; @@ -1794,7 +1795,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) { @@ -1823,7 +1824,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) { @@ -2338,8 +2339,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(); } @@ -2623,14 +2626,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; } } @@ -2893,14 +2896,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; } } @@ -2934,7 +2937,7 @@ final public class MediaCodec { int res = native_dequeueInputBuffer(timeoutUs); if (res >= 0) { synchronized(mBufferLock) { - validateInputByteBuffer(mCachedInputBuffers, res); + validateInputByteBufferLocked(mCachedInputBuffers, res); } } return res; @@ -3531,10 +3534,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()); } } @@ -3628,9 +3631,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; @@ -3782,15 +3785,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); @@ -3798,9 +3810,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); @@ -3809,10 +3826,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); @@ -3821,9 +3844,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); @@ -3832,7 +3860,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) { @@ -3842,27 +3870,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(); @@ -3870,14 +3900,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 { @@ -3913,7 +3960,7 @@ final public class MediaCodec { + "objects and attach to QueueRequest objects."); } if (mCachedInputBuffers == null) { - cacheBuffers(true /* input */); + cacheBuffersLocked(true /* input */); } if (mCachedInputBuffers == null) { throw new IllegalStateException(); @@ -3954,7 +4001,7 @@ final public class MediaCodec { + "Please use getOutputFrame to get output frames."); } if (mCachedOutputBuffers == null) { - cacheBuffers(false /* input */); + cacheBuffersLocked(false /* input */); } if (mCachedOutputBuffers == null) { throw new IllegalStateException(); @@ -3994,7 +4041,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; @@ -4031,7 +4078,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; @@ -4067,7 +4114,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; @@ -4102,7 +4149,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; |