mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Move ownership of MediaCodec to MediaCodecAdapter
Move ownership of MediaCodec to MediaCodecAdapter so that all MediaCodec interactions go through MediaCodecAdapter. PiperOrigin-RevId: 341066926
This commit is contained in:
parent
8b5ecdb98d
commit
1d4321b86e
7 changed files with 70 additions and 84 deletions
|
|
@ -311,7 +311,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
||||||
@Override
|
@Override
|
||||||
protected void configureCodec(
|
protected void configureCodec(
|
||||||
MediaCodecInfo codecInfo,
|
MediaCodecInfo codecInfo,
|
||||||
MediaCodecAdapter codecAdapter,
|
MediaCodecAdapter codec,
|
||||||
Format format,
|
Format format,
|
||||||
@Nullable MediaCrypto crypto,
|
@Nullable MediaCrypto crypto,
|
||||||
float codecOperatingRate) {
|
float codecOperatingRate) {
|
||||||
|
|
@ -319,7 +319,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
||||||
codecNeedsDiscardChannelsWorkaround = codecNeedsDiscardChannelsWorkaround(codecInfo.name);
|
codecNeedsDiscardChannelsWorkaround = codecNeedsDiscardChannelsWorkaround(codecInfo.name);
|
||||||
MediaFormat mediaFormat =
|
MediaFormat mediaFormat =
|
||||||
getMediaFormat(format, codecInfo.codecMimeType, codecMaxInputSize, codecOperatingRate);
|
getMediaFormat(format, codecInfo.codecMimeType, codecMaxInputSize, codecOperatingRate);
|
||||||
codecAdapter.configure(mediaFormat, /* surface= */ null, crypto, /* flags= */ 0);
|
codec.configure(mediaFormat, /* surface= */ null, crypto, /* flags= */ 0);
|
||||||
// Store the input MIME type if we're only using the codec for decryption.
|
// Store the input MIME type if we're only using the codec for decryption.
|
||||||
boolean decryptOnlyCodecEnabled =
|
boolean decryptOnlyCodecEnabled =
|
||||||
MimeTypes.AUDIO_RAW.equals(codecInfo.mimeType)
|
MimeTypes.AUDIO_RAW.equals(codecInfo.mimeType)
|
||||||
|
|
@ -330,7 +330,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
||||||
@Override
|
@Override
|
||||||
@KeepCodecResult
|
@KeepCodecResult
|
||||||
protected int canKeepCodec(
|
protected int canKeepCodec(
|
||||||
MediaCodec codec, MediaCodecInfo codecInfo, Format oldFormat, Format newFormat) {
|
MediaCodecAdapter codec, MediaCodecInfo codecInfo, Format oldFormat, Format newFormat) {
|
||||||
if (getCodecMaxInputSize(codecInfo, newFormat) > codecMaxInputSize) {
|
if (getCodecMaxInputSize(codecInfo, newFormat) > codecMaxInputSize) {
|
||||||
return KEEP_CODEC_RESULT_NO;
|
return KEEP_CODEC_RESULT_NO;
|
||||||
}
|
}
|
||||||
|
|
@ -558,7 +558,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
||||||
protected boolean processOutputBuffer(
|
protected boolean processOutputBuffer(
|
||||||
long positionUs,
|
long positionUs,
|
||||||
long elapsedRealtimeUs,
|
long elapsedRealtimeUs,
|
||||||
@Nullable MediaCodec codec,
|
@Nullable MediaCodecAdapter codec,
|
||||||
@Nullable ByteBuffer buffer,
|
@Nullable ByteBuffer buffer,
|
||||||
int bufferIndex,
|
int bufferIndex,
|
||||||
int bufferFlags,
|
int bufferFlags,
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,7 @@ import java.nio.ByteBuffer;
|
||||||
private final MediaCodec codec;
|
private final MediaCodec codec;
|
||||||
private final AsynchronousMediaCodecCallback asynchronousMediaCodecCallback;
|
private final AsynchronousMediaCodecCallback asynchronousMediaCodecCallback;
|
||||||
private final AsynchronousMediaCodecBufferEnqueuer bufferEnqueuer;
|
private final AsynchronousMediaCodecBufferEnqueuer bufferEnqueuer;
|
||||||
|
private boolean codecReleased;
|
||||||
@State private int state;
|
@State private int state;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -162,18 +163,20 @@ import java.nio.ByteBuffer;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void release() {
|
public void release() {
|
||||||
if (state == STATE_STARTED) {
|
try {
|
||||||
bufferEnqueuer.shutdown();
|
if (state == STATE_STARTED) {
|
||||||
|
bufferEnqueuer.shutdown();
|
||||||
|
}
|
||||||
|
if (state == STATE_CONFIGURED || state == STATE_STARTED) {
|
||||||
|
asynchronousMediaCodecCallback.shutdown();
|
||||||
|
}
|
||||||
|
state = STATE_SHUT_DOWN;
|
||||||
|
} finally {
|
||||||
|
if (!codecReleased) {
|
||||||
|
codec.release();
|
||||||
|
codecReleased = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (state == STATE_CONFIGURED || state == STATE_STARTED) {
|
|
||||||
asynchronousMediaCodecCallback.shutdown();
|
|
||||||
}
|
|
||||||
state = STATE_SHUT_DOWN;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MediaCodec getCodec() {
|
|
||||||
return codec;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -157,9 +157,6 @@ public interface MediaCodecAdapter {
|
||||||
/** Releases the adapter and the underlying {@link MediaCodec}. */
|
/** Releases the adapter and the underlying {@link MediaCodec}. */
|
||||||
void release();
|
void release();
|
||||||
|
|
||||||
/** Returns the {@link MediaCodec} instance of this adapter. */
|
|
||||||
MediaCodec getCodec();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a callback to be invoked when an output frame is rendered on the output surface.
|
* Registers a callback to be invoked when an output frame is rendered on the output surface.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -306,8 +306,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||||
private boolean mediaCryptoRequiresSecureDecoder;
|
private boolean mediaCryptoRequiresSecureDecoder;
|
||||||
private long renderTimeLimitMs;
|
private long renderTimeLimitMs;
|
||||||
private float playbackSpeed;
|
private float playbackSpeed;
|
||||||
@Nullable private MediaCodec codec;
|
@Nullable private MediaCodecAdapter codec;
|
||||||
@Nullable private MediaCodecAdapter codecAdapter;
|
|
||||||
@Nullable private Format codecInputFormat;
|
@Nullable private Format codecInputFormat;
|
||||||
@Nullable private MediaFormat codecOutputMediaFormat;
|
@Nullable private MediaFormat codecOutputMediaFormat;
|
||||||
private boolean codecOutputMediaFormatChanged;
|
private boolean codecOutputMediaFormatChanged;
|
||||||
|
|
@ -464,7 +463,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||||
* Configures a newly created {@link MediaCodec}.
|
* Configures a newly created {@link MediaCodec}.
|
||||||
*
|
*
|
||||||
* @param codecInfo Information about the {@link MediaCodec} being configured.
|
* @param codecInfo Information about the {@link MediaCodec} being configured.
|
||||||
* @param codecAdapter The {@link MediaCodecAdapter} to configure.
|
* @param codec The {@link MediaCodecAdapter} to configure.
|
||||||
* @param format The {@link Format} for which the codec is being configured.
|
* @param format The {@link Format} for which the codec is being configured.
|
||||||
* @param crypto For drm protected playbacks, a {@link MediaCrypto} to use for decryption.
|
* @param crypto For drm protected playbacks, a {@link MediaCrypto} to use for decryption.
|
||||||
* @param codecOperatingRate The codec operating rate, or {@link #CODEC_OPERATING_RATE_UNSET} if
|
* @param codecOperatingRate The codec operating rate, or {@link #CODEC_OPERATING_RATE_UNSET} if
|
||||||
|
|
@ -472,7 +471,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||||
*/
|
*/
|
||||||
protected abstract void configureCodec(
|
protected abstract void configureCodec(
|
||||||
MediaCodecInfo codecInfo,
|
MediaCodecInfo codecInfo,
|
||||||
MediaCodecAdapter codecAdapter,
|
MediaCodecAdapter codec,
|
||||||
Format format,
|
Format format,
|
||||||
@Nullable MediaCrypto crypto,
|
@Nullable MediaCrypto crypto,
|
||||||
float codecOperatingRate);
|
float codecOperatingRate);
|
||||||
|
|
@ -608,7 +607,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
protected final MediaCodec getCodec() {
|
protected final MediaCodecAdapter getCodec() {
|
||||||
return codec;
|
return codec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -718,17 +717,13 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||||
|
|
||||||
protected void releaseCodec() {
|
protected void releaseCodec() {
|
||||||
try {
|
try {
|
||||||
if (codecAdapter != null) {
|
|
||||||
codecAdapter.release();
|
|
||||||
}
|
|
||||||
if (codec != null) {
|
if (codec != null) {
|
||||||
decoderCounters.decoderReleaseCount++;
|
|
||||||
codec.release();
|
codec.release();
|
||||||
|
decoderCounters.decoderReleaseCount++;
|
||||||
onCodecReleased(codecInfo.name);
|
onCodecReleased(codecInfo.name);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
codec = null;
|
codec = null;
|
||||||
codecAdapter = null;
|
|
||||||
try {
|
try {
|
||||||
if (mediaCrypto != null) {
|
if (mediaCrypto != null) {
|
||||||
mediaCrypto.release();
|
mediaCrypto.release();
|
||||||
|
|
@ -844,7 +839,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||||
/** Flushes the codec. */
|
/** Flushes the codec. */
|
||||||
private void flushCodec() {
|
private void flushCodec() {
|
||||||
try {
|
try {
|
||||||
codecAdapter.flush();
|
codec.flush();
|
||||||
} finally {
|
} finally {
|
||||||
resetCodecStateForFlush();
|
resetCodecStateForFlush();
|
||||||
}
|
}
|
||||||
|
|
@ -1040,7 +1035,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||||
private void initCodec(MediaCodecInfo codecInfo, MediaCrypto crypto) throws Exception {
|
private void initCodec(MediaCodecInfo codecInfo, MediaCrypto crypto) throws Exception {
|
||||||
long codecInitializingTimestamp;
|
long codecInitializingTimestamp;
|
||||||
long codecInitializedTimestamp;
|
long codecInitializedTimestamp;
|
||||||
MediaCodec codec = null;
|
@Nullable MediaCodecAdapter codecAdapter = null;
|
||||||
String codecName = codecInfo.name;
|
String codecName = codecInfo.name;
|
||||||
|
|
||||||
float codecOperatingRate =
|
float codecOperatingRate =
|
||||||
|
|
@ -1051,11 +1046,10 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||||
codecOperatingRate = CODEC_OPERATING_RATE_UNSET;
|
codecOperatingRate = CODEC_OPERATING_RATE_UNSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable MediaCodecAdapter codecAdapter = null;
|
|
||||||
try {
|
try {
|
||||||
codecInitializingTimestamp = SystemClock.elapsedRealtime();
|
codecInitializingTimestamp = SystemClock.elapsedRealtime();
|
||||||
TraceUtil.beginSection("createCodec:" + codecName);
|
TraceUtil.beginSection("createCodec:" + codecName);
|
||||||
codec = MediaCodec.createByCodecName(codecName);
|
MediaCodec codec = MediaCodec.createByCodecName(codecName);
|
||||||
if (enableAsynchronousBufferQueueing && Util.SDK_INT >= 23) {
|
if (enableAsynchronousBufferQueueing && Util.SDK_INT >= 23) {
|
||||||
codecAdapter = new AsynchronousMediaCodecAdapter(codec, getTrackType());
|
codecAdapter = new AsynchronousMediaCodecAdapter(codec, getTrackType());
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1073,14 +1067,10 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||||
if (codecAdapter != null) {
|
if (codecAdapter != null) {
|
||||||
codecAdapter.release();
|
codecAdapter.release();
|
||||||
}
|
}
|
||||||
if (codec != null) {
|
|
||||||
codec.release();
|
|
||||||
}
|
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.codec = codec;
|
this.codec = codecAdapter;
|
||||||
this.codecAdapter = codecAdapter;
|
|
||||||
this.codecInfo = codecInfo;
|
this.codecInfo = codecInfo;
|
||||||
this.codecOperatingRate = codecOperatingRate;
|
this.codecOperatingRate = codecOperatingRate;
|
||||||
codecInputFormat = inputFormat;
|
codecInputFormat = inputFormat;
|
||||||
|
|
@ -1148,11 +1138,11 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inputIndex < 0) {
|
if (inputIndex < 0) {
|
||||||
inputIndex = codecAdapter.dequeueInputBufferIndex();
|
inputIndex = codec.dequeueInputBufferIndex();
|
||||||
if (inputIndex < 0) {
|
if (inputIndex < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
buffer.data = codecAdapter.getInputBuffer(inputIndex);
|
buffer.data = codec.getInputBuffer(inputIndex);
|
||||||
buffer.clear();
|
buffer.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1163,7 +1153,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||||
// Do nothing.
|
// Do nothing.
|
||||||
} else {
|
} else {
|
||||||
codecReceivedEos = true;
|
codecReceivedEos = true;
|
||||||
codecAdapter.queueInputBuffer(inputIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
|
codec.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;
|
||||||
|
|
@ -1173,7 +1163,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);
|
||||||
codecAdapter.queueInputBuffer(inputIndex, 0, ADAPTATION_WORKAROUND_BUFFER.length, 0, 0);
|
codec.queueInputBuffer(inputIndex, 0, ADAPTATION_WORKAROUND_BUFFER.length, 0, 0);
|
||||||
resetInputBuffer();
|
resetInputBuffer();
|
||||||
codecReceivedBuffers = true;
|
codecReceivedBuffers = true;
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -1232,7 +1222,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||||
// Do nothing.
|
// Do nothing.
|
||||||
} else {
|
} else {
|
||||||
codecReceivedEos = true;
|
codecReceivedEos = true;
|
||||||
codecAdapter.queueInputBuffer(
|
codec.queueInputBuffer(
|
||||||
inputIndex,
|
inputIndex,
|
||||||
/* offset= */ 0,
|
/* offset= */ 0,
|
||||||
/* size= */ 0,
|
/* size= */ 0,
|
||||||
|
|
@ -1303,10 +1293,10 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||||
onQueueInputBuffer(buffer);
|
onQueueInputBuffer(buffer);
|
||||||
try {
|
try {
|
||||||
if (bufferEncrypted) {
|
if (bufferEncrypted) {
|
||||||
codecAdapter.queueSecureInputBuffer(
|
codec.queueSecureInputBuffer(
|
||||||
inputIndex, /* offset= */ 0, buffer.cryptoInfo, presentationTimeUs, /* flags= */ 0);
|
inputIndex, /* offset= */ 0, buffer.cryptoInfo, presentationTimeUs, /* flags= */ 0);
|
||||||
} else {
|
} else {
|
||||||
codecAdapter.queueInputBuffer(
|
codec.queueInputBuffer(
|
||||||
inputIndex, /* offset= */ 0, buffer.data.limit(), presentationTimeUs, /* flags= */ 0);
|
inputIndex, /* offset= */ 0, buffer.data.limit(), presentationTimeUs, /* flags= */ 0);
|
||||||
}
|
}
|
||||||
} catch (CryptoException e) {
|
} catch (CryptoException e) {
|
||||||
|
|
@ -1525,7 +1515,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||||
*
|
*
|
||||||
* <p>The default implementation returns {@link MediaCodecInfo#KEEP_CODEC_RESULT_NO}.
|
* <p>The default implementation returns {@link MediaCodecInfo#KEEP_CODEC_RESULT_NO}.
|
||||||
*
|
*
|
||||||
* @param codec The existing {@link MediaCodec} instance.
|
* @param codec The existing {@link MediaCodecAdapter} instance.
|
||||||
* @param codecInfo A {@link MediaCodecInfo} describing the decoder.
|
* @param codecInfo A {@link MediaCodecInfo} describing the decoder.
|
||||||
* @param oldFormat The {@link Format} for which the existing instance is configured.
|
* @param oldFormat The {@link Format} for which the existing instance is configured.
|
||||||
* @param newFormat The new {@link Format}.
|
* @param newFormat The new {@link Format}.
|
||||||
|
|
@ -1533,7 +1523,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||||
*/
|
*/
|
||||||
@KeepCodecResult
|
@KeepCodecResult
|
||||||
protected int canKeepCodec(
|
protected int canKeepCodec(
|
||||||
MediaCodec codec, MediaCodecInfo codecInfo, Format oldFormat, Format newFormat) {
|
MediaCodecAdapter codec, MediaCodecInfo codecInfo, Format oldFormat, Format newFormat) {
|
||||||
return KEEP_CODEC_RESULT_NO;
|
return KEEP_CODEC_RESULT_NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1676,7 +1666,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||||
int outputIndex;
|
int outputIndex;
|
||||||
if (codecNeedsEosOutputExceptionWorkaround && codecReceivedEos) {
|
if (codecNeedsEosOutputExceptionWorkaround && codecReceivedEos) {
|
||||||
try {
|
try {
|
||||||
outputIndex = codecAdapter.dequeueOutputBufferIndex(outputBufferInfo);
|
outputIndex = codec.dequeueOutputBufferIndex(outputBufferInfo);
|
||||||
} catch (IllegalStateException e) {
|
} catch (IllegalStateException e) {
|
||||||
processEndOfStream();
|
processEndOfStream();
|
||||||
if (outputStreamEnded) {
|
if (outputStreamEnded) {
|
||||||
|
|
@ -1686,7 +1676,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
outputIndex = codecAdapter.dequeueOutputBufferIndex(outputBufferInfo);
|
outputIndex = codec.dequeueOutputBufferIndex(outputBufferInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (outputIndex < 0) {
|
if (outputIndex < 0) {
|
||||||
|
|
@ -1715,7 +1705,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.outputIndex = outputIndex;
|
this.outputIndex = outputIndex;
|
||||||
outputBuffer = codecAdapter.getOutputBuffer(outputIndex);
|
outputBuffer = codec.getOutputBuffer(outputIndex);
|
||||||
|
|
||||||
// The dequeued buffer is a media buffer. Do some initial setup.
|
// The dequeued buffer is a media buffer. Do some initial setup.
|
||||||
// It will be processed by calling processOutputBuffer (possibly multiple times).
|
// It will be processed by calling processOutputBuffer (possibly multiple times).
|
||||||
|
|
@ -1791,7 +1781,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||||
/** Processes a change in the decoder output {@link MediaFormat}. */
|
/** Processes a change in the decoder output {@link MediaFormat}. */
|
||||||
private void processOutputMediaFormatChanged() {
|
private void processOutputMediaFormatChanged() {
|
||||||
codecHasOutputMediaFormat = true;
|
codecHasOutputMediaFormat = true;
|
||||||
MediaFormat mediaFormat = codecAdapter.getOutputFormat();
|
MediaFormat mediaFormat = codec.getOutputFormat();
|
||||||
if (codecAdaptationWorkaroundMode != ADAPTATION_WORKAROUND_MODE_NEVER
|
if (codecAdaptationWorkaroundMode != ADAPTATION_WORKAROUND_MODE_NEVER
|
||||||
&& mediaFormat.getInteger(MediaFormat.KEY_WIDTH) == ADAPTATION_WORKAROUND_SLICE_WIDTH_HEIGHT
|
&& mediaFormat.getInteger(MediaFormat.KEY_WIDTH) == ADAPTATION_WORKAROUND_SLICE_WIDTH_HEIGHT
|
||||||
&& mediaFormat.getInteger(MediaFormat.KEY_HEIGHT)
|
&& mediaFormat.getInteger(MediaFormat.KEY_HEIGHT)
|
||||||
|
|
@ -1825,7 +1815,8 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||||
* iteration of the rendering loop.
|
* iteration of the rendering loop.
|
||||||
* @param elapsedRealtimeUs {@link SystemClock#elapsedRealtime()} in microseconds, measured at the
|
* @param elapsedRealtimeUs {@link SystemClock#elapsedRealtime()} in microseconds, measured at the
|
||||||
* start of the current iteration of the rendering loop.
|
* start of the current iteration of the rendering loop.
|
||||||
* @param codec The {@link MediaCodec} instance, or null in bypass mode were no codec is used.
|
* @param codec The {@link MediaCodecAdapter} instance, or null in bypass mode were no codec is
|
||||||
|
* used.
|
||||||
* @param buffer The output buffer to process, or null if the buffer data is not made available to
|
* @param buffer The output buffer to process, or null if the buffer data is not made available to
|
||||||
* the application layer (see {@link MediaCodec#getOutputBuffer(int)}). This {@code buffer}
|
* the application layer (see {@link MediaCodec#getOutputBuffer(int)}). This {@code buffer}
|
||||||
* can only be null for video data. Note that the buffer data can still be rendered in this
|
* can only be null for video data. Note that the buffer data can still be rendered in this
|
||||||
|
|
@ -1845,7 +1836,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||||
protected abstract boolean processOutputBuffer(
|
protected abstract boolean processOutputBuffer(
|
||||||
long positionUs,
|
long positionUs,
|
||||||
long elapsedRealtimeUs,
|
long elapsedRealtimeUs,
|
||||||
@Nullable MediaCodec codec,
|
@Nullable MediaCodecAdapter codec,
|
||||||
@Nullable ByteBuffer buffer,
|
@Nullable ByteBuffer buffer,
|
||||||
int bufferIndex,
|
int bufferIndex,
|
||||||
int bufferFlags,
|
int bufferFlags,
|
||||||
|
|
@ -1903,8 +1894,8 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the offset that should be subtracted from {@code bufferPresentationTimeUs} in {@link
|
* Returns the offset that should be subtracted from {@code bufferPresentationTimeUs} in {@link
|
||||||
* #processOutputBuffer(long, long, MediaCodec, ByteBuffer, int, int, int, long, boolean, boolean,
|
* #processOutputBuffer(long, long, MediaCodecAdapter, ByteBuffer, int, int, int, long, boolean,
|
||||||
* Format)} to get the playback position with respect to the media.
|
* boolean, Format)} to get the playback position with respect to the media.
|
||||||
*/
|
*/
|
||||||
protected final long getOutputStreamOffsetUs() {
|
protected final long getOutputStreamOffsetUs() {
|
||||||
return outputStreamOffsetUs;
|
return outputStreamOffsetUs;
|
||||||
|
|
|
||||||
|
|
@ -138,11 +138,7 @@ import java.nio.ByteBuffer;
|
||||||
public void release() {
|
public void release() {
|
||||||
inputByteBuffers = null;
|
inputByteBuffers = null;
|
||||||
outputByteBuffers = null;
|
outputByteBuffers = null;
|
||||||
}
|
codec.release();
|
||||||
|
|
||||||
@Override
|
|
||||||
public MediaCodec getCodec() {
|
|
||||||
return codec;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -461,7 +461,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
||||||
setSurface((Surface) message);
|
setSurface((Surface) message);
|
||||||
} else if (messageType == MSG_SET_SCALING_MODE) {
|
} else if (messageType == MSG_SET_SCALING_MODE) {
|
||||||
scalingMode = (Integer) message;
|
scalingMode = (Integer) message;
|
||||||
MediaCodec codec = getCodec();
|
@Nullable MediaCodecAdapter codec = getCodec();
|
||||||
if (codec != null) {
|
if (codec != null) {
|
||||||
codec.setVideoScalingMode(scalingMode);
|
codec.setVideoScalingMode(scalingMode);
|
||||||
}
|
}
|
||||||
|
|
@ -493,7 +493,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
||||||
updateSurfaceFrameRate(/* isNewSurface= */ true);
|
updateSurfaceFrameRate(/* isNewSurface= */ true);
|
||||||
|
|
||||||
@State int state = getState();
|
@State int state = getState();
|
||||||
MediaCodec codec = getCodec();
|
@Nullable MediaCodecAdapter codec = getCodec();
|
||||||
if (codec != null) {
|
if (codec != null) {
|
||||||
if (Util.SDK_INT >= 23 && surface != null && !codecNeedsSetOutputSurfaceWorkaround) {
|
if (Util.SDK_INT >= 23 && surface != null && !codecNeedsSetOutputSurfaceWorkaround) {
|
||||||
setOutputSurfaceV23(codec, surface);
|
setOutputSurfaceV23(codec, surface);
|
||||||
|
|
@ -537,7 +537,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
||||||
@Override
|
@Override
|
||||||
protected void configureCodec(
|
protected void configureCodec(
|
||||||
MediaCodecInfo codecInfo,
|
MediaCodecInfo codecInfo,
|
||||||
MediaCodecAdapter codecAdapter,
|
MediaCodecAdapter codec,
|
||||||
Format format,
|
Format format,
|
||||||
@Nullable MediaCrypto crypto,
|
@Nullable MediaCrypto crypto,
|
||||||
float codecOperatingRate) {
|
float codecOperatingRate) {
|
||||||
|
|
@ -560,16 +560,16 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
||||||
}
|
}
|
||||||
surface = dummySurface;
|
surface = dummySurface;
|
||||||
}
|
}
|
||||||
codecAdapter.configure(mediaFormat, surface, crypto, 0);
|
codec.configure(mediaFormat, surface, crypto, 0);
|
||||||
if (Util.SDK_INT >= 23 && tunneling) {
|
if (Util.SDK_INT >= 23 && tunneling) {
|
||||||
tunnelingOnFrameRenderedListener = new OnFrameRenderedListenerV23(codecAdapter.getCodec());
|
tunnelingOnFrameRenderedListener = new OnFrameRenderedListenerV23(codec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@KeepCodecResult
|
@KeepCodecResult
|
||||||
protected int canKeepCodec(
|
protected int canKeepCodec(
|
||||||
MediaCodec codec, MediaCodecInfo codecInfo, Format oldFormat, Format newFormat) {
|
MediaCodecAdapter codec, MediaCodecInfo codecInfo, Format oldFormat, Format newFormat) {
|
||||||
if (newFormat.width > codecMaxValues.width
|
if (newFormat.width > codecMaxValues.width
|
||||||
|| newFormat.height > codecMaxValues.height
|
|| newFormat.height > codecMaxValues.height
|
||||||
|| getMaxInputSize(codecInfo, newFormat) > codecMaxValues.inputSize) {
|
|| getMaxInputSize(codecInfo, newFormat) > codecMaxValues.inputSize) {
|
||||||
|
|
@ -651,7 +651,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onOutputFormatChanged(Format format, @Nullable MediaFormat mediaFormat) {
|
protected void onOutputFormatChanged(Format format, @Nullable MediaFormat mediaFormat) {
|
||||||
@Nullable MediaCodec codec = getCodec();
|
@Nullable MediaCodecAdapter codec = getCodec();
|
||||||
if (codec != null) {
|
if (codec != null) {
|
||||||
// Must be applied each time the output format changes.
|
// Must be applied each time the output format changes.
|
||||||
codec.setVideoScalingMode(scalingMode);
|
codec.setVideoScalingMode(scalingMode);
|
||||||
|
|
@ -729,7 +729,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
||||||
protected boolean processOutputBuffer(
|
protected boolean processOutputBuffer(
|
||||||
long positionUs,
|
long positionUs,
|
||||||
long elapsedRealtimeUs,
|
long elapsedRealtimeUs,
|
||||||
@Nullable MediaCodec codec,
|
@Nullable MediaCodecAdapter codec,
|
||||||
@Nullable ByteBuffer buffer,
|
@Nullable ByteBuffer buffer,
|
||||||
int bufferIndex,
|
int bufferIndex,
|
||||||
int bufferFlags,
|
int bufferFlags,
|
||||||
|
|
@ -942,7 +942,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
||||||
* @param index The index of the output buffer to skip.
|
* @param index The index of the output buffer to skip.
|
||||||
* @param presentationTimeUs The presentation time of the output buffer, in microseconds.
|
* @param presentationTimeUs The presentation time of the output buffer, in microseconds.
|
||||||
*/
|
*/
|
||||||
protected void skipOutputBuffer(MediaCodec codec, int index, long presentationTimeUs) {
|
protected void skipOutputBuffer(MediaCodecAdapter codec, int index, long presentationTimeUs) {
|
||||||
TraceUtil.beginSection("skipVideoBuffer");
|
TraceUtil.beginSection("skipVideoBuffer");
|
||||||
codec.releaseOutputBuffer(index, false);
|
codec.releaseOutputBuffer(index, false);
|
||||||
TraceUtil.endSection();
|
TraceUtil.endSection();
|
||||||
|
|
@ -956,7 +956,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
||||||
* @param index The index of the output buffer to drop.
|
* @param index The index of the output buffer to drop.
|
||||||
* @param presentationTimeUs The presentation time of the output buffer, in microseconds.
|
* @param presentationTimeUs The presentation time of the output buffer, in microseconds.
|
||||||
*/
|
*/
|
||||||
protected void dropOutputBuffer(MediaCodec codec, int index, long presentationTimeUs) {
|
protected void dropOutputBuffer(MediaCodecAdapter codec, int index, long presentationTimeUs) {
|
||||||
TraceUtil.beginSection("dropVideoBuffer");
|
TraceUtil.beginSection("dropVideoBuffer");
|
||||||
codec.releaseOutputBuffer(index, false);
|
codec.releaseOutputBuffer(index, false);
|
||||||
TraceUtil.endSection();
|
TraceUtil.endSection();
|
||||||
|
|
@ -978,7 +978,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
||||||
* @throws ExoPlaybackException If an error occurs flushing the codec.
|
* @throws ExoPlaybackException If an error occurs flushing the codec.
|
||||||
*/
|
*/
|
||||||
protected boolean maybeDropBuffersToKeyframe(
|
protected boolean maybeDropBuffersToKeyframe(
|
||||||
MediaCodec codec,
|
MediaCodecAdapter codec,
|
||||||
int index,
|
int index,
|
||||||
long presentationTimeUs,
|
long presentationTimeUs,
|
||||||
long positionUs,
|
long positionUs,
|
||||||
|
|
@ -1037,7 +1037,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
||||||
* @param index The index of the output buffer to drop.
|
* @param index The index of the output buffer to drop.
|
||||||
* @param presentationTimeUs The presentation time of the output buffer, in microseconds.
|
* @param presentationTimeUs The presentation time of the output buffer, in microseconds.
|
||||||
*/
|
*/
|
||||||
protected void renderOutputBuffer(MediaCodec codec, int index, long presentationTimeUs) {
|
protected void renderOutputBuffer(MediaCodecAdapter codec, int index, long presentationTimeUs) {
|
||||||
maybeNotifyVideoSizeChanged();
|
maybeNotifyVideoSizeChanged();
|
||||||
TraceUtil.beginSection("releaseOutputBuffer");
|
TraceUtil.beginSection("releaseOutputBuffer");
|
||||||
codec.releaseOutputBuffer(index, true);
|
codec.releaseOutputBuffer(index, true);
|
||||||
|
|
@ -1059,7 +1059,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
||||||
*/
|
*/
|
||||||
@RequiresApi(21)
|
@RequiresApi(21)
|
||||||
protected void renderOutputBufferV21(
|
protected void renderOutputBufferV21(
|
||||||
MediaCodec codec, int index, long presentationTimeUs, long releaseTimeNs) {
|
MediaCodecAdapter codec, int index, long presentationTimeUs, long releaseTimeNs) {
|
||||||
maybeNotifyVideoSizeChanged();
|
maybeNotifyVideoSizeChanged();
|
||||||
TraceUtil.beginSection("releaseOutputBuffer");
|
TraceUtil.beginSection("releaseOutputBuffer");
|
||||||
codec.releaseOutputBuffer(index, releaseTimeNs);
|
codec.releaseOutputBuffer(index, releaseTimeNs);
|
||||||
|
|
@ -1132,7 +1132,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
||||||
// OnFrameRenderedListenerV23.onFrameRenderedListener for tunneled playback on API level 23 and
|
// OnFrameRenderedListenerV23.onFrameRenderedListener for tunneled playback on API level 23 and
|
||||||
// above.
|
// above.
|
||||||
if (Util.SDK_INT >= 23 && tunneling) {
|
if (Util.SDK_INT >= 23 && tunneling) {
|
||||||
MediaCodec codec = getCodec();
|
@Nullable MediaCodecAdapter codec = getCodec();
|
||||||
// If codec is null then the listener will be instantiated in configureCodec.
|
// If codec is null then the listener will be instantiated in configureCodec.
|
||||||
if (codec != null) {
|
if (codec != null) {
|
||||||
tunnelingOnFrameRenderedListener = new OnFrameRenderedListenerV23(codec);
|
tunnelingOnFrameRenderedListener = new OnFrameRenderedListenerV23(codec);
|
||||||
|
|
@ -1213,14 +1213,14 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(29)
|
@RequiresApi(29)
|
||||||
private static void setHdr10PlusInfoV29(MediaCodec codec, byte[] hdr10PlusInfo) {
|
private static void setHdr10PlusInfoV29(MediaCodecAdapter codec, byte[] hdr10PlusInfo) {
|
||||||
Bundle codecParameters = new Bundle();
|
Bundle codecParameters = new Bundle();
|
||||||
codecParameters.putByteArray(MediaCodec.PARAMETER_KEY_HDR10_PLUS_INFO, hdr10PlusInfo);
|
codecParameters.putByteArray(MediaCodec.PARAMETER_KEY_HDR10_PLUS_INFO, hdr10PlusInfo);
|
||||||
codec.setParameters(codecParameters);
|
codec.setParameters(codecParameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(23)
|
@RequiresApi(23)
|
||||||
protected void setOutputSurfaceV23(MediaCodec codec, Surface surface) {
|
protected void setOutputSurfaceV23(MediaCodecAdapter codec, Surface surface) {
|
||||||
codec.setOutputSurface(surface);
|
codec.setOutputSurface(surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1762,19 +1762,19 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
||||||
|
|
||||||
@RequiresApi(23)
|
@RequiresApi(23)
|
||||||
private final class OnFrameRenderedListenerV23
|
private final class OnFrameRenderedListenerV23
|
||||||
implements MediaCodec.OnFrameRenderedListener, Handler.Callback {
|
implements MediaCodecAdapter.OnFrameRenderedListener, Handler.Callback {
|
||||||
|
|
||||||
private static final int HANDLE_FRAME_RENDERED = 0;
|
private static final int HANDLE_FRAME_RENDERED = 0;
|
||||||
|
|
||||||
private final Handler handler;
|
private final Handler handler;
|
||||||
|
|
||||||
public OnFrameRenderedListenerV23(MediaCodec codec) {
|
public OnFrameRenderedListenerV23(MediaCodecAdapter codec) {
|
||||||
handler = Util.createHandlerForCurrentLooper(/* callback= */ this);
|
handler = Util.createHandlerForCurrentLooper(/* callback= */ this);
|
||||||
codec.setOnFrameRenderedListener(/* listener= */ this, handler);
|
codec.setOnFrameRenderedListener(/* listener= */ this, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFrameRendered(MediaCodec codec, long presentationTimeUs, long nanoTime) {
|
public void onFrameRendered(MediaCodecAdapter codec, long presentationTimeUs, long nanoTime) {
|
||||||
// Workaround bug in MediaCodec that causes deadlock if you call directly back into the
|
// Workaround bug in MediaCodec that causes deadlock if you call directly back into the
|
||||||
// MediaCodec from this listener method.
|
// MediaCodec from this listener method.
|
||||||
// Deadlock occurs because MediaCodec calls this listener method holding a lock,
|
// Deadlock occurs because MediaCodec calls this listener method holding a lock,
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@ package com.google.android.exoplayer2.playbacktests.gts;
|
||||||
import static java.lang.Math.max;
|
import static java.lang.Math.max;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.media.MediaCodec;
|
|
||||||
import android.media.MediaCrypto;
|
import android.media.MediaCrypto;
|
||||||
import android.media.MediaFormat;
|
import android.media.MediaFormat;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
|
@ -133,7 +132,7 @@ import java.util.ArrayList;
|
||||||
@Override
|
@Override
|
||||||
protected void configureCodec(
|
protected void configureCodec(
|
||||||
MediaCodecInfo codecInfo,
|
MediaCodecInfo codecInfo,
|
||||||
MediaCodecAdapter codecAdapter,
|
MediaCodecAdapter codec,
|
||||||
Format format,
|
Format format,
|
||||||
MediaCrypto crypto,
|
MediaCrypto crypto,
|
||||||
float operatingRate) {
|
float operatingRate) {
|
||||||
|
|
@ -143,7 +142,7 @@ import java.util.ArrayList;
|
||||||
// dropped frames allowed, this is not desired behavior. Hence we skip (rather than drop)
|
// dropped frames allowed, this is not desired behavior. Hence we skip (rather than drop)
|
||||||
// frames up to the current playback position [Internal: b/66494991].
|
// frames up to the current playback position [Internal: b/66494991].
|
||||||
skipToPositionBeforeRenderingFirstFrame = getState() == Renderer.STATE_STARTED;
|
skipToPositionBeforeRenderingFirstFrame = getState() == Renderer.STATE_STARTED;
|
||||||
super.configureCodec(codecInfo, codecAdapter, format, crypto, operatingRate);
|
super.configureCodec(codecInfo, codec, format, crypto, operatingRate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -200,7 +199,7 @@ import java.util.ArrayList;
|
||||||
protected boolean processOutputBuffer(
|
protected boolean processOutputBuffer(
|
||||||
long positionUs,
|
long positionUs,
|
||||||
long elapsedRealtimeUs,
|
long elapsedRealtimeUs,
|
||||||
@Nullable MediaCodec codec,
|
@Nullable MediaCodecAdapter codec,
|
||||||
ByteBuffer buffer,
|
ByteBuffer buffer,
|
||||||
int bufferIndex,
|
int bufferIndex,
|
||||||
int bufferFlags,
|
int bufferFlags,
|
||||||
|
|
@ -231,7 +230,7 @@ import java.util.ArrayList;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void renderOutputBuffer(MediaCodec codec, int index, long presentationTimeUs) {
|
protected void renderOutputBuffer(MediaCodecAdapter codec, int index, long presentationTimeUs) {
|
||||||
skipToPositionBeforeRenderingFirstFrame = false;
|
skipToPositionBeforeRenderingFirstFrame = false;
|
||||||
super.renderOutputBuffer(codec, index, presentationTimeUs);
|
super.renderOutputBuffer(codec, index, presentationTimeUs);
|
||||||
}
|
}
|
||||||
|
|
@ -239,7 +238,7 @@ import java.util.ArrayList;
|
||||||
@RequiresApi(21)
|
@RequiresApi(21)
|
||||||
@Override
|
@Override
|
||||||
protected void renderOutputBufferV21(
|
protected void renderOutputBufferV21(
|
||||||
MediaCodec codec, int index, long presentationTimeUs, long releaseTimeNs) {
|
MediaCodecAdapter codec, int index, long presentationTimeUs, long releaseTimeNs) {
|
||||||
skipToPositionBeforeRenderingFirstFrame = false;
|
skipToPositionBeforeRenderingFirstFrame = false;
|
||||||
super.renderOutputBufferV21(codec, index, presentationTimeUs, releaseTimeNs);
|
super.renderOutputBufferV21(codec, index, presentationTimeUs, releaseTimeNs);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue