Commit fbb0cc0f authored by Chris Kuiper's avatar Chris Kuiper Committed by Commit Bot

[Chromecast] Make CMA backend for Android more robust, part 2

This address issues pointed out in the previous change. Additionally it tweaks
the low-pass filter coefficients slightly and adds an additional logic to
ignore timestamps that are clearly incorrect due to them deviating from the
reference time by a large amount.

Bug: [internal] b/72341571
Test: Running multizone certification test cases on a mix of speakers.

Change-Id: I52cfdd88f4d1f989823cab791986a2bce6dd810c
Reviewed-on: https://chromium-review.googlesource.com/883406Reviewed-by: default avatarKenneth MacKay <kmackay@chromium.org>
Commit-Queue: Chris Kuiper <ckuiper@chromium.org>
Cr-Commit-Position: refs/heads/master@{#531704}
parent 06cc5abb
...@@ -94,11 +94,19 @@ class AudioSinkAudioTrackImpl { ...@@ -94,11 +94,19 @@ class AudioSinkAudioTrackImpl {
private static final long TIMESTAMP_UPDATE_PERIOD = 250 * MSEC_IN_NSEC; private static final long TIMESTAMP_UPDATE_PERIOD = 250 * MSEC_IN_NSEC;
private static final long UNDERRUN_LOG_THROTTLE_PERIOD = SEC_IN_NSEC; private static final long UNDERRUN_LOG_THROTTLE_PERIOD = SEC_IN_NSEC;
// Maximum amount a timestamp may deviate from the previous one to be considered stable. // Maximum amount a timestamp may deviate from the previous one to be considered stable at
private static final long MAX_TIMESTAMP_DEVIATION_NSEC = 150 * USEC_IN_NSEC; // startup or after an underrun event.
// Number of consecutive stable timestamps needed to make it a valid reference point. private static final long MAX_STABLE_TIMESTAMP_DEVIATION_NSEC = 150 * USEC_IN_NSEC;
// Number of consecutive stable timestamps needed to make it a valid reference point at startup
// or after an underrun event.
private static final int MIN_TIMESTAMP_STABILITY_CNT = 3; private static final int MIN_TIMESTAMP_STABILITY_CNT = 3;
// Minimum time timestamps need to be stable to make it a valid reference point at startup or
// after an underrun event. This is an additional safeguard.
private static final long MIN_TIMESTAMP_STABILITY_TIME_NSEC = SEC_IN_NSEC; private static final long MIN_TIMESTAMP_STABILITY_TIME_NSEC = SEC_IN_NSEC;
// After startup, any timestamp deviating more than this amount is ignored.
private static final long TSTAMP_DEV_THRESHOLD_TO_IGNORE_NSEC = 500 * USEC_IN_NSEC;
// Don't ignore timestamps for longer than this amount of time.
private static final long MAX_TIME_IGNORING_TSTAMPS_NSECS = SEC_IN_NSEC;
// Additional padding for minimum buffer time, determined experimentally. // Additional padding for minimum buffer time, determined experimentally.
private static final long MIN_BUFFERED_TIME_PADDING_US = 20000; private static final long MIN_BUFFERED_TIME_PADDING_US = 20000;
...@@ -586,7 +594,7 @@ class AudioSinkAudioTrackImpl { ...@@ -586,7 +594,7 @@ class AudioSinkAudioTrackImpl {
} }
long deviation = mRefNanoTimeAtFramePos0Candidate - newNanoTimeAtFramePos0; long deviation = mRefNanoTimeAtFramePos0Candidate - newNanoTimeAtFramePos0;
if (Math.abs(deviation) > MAX_TIMESTAMP_DEVIATION_NSEC) { if (Math.abs(deviation) > MAX_STABLE_TIMESTAMP_DEVIATION_NSEC) {
// not stable // not stable
Log.i(TAG, Log.i(TAG,
"Timestamp [" + mTimestampStabilityCounter + "/" "Timestamp [" + mTimestampStabilityCounter + "/"
...@@ -651,7 +659,7 @@ class AudioSinkAudioTrackImpl { ...@@ -651,7 +659,7 @@ class AudioSinkAudioTrackImpl {
// //
// At this point we just do the same as when in STARTING_UP, but eventually there // At this point we just do the same as when in STARTING_UP, but eventually there
// should be a more refined way to figure out when the timestamps returned from the // should be a more refined way to figure out when the timestamps returned from the
// AudioTrack are usuable again. // AudioTrack are usable again.
if (!isTimestampStable(newNanoTimeAtFramePos0)) { if (!isTimestampStable(newNanoTimeAtFramePos0)) {
return; return;
} }
...@@ -665,10 +673,24 @@ class AudioSinkAudioTrackImpl { ...@@ -665,10 +673,24 @@ class AudioSinkAudioTrackImpl {
case STABLE: case STABLE:
// Timestamps can be jittery, and on some systems they are occasionally off by // Timestamps can be jittery, and on some systems they are occasionally off by
// hundreds of usecs. Use a low-pass filter to handle this: 0.05*New + 0.95*Ref. Do // hundreds of usecs. Filter out timestamps that are too jittery and use a low-pass
// integer math with proper rounding. // filter on the smaller ones.
// Note that the low-pass filter approach does not work well when the media clock
// rate does not match the system clock rate, and the timestamp drifts as a result.
// Currently none of the devices using this code do this.
long devNsec = mRefNanoTimeAtFramePos0 - newNanoTimeAtFramePos0;
if (Math.abs(devNsec) > TSTAMP_DEV_THRESHOLD_TO_IGNORE_NSEC) {
Log.i(TAG, "Too jittery timestamp (" + convertNsecsToUsecs(devNsec) + ")");
long timeSinceLastGoodTstamp = elapsedNsec(mLastTimestampUpdateNsec);
if (timeSinceLastGoodTstamp <= MAX_TIME_IGNORING_TSTAMPS_NSECS) {
return; // Ignore this one.
}
// We ignored jittery timestamps for too long, let this one pass.
Log.i(TAG, "Too many jittery timestamps ignored!");
}
// Low-pass filter: 0.10*New + 0.90*Ref. Do integer math with proper rounding.
mRefNanoTimeAtFramePos0 = mRefNanoTimeAtFramePos0 =
(5 * newNanoTimeAtFramePos0 + 95 * mRefNanoTimeAtFramePos0 + 50) / 100; (10 * newNanoTimeAtFramePos0 + 90 * mRefNanoTimeAtFramePos0 + 50) / 100;
break; break;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment