Commit 665092e4 by christosts Committed by Ian Baker

MediaCodecAdapter supports queueing input buffers

Add queueInputBuffer() and queueSecureInputBuffer() in
MediaCodecAdapter.

PiperOrigin-RevId: 290720307
parent cf393983
...@@ -64,6 +64,18 @@ import com.google.android.exoplayer2.util.Assertions; ...@@ -64,6 +64,18 @@ import com.google.android.exoplayer2.util.Assertions;
} }
@Override @Override
public void queueInputBuffer(
int index, int offset, int size, long presentationTimeUs, int flags) {
codec.queueInputBuffer(index, offset, size, presentationTimeUs, flags);
}
@Override
public void queueSecureInputBuffer(
int index, int offset, MediaCodec.CryptoInfo info, long presentationTimeUs, int flags) {
codec.queueSecureInputBuffer(index, offset, info, presentationTimeUs, flags);
}
@Override
public int dequeueInputBufferIndex() { public int dequeueInputBufferIndex() {
if (flushing) { if (flushing) {
return MediaCodec.INFO_TRY_AGAIN_LATER; return MediaCodec.INFO_TRY_AGAIN_LATER;
......
...@@ -33,8 +33,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -33,8 +33,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
* A {@link MediaCodecAdapter} that operates the underlying {@link MediaCodec} in asynchronous mode * A {@link MediaCodecAdapter} that operates the underlying {@link MediaCodec} in asynchronous mode
* and routes {@link MediaCodec.Callback} callbacks on a dedicated Thread that is managed * and routes {@link MediaCodec.Callback} callbacks on a dedicated Thread that is managed
* internally. * internally.
*
* <p>After creating an instance, you need to call {@link #start()} to start the internal Thread.
*/ */
@RequiresApi(23) @RequiresApi(23)
/* package */ final class DedicatedThreadAsyncMediaCodecAdapter extends MediaCodec.Callback /* package */ final class DedicatedThreadAsyncMediaCodecAdapter extends MediaCodec.Callback
...@@ -89,6 +87,22 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -89,6 +87,22 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
} }
@Override @Override
public void queueInputBuffer(
int index, int offset, int size, long presentationTimeUs, int flags) {
// This method does not need to be synchronized because it does not interact with the
// mediaCodecAsyncCallback.
codec.queueInputBuffer(index, offset, size, presentationTimeUs, flags);
}
@Override
public void queueSecureInputBuffer(
int index, int offset, MediaCodec.CryptoInfo info, long presentationTimeUs, int flags) {
// This method does not need to be synchronized because it does not interact with the
// mediaCodecAsyncCallback.
codec.queueSecureInputBuffer(index, offset, info, presentationTimeUs, flags);
}
@Override
public synchronized int dequeueInputBufferIndex() { public synchronized int dequeueInputBufferIndex() {
if (isFlushing()) { if (isFlushing()) {
return MediaCodec.INFO_TRY_AGAIN_LATER; return MediaCodec.INFO_TRY_AGAIN_LATER;
......
...@@ -66,6 +66,27 @@ import android.media.MediaFormat; ...@@ -66,6 +66,27 @@ import android.media.MediaFormat;
MediaFormat getOutputFormat(); MediaFormat getOutputFormat();
/** /**
* Submit an input buffer for decoding.
*
* <p>The {@code index} must be an input buffer index that has been obtained from a previous call
* to {@link #dequeueInputBufferIndex()}.
*
* @see MediaCodec#queueInputBuffer
*/
void queueInputBuffer(int index, int offset, int size, long presentationTimeUs, int flags);
/**
* Submit an input buffer that is potentially encrypted for decoding.
*
* <p>The {@code index} must be an input buffer index that has been obtained from a previous call
* to {@link #dequeueInputBufferIndex()}.
*
* @see MediaCodec#queueSecureInputBuffer
*/
void queueSecureInputBuffer(
int index, int offset, MediaCodec.CryptoInfo info, long presentationTimeUs, int flags);
/**
* Flushes the {@code MediaCodecAdapter}. * Flushes the {@code MediaCodecAdapter}.
* *
* <p>Note: {@link #flush()} should also call any {@link MediaCodec} methods needed to flush the * <p>Note: {@link #flush()} should also call any {@link MediaCodec} methods needed to flush the
......
...@@ -1136,7 +1136,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -1136,7 +1136,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
// Do nothing. // Do nothing.
} else { } else {
codecReceivedEos = true; codecReceivedEos = true;
codec.queueInputBuffer(inputIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM); codecAdapter.queueInputBuffer(inputIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
resetInputBuffer(); resetInputBuffer();
} }
codecDrainState = DRAIN_STATE_WAIT_END_OF_STREAM; codecDrainState = DRAIN_STATE_WAIT_END_OF_STREAM;
...@@ -1146,7 +1146,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -1146,7 +1146,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
if (codecNeedsAdaptationWorkaroundBuffer) { if (codecNeedsAdaptationWorkaroundBuffer) {
codecNeedsAdaptationWorkaroundBuffer = false; codecNeedsAdaptationWorkaroundBuffer = false;
buffer.data.put(ADAPTATION_WORKAROUND_BUFFER); buffer.data.put(ADAPTATION_WORKAROUND_BUFFER);
codec.queueInputBuffer(inputIndex, 0, ADAPTATION_WORKAROUND_BUFFER.length, 0, 0); codecAdapter.queueInputBuffer(inputIndex, 0, ADAPTATION_WORKAROUND_BUFFER.length, 0, 0);
resetInputBuffer(); resetInputBuffer();
codecReceivedBuffers = true; codecReceivedBuffers = true;
return true; return true;
...@@ -1210,7 +1210,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -1210,7 +1210,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
// Do nothing. // Do nothing.
} else { } else {
codecReceivedEos = true; codecReceivedEos = true;
codec.queueInputBuffer(inputIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM); codecAdapter.queueInputBuffer(inputIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
resetInputBuffer(); resetInputBuffer();
} }
} catch (CryptoException e) { } catch (CryptoException e) {
...@@ -1261,9 +1261,9 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -1261,9 +1261,9 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
if (bufferEncrypted) { if (bufferEncrypted) {
MediaCodec.CryptoInfo cryptoInfo = getFrameworkCryptoInfo(buffer, MediaCodec.CryptoInfo cryptoInfo = getFrameworkCryptoInfo(buffer,
adaptiveReconfigurationBytes); adaptiveReconfigurationBytes);
codec.queueSecureInputBuffer(inputIndex, 0, cryptoInfo, presentationTimeUs, 0); codecAdapter.queueSecureInputBuffer(inputIndex, 0, cryptoInfo, presentationTimeUs, 0);
} else { } else {
codec.queueInputBuffer(inputIndex, 0, buffer.data.limit(), presentationTimeUs, 0); codecAdapter.queueInputBuffer(inputIndex, 0, buffer.data.limit(), presentationTimeUs, 0);
} }
resetInputBuffer(); resetInputBuffer();
codecReceivedBuffers = true; codecReceivedBuffers = true;
......
...@@ -46,8 +46,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -46,8 +46,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
* MediaCodec.Callback} methods will be accessed by the internal Thread. This class is * MediaCodec.Callback} methods will be accessed by the internal Thread. This class is
* <strong>NOT</strong> generally thread-safe in the sense that its public methods cannot be called * <strong>NOT</strong> generally thread-safe in the sense that its public methods cannot be called
* by any thread. * by any thread.
*
* <p>After creating an instance, you need to call {@link #start()} to start the internal Thread.
*/ */
@RequiresApi(23) @RequiresApi(23)
/* package */ final class MultiLockAsyncMediaCodecAdapter extends MediaCodec.Callback /* package */ final class MultiLockAsyncMediaCodecAdapter extends MediaCodec.Callback
...@@ -162,6 +160,22 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -162,6 +160,22 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
} }
@Override @Override
public void queueInputBuffer(
int index, int offset, int size, long presentationTimeUs, int flags) {
// This method does not need to be synchronized because it is not interacting with
// MediaCodec.Callback and dequeueing buffers operations.
codec.queueInputBuffer(index, offset, size, presentationTimeUs, flags);
}
@Override
public void queueSecureInputBuffer(
int index, int offset, MediaCodec.CryptoInfo info, long presentationTimeUs, int flags) {
// This method does not need to be synchronized because it is not interacting with
// MediaCodec.Callback and dequeueing buffers operations.
codec.queueSecureInputBuffer(index, offset, info, presentationTimeUs, flags);
}
@Override
public void flush() { public void flush() {
synchronized (objectStateLock) { synchronized (objectStateLock) {
codec.flush(); codec.flush();
......
...@@ -51,6 +51,18 @@ import android.media.MediaFormat; ...@@ -51,6 +51,18 @@ import android.media.MediaFormat;
} }
@Override @Override
public void queueInputBuffer(
int index, int offset, int size, long presentationTimeUs, int flags) {
codec.queueInputBuffer(index, offset, size, presentationTimeUs, flags);
}
@Override
public void queueSecureInputBuffer(
int index, int offset, MediaCodec.CryptoInfo info, long presentationTimeUs, int flags) {
codec.queueSecureInputBuffer(index, offset, info, presentationTimeUs, flags);
}
@Override
public void flush() { public void flush() {
codec.flush(); codec.flush();
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment