mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Move common bookkeeping to MediaCodecRenderer.
This is a no-op change and just moves some duplicated logic into the base class. PiperOrigin-RevId: 294615218
This commit is contained in:
parent
bdfd24290f
commit
29c43b5e24
@ -22,7 +22,6 @@ import android.media.MediaCrypto;
|
|||||||
import android.media.MediaFormat;
|
import android.media.MediaFormat;
|
||||||
import android.media.audiofx.Virtualizer;
|
import android.media.audiofx.Virtualizer;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import androidx.annotation.CallSuper;
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.ExoPlaybackException;
|
import com.google.android.exoplayer2.ExoPlaybackException;
|
||||||
@ -43,7 +42,6 @@ import com.google.android.exoplayer2.mediacodec.MediaCodecUtil;
|
|||||||
import com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException;
|
import com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException;
|
||||||
import com.google.android.exoplayer2.mediacodec.MediaFormatUtil;
|
import com.google.android.exoplayer2.mediacodec.MediaFormatUtil;
|
||||||
import com.google.android.exoplayer2.source.MediaSource;
|
import com.google.android.exoplayer2.source.MediaSource;
|
||||||
import com.google.android.exoplayer2.util.Log;
|
|
||||||
import com.google.android.exoplayer2.util.MediaClock;
|
import com.google.android.exoplayer2.util.MediaClock;
|
||||||
import com.google.android.exoplayer2.util.MimeTypes;
|
import com.google.android.exoplayer2.util.MimeTypes;
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
@ -71,13 +69,6 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public class MediaCodecAudioRenderer extends MediaCodecRenderer implements MediaClock {
|
public class MediaCodecAudioRenderer extends MediaCodecRenderer implements MediaClock {
|
||||||
|
|
||||||
/**
|
|
||||||
* Maximum number of tracked pending stream change times. Generally there is zero or one pending
|
|
||||||
* stream change. We track more to allow for pending changes that have fewer samples than the
|
|
||||||
* codec latency.
|
|
||||||
*/
|
|
||||||
private static final int MAX_PENDING_STREAM_CHANGE_COUNT = 10;
|
|
||||||
|
|
||||||
private static final String TAG = "MediaCodecAudioRenderer";
|
private static final String TAG = "MediaCodecAudioRenderer";
|
||||||
/**
|
/**
|
||||||
* Custom key used to indicate bits per sample by some decoders on Vivo devices. For example
|
* Custom key used to indicate bits per sample by some decoders on Vivo devices. For example
|
||||||
@ -88,7 +79,6 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
|||||||
private final Context context;
|
private final Context context;
|
||||||
private final EventDispatcher eventDispatcher;
|
private final EventDispatcher eventDispatcher;
|
||||||
private final AudioSink audioSink;
|
private final AudioSink audioSink;
|
||||||
private final long[] pendingStreamChangeTimesUs;
|
|
||||||
|
|
||||||
private int codecMaxInputSize;
|
private int codecMaxInputSize;
|
||||||
private boolean passthroughEnabled;
|
private boolean passthroughEnabled;
|
||||||
@ -99,8 +89,6 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
|||||||
private long currentPositionUs;
|
private long currentPositionUs;
|
||||||
private boolean allowFirstBufferPositionDiscontinuity;
|
private boolean allowFirstBufferPositionDiscontinuity;
|
||||||
private boolean allowPositionDiscontinuity;
|
private boolean allowPositionDiscontinuity;
|
||||||
private long lastInputTimeUs;
|
|
||||||
private int pendingStreamChangeCount;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param context A context.
|
* @param context A context.
|
||||||
@ -354,8 +342,6 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
|||||||
/* assumedMinimumCodecOperatingRate= */ 44100);
|
/* assumedMinimumCodecOperatingRate= */ 44100);
|
||||||
this.context = context.getApplicationContext();
|
this.context = context.getApplicationContext();
|
||||||
this.audioSink = audioSink;
|
this.audioSink = audioSink;
|
||||||
lastInputTimeUs = C.TIME_UNSET;
|
|
||||||
pendingStreamChangeTimesUs = new long[MAX_PENDING_STREAM_CHANGE_COUNT];
|
|
||||||
eventDispatcher = new EventDispatcher(eventHandler, eventListener);
|
eventDispatcher = new EventDispatcher(eventHandler, eventListener);
|
||||||
audioSink.setListener(new AudioSinkListener());
|
audioSink.setListener(new AudioSinkListener());
|
||||||
}
|
}
|
||||||
@ -666,22 +652,6 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onStreamChanged(Format[] formats, long offsetUs) throws ExoPlaybackException {
|
|
||||||
super.onStreamChanged(formats, offsetUs);
|
|
||||||
if (lastInputTimeUs != C.TIME_UNSET) {
|
|
||||||
if (pendingStreamChangeCount == pendingStreamChangeTimesUs.length) {
|
|
||||||
Log.w(
|
|
||||||
TAG,
|
|
||||||
"Too many stream changes, so dropping change at "
|
|
||||||
+ pendingStreamChangeTimesUs[pendingStreamChangeCount - 1]);
|
|
||||||
} else {
|
|
||||||
pendingStreamChangeCount++;
|
|
||||||
}
|
|
||||||
pendingStreamChangeTimesUs[pendingStreamChangeCount - 1] = lastInputTimeUs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPositionReset(long positionUs, boolean joining) throws ExoPlaybackException {
|
protected void onPositionReset(long positionUs, boolean joining) throws ExoPlaybackException {
|
||||||
super.onPositionReset(positionUs, joining);
|
super.onPositionReset(positionUs, joining);
|
||||||
@ -689,8 +659,6 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
|||||||
currentPositionUs = positionUs;
|
currentPositionUs = positionUs;
|
||||||
allowFirstBufferPositionDiscontinuity = true;
|
allowFirstBufferPositionDiscontinuity = true;
|
||||||
allowPositionDiscontinuity = true;
|
allowPositionDiscontinuity = true;
|
||||||
lastInputTimeUs = C.TIME_UNSET;
|
|
||||||
pendingStreamChangeCount = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -709,8 +677,6 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
|||||||
@Override
|
@Override
|
||||||
protected void onDisabled() {
|
protected void onDisabled() {
|
||||||
try {
|
try {
|
||||||
lastInputTimeUs = C.TIME_UNSET;
|
|
||||||
pendingStreamChangeCount = 0;
|
|
||||||
audioSink.flush();
|
audioSink.flush();
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
@ -769,22 +735,12 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
|||||||
}
|
}
|
||||||
allowFirstBufferPositionDiscontinuity = false;
|
allowFirstBufferPositionDiscontinuity = false;
|
||||||
}
|
}
|
||||||
lastInputTimeUs = Math.max(buffer.timeUs, lastInputTimeUs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@CallSuper
|
|
||||||
@Override
|
@Override
|
||||||
protected void onProcessedOutputBuffer(long presentationTimeUs) {
|
protected void onProcessedStreamChange() {
|
||||||
while (pendingStreamChangeCount != 0 && presentationTimeUs >= pendingStreamChangeTimesUs[0]) {
|
super.onProcessedStreamChange();
|
||||||
audioSink.handleDiscontinuity();
|
audioSink.handleDiscontinuity();
|
||||||
pendingStreamChangeCount--;
|
|
||||||
System.arraycopy(
|
|
||||||
pendingStreamChangeTimesUs,
|
|
||||||
/* srcPos= */ 1,
|
|
||||||
pendingStreamChangeTimesUs,
|
|
||||||
/* destPos= */ 0,
|
|
||||||
pendingStreamChangeCount);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -803,8 +759,8 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
|||||||
if (codecNeedsEosBufferTimestampWorkaround
|
if (codecNeedsEosBufferTimestampWorkaround
|
||||||
&& bufferPresentationTimeUs == 0
|
&& bufferPresentationTimeUs == 0
|
||||||
&& (bufferFlags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0
|
&& (bufferFlags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0
|
||||||
&& lastInputTimeUs != C.TIME_UNSET) {
|
&& getLargestQueuedPresentationTimeUs() != C.TIME_UNSET) {
|
||||||
bufferPresentationTimeUs = lastInputTimeUs;
|
bufferPresentationTimeUs = getLargestQueuedPresentationTimeUs();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (passthroughEnabled && (bufferFlags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
|
if (passthroughEnabled && (bufferFlags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
|
||||||
|
@ -262,6 +262,10 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||||||
*/
|
*/
|
||||||
private static final long MAX_CODEC_HOTSWAP_TIME_MS = 1000;
|
private static final long MAX_CODEC_HOTSWAP_TIME_MS = 1000;
|
||||||
|
|
||||||
|
// Generally there is zero or one pending output stream offset. We track more offsets to allow for
|
||||||
|
// pending output streams that have fewer frames than the codec latency.
|
||||||
|
private static final int MAX_PENDING_OUTPUT_STREAM_OFFSET_COUNT = 10;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The possible return values for {@link #canKeepCodec(MediaCodec, MediaCodecInfo, Format,
|
* The possible return values for {@link #canKeepCodec(MediaCodec, MediaCodecInfo, Format,
|
||||||
* Format)}.
|
* Format)}.
|
||||||
@ -384,6 +388,8 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||||||
private final TimedValueQueue<Format> formatQueue;
|
private final TimedValueQueue<Format> formatQueue;
|
||||||
private final ArrayList<Long> decodeOnlyPresentationTimestamps;
|
private final ArrayList<Long> decodeOnlyPresentationTimestamps;
|
||||||
private final MediaCodec.BufferInfo outputBufferInfo;
|
private final MediaCodec.BufferInfo outputBufferInfo;
|
||||||
|
private final long[] pendingOutputStreamOffsetsUs;
|
||||||
|
private final long[] pendingOutputStreamSwitchTimesUs;
|
||||||
|
|
||||||
private boolean drmResourcesAcquired;
|
private boolean drmResourcesAcquired;
|
||||||
@Nullable private Format inputFormat;
|
@Nullable private Format inputFormat;
|
||||||
@ -435,6 +441,8 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||||||
private boolean pendingOutputEndOfStream;
|
private boolean pendingOutputEndOfStream;
|
||||||
@MediaCodecOperationMode private int mediaCodecOperationMode;
|
@MediaCodecOperationMode private int mediaCodecOperationMode;
|
||||||
protected DecoderCounters decoderCounters;
|
protected DecoderCounters decoderCounters;
|
||||||
|
private long outputStreamOffsetUs;
|
||||||
|
private int pendingOutputStreamOffsetCount;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param trackType The track type that the renderer handles. One of the {@code C.TRACK_TYPE_*}
|
* @param trackType The track type that the renderer handles. One of the {@code C.TRACK_TYPE_*}
|
||||||
@ -475,6 +483,9 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||||||
rendererOperatingRate = 1f;
|
rendererOperatingRate = 1f;
|
||||||
renderTimeLimitMs = C.TIME_UNSET;
|
renderTimeLimitMs = C.TIME_UNSET;
|
||||||
mediaCodecOperationMode = OPERATION_MODE_SYNCHRONOUS;
|
mediaCodecOperationMode = OPERATION_MODE_SYNCHRONOUS;
|
||||||
|
pendingOutputStreamOffsetsUs = new long[MAX_PENDING_OUTPUT_STREAM_OFFSET_COUNT];
|
||||||
|
pendingOutputStreamSwitchTimesUs = new long[MAX_PENDING_OUTPUT_STREAM_OFFSET_COUNT];
|
||||||
|
outputStreamOffsetUs = C.TIME_UNSET;
|
||||||
resetCodecStateForRelease();
|
resetCodecStateForRelease();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -687,6 +698,25 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||||||
decoderCounters = new DecoderCounters();
|
decoderCounters = new DecoderCounters();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onStreamChanged(Format[] formats, long offsetUs) throws ExoPlaybackException {
|
||||||
|
if (outputStreamOffsetUs == C.TIME_UNSET) {
|
||||||
|
outputStreamOffsetUs = offsetUs;
|
||||||
|
} else {
|
||||||
|
if (pendingOutputStreamOffsetCount == pendingOutputStreamOffsetsUs.length) {
|
||||||
|
Log.w(
|
||||||
|
TAG,
|
||||||
|
"Too many stream changes, so dropping offset: "
|
||||||
|
+ pendingOutputStreamOffsetsUs[pendingOutputStreamOffsetCount - 1]);
|
||||||
|
} else {
|
||||||
|
pendingOutputStreamOffsetCount++;
|
||||||
|
}
|
||||||
|
pendingOutputStreamOffsetsUs[pendingOutputStreamOffsetCount - 1] = offsetUs;
|
||||||
|
pendingOutputStreamSwitchTimesUs[pendingOutputStreamOffsetCount - 1] =
|
||||||
|
largestQueuedPresentationTimeUs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPositionReset(long positionUs, boolean joining) throws ExoPlaybackException {
|
protected void onPositionReset(long positionUs, boolean joining) throws ExoPlaybackException {
|
||||||
inputStreamEnded = false;
|
inputStreamEnded = false;
|
||||||
@ -700,6 +730,10 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||||||
waitingForFirstSampleInFormat = true;
|
waitingForFirstSampleInFormat = true;
|
||||||
}
|
}
|
||||||
formatQueue.clear();
|
formatQueue.clear();
|
||||||
|
if (pendingOutputStreamOffsetCount != 0) {
|
||||||
|
outputStreamOffsetUs = pendingOutputStreamOffsetsUs[pendingOutputStreamOffsetCount - 1];
|
||||||
|
pendingOutputStreamOffsetCount = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -715,6 +749,8 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||||||
@Override
|
@Override
|
||||||
protected void onDisabled() {
|
protected void onDisabled() {
|
||||||
inputFormat = null;
|
inputFormat = null;
|
||||||
|
outputStreamOffsetUs = C.TIME_UNSET;
|
||||||
|
pendingOutputStreamOffsetCount = 0;
|
||||||
if (sourceDrmSession != null || codecDrmSession != null) {
|
if (sourceDrmSession != null || codecDrmSession != null) {
|
||||||
// TODO: Do something better with this case.
|
// TODO: Do something better with this case.
|
||||||
onReset();
|
onReset();
|
||||||
@ -1473,12 +1509,33 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when an output buffer is successfully processed.
|
* Called when an output buffer is successfully processed.
|
||||||
* <p>
|
|
||||||
* The default implementation is a no-op.
|
|
||||||
*
|
*
|
||||||
* @param presentationTimeUs The timestamp associated with the output buffer.
|
* @param presentationTimeUs The timestamp associated with the output buffer.
|
||||||
*/
|
*/
|
||||||
|
@CallSuper
|
||||||
protected void onProcessedOutputBuffer(long presentationTimeUs) {
|
protected void onProcessedOutputBuffer(long presentationTimeUs) {
|
||||||
|
while (pendingOutputStreamOffsetCount != 0
|
||||||
|
&& presentationTimeUs >= pendingOutputStreamSwitchTimesUs[0]) {
|
||||||
|
outputStreamOffsetUs = pendingOutputStreamOffsetsUs[0];
|
||||||
|
pendingOutputStreamOffsetCount--;
|
||||||
|
System.arraycopy(
|
||||||
|
pendingOutputStreamOffsetsUs,
|
||||||
|
/* srcPos= */ 1,
|
||||||
|
pendingOutputStreamOffsetsUs,
|
||||||
|
/* destPos= */ 0,
|
||||||
|
pendingOutputStreamOffsetCount);
|
||||||
|
System.arraycopy(
|
||||||
|
pendingOutputStreamSwitchTimesUs,
|
||||||
|
/* srcPos= */ 1,
|
||||||
|
pendingOutputStreamSwitchTimesUs,
|
||||||
|
/* destPos= */ 0,
|
||||||
|
pendingOutputStreamOffsetCount);
|
||||||
|
onProcessedStreamChange();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Called after the last output buffer before a stream change has been processed. */
|
||||||
|
protected void onProcessedStreamChange() {
|
||||||
// Do nothing.
|
// Do nothing.
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1833,6 +1890,20 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||||||
pendingOutputEndOfStream = true;
|
pendingOutputEndOfStream = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Returns the largest queued input presentation time, in microseconds. */
|
||||||
|
protected final long getLargestQueuedPresentationTimeUs() {
|
||||||
|
return largestQueuedPresentationTimeUs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the offset that should be subtracted from {@code bufferPresentationTimeUs} in {@link
|
||||||
|
* #processOutputBuffer(long, long, MediaCodec, ByteBuffer, int, int, long, boolean, boolean,
|
||||||
|
* Format)} to get the playback position with respect to the media.
|
||||||
|
*/
|
||||||
|
protected final long getOutputStreamOffsetUs() {
|
||||||
|
return outputStreamOffsetUs;
|
||||||
|
}
|
||||||
|
|
||||||
private void reinitializeCodec() throws ExoPlaybackException {
|
private void reinitializeCodec() throws ExoPlaybackException {
|
||||||
releaseCodec();
|
releaseCodec();
|
||||||
maybeInitCodec();
|
maybeInitCodec();
|
||||||
|
@ -87,9 +87,6 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
|||||||
private static final int[] STANDARD_LONG_EDGE_VIDEO_PX = new int[] {
|
private static final int[] STANDARD_LONG_EDGE_VIDEO_PX = new int[] {
|
||||||
1920, 1600, 1440, 1280, 960, 854, 640, 540, 480};
|
1920, 1600, 1440, 1280, 960, 854, 640, 540, 480};
|
||||||
|
|
||||||
// Generally there is zero or one pending output stream offset. We track more offsets to allow for
|
|
||||||
// pending output streams that have fewer frames than the codec latency.
|
|
||||||
private static final int MAX_PENDING_OUTPUT_STREAM_OFFSET_COUNT = 10;
|
|
||||||
/**
|
/**
|
||||||
* Scale factor for the initial maximum input size used to configure the codec in non-adaptive
|
* Scale factor for the initial maximum input size used to configure the codec in non-adaptive
|
||||||
* playbacks. See {@link #getCodecMaxValues(MediaCodecInfo, Format, Format[])}.
|
* playbacks. See {@link #getCodecMaxValues(MediaCodecInfo, Format, Format[])}.
|
||||||
@ -125,8 +122,6 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
|||||||
private final long allowedJoiningTimeMs;
|
private final long allowedJoiningTimeMs;
|
||||||
private final int maxDroppedFramesToNotify;
|
private final int maxDroppedFramesToNotify;
|
||||||
private final boolean deviceNeedsNoPostProcessWorkaround;
|
private final boolean deviceNeedsNoPostProcessWorkaround;
|
||||||
private final long[] pendingOutputStreamOffsetsUs;
|
|
||||||
private final long[] pendingOutputStreamSwitchTimesUs;
|
|
||||||
|
|
||||||
private CodecMaxValues codecMaxValues;
|
private CodecMaxValues codecMaxValues;
|
||||||
private boolean codecNeedsSetOutputSurfaceWorkaround;
|
private boolean codecNeedsSetOutputSurfaceWorkaround;
|
||||||
@ -159,10 +154,6 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
|||||||
private boolean tunneling;
|
private boolean tunneling;
|
||||||
private int tunnelingAudioSessionId;
|
private int tunnelingAudioSessionId;
|
||||||
/* package */ @Nullable OnFrameRenderedListenerV23 tunnelingOnFrameRenderedListener;
|
/* package */ @Nullable OnFrameRenderedListenerV23 tunnelingOnFrameRenderedListener;
|
||||||
|
|
||||||
private long lastInputTimeUs;
|
|
||||||
private long outputStreamOffsetUs;
|
|
||||||
private int pendingOutputStreamOffsetCount;
|
|
||||||
@Nullable private VideoFrameMetadataListener frameMetadataListener;
|
@Nullable private VideoFrameMetadataListener frameMetadataListener;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -347,10 +338,6 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
|||||||
frameReleaseTimeHelper = new VideoFrameReleaseTimeHelper(this.context);
|
frameReleaseTimeHelper = new VideoFrameReleaseTimeHelper(this.context);
|
||||||
eventDispatcher = new EventDispatcher(eventHandler, eventListener);
|
eventDispatcher = new EventDispatcher(eventHandler, eventListener);
|
||||||
deviceNeedsNoPostProcessWorkaround = deviceNeedsNoPostProcessWorkaround();
|
deviceNeedsNoPostProcessWorkaround = deviceNeedsNoPostProcessWorkaround();
|
||||||
pendingOutputStreamOffsetsUs = new long[MAX_PENDING_OUTPUT_STREAM_OFFSET_COUNT];
|
|
||||||
pendingOutputStreamSwitchTimesUs = new long[MAX_PENDING_OUTPUT_STREAM_OFFSET_COUNT];
|
|
||||||
outputStreamOffsetUs = C.TIME_UNSET;
|
|
||||||
lastInputTimeUs = C.TIME_UNSET;
|
|
||||||
joiningDeadlineMs = C.TIME_UNSET;
|
joiningDeadlineMs = C.TIME_UNSET;
|
||||||
currentWidth = Format.NO_VALUE;
|
currentWidth = Format.NO_VALUE;
|
||||||
currentHeight = Format.NO_VALUE;
|
currentHeight = Format.NO_VALUE;
|
||||||
@ -484,34 +471,12 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
|||||||
frameReleaseTimeHelper.enable();
|
frameReleaseTimeHelper.enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onStreamChanged(Format[] formats, long offsetUs) throws ExoPlaybackException {
|
|
||||||
if (outputStreamOffsetUs == C.TIME_UNSET) {
|
|
||||||
outputStreamOffsetUs = offsetUs;
|
|
||||||
} else {
|
|
||||||
if (pendingOutputStreamOffsetCount == pendingOutputStreamOffsetsUs.length) {
|
|
||||||
Log.w(TAG, "Too many stream changes, so dropping offset: "
|
|
||||||
+ pendingOutputStreamOffsetsUs[pendingOutputStreamOffsetCount - 1]);
|
|
||||||
} else {
|
|
||||||
pendingOutputStreamOffsetCount++;
|
|
||||||
}
|
|
||||||
pendingOutputStreamOffsetsUs[pendingOutputStreamOffsetCount - 1] = offsetUs;
|
|
||||||
pendingOutputStreamSwitchTimesUs[pendingOutputStreamOffsetCount - 1] = lastInputTimeUs;
|
|
||||||
}
|
|
||||||
super.onStreamChanged(formats, offsetUs);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPositionReset(long positionUs, boolean joining) throws ExoPlaybackException {
|
protected void onPositionReset(long positionUs, boolean joining) throws ExoPlaybackException {
|
||||||
super.onPositionReset(positionUs, joining);
|
super.onPositionReset(positionUs, joining);
|
||||||
clearRenderedFirstFrame();
|
clearRenderedFirstFrame();
|
||||||
initialPositionUs = C.TIME_UNSET;
|
initialPositionUs = C.TIME_UNSET;
|
||||||
consecutiveDroppedFrameCount = 0;
|
consecutiveDroppedFrameCount = 0;
|
||||||
lastInputTimeUs = C.TIME_UNSET;
|
|
||||||
if (pendingOutputStreamOffsetCount != 0) {
|
|
||||||
outputStreamOffsetUs = pendingOutputStreamOffsetsUs[pendingOutputStreamOffsetCount - 1];
|
|
||||||
pendingOutputStreamOffsetCount = 0;
|
|
||||||
}
|
|
||||||
if (joining) {
|
if (joining) {
|
||||||
setJoiningDeadlineMs();
|
setJoiningDeadlineMs();
|
||||||
} else {
|
} else {
|
||||||
@ -556,9 +521,6 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDisabled() {
|
protected void onDisabled() {
|
||||||
lastInputTimeUs = C.TIME_UNSET;
|
|
||||||
outputStreamOffsetUs = C.TIME_UNSET;
|
|
||||||
pendingOutputStreamOffsetCount = 0;
|
|
||||||
currentMediaFormat = null;
|
currentMediaFormat = null;
|
||||||
clearReportedVideoSize();
|
clearReportedVideoSize();
|
||||||
clearRenderedFirstFrame();
|
clearRenderedFirstFrame();
|
||||||
@ -759,7 +721,6 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
|||||||
if (!tunneling) {
|
if (!tunneling) {
|
||||||
buffersInCodecCount++;
|
buffersInCodecCount++;
|
||||||
}
|
}
|
||||||
lastInputTimeUs = Math.max(buffer.timeUs, lastInputTimeUs);
|
|
||||||
if (Util.SDK_INT < 23 && tunneling) {
|
if (Util.SDK_INT < 23 && tunneling) {
|
||||||
// In tunneled mode before API 23 we don't have a way to know when the buffer is output, so
|
// In tunneled mode before API 23 we don't have a way to know when the buffer is output, so
|
||||||
// treat it as if it were output immediately.
|
// treat it as if it were output immediately.
|
||||||
@ -838,6 +799,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
|||||||
initialPositionUs = positionUs;
|
initialPositionUs = positionUs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
long outputStreamOffsetUs = getOutputStreamOffsetUs();
|
||||||
long presentationTimeUs = bufferPresentationTimeUs - outputStreamOffsetUs;
|
long presentationTimeUs = bufferPresentationTimeUs - outputStreamOffsetUs;
|
||||||
|
|
||||||
if (isDecodeOnlyBuffer && !isLastBuffer) {
|
if (isDecodeOnlyBuffer && !isLastBuffer) {
|
||||||
@ -970,15 +932,6 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the offset that should be subtracted from {@code bufferPresentationTimeUs} in {@link
|
|
||||||
* #processOutputBuffer(long, long, MediaCodec, ByteBuffer, int, int, long, boolean, boolean,
|
|
||||||
* Format)} to get the playback position with respect to the media.
|
|
||||||
*/
|
|
||||||
protected long getOutputStreamOffsetUs() {
|
|
||||||
return outputStreamOffsetUs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Called when a buffer was processed in tunneling mode. */
|
/** Called when a buffer was processed in tunneling mode. */
|
||||||
protected void onProcessedTunneledBuffer(long presentationTimeUs) {
|
protected void onProcessedTunneledBuffer(long presentationTimeUs) {
|
||||||
@Nullable Format format = updateOutputFormatForTime(presentationTimeUs);
|
@Nullable Format format = updateOutputFormatForTime(presentationTimeUs);
|
||||||
@ -995,35 +948,19 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
|||||||
setPendingOutputEndOfStream();
|
setPendingOutputEndOfStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when an output buffer is successfully processed.
|
|
||||||
*
|
|
||||||
* @param presentationTimeUs The timestamp associated with the output buffer.
|
|
||||||
*/
|
|
||||||
@CallSuper
|
@CallSuper
|
||||||
@Override
|
@Override
|
||||||
protected void onProcessedOutputBuffer(long presentationTimeUs) {
|
protected void onProcessedOutputBuffer(long presentationTimeUs) {
|
||||||
|
super.onProcessedOutputBuffer(presentationTimeUs);
|
||||||
if (!tunneling) {
|
if (!tunneling) {
|
||||||
buffersInCodecCount--;
|
buffersInCodecCount--;
|
||||||
}
|
}
|
||||||
while (pendingOutputStreamOffsetCount != 0
|
}
|
||||||
&& presentationTimeUs >= pendingOutputStreamSwitchTimesUs[0]) {
|
|
||||||
outputStreamOffsetUs = pendingOutputStreamOffsetsUs[0];
|
@Override
|
||||||
pendingOutputStreamOffsetCount--;
|
protected void onProcessedStreamChange() {
|
||||||
System.arraycopy(
|
super.onProcessedStreamChange();
|
||||||
pendingOutputStreamOffsetsUs,
|
clearRenderedFirstFrame();
|
||||||
/* srcPos= */ 1,
|
|
||||||
pendingOutputStreamOffsetsUs,
|
|
||||||
/* destPos= */ 0,
|
|
||||||
pendingOutputStreamOffsetCount);
|
|
||||||
System.arraycopy(
|
|
||||||
pendingOutputStreamSwitchTimesUs,
|
|
||||||
/* srcPos= */ 1,
|
|
||||||
pendingOutputStreamSwitchTimesUs,
|
|
||||||
/* destPos= */ 0,
|
|
||||||
pendingOutputStreamOffsetCount);
|
|
||||||
clearRenderedFirstFrame();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user