Keep AudioTrack on seek - experimental.
PiperOrigin-RevId: 326622573
This commit is contained in:
parent
c2ac33af1b
commit
eabc486b58
@ -362,6 +362,18 @@ public interface AudioSink {
|
|||||||
*/
|
*/
|
||||||
void flush();
|
void flush();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flushes the sink, after which it is ready to receive buffers from a new playback position.
|
||||||
|
*
|
||||||
|
* <p>Does not release the {@link AudioTrack} held by the sink.
|
||||||
|
*
|
||||||
|
* <p>This method is experimental, and will be renamed or removed in a future release.
|
||||||
|
*
|
||||||
|
* <p>Only for experimental use as part of {@link
|
||||||
|
* MediaCodecAudioRenderer#experimentalSetEnableKeepAudioTrackOnSeek(boolean)}.
|
||||||
|
*/
|
||||||
|
void experimentalFlushWithoutAudioTrackRelease();
|
||||||
|
|
||||||
/** Resets the renderer, releasing any resources that it currently holds. */
|
/** Resets the renderer, releasing any resources that it currently holds. */
|
||||||
void reset();
|
void reset();
|
||||||
}
|
}
|
||||||
|
@ -112,6 +112,8 @@ public abstract class DecoderAudioRenderer<
|
|||||||
private int encoderDelay;
|
private int encoderDelay;
|
||||||
private int encoderPadding;
|
private int encoderPadding;
|
||||||
|
|
||||||
|
private boolean experimentalKeepAudioTrackOnSeek;
|
||||||
|
|
||||||
@Nullable private T decoder;
|
@Nullable private T decoder;
|
||||||
|
|
||||||
@Nullable private DecoderInputBuffer inputBuffer;
|
@Nullable private DecoderInputBuffer inputBuffer;
|
||||||
@ -185,6 +187,19 @@ public abstract class DecoderAudioRenderer<
|
|||||||
audioTrackNeedsConfigure = true;
|
audioTrackNeedsConfigure = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether to enable the experimental feature that keeps and flushes the {@link
|
||||||
|
* android.media.AudioTrack} when a seek occurs, as opposed to releasing and reinitialising. Off
|
||||||
|
* by default.
|
||||||
|
*
|
||||||
|
* <p>This method is experimental, and will be renamed or removed in a future release.
|
||||||
|
*
|
||||||
|
* @param enableKeepAudioTrackOnSeek Whether to keep the {@link android.media.AudioTrack} on seek.
|
||||||
|
*/
|
||||||
|
public void experimentalSetEnableKeepAudioTrackOnSeek(boolean enableKeepAudioTrackOnSeek) {
|
||||||
|
this.experimentalKeepAudioTrackOnSeek = enableKeepAudioTrackOnSeek;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
public MediaClock getMediaClock() {
|
public MediaClock getMediaClock() {
|
||||||
@ -507,7 +522,12 @@ public abstract class DecoderAudioRenderer<
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPositionReset(long positionUs, boolean joining) throws ExoPlaybackException {
|
protected void onPositionReset(long positionUs, boolean joining) throws ExoPlaybackException {
|
||||||
audioSink.flush();
|
if (experimentalKeepAudioTrackOnSeek) {
|
||||||
|
audioSink.experimentalFlushWithoutAudioTrackRelease();
|
||||||
|
} else {
|
||||||
|
audioSink.flush();
|
||||||
|
}
|
||||||
|
|
||||||
currentPositionUs = positionUs;
|
currentPositionUs = positionUs;
|
||||||
allowFirstBufferPositionDiscontinuity = true;
|
allowFirstBufferPositionDiscontinuity = true;
|
||||||
allowPositionDiscontinuity = true;
|
allowPositionDiscontinuity = true;
|
||||||
|
@ -279,7 +279,9 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
@MonotonicNonNull private StreamEventCallbackV29 offloadStreamEventCallbackV29;
|
@MonotonicNonNull private StreamEventCallbackV29 offloadStreamEventCallbackV29;
|
||||||
|
|
||||||
@Nullable private Listener listener;
|
@Nullable private Listener listener;
|
||||||
/** Used to keep the audio session active on pre-V21 builds (see {@link #initialize(long)}). */
|
/**
|
||||||
|
* Used to keep the audio session active on pre-V21 builds (see {@link #initializeAudioTrack()}).
|
||||||
|
*/
|
||||||
@Nullable private AudioTrack keepSessionIdAudioTrack;
|
@Nullable private AudioTrack keepSessionIdAudioTrack;
|
||||||
|
|
||||||
@Nullable private Configuration pendingConfiguration;
|
@Nullable private Configuration pendingConfiguration;
|
||||||
@ -300,6 +302,7 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
private long writtenEncodedFrames;
|
private long writtenEncodedFrames;
|
||||||
private int framesPerEncodedSample;
|
private int framesPerEncodedSample;
|
||||||
private boolean startMediaTimeUsNeedsSync;
|
private boolean startMediaTimeUsNeedsSync;
|
||||||
|
private boolean startMediaTimeUsNeedsInit;
|
||||||
private long startMediaTimeUs;
|
private long startMediaTimeUs;
|
||||||
private float volume;
|
private float volume;
|
||||||
|
|
||||||
@ -470,7 +473,7 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getCurrentPositionUs(boolean sourceEnded) {
|
public long getCurrentPositionUs(boolean sourceEnded) {
|
||||||
if (!isInitialized()) {
|
if (!isAudioTrackInitialized() || startMediaTimeUsNeedsInit) {
|
||||||
return CURRENT_POSITION_NOT_SET;
|
return CURRENT_POSITION_NOT_SET;
|
||||||
}
|
}
|
||||||
long positionUs = audioTrackPositionTracker.getCurrentPositionUs(sourceEnded);
|
long positionUs = audioTrackPositionTracker.getCurrentPositionUs(sourceEnded);
|
||||||
@ -581,7 +584,7 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
specifiedBufferSize,
|
specifiedBufferSize,
|
||||||
canApplyPlaybackParameters,
|
canApplyPlaybackParameters,
|
||||||
availableAudioProcessors);
|
availableAudioProcessors);
|
||||||
if (isInitialized()) {
|
if (isAudioTrackInitialized()) {
|
||||||
this.pendingConfiguration = pendingConfiguration;
|
this.pendingConfiguration = pendingConfiguration;
|
||||||
} else {
|
} else {
|
||||||
configuration = pendingConfiguration;
|
configuration = pendingConfiguration;
|
||||||
@ -612,7 +615,7 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initialize(long presentationTimeUs) throws InitializationException {
|
private void initializeAudioTrack() throws InitializationException {
|
||||||
// If we're asynchronously releasing a previous audio track then we block until it has been
|
// If we're asynchronously releasing a previous audio track then we block until it has been
|
||||||
// released. This guarantees that we cannot end up in a state where we have multiple audio
|
// released. This guarantees that we cannot end up in a state where we have multiple audio
|
||||||
// track instances. Without this guarantee it would be possible, in extreme cases, to exhaust
|
// track instances. Without this guarantee it would be possible, in extreme cases, to exhaust
|
||||||
@ -647,17 +650,9 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
startMediaTimeUs = max(0, presentationTimeUs);
|
|
||||||
startMediaTimeUsNeedsSync = false;
|
|
||||||
|
|
||||||
if (enableAudioTrackPlaybackParams && Util.SDK_INT >= 23) {
|
|
||||||
setAudioTrackPlaybackSpeedV23(audioTrackPlaybackSpeed);
|
|
||||||
}
|
|
||||||
applyAudioProcessorPlaybackSpeedAndSkipSilence(presentationTimeUs);
|
|
||||||
|
|
||||||
audioTrackPositionTracker.setAudioTrack(
|
audioTrackPositionTracker.setAudioTrack(
|
||||||
audioTrack,
|
audioTrack,
|
||||||
configuration.outputMode == OUTPUT_MODE_PASSTHROUGH,
|
/* isPassthrough= */ configuration.outputMode == OUTPUT_MODE_PASSTHROUGH,
|
||||||
configuration.outputEncoding,
|
configuration.outputEncoding,
|
||||||
configuration.outputPcmFrameSize,
|
configuration.outputPcmFrameSize,
|
||||||
configuration.bufferSize);
|
configuration.bufferSize);
|
||||||
@ -667,12 +662,14 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
audioTrack.attachAuxEffect(auxEffectInfo.effectId);
|
audioTrack.attachAuxEffect(auxEffectInfo.effectId);
|
||||||
audioTrack.setAuxEffectSendLevel(auxEffectInfo.sendLevel);
|
audioTrack.setAuxEffectSendLevel(auxEffectInfo.sendLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
startMediaTimeUsNeedsInit = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void play() {
|
public void play() {
|
||||||
playing = true;
|
playing = true;
|
||||||
if (isInitialized()) {
|
if (isAudioTrackInitialized()) {
|
||||||
audioTrackPositionTracker.start();
|
audioTrackPositionTracker.start();
|
||||||
audioTrack.play();
|
audioTrack.play();
|
||||||
}
|
}
|
||||||
@ -716,8 +713,20 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
applyAudioProcessorPlaybackSpeedAndSkipSilence(presentationTimeUs);
|
applyAudioProcessorPlaybackSpeedAndSkipSilence(presentationTimeUs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isInitialized()) {
|
if (!isAudioTrackInitialized()) {
|
||||||
initialize(presentationTimeUs);
|
initializeAudioTrack();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (startMediaTimeUsNeedsInit) {
|
||||||
|
startMediaTimeUs = max(0, presentationTimeUs);
|
||||||
|
startMediaTimeUsNeedsSync = false;
|
||||||
|
startMediaTimeUsNeedsInit = false;
|
||||||
|
|
||||||
|
if (enableAudioTrackPlaybackParams && Util.SDK_INT >= 23) {
|
||||||
|
setAudioTrackPlaybackSpeedV23(audioTrackPlaybackSpeed);
|
||||||
|
}
|
||||||
|
applyAudioProcessorPlaybackSpeedAndSkipSilence(presentationTimeUs);
|
||||||
|
|
||||||
if (playing) {
|
if (playing) {
|
||||||
play();
|
play();
|
||||||
}
|
}
|
||||||
@ -945,7 +954,7 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void playToEndOfStream() throws WriteException {
|
public void playToEndOfStream() throws WriteException {
|
||||||
if (!handledEndOfStream && isInitialized() && drainToEndOfStream()) {
|
if (!handledEndOfStream && isAudioTrackInitialized() && drainToEndOfStream()) {
|
||||||
playPendingData();
|
playPendingData();
|
||||||
handledEndOfStream = true;
|
handledEndOfStream = true;
|
||||||
}
|
}
|
||||||
@ -987,12 +996,13 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isEnded() {
|
public boolean isEnded() {
|
||||||
return !isInitialized() || (handledEndOfStream && !hasPendingData());
|
return !isAudioTrackInitialized() || (handledEndOfStream && !hasPendingData());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasPendingData() {
|
public boolean hasPendingData() {
|
||||||
return isInitialized() && audioTrackPositionTracker.hasPendingData(getWrittenFrames());
|
return isAudioTrackInitialized()
|
||||||
|
&& audioTrackPositionTracker.hasPendingData(getWrittenFrames());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -1090,7 +1100,7 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setVolumeInternal() {
|
private void setVolumeInternal() {
|
||||||
if (!isInitialized()) {
|
if (!isAudioTrackInitialized()) {
|
||||||
// Do nothing.
|
// Do nothing.
|
||||||
} else if (Util.SDK_INT >= 21) {
|
} else if (Util.SDK_INT >= 21) {
|
||||||
setVolumeInternalV21(audioTrack, volume);
|
setVolumeInternalV21(audioTrack, volume);
|
||||||
@ -1102,14 +1112,14 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
@Override
|
@Override
|
||||||
public void pause() {
|
public void pause() {
|
||||||
playing = false;
|
playing = false;
|
||||||
if (isInitialized() && audioTrackPositionTracker.pause()) {
|
if (isAudioTrackInitialized() && audioTrackPositionTracker.pause()) {
|
||||||
audioTrack.pause();
|
audioTrack.pause();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void flush() {
|
public void flush() {
|
||||||
if (isInitialized()) {
|
if (isAudioTrackInitialized()) {
|
||||||
resetSinkStateForFlush();
|
resetSinkStateForFlush();
|
||||||
|
|
||||||
if (audioTrackPositionTracker.isPlaying()) {
|
if (audioTrackPositionTracker.isPlaying()) {
|
||||||
@ -1141,6 +1151,36 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void experimentalFlushWithoutAudioTrackRelease() {
|
||||||
|
// Prior to SDK 25, AudioTrack flush does not work as intended, and therefore it must be
|
||||||
|
// released and reinitialized. (Internal reference: b/143500232)
|
||||||
|
if (Util.SDK_INT < 25) {
|
||||||
|
flush();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isAudioTrackInitialized()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
resetSinkStateForFlush();
|
||||||
|
if (audioTrackPositionTracker.isPlaying()) {
|
||||||
|
audioTrack.pause();
|
||||||
|
}
|
||||||
|
audioTrack.flush();
|
||||||
|
|
||||||
|
audioTrackPositionTracker.reset();
|
||||||
|
audioTrackPositionTracker.setAudioTrack(
|
||||||
|
audioTrack,
|
||||||
|
/* isPassthrough= */ configuration.outputMode == OUTPUT_MODE_PASSTHROUGH,
|
||||||
|
configuration.outputEncoding,
|
||||||
|
configuration.outputPcmFrameSize,
|
||||||
|
configuration.bufferSize);
|
||||||
|
|
||||||
|
startMediaTimeUsNeedsInit = true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reset() {
|
public void reset() {
|
||||||
flush();
|
flush();
|
||||||
@ -1204,7 +1244,7 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
|
|
||||||
@RequiresApi(23)
|
@RequiresApi(23)
|
||||||
private void setAudioTrackPlaybackSpeedV23(float audioTrackPlaybackSpeed) {
|
private void setAudioTrackPlaybackSpeedV23(float audioTrackPlaybackSpeed) {
|
||||||
if (isInitialized()) {
|
if (isAudioTrackInitialized()) {
|
||||||
PlaybackParams playbackParams =
|
PlaybackParams playbackParams =
|
||||||
new PlaybackParams()
|
new PlaybackParams()
|
||||||
.allowDefaults()
|
.allowDefaults()
|
||||||
@ -1233,7 +1273,7 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
skipSilence,
|
skipSilence,
|
||||||
/* mediaTimeUs= */ C.TIME_UNSET,
|
/* mediaTimeUs= */ C.TIME_UNSET,
|
||||||
/* audioTrackPositionUs= */ C.TIME_UNSET);
|
/* audioTrackPositionUs= */ C.TIME_UNSET);
|
||||||
if (isInitialized()) {
|
if (isAudioTrackInitialized()) {
|
||||||
// Drain the audio processors so we can determine the frame position at which the new
|
// Drain the audio processors so we can determine the frame position at which the new
|
||||||
// parameters apply.
|
// parameters apply.
|
||||||
this.afterDrainParameters = mediaPositionParameters;
|
this.afterDrainParameters = mediaPositionParameters;
|
||||||
@ -1313,7 +1353,7 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
+ configuration.framesToDurationUs(audioProcessorChain.getSkippedOutputFrameCount());
|
+ configuration.framesToDurationUs(audioProcessorChain.getSkippedOutputFrameCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isInitialized() {
|
private boolean isAudioTrackInitialized() {
|
||||||
return audioTrack != null;
|
return audioTrack != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,6 +147,11 @@ public class ForwardingAudioSink implements AudioSink {
|
|||||||
sink.flush();
|
sink.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void experimentalFlushWithoutAudioTrackRelease() {
|
||||||
|
sink.experimentalFlushWithoutAudioTrackRelease();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reset() {
|
public void reset() {
|
||||||
sink.reset();
|
sink.reset();
|
||||||
|
@ -97,6 +97,8 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
|||||||
private boolean allowFirstBufferPositionDiscontinuity;
|
private boolean allowFirstBufferPositionDiscontinuity;
|
||||||
private boolean allowPositionDiscontinuity;
|
private boolean allowPositionDiscontinuity;
|
||||||
|
|
||||||
|
private boolean experimentalKeepAudioTrackOnSeek;
|
||||||
|
|
||||||
@Nullable private WakeupListener wakeupListener;
|
@Nullable private WakeupListener wakeupListener;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -205,6 +207,19 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
|||||||
return TAG;
|
return TAG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether to enable the experimental feature that keeps and flushes the {@link
|
||||||
|
* android.media.AudioTrack} when a seek occurs, as opposed to releasing and reinitialising. Off
|
||||||
|
* by default.
|
||||||
|
*
|
||||||
|
* <p>This method is experimental, and will be renamed or removed in a future release.
|
||||||
|
*
|
||||||
|
* @param enableKeepAudioTrackOnSeek Whether to keep the {@link android.media.AudioTrack} on seek.
|
||||||
|
*/
|
||||||
|
public void experimentalSetEnableKeepAudioTrackOnSeek(boolean enableKeepAudioTrackOnSeek) {
|
||||||
|
this.experimentalKeepAudioTrackOnSeek = enableKeepAudioTrackOnSeek;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Capabilities
|
@Capabilities
|
||||||
protected int supportsFormat(MediaCodecSelector mediaCodecSelector, Format format)
|
protected int supportsFormat(MediaCodecSelector mediaCodecSelector, Format format)
|
||||||
@ -465,7 +480,12 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
|||||||
@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);
|
||||||
audioSink.flush();
|
if (experimentalKeepAudioTrackOnSeek) {
|
||||||
|
audioSink.experimentalFlushWithoutAudioTrackRelease();
|
||||||
|
} else {
|
||||||
|
audioSink.flush();
|
||||||
|
}
|
||||||
|
|
||||||
currentPositionUs = positionUs;
|
currentPositionUs = positionUs;
|
||||||
allowFirstBufferPositionDiscontinuity = true;
|
allowFirstBufferPositionDiscontinuity = true;
|
||||||
allowPositionDiscontinuity = true;
|
allowPositionDiscontinuity = true;
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.audio;
|
package com.google.android.exoplayer2.audio;
|
||||||
|
|
||||||
|
import static com.google.android.exoplayer2.audio.AudioSink.CURRENT_POSITION_NOT_SET;
|
||||||
import static com.google.android.exoplayer2.audio.AudioSink.SINK_FORMAT_SUPPORTED_DIRECTLY;
|
import static com.google.android.exoplayer2.audio.AudioSink.SINK_FORMAT_SUPPORTED_DIRECTLY;
|
||||||
import static com.google.android.exoplayer2.audio.AudioSink.SINK_FORMAT_SUPPORTED_WITH_TRANSCODING;
|
import static com.google.android.exoplayer2.audio.AudioSink.SINK_FORMAT_SUPPORTED_WITH_TRANSCODING;
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
@ -275,6 +276,34 @@ public final class DefaultAudioSinkTest {
|
|||||||
assertThat(defaultAudioSink.supportsFormat(aacLcFormat)).isFalse();
|
assertThat(defaultAudioSink.supportsFormat(aacLcFormat)).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void handlesBufferAfterExperimentalFlush() throws Exception {
|
||||||
|
// This is demonstrating that no Exceptions are thrown as a result of handling a buffer after an
|
||||||
|
// experimental flush.
|
||||||
|
configureDefaultAudioSink(CHANNEL_COUNT_STEREO);
|
||||||
|
defaultAudioSink.handleBuffer(
|
||||||
|
createDefaultSilenceBuffer(), /* presentationTimeUs= */ 0, /* encodedAccessUnitCount= */ 1);
|
||||||
|
|
||||||
|
// After the experimental flush we can successfully queue more input.
|
||||||
|
defaultAudioSink.experimentalFlushWithoutAudioTrackRelease();
|
||||||
|
defaultAudioSink.handleBuffer(
|
||||||
|
createDefaultSilenceBuffer(),
|
||||||
|
/* presentationTimeUs= */ 5_000,
|
||||||
|
/* encodedAccessUnitCount= */ 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getCurrentPosition_returnsUnset_afterExperimentalFlush() throws Exception {
|
||||||
|
configureDefaultAudioSink(CHANNEL_COUNT_STEREO);
|
||||||
|
defaultAudioSink.handleBuffer(
|
||||||
|
createDefaultSilenceBuffer(),
|
||||||
|
/* presentationTimeUs= */ 5 * C.MICROS_PER_SECOND,
|
||||||
|
/* encodedAccessUnitCount= */ 1);
|
||||||
|
defaultAudioSink.experimentalFlushWithoutAudioTrackRelease();
|
||||||
|
assertThat(defaultAudioSink.getCurrentPositionUs(/* sourceEnded= */ false))
|
||||||
|
.isEqualTo(CURRENT_POSITION_NOT_SET);
|
||||||
|
}
|
||||||
|
|
||||||
private void configureDefaultAudioSink(int channelCount) throws AudioSink.ConfigurationException {
|
private void configureDefaultAudioSink(int channelCount) throws AudioSink.ConfigurationException {
|
||||||
configureDefaultAudioSink(channelCount, /* trimStartFrames= */ 0, /* trimEndFrames= */ 0);
|
configureDefaultAudioSink(channelCount, /* trimStartFrames= */ 0, /* trimEndFrames= */ 0);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user