blob: 628001358778127c82ecdee621b49c590472da41 [file] [log] [blame]
Phil Burk204a1632017-01-03 17:23:43 -08001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Phil Burk5204d312017-05-04 17:16:13 -070017#ifndef ANDROID_AAUDIO_ISOCHRONOUS_CLOCK_MODEL_H
18#define ANDROID_AAUDIO_ISOCHRONOUS_CLOCK_MODEL_H
Phil Burk204a1632017-01-03 17:23:43 -080019
20#include <stdint.h>
Phil Burkef34be52019-09-26 13:45:25 -070021
22#include <audio_utils/Histogram.h>
23
Phil Burkfceeee72019-06-14 11:18:45 -070024#include "utility/AudioClock.h"
Phil Burk204a1632017-01-03 17:23:43 -080025
Phil Burk5ed503c2017-02-01 09:38:15 -080026namespace aaudio {
Phil Burk204a1632017-01-03 17:23:43 -080027
28/**
29 * Model an isochronous data stream using occasional timestamps as input.
30 * This can be used to predict the position of the stream at a given time.
31 *
32 * This class is not thread safe and should only be called from one thread.
33 */
34class IsochronousClockModel {
35
36public:
37 IsochronousClockModel();
Phil Burk9e1f44b2020-04-08 16:02:05 -070038 virtual ~IsochronousClockModel() = default;
Phil Burk204a1632017-01-03 17:23:43 -080039
Phil Burk3316d5e2017-02-15 11:23:01 -080040 void start(int64_t nanoTime);
41 void stop(int64_t nanoTime);
Phil Burk204a1632017-01-03 17:23:43 -080042
Phil Burk377c1c22018-12-12 16:06:54 -080043 /**
44 * @return true if the model is starting up
45 */
46 bool isStarting() const;
47
48 /**
49 * @return true if the model is running and producing valid results
50 */
51 bool isRunning() const;
Phil Burkbcc36742017-08-31 17:24:51 -070052
Phil Burk3316d5e2017-02-15 11:23:01 -080053 void processTimestamp(int64_t framePosition, int64_t nanoTime);
Phil Burk204a1632017-01-03 17:23:43 -080054
55 /**
56 * @param sampleRate rate of the stream in frames per second
57 */
Phil Burk3316d5e2017-02-15 11:23:01 -080058 void setSampleRate(int32_t sampleRate);
Phil Burk204a1632017-01-03 17:23:43 -080059
Phil Burkec89b2e2017-06-20 15:05:06 -070060 void setPositionAndTime(int64_t framePosition, int64_t nanoTime);
61
Phil Burk3316d5e2017-02-15 11:23:01 -080062 int32_t getSampleRate() const {
Phil Burk204a1632017-01-03 17:23:43 -080063 return mSampleRate;
64 }
65
66 /**
67 * This must be set accurately in order to track the isochronous stream.
68 *
69 * @param framesPerBurst number of frames that stream advance at one time.
70 */
Phil Burk3316d5e2017-02-15 11:23:01 -080071 void setFramesPerBurst(int32_t framesPerBurst);
Phil Burk204a1632017-01-03 17:23:43 -080072
Phil Burk3316d5e2017-02-15 11:23:01 -080073 int32_t getFramesPerBurst() const {
Phil Burk204a1632017-01-03 17:23:43 -080074 return mFramesPerBurst;
75 }
76
77 /**
78 * Calculate an estimated time when the stream will be at that position.
79 *
80 * @param framePosition position of the stream in frames
81 * @return time in nanoseconds
82 */
Phil Burk3316d5e2017-02-15 11:23:01 -080083 int64_t convertPositionToTime(int64_t framePosition) const;
Phil Burk204a1632017-01-03 17:23:43 -080084
85 /**
Phil Burkfceeee72019-06-14 11:18:45 -070086 * Calculate the latest estimated time that the stream will be at that position.
87 * The more jittery the clock is then the later this will be.
88 *
89 * @param framePosition
90 * @return time in nanoseconds
91 */
92 int64_t convertPositionToLatestTime(int64_t framePosition) const;
93
94 /**
Phil Burk204a1632017-01-03 17:23:43 -080095 * Calculate an estimated position where the stream will be at the specified time.
96 *
97 * @param nanoTime time of interest
98 * @return position in frames
99 */
Phil Burk3316d5e2017-02-15 11:23:01 -0800100 int64_t convertTimeToPosition(int64_t nanoTime) const;
Phil Burk204a1632017-01-03 17:23:43 -0800101
102 /**
Phil Burkfceeee72019-06-14 11:18:45 -0700103 * Calculate the corresponding estimated position based on the specified time being
104 * the latest possible time.
105 *
106 * For the same nanoTime, this may return an earlier position than
107 * convertTimeToPosition().
108 *
109 * @param nanoTime
110 * @return position in frames
111 */
112 int64_t convertLatestTimeToPosition(int64_t nanoTime) const;
113
114 /**
Phil Burk204a1632017-01-03 17:23:43 -0800115 * @param framesDelta difference in frames
116 * @return duration in nanoseconds
117 */
Phil Burk3316d5e2017-02-15 11:23:01 -0800118 int64_t convertDeltaPositionToTime(int64_t framesDelta) const;
Phil Burk204a1632017-01-03 17:23:43 -0800119
120 /**
121 * @param nanosDelta duration in nanoseconds
122 * @return frames that stream will advance in that time
123 */
Phil Burk3316d5e2017-02-15 11:23:01 -0800124 int64_t convertDeltaTimeToPosition(int64_t nanosDelta) const;
Phil Burk204a1632017-01-03 17:23:43 -0800125
Phil Burkec89b2e2017-06-20 15:05:06 -0700126 void dump() const;
127
Phil Burkef34be52019-09-26 13:45:25 -0700128 void dumpHistogram() const;
129
Phil Burk204a1632017-01-03 17:23:43 -0800130private:
Phil Burkfceeee72019-06-14 11:18:45 -0700131
132 int32_t getLateTimeOffsetNanos() const;
Phil Burk9e1f44b2020-04-08 16:02:05 -0700133 void update();
Phil Burkfceeee72019-06-14 11:18:45 -0700134
Phil Burk204a1632017-01-03 17:23:43 -0800135 enum clock_model_state_t {
136 STATE_STOPPED,
137 STATE_STARTING,
138 STATE_SYNCING,
139 STATE_RUNNING
140 };
141
Phil Burkfceeee72019-06-14 11:18:45 -0700142 // Amount of time to drift forward when we get a late timestamp.
Phil Burk34e2d2d2019-09-26 12:46:10 -0700143 static constexpr int32_t kDriftNanos = 1 * 1000;
144 // Safety margin to add to the late edge of the timestamp window.
Phil Burkfceeee72019-06-14 11:18:45 -0700145 static constexpr int32_t kExtraLatenessNanos = 100 * 1000;
Phil Burk34e2d2d2019-09-26 12:46:10 -0700146 // Initial small threshold for causing a drift later in time.
147 static constexpr int32_t kInitialLatenessForDriftNanos = 10 * 1000;
Phil Burkfceeee72019-06-14 11:18:45 -0700148
Phil Burkef34be52019-09-26 13:45:25 -0700149 static constexpr int32_t kHistogramBinWidthMicros = 50;
150 static constexpr int32_t kHistogramBinCount = 128;
151
Phil Burk34e2d2d2019-09-26 12:46:10 -0700152 int64_t mMarkerFramePosition; // Estimated HW position.
153 int64_t mMarkerNanoTime; // Estimated HW time.
Phil Burk3316d5e2017-02-15 11:23:01 -0800154 int32_t mSampleRate;
Phil Burk34e2d2d2019-09-26 12:46:10 -0700155 int32_t mFramesPerBurst; // number of frames transferred at one time.
156 int32_t mBurstPeriodNanos; // Time between HW bursts.
Phil Burkfceeee72019-06-14 11:18:45 -0700157 // Includes mBurstPeriodNanos because we sample randomly over time.
158 int32_t mMaxMeasuredLatenessNanos;
Phil Burk34e2d2d2019-09-26 12:46:10 -0700159 // Threshold for lateness that triggers a drift later in time.
160 int32_t mLatenessForDriftNanos;
161 clock_model_state_t mState; // State machine handles startup sequence.
Phil Burk204a1632017-01-03 17:23:43 -0800162
Phil Burk34e2d2d2019-09-26 12:46:10 -0700163 int32_t mTimestampCount = 0; // For logging.
Phil Burkfceeee72019-06-14 11:18:45 -0700164
Phil Burkef34be52019-09-26 13:45:25 -0700165 // distribution of timestamps relative to earliest
166 std::unique_ptr<android::audio_utils::Histogram> mHistogramMicros;
167
Phil Burk204a1632017-01-03 17:23:43 -0800168};
169
Phil Burk5ed503c2017-02-01 09:38:15 -0800170} /* namespace aaudio */
Phil Burk204a1632017-01-03 17:23:43 -0800171
Phil Burk5204d312017-05-04 17:16:13 -0700172#endif //ANDROID_AAUDIO_ISOCHRONOUS_CLOCK_MODEL_H