Consolidate position-related error handling in DefaultAudioSink
This is a step towards factoring out position tracking functionality. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=189155624
This commit is contained in:
parent
405d39b518
commit
db0d656932
@ -181,6 +181,7 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
private final ConditionVariable releasingConditionVariable;
|
private final ConditionVariable releasingConditionVariable;
|
||||||
private final long[] playheadOffsets;
|
private final long[] playheadOffsets;
|
||||||
private final AudioTrackUtil audioTrackUtil;
|
private final AudioTrackUtil audioTrackUtil;
|
||||||
|
private final AudioTrackPositionErrorListener audioTrackPositionErrorListener;
|
||||||
private final ArrayDeque<PlaybackParametersCheckpoint> playbackParametersCheckpoints;
|
private final ArrayDeque<PlaybackParametersCheckpoint> playbackParametersCheckpoints;
|
||||||
|
|
||||||
@Nullable private Listener listener;
|
@Nullable private Listener listener;
|
||||||
@ -285,6 +286,7 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
} else {
|
} else {
|
||||||
audioTrackUtil = new AudioTrackUtil();
|
audioTrackUtil = new AudioTrackUtil();
|
||||||
}
|
}
|
||||||
|
audioTrackPositionErrorListener = new DefaultAudioTrackPositionErrorListener();
|
||||||
channelMappingAudioProcessor = new ChannelMappingAudioProcessor();
|
channelMappingAudioProcessor = new ChannelMappingAudioProcessor();
|
||||||
trimmingAudioProcessor = new TrimmingAudioProcessor();
|
trimmingAudioProcessor = new TrimmingAudioProcessor();
|
||||||
sonicAudioProcessor = new SonicAudioProcessor();
|
sonicAudioProcessor = new SonicAudioProcessor();
|
||||||
@ -611,8 +613,7 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
boolean hadData = hasData;
|
boolean hadData = hasData;
|
||||||
hasData = hasPendingData();
|
hasData = hasPendingData();
|
||||||
if (hadData && !hasData && audioTrack.getPlayState() != PLAYSTATE_STOPPED && listener != null) {
|
if (hadData && !hasData && audioTrack.getPlayState() != PLAYSTATE_STOPPED && listener != null) {
|
||||||
long elapsedSinceLastFeedMs = SystemClock.elapsedRealtime() - lastFeedElapsedRealtimeMs;
|
audioTrackPositionErrorListener.onUnderrun(bufferSize, C.usToMs(bufferSizeUs));
|
||||||
listener.onUnderrun(bufferSize, C.usToMs(bufferSizeUs), elapsedSinceLastFeedMs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inputBuffer == null) {
|
if (inputBuffer == null) {
|
||||||
@ -1107,45 +1108,19 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
audioTimestampSet = false;
|
audioTimestampSet = false;
|
||||||
} else if (Math.abs(audioTimestampSystemTimeUs - systemTimeUs)
|
} else if (Math.abs(audioTimestampSystemTimeUs - systemTimeUs)
|
||||||
> MAX_AUDIO_TIMESTAMP_OFFSET_US) {
|
> MAX_AUDIO_TIMESTAMP_OFFSET_US) {
|
||||||
// The timestamp time base is probably wrong.
|
audioTrackPositionErrorListener.onSystemTimeUsMismatch(
|
||||||
String message =
|
audioTimestampPositionFrames,
|
||||||
"Spurious audio timestamp (system clock mismatch): "
|
audioTimestampSystemTimeUs,
|
||||||
+ audioTimestampPositionFrames
|
systemTimeUs,
|
||||||
+ ", "
|
playbackPositionUs);
|
||||||
+ audioTimestampSystemTimeUs
|
|
||||||
+ ", "
|
|
||||||
+ systemTimeUs
|
|
||||||
+ ", "
|
|
||||||
+ playbackPositionUs
|
|
||||||
+ ", "
|
|
||||||
+ getSubmittedFrames()
|
|
||||||
+ ", "
|
|
||||||
+ getWrittenFrames();
|
|
||||||
if (failOnSpuriousAudioTimestamp) {
|
|
||||||
throw new InvalidAudioTrackTimestampException(message);
|
|
||||||
}
|
|
||||||
Log.w(TAG, message);
|
|
||||||
audioTimestampSet = false;
|
audioTimestampSet = false;
|
||||||
} else if (Math.abs(framesToDurationUs(audioTimestampPositionFrames) - playbackPositionUs)
|
} else if (Math.abs(framesToDurationUs(audioTimestampPositionFrames) - playbackPositionUs)
|
||||||
> MAX_AUDIO_TIMESTAMP_OFFSET_US) {
|
> MAX_AUDIO_TIMESTAMP_OFFSET_US) {
|
||||||
// The timestamp frame position is probably wrong.
|
audioTrackPositionErrorListener.onPositionFramesMismatch(
|
||||||
String message =
|
audioTimestampPositionFrames,
|
||||||
"Spurious audio timestamp (frame position mismatch): "
|
audioTimestampSystemTimeUs,
|
||||||
+ audioTimestampPositionFrames
|
systemTimeUs,
|
||||||
+ ", "
|
playbackPositionUs);
|
||||||
+ audioTimestampSystemTimeUs
|
|
||||||
+ ", "
|
|
||||||
+ systemTimeUs
|
|
||||||
+ ", "
|
|
||||||
+ playbackPositionUs
|
|
||||||
+ ", "
|
|
||||||
+ getSubmittedFrames()
|
|
||||||
+ ", "
|
|
||||||
+ getWrittenFrames();
|
|
||||||
if (failOnSpuriousAudioTimestamp) {
|
|
||||||
throw new InvalidAudioTrackTimestampException(message);
|
|
||||||
}
|
|
||||||
Log.w(TAG, message);
|
|
||||||
audioTimestampSet = false;
|
audioTimestampSet = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1159,7 +1134,7 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
latencyUs = Math.max(latencyUs, 0);
|
latencyUs = Math.max(latencyUs, 0);
|
||||||
// Sanity check that the latency isn't too large.
|
// Sanity check that the latency isn't too large.
|
||||||
if (latencyUs > MAX_LATENCY_US) {
|
if (latencyUs > MAX_LATENCY_US) {
|
||||||
Log.w(TAG, "Ignoring impossibly large audio latency: " + latencyUs);
|
audioTrackPositionErrorListener.onInvalidLatency(latencyUs);
|
||||||
latencyUs = 0;
|
latencyUs = 0;
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -1625,4 +1600,126 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(b/74325207): Factor out position tracking functionality into a separate class.
|
||||||
|
|
||||||
|
/** Interface for errors relating to the audio track position. */
|
||||||
|
private interface AudioTrackPositionErrorListener {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the frame position is too far from the expected frame position.
|
||||||
|
*
|
||||||
|
* @param audioTimestampPositionFrames The frame position of the last known audio track
|
||||||
|
* timestamp.
|
||||||
|
* @param audioTimestampSystemTimeUs The system time associated with the last known audio track
|
||||||
|
* timestamp, in microseconds.
|
||||||
|
* @param systemTimeUs The current time.
|
||||||
|
* @param playbackPositionUs The current playback head position in microseconds.
|
||||||
|
*/
|
||||||
|
void onPositionFramesMismatch(
|
||||||
|
long audioTimestampPositionFrames,
|
||||||
|
long audioTimestampSystemTimeUs,
|
||||||
|
long systemTimeUs,
|
||||||
|
long playbackPositionUs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the system time associated with the last known audio track timestamp is
|
||||||
|
* unexpectedly far from the current time.
|
||||||
|
*
|
||||||
|
* @param audioTimestampPositionFrames The frame position of the last known audio track
|
||||||
|
* timestamp.
|
||||||
|
* @param audioTimestampSystemTimeUs The system time associated with the last known audio track
|
||||||
|
* timestamp, in microseconds.
|
||||||
|
* @param systemTimeUs The current time.
|
||||||
|
* @param playbackPositionUs The current playback head position in microseconds.
|
||||||
|
*/
|
||||||
|
void onSystemTimeUsMismatch(
|
||||||
|
long audioTimestampPositionFrames,
|
||||||
|
long audioTimestampSystemTimeUs,
|
||||||
|
long systemTimeUs,
|
||||||
|
long playbackPositionUs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the audio track has provided an invalid latency.
|
||||||
|
*
|
||||||
|
* @param latencyUs The reported latency in microseconds.
|
||||||
|
*/
|
||||||
|
void onInvalidLatency(long latencyUs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called if the audio track runs out of data to play.
|
||||||
|
*
|
||||||
|
* @param bufferSize The size of the sink's buffer, in bytes.
|
||||||
|
* @param bufferSizeMs The size of the sink's buffer, in milliseconds, if it is configured for
|
||||||
|
* PCM output. {@link C#TIME_UNSET} if it is configured for encoded audio output, as the
|
||||||
|
* buffered media can have a variable bitrate so the duration may be unknown.
|
||||||
|
*/
|
||||||
|
void onUnderrun(int bufferSize, long bufferSizeMs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final class DefaultAudioTrackPositionErrorListener
|
||||||
|
implements AudioTrackPositionErrorListener {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPositionFramesMismatch(
|
||||||
|
long audioTimestampPositionFrames,
|
||||||
|
long audioTimestampSystemTimeUs,
|
||||||
|
long systemTimeUs,
|
||||||
|
long playbackPositionUs) {
|
||||||
|
String message =
|
||||||
|
"Spurious audio timestamp (frame position mismatch): "
|
||||||
|
+ audioTimestampPositionFrames
|
||||||
|
+ ", "
|
||||||
|
+ audioTimestampSystemTimeUs
|
||||||
|
+ ", "
|
||||||
|
+ systemTimeUs
|
||||||
|
+ ", "
|
||||||
|
+ playbackPositionUs
|
||||||
|
+ ", "
|
||||||
|
+ getSubmittedFrames()
|
||||||
|
+ ", "
|
||||||
|
+ getWrittenFrames();
|
||||||
|
if (failOnSpuriousAudioTimestamp) {
|
||||||
|
throw new InvalidAudioTrackTimestampException(message);
|
||||||
|
}
|
||||||
|
Log.w(TAG, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSystemTimeUsMismatch(
|
||||||
|
long audioTimestampPositionFrames,
|
||||||
|
long audioTimestampSystemTimeUs,
|
||||||
|
long systemTimeUs,
|
||||||
|
long playbackPositionUs) {
|
||||||
|
String message =
|
||||||
|
"Spurious audio timestamp (system clock mismatch): "
|
||||||
|
+ audioTimestampPositionFrames
|
||||||
|
+ ", "
|
||||||
|
+ audioTimestampSystemTimeUs
|
||||||
|
+ ", "
|
||||||
|
+ systemTimeUs
|
||||||
|
+ ", "
|
||||||
|
+ playbackPositionUs
|
||||||
|
+ ", "
|
||||||
|
+ getSubmittedFrames()
|
||||||
|
+ ", "
|
||||||
|
+ getWrittenFrames();
|
||||||
|
if (failOnSpuriousAudioTimestamp) {
|
||||||
|
throw new InvalidAudioTrackTimestampException(message);
|
||||||
|
}
|
||||||
|
Log.w(TAG, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInvalidLatency(long latencyUs) {
|
||||||
|
Log.w(TAG, "Ignoring impossibly large audio latency: " + latencyUs);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUnderrun(int bufferSize, long bufferSizeMs) {
|
||||||
|
if (listener != null) {
|
||||||
|
long elapsedSinceLastFeedMs = SystemClock.elapsedRealtime() - lastFeedElapsedRealtimeMs;
|
||||||
|
listener.onUnderrun(bufferSize, bufferSizeMs, elapsedSinceLastFeedMs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user