Skip to content

Commit

Permalink
Use ArrayDeque for pending output stream changes.
Browse files Browse the repository at this point in the history
The current logic uses manual array operations to keep track of pending
changes. Modernize this code by using an ArrayDeque and a data class.
This also allows to extend the output stream information in the future.

This also fixes a bug where a position reset accidentally assigns a pending
stream offset instead of keeping the current one.

PiperOrigin-RevId: 511787571
(cherry picked from commit f042012)
  • Loading branch information
tonihei committed Feb 28, 2023
1 parent 58a977e commit 5ab4223
Showing 1 changed file with 42 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -208,10 +208,6 @@ private static String buildCustomDiagnosticInfo(int errorCode) {
*/
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;

@Documented
@Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
Expand Down Expand Up @@ -306,9 +302,7 @@ private static String buildCustomDiagnosticInfo(int errorCode) {
private final TimedValueQueue<Format> formatQueue;
private final ArrayList<Long> decodeOnlyPresentationTimestamps;
private final MediaCodec.BufferInfo outputBufferInfo;
private final long[] pendingOutputStreamStartPositionsUs;
private final long[] pendingOutputStreamOffsetsUs;
private final long[] pendingOutputStreamSwitchTimesUs;
private final ArrayDeque<OutputStreamInfo> pendingOutputStreamChanges;

@Nullable private Format inputFormat;
@Nullable private Format outputFormat;
Expand Down Expand Up @@ -363,9 +357,7 @@ private static String buildCustomDiagnosticInfo(int errorCode) {
private boolean pendingOutputEndOfStream;
@Nullable private ExoPlaybackException pendingPlaybackException;
protected DecoderCounters decoderCounters;
private long outputStreamStartPositionUs;
private long outputStreamOffsetUs;
private int pendingOutputStreamOffsetCount;
private OutputStreamInfo outputStreamInfo;

/**
* @param trackType The {@link C.TrackType track type} that the renderer handles.
Expand Down Expand Up @@ -398,11 +390,8 @@ public MediaCodecRenderer(
currentPlaybackSpeed = 1f;
targetPlaybackSpeed = 1f;
renderTimeLimitMs = C.TIME_UNSET;
pendingOutputStreamStartPositionsUs = new long[MAX_PENDING_OUTPUT_STREAM_OFFSET_COUNT];
pendingOutputStreamOffsetsUs = new long[MAX_PENDING_OUTPUT_STREAM_OFFSET_COUNT];
pendingOutputStreamSwitchTimesUs = new long[MAX_PENDING_OUTPUT_STREAM_OFFSET_COUNT];
outputStreamStartPositionUs = C.TIME_UNSET;
setOutputStreamOffsetUs(C.TIME_UNSET);
pendingOutputStreamChanges = new ArrayDeque<>();
setOutputStreamInfo(OutputStreamInfo.UNSET);
// MediaCodec outputs audio buffers in native endian:
// https://developer.android.com/reference/android/media/MediaCodec#raw-audio-buffers
// and code called from MediaCodecAudioRenderer.processOutputBuffer expects this endianness.
Expand Down Expand Up @@ -648,23 +637,14 @@ protected void onEnabled(boolean joining, boolean mayRenderStartOfStream)
@Override
protected void onStreamChanged(Format[] formats, long startPositionUs, long offsetUs)
throws ExoPlaybackException {
if (this.outputStreamOffsetUs == C.TIME_UNSET) {
checkState(this.outputStreamStartPositionUs == C.TIME_UNSET);
this.outputStreamStartPositionUs = startPositionUs;
setOutputStreamOffsetUs(offsetUs);
if (outputStreamInfo.streamOffsetUs == C.TIME_UNSET) {
checkState(outputStreamInfo.startPositionUs == C.TIME_UNSET);
setOutputStreamInfo(
new OutputStreamInfo(
/* previousStreamLastBufferTimeUs= */ C.TIME_UNSET, startPositionUs, offsetUs));
} else {
if (pendingOutputStreamOffsetCount == pendingOutputStreamOffsetsUs.length) {
Log.w(
TAG,
"Too many stream changes, so dropping offset: "
+ pendingOutputStreamOffsetsUs[pendingOutputStreamOffsetCount - 1]);
} else {
pendingOutputStreamOffsetCount++;
}
pendingOutputStreamStartPositionsUs[pendingOutputStreamOffsetCount - 1] = startPositionUs;
pendingOutputStreamOffsetsUs[pendingOutputStreamOffsetCount - 1] = offsetUs;
pendingOutputStreamSwitchTimesUs[pendingOutputStreamOffsetCount - 1] =
largestQueuedPresentationTimeUs;
pendingOutputStreamChanges.add(
new OutputStreamInfo(largestQueuedPresentationTimeUs, startPositionUs, offsetUs));
}
}

Expand All @@ -687,12 +667,7 @@ protected void onPositionReset(long positionUs, boolean joining) throws ExoPlayb
waitingForFirstSampleInFormat = true;
}
formatQueue.clear();
if (pendingOutputStreamOffsetCount != 0) {
setOutputStreamOffsetUs(pendingOutputStreamOffsetsUs[pendingOutputStreamOffsetCount - 1]);
outputStreamStartPositionUs =
pendingOutputStreamStartPositionsUs[pendingOutputStreamOffsetCount - 1];
pendingOutputStreamOffsetCount = 0;
}
pendingOutputStreamChanges.clear();
}

@Override
Expand All @@ -706,9 +681,8 @@ public void setPlaybackSpeed(float currentPlaybackSpeed, float targetPlaybackSpe
@Override
protected void onDisabled() {
inputFormat = null;
outputStreamStartPositionUs = C.TIME_UNSET;
setOutputStreamOffsetUs(C.TIME_UNSET);
pendingOutputStreamOffsetCount = 0;
setOutputStreamInfo(OutputStreamInfo.UNSET);
pendingOutputStreamChanges.clear();
flushOrReleaseCodec();
}

Expand Down Expand Up @@ -1593,29 +1567,9 @@ protected void onQueueInputBuffer(DecoderInputBuffer buffer) throws ExoPlaybackE
*/
@CallSuper
protected void onProcessedOutputBuffer(long presentationTimeUs) {
while (pendingOutputStreamOffsetCount != 0
&& presentationTimeUs >= pendingOutputStreamSwitchTimesUs[0]) {
outputStreamStartPositionUs = pendingOutputStreamStartPositionsUs[0];
setOutputStreamOffsetUs(pendingOutputStreamOffsetsUs[0]);
pendingOutputStreamOffsetCount--;
System.arraycopy(
pendingOutputStreamStartPositionsUs,
/* srcPos= */ 1,
pendingOutputStreamStartPositionsUs,
/* destPos= */ 0,
pendingOutputStreamOffsetCount);
System.arraycopy(
pendingOutputStreamOffsetsUs,
/* srcPos= */ 1,
pendingOutputStreamOffsetsUs,
/* destPos= */ 0,
pendingOutputStreamOffsetCount);
System.arraycopy(
pendingOutputStreamSwitchTimesUs,
/* srcPos= */ 1,
pendingOutputStreamSwitchTimesUs,
/* destPos= */ 0,
pendingOutputStreamOffsetCount);
if (!pendingOutputStreamChanges.isEmpty()
&& presentationTimeUs >= pendingOutputStreamChanges.peek().previousStreamLastBufferTimeUs) {
setOutputStreamInfo(pendingOutputStreamChanges.poll());
onProcessedStreamChange();
}
}
Expand Down Expand Up @@ -2062,13 +2016,13 @@ protected final void setPendingOutputEndOfStream() {
* boolean, Format)} to get the playback position with respect to the media.
*/
protected final long getOutputStreamOffsetUs() {
return outputStreamOffsetUs;
return outputStreamInfo.streamOffsetUs;
}

private void setOutputStreamOffsetUs(long outputStreamOffsetUs) {
this.outputStreamOffsetUs = outputStreamOffsetUs;
if (outputStreamOffsetUs != C.TIME_UNSET) {
onOutputStreamOffsetUsChanged(outputStreamOffsetUs);
private void setOutputStreamInfo(OutputStreamInfo outputStreamInfo) {
this.outputStreamInfo = outputStreamInfo;
if (outputStreamInfo.streamOffsetUs != C.TIME_UNSET) {
onOutputStreamOffsetUsChanged(outputStreamInfo.streamOffsetUs);
}
}

Expand Down Expand Up @@ -2515,6 +2469,26 @@ private static boolean codecNeedsMonoChannelCountWorkaround(String name, Format
&& "OMX.MTK.AUDIO.DECODER.MP3".equals(name);
}

private static final class OutputStreamInfo {

public static final OutputStreamInfo UNSET =
new OutputStreamInfo(
/* previousStreamLastBufferTimeUs= */ C.TIME_UNSET,
/* startPositionUs= */ C.TIME_UNSET,
/* streamOffsetUs= */ C.TIME_UNSET);

public final long previousStreamLastBufferTimeUs;
public final long startPositionUs;
public final long streamOffsetUs;

public OutputStreamInfo(
long previousStreamLastBufferTimeUs, long startPositionUs, long streamOffsetUs) {
this.previousStreamLastBufferTimeUs = previousStreamLastBufferTimeUs;
this.startPositionUs = startPositionUs;
this.streamOffsetUs = streamOffsetUs;
}
}

@RequiresApi(31)
private static final class Api31 {
private Api31() {}
Expand Down

0 comments on commit 5ab4223

Please sign in to comment.