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:
christosts 2020-11-06 17:51:37 +00:00 committed by kim-vde
parent 8b5ecdb98d
commit 1d4321b86e
7 changed files with 70 additions and 84 deletions

View file

@ -311,7 +311,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
@Override
protected void configureCodec(
MediaCodecInfo codecInfo,
MediaCodecAdapter codecAdapter,
MediaCodecAdapter codec,
Format format,
@Nullable MediaCrypto crypto,
float codecOperatingRate) {
@ -319,7 +319,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
codecNeedsDiscardChannelsWorkaround = codecNeedsDiscardChannelsWorkaround(codecInfo.name);
MediaFormat mediaFormat =
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.
boolean decryptOnlyCodecEnabled =
MimeTypes.AUDIO_RAW.equals(codecInfo.mimeType)
@ -330,7 +330,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
@Override
@KeepCodecResult
protected int canKeepCodec(
MediaCodec codec, MediaCodecInfo codecInfo, Format oldFormat, Format newFormat) {
MediaCodecAdapter codec, MediaCodecInfo codecInfo, Format oldFormat, Format newFormat) {
if (getCodecMaxInputSize(codecInfo, newFormat) > codecMaxInputSize) {
return KEEP_CODEC_RESULT_NO;
}
@ -558,7 +558,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
protected boolean processOutputBuffer(
long positionUs,
long elapsedRealtimeUs,
@Nullable MediaCodec codec,
@Nullable MediaCodecAdapter codec,
@Nullable ByteBuffer buffer,
int bufferIndex,
int bufferFlags,

View file

@ -56,6 +56,7 @@ import java.nio.ByteBuffer;
private final MediaCodec codec;
private final AsynchronousMediaCodecCallback asynchronousMediaCodecCallback;
private final AsynchronousMediaCodecBufferEnqueuer bufferEnqueuer;
private boolean codecReleased;
@State private int state;
/**
@ -162,18 +163,20 @@ import java.nio.ByteBuffer;
@Override
public void release() {
if (state == STATE_STARTED) {
bufferEnqueuer.shutdown();
try {
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

View file

@ -157,9 +157,6 @@ public interface MediaCodecAdapter {
/** Releases the adapter and the underlying {@link MediaCodec}. */
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.
*

View file

@ -306,8 +306,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
private boolean mediaCryptoRequiresSecureDecoder;
private long renderTimeLimitMs;
private float playbackSpeed;
@Nullable private MediaCodec codec;
@Nullable private MediaCodecAdapter codecAdapter;
@Nullable private MediaCodecAdapter codec;
@Nullable private Format codecInputFormat;
@Nullable private MediaFormat codecOutputMediaFormat;
private boolean codecOutputMediaFormatChanged;
@ -464,7 +463,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
* Configures a newly created {@link MediaCodec}.
*
* @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 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
@ -472,7 +471,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
*/
protected abstract void configureCodec(
MediaCodecInfo codecInfo,
MediaCodecAdapter codecAdapter,
MediaCodecAdapter codec,
Format format,
@Nullable MediaCrypto crypto,
float codecOperatingRate);
@ -608,7 +607,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
}
@Nullable
protected final MediaCodec getCodec() {
protected final MediaCodecAdapter getCodec() {
return codec;
}
@ -718,17 +717,13 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
protected void releaseCodec() {
try {
if (codecAdapter != null) {
codecAdapter.release();
}
if (codec != null) {
decoderCounters.decoderReleaseCount++;
codec.release();
decoderCounters.decoderReleaseCount++;
onCodecReleased(codecInfo.name);
}
} finally {
codec = null;
codecAdapter = null;
try {
if (mediaCrypto != null) {
mediaCrypto.release();
@ -844,7 +839,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
/** Flushes the codec. */
private void flushCodec() {
try {
codecAdapter.flush();
codec.flush();
} finally {
resetCodecStateForFlush();
}
@ -1040,7 +1035,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
private void initCodec(MediaCodecInfo codecInfo, MediaCrypto crypto) throws Exception {
long codecInitializingTimestamp;
long codecInitializedTimestamp;
MediaCodec codec = null;
@Nullable MediaCodecAdapter codecAdapter = null;
String codecName = codecInfo.name;
float codecOperatingRate =
@ -1051,11 +1046,10 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
codecOperatingRate = CODEC_OPERATING_RATE_UNSET;
}
@Nullable MediaCodecAdapter codecAdapter = null;
try {
codecInitializingTimestamp = SystemClock.elapsedRealtime();
TraceUtil.beginSection("createCodec:" + codecName);
codec = MediaCodec.createByCodecName(codecName);
MediaCodec codec = MediaCodec.createByCodecName(codecName);
if (enableAsynchronousBufferQueueing && Util.SDK_INT >= 23) {
codecAdapter = new AsynchronousMediaCodecAdapter(codec, getTrackType());
} else {
@ -1073,14 +1067,10 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
if (codecAdapter != null) {
codecAdapter.release();
}
if (codec != null) {
codec.release();
}
throw e;
}
this.codec = codec;
this.codecAdapter = codecAdapter;
this.codec = codecAdapter;
this.codecInfo = codecInfo;
this.codecOperatingRate = codecOperatingRate;
codecInputFormat = inputFormat;
@ -1148,11 +1138,11 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
}
if (inputIndex < 0) {
inputIndex = codecAdapter.dequeueInputBufferIndex();
inputIndex = codec.dequeueInputBufferIndex();
if (inputIndex < 0) {
return false;
}
buffer.data = codecAdapter.getInputBuffer(inputIndex);
buffer.data = codec.getInputBuffer(inputIndex);
buffer.clear();
}
@ -1163,7 +1153,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
// Do nothing.
} else {
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();
}
codecDrainState = DRAIN_STATE_WAIT_END_OF_STREAM;
@ -1173,7 +1163,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
if (codecNeedsAdaptationWorkaroundBuffer) {
codecNeedsAdaptationWorkaroundBuffer = false;
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();
codecReceivedBuffers = true;
return true;
@ -1232,7 +1222,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
// Do nothing.
} else {
codecReceivedEos = true;
codecAdapter.queueInputBuffer(
codec.queueInputBuffer(
inputIndex,
/* offset= */ 0,
/* size= */ 0,
@ -1303,10 +1293,10 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
onQueueInputBuffer(buffer);
try {
if (bufferEncrypted) {
codecAdapter.queueSecureInputBuffer(
codec.queueSecureInputBuffer(
inputIndex, /* offset= */ 0, buffer.cryptoInfo, presentationTimeUs, /* flags= */ 0);
} else {
codecAdapter.queueInputBuffer(
codec.queueInputBuffer(
inputIndex, /* offset= */ 0, buffer.data.limit(), presentationTimeUs, /* flags= */ 0);
}
} catch (CryptoException e) {
@ -1525,7 +1515,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
*
* <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 oldFormat The {@link Format} for which the existing instance is configured.
* @param newFormat The new {@link Format}.
@ -1533,7 +1523,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
*/
@KeepCodecResult
protected int canKeepCodec(
MediaCodec codec, MediaCodecInfo codecInfo, Format oldFormat, Format newFormat) {
MediaCodecAdapter codec, MediaCodecInfo codecInfo, Format oldFormat, Format newFormat) {
return KEEP_CODEC_RESULT_NO;
}
@ -1676,7 +1666,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
int outputIndex;
if (codecNeedsEosOutputExceptionWorkaround && codecReceivedEos) {
try {
outputIndex = codecAdapter.dequeueOutputBufferIndex(outputBufferInfo);
outputIndex = codec.dequeueOutputBufferIndex(outputBufferInfo);
} catch (IllegalStateException e) {
processEndOfStream();
if (outputStreamEnded) {
@ -1686,7 +1676,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
return false;
}
} else {
outputIndex = codecAdapter.dequeueOutputBufferIndex(outputBufferInfo);
outputIndex = codec.dequeueOutputBufferIndex(outputBufferInfo);
}
if (outputIndex < 0) {
@ -1715,7 +1705,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
}
this.outputIndex = outputIndex;
outputBuffer = codecAdapter.getOutputBuffer(outputIndex);
outputBuffer = codec.getOutputBuffer(outputIndex);
// The dequeued buffer is a media buffer. Do some initial setup.
// 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}. */
private void processOutputMediaFormatChanged() {
codecHasOutputMediaFormat = true;
MediaFormat mediaFormat = codecAdapter.getOutputFormat();
MediaFormat mediaFormat = codec.getOutputFormat();
if (codecAdaptationWorkaroundMode != ADAPTATION_WORKAROUND_MODE_NEVER
&& mediaFormat.getInteger(MediaFormat.KEY_WIDTH) == ADAPTATION_WORKAROUND_SLICE_WIDTH_HEIGHT
&& mediaFormat.getInteger(MediaFormat.KEY_HEIGHT)
@ -1825,7 +1815,8 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
* iteration of the rendering loop.
* @param elapsedRealtimeUs {@link SystemClock#elapsedRealtime()} in microseconds, measured at the
* 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
* 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
@ -1845,7 +1836,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
protected abstract boolean processOutputBuffer(
long positionUs,
long elapsedRealtimeUs,
@Nullable MediaCodec codec,
@Nullable MediaCodecAdapter codec,
@Nullable ByteBuffer buffer,
int bufferIndex,
int bufferFlags,
@ -1903,8 +1894,8 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
/**
* Returns the offset that should be subtracted from {@code bufferPresentationTimeUs} in {@link
* #processOutputBuffer(long, long, MediaCodec, ByteBuffer, int, int, int, long, boolean, boolean,
* Format)} to get the playback position with respect to the media.
* #processOutputBuffer(long, long, MediaCodecAdapter, ByteBuffer, int, int, int, long, boolean,
* boolean, Format)} to get the playback position with respect to the media.
*/
protected final long getOutputStreamOffsetUs() {
return outputStreamOffsetUs;

View file

@ -138,11 +138,7 @@ import java.nio.ByteBuffer;
public void release() {
inputByteBuffers = null;
outputByteBuffers = null;
}
@Override
public MediaCodec getCodec() {
return codec;
codec.release();
}
@Override

View file

@ -461,7 +461,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
setSurface((Surface) message);
} else if (messageType == MSG_SET_SCALING_MODE) {
scalingMode = (Integer) message;
MediaCodec codec = getCodec();
@Nullable MediaCodecAdapter codec = getCodec();
if (codec != null) {
codec.setVideoScalingMode(scalingMode);
}
@ -493,7 +493,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
updateSurfaceFrameRate(/* isNewSurface= */ true);
@State int state = getState();
MediaCodec codec = getCodec();
@Nullable MediaCodecAdapter codec = getCodec();
if (codec != null) {
if (Util.SDK_INT >= 23 && surface != null && !codecNeedsSetOutputSurfaceWorkaround) {
setOutputSurfaceV23(codec, surface);
@ -537,7 +537,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
@Override
protected void configureCodec(
MediaCodecInfo codecInfo,
MediaCodecAdapter codecAdapter,
MediaCodecAdapter codec,
Format format,
@Nullable MediaCrypto crypto,
float codecOperatingRate) {
@ -560,16 +560,16 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
}
surface = dummySurface;
}
codecAdapter.configure(mediaFormat, surface, crypto, 0);
codec.configure(mediaFormat, surface, crypto, 0);
if (Util.SDK_INT >= 23 && tunneling) {
tunnelingOnFrameRenderedListener = new OnFrameRenderedListenerV23(codecAdapter.getCodec());
tunnelingOnFrameRenderedListener = new OnFrameRenderedListenerV23(codec);
}
}
@Override
@KeepCodecResult
protected int canKeepCodec(
MediaCodec codec, MediaCodecInfo codecInfo, Format oldFormat, Format newFormat) {
MediaCodecAdapter codec, MediaCodecInfo codecInfo, Format oldFormat, Format newFormat) {
if (newFormat.width > codecMaxValues.width
|| newFormat.height > codecMaxValues.height
|| getMaxInputSize(codecInfo, newFormat) > codecMaxValues.inputSize) {
@ -651,7 +651,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
@Override
protected void onOutputFormatChanged(Format format, @Nullable MediaFormat mediaFormat) {
@Nullable MediaCodec codec = getCodec();
@Nullable MediaCodecAdapter codec = getCodec();
if (codec != null) {
// Must be applied each time the output format changes.
codec.setVideoScalingMode(scalingMode);
@ -729,7 +729,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
protected boolean processOutputBuffer(
long positionUs,
long elapsedRealtimeUs,
@Nullable MediaCodec codec,
@Nullable MediaCodecAdapter codec,
@Nullable ByteBuffer buffer,
int bufferIndex,
int bufferFlags,
@ -942,7 +942,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
* @param index The index of the output buffer to skip.
* @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");
codec.releaseOutputBuffer(index, false);
TraceUtil.endSection();
@ -956,7 +956,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
* @param index The index of the output buffer to drop.
* @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");
codec.releaseOutputBuffer(index, false);
TraceUtil.endSection();
@ -978,7 +978,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
* @throws ExoPlaybackException If an error occurs flushing the codec.
*/
protected boolean maybeDropBuffersToKeyframe(
MediaCodec codec,
MediaCodecAdapter codec,
int index,
long presentationTimeUs,
long positionUs,
@ -1037,7 +1037,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
* @param index The index of the output buffer to drop.
* @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();
TraceUtil.beginSection("releaseOutputBuffer");
codec.releaseOutputBuffer(index, true);
@ -1059,7 +1059,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
*/
@RequiresApi(21)
protected void renderOutputBufferV21(
MediaCodec codec, int index, long presentationTimeUs, long releaseTimeNs) {
MediaCodecAdapter codec, int index, long presentationTimeUs, long releaseTimeNs) {
maybeNotifyVideoSizeChanged();
TraceUtil.beginSection("releaseOutputBuffer");
codec.releaseOutputBuffer(index, releaseTimeNs);
@ -1132,7 +1132,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
// OnFrameRenderedListenerV23.onFrameRenderedListener for tunneled playback on API level 23 and
// above.
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 != null) {
tunnelingOnFrameRenderedListener = new OnFrameRenderedListenerV23(codec);
@ -1213,14 +1213,14 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
}
@RequiresApi(29)
private static void setHdr10PlusInfoV29(MediaCodec codec, byte[] hdr10PlusInfo) {
private static void setHdr10PlusInfoV29(MediaCodecAdapter codec, byte[] hdr10PlusInfo) {
Bundle codecParameters = new Bundle();
codecParameters.putByteArray(MediaCodec.PARAMETER_KEY_HDR10_PLUS_INFO, hdr10PlusInfo);
codec.setParameters(codecParameters);
}
@RequiresApi(23)
protected void setOutputSurfaceV23(MediaCodec codec, Surface surface) {
protected void setOutputSurfaceV23(MediaCodecAdapter codec, Surface surface) {
codec.setOutputSurface(surface);
}
@ -1762,19 +1762,19 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
@RequiresApi(23)
private final class OnFrameRenderedListenerV23
implements MediaCodec.OnFrameRenderedListener, Handler.Callback {
implements MediaCodecAdapter.OnFrameRenderedListener, Handler.Callback {
private static final int HANDLE_FRAME_RENDERED = 0;
private final Handler handler;
public OnFrameRenderedListenerV23(MediaCodec codec) {
public OnFrameRenderedListenerV23(MediaCodecAdapter codec) {
handler = Util.createHandlerForCurrentLooper(/* callback= */ this);
codec.setOnFrameRenderedListener(/* listener= */ this, handler);
}
@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
// MediaCodec from this listener method.
// Deadlock occurs because MediaCodec calls this listener method holding a lock,

View file

@ -18,7 +18,6 @@ package com.google.android.exoplayer2.playbacktests.gts;
import static java.lang.Math.max;
import android.content.Context;
import android.media.MediaCodec;
import android.media.MediaCrypto;
import android.media.MediaFormat;
import android.os.Handler;
@ -133,7 +132,7 @@ import java.util.ArrayList;
@Override
protected void configureCodec(
MediaCodecInfo codecInfo,
MediaCodecAdapter codecAdapter,
MediaCodecAdapter codec,
Format format,
MediaCrypto crypto,
float operatingRate) {
@ -143,7 +142,7 @@ import java.util.ArrayList;
// dropped frames allowed, this is not desired behavior. Hence we skip (rather than drop)
// frames up to the current playback position [Internal: b/66494991].
skipToPositionBeforeRenderingFirstFrame = getState() == Renderer.STATE_STARTED;
super.configureCodec(codecInfo, codecAdapter, format, crypto, operatingRate);
super.configureCodec(codecInfo, codec, format, crypto, operatingRate);
}
@Override
@ -200,7 +199,7 @@ import java.util.ArrayList;
protected boolean processOutputBuffer(
long positionUs,
long elapsedRealtimeUs,
@Nullable MediaCodec codec,
@Nullable MediaCodecAdapter codec,
ByteBuffer buffer,
int bufferIndex,
int bufferFlags,
@ -231,7 +230,7 @@ import java.util.ArrayList;
}
@Override
protected void renderOutputBuffer(MediaCodec codec, int index, long presentationTimeUs) {
protected void renderOutputBuffer(MediaCodecAdapter codec, int index, long presentationTimeUs) {
skipToPositionBeforeRenderingFirstFrame = false;
super.renderOutputBuffer(codec, index, presentationTimeUs);
}
@ -239,7 +238,7 @@ import java.util.ArrayList;
@RequiresApi(21)
@Override
protected void renderOutputBufferV21(
MediaCodec codec, int index, long presentationTimeUs, long releaseTimeNs) {
MediaCodecAdapter codec, int index, long presentationTimeUs, long releaseTimeNs) {
skipToPositionBeforeRenderingFirstFrame = false;
super.renderOutputBufferV21(codec, index, presentationTimeUs, releaseTimeNs);
}