blob: a86d2645a66bcc8dd663cc41195216d442eb150e [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 Burkfceeee72019-06-14 11:18:45 -070021#include "utility/AudioClock.h"
Phil Burk204a1632017-01-03 17:23:43 -080022
Phil Burk5ed503c2017-02-01 09:38:15 -080023namespace aaudio {
Phil Burk204a1632017-01-03 17:23:43 -080024
25/**
26 * Model an isochronous data stream using occasional timestamps as input.
27 * This can be used to predict the position of the stream at a given time.
28 *
29 * This class is not thread safe and should only be called from one thread.
30 */
31class IsochronousClockModel {
32
33public:
34 IsochronousClockModel();
35 virtual ~IsochronousClockModel();
36
Phil Burk3316d5e2017-02-15 11:23:01 -080037 void start(int64_t nanoTime);
38 void stop(int64_t nanoTime);
Phil Burk204a1632017-01-03 17:23:43 -080039
Phil Burk377c1c22018-12-12 16:06:54 -080040 /**
41 * @return true if the model is starting up
42 */
43 bool isStarting() const;
44
45 /**
46 * @return true if the model is running and producing valid results
47 */
48 bool isRunning() const;
Phil Burkbcc36742017-08-31 17:24:51 -070049
Phil Burk3316d5e2017-02-15 11:23:01 -080050 void processTimestamp(int64_t framePosition, int64_t nanoTime);
Phil Burk204a1632017-01-03 17:23:43 -080051
52 /**
53 * @param sampleRate rate of the stream in frames per second
54 */
Phil Burk3316d5e2017-02-15 11:23:01 -080055 void setSampleRate(int32_t sampleRate);
Phil Burk204a1632017-01-03 17:23:43 -080056
Phil Burkec89b2e2017-06-20 15:05:06 -070057 void setPositionAndTime(int64_t framePosition, int64_t nanoTime);
58
Phil Burk3316d5e2017-02-15 11:23:01 -080059 int32_t getSampleRate() const {
Phil Burk204a1632017-01-03 17:23:43 -080060 return mSampleRate;
61 }
62
63 /**
64 * This must be set accurately in order to track the isochronous stream.
65 *
66 * @param framesPerBurst number of frames that stream advance at one time.
67 */
Phil Burk3316d5e2017-02-15 11:23:01 -080068 void setFramesPerBurst(int32_t framesPerBurst);
Phil Burk204a1632017-01-03 17:23:43 -080069
Phil Burk3316d5e2017-02-15 11:23:01 -080070 int32_t getFramesPerBurst() const {
Phil Burk204a1632017-01-03 17:23:43 -080071 return mFramesPerBurst;
72 }
73
74 /**
75 * Calculate an estimated time when the stream will be at that position.
76 *
77 * @param framePosition position of the stream in frames
78 * @return time in nanoseconds
79 */
Phil Burk3316d5e2017-02-15 11:23:01 -080080 int64_t convertPositionToTime(int64_t framePosition) const;
Phil Burk204a1632017-01-03 17:23:43 -080081
82 /**
Phil Burkfceeee72019-06-14 11:18:45 -070083 * Calculate the latest estimated time that the stream will be at that position.
84 * The more jittery the clock is then the later this will be.
85 *
86 * @param framePosition
87 * @return time in nanoseconds
88 */
89 int64_t convertPositionToLatestTime(int64_t framePosition) const;
90
91 /**
Phil Burk204a1632017-01-03 17:23:43 -080092 * Calculate an estimated position where the stream will be at the specified time.
93 *
94 * @param nanoTime time of interest
95 * @return position in frames
96 */
Phil Burk3316d5e2017-02-15 11:23:01 -080097 int64_t convertTimeToPosition(int64_t nanoTime) const;
Phil Burk204a1632017-01-03 17:23:43 -080098
99 /**
Phil Burkfceeee72019-06-14 11:18:45 -0700100 * Calculate the corresponding estimated position based on the specified time being
101 * the latest possible time.
102 *
103 * For the same nanoTime, this may return an earlier position than
104 * convertTimeToPosition().
105 *
106 * @param nanoTime
107 * @return position in frames
108 */
109 int64_t convertLatestTimeToPosition(int64_t nanoTime) const;
110
111 /**
Phil Burk204a1632017-01-03 17:23:43 -0800112 * @param framesDelta difference in frames
113 * @return duration in nanoseconds
114 */
Phil Burk3316d5e2017-02-15 11:23:01 -0800115 int64_t convertDeltaPositionToTime(int64_t framesDelta) const;
Phil Burk204a1632017-01-03 17:23:43 -0800116
117 /**
118 * @param nanosDelta duration in nanoseconds
119 * @return frames that stream will advance in that time
120 */
Phil Burk3316d5e2017-02-15 11:23:01 -0800121 int64_t convertDeltaTimeToPosition(int64_t nanosDelta) const;
Phil Burk204a1632017-01-03 17:23:43 -0800122
Phil Burkec89b2e2017-06-20 15:05:06 -0700123 void dump() const;
124
Phil Burk204a1632017-01-03 17:23:43 -0800125private:
Phil Burkfceeee72019-06-14 11:18:45 -0700126
127 int32_t getLateTimeOffsetNanos() const;
128
Phil Burk204a1632017-01-03 17:23:43 -0800129 enum clock_model_state_t {
130 STATE_STOPPED,
131 STATE_STARTING,
132 STATE_SYNCING,
133 STATE_RUNNING
134 };
135
Phil Burkfceeee72019-06-14 11:18:45 -0700136 // Amount of time to drift forward when we get a late timestamp.
Phil Burk34e2d2d2019-09-26 12:46:10 -0700137 static constexpr int32_t kDriftNanos = 1 * 1000;
138 // Safety margin to add to the late edge of the timestamp window.
Phil Burkfceeee72019-06-14 11:18:45 -0700139 static constexpr int32_t kExtraLatenessNanos = 100 * 1000;
Phil Burk34e2d2d2019-09-26 12:46:10 -0700140 // Initial small threshold for causing a drift later in time.
141 static constexpr int32_t kInitialLatenessForDriftNanos = 10 * 1000;
Phil Burkfceeee72019-06-14 11:18:45 -0700142
Phil Burk34e2d2d2019-09-26 12:46:10 -0700143 int64_t mMarkerFramePosition; // Estimated HW position.
144 int64_t mMarkerNanoTime; // Estimated HW time.
Phil Burk3316d5e2017-02-15 11:23:01 -0800145 int32_t mSampleRate;
Phil Burk34e2d2d2019-09-26 12:46:10 -0700146 int32_t mFramesPerBurst; // number of frames transferred at one time.
147 int32_t mBurstPeriodNanos; // Time between HW bursts.
Phil Burkfceeee72019-06-14 11:18:45 -0700148 // Includes mBurstPeriodNanos because we sample randomly over time.
149 int32_t mMaxMeasuredLatenessNanos;
Phil Burk34e2d2d2019-09-26 12:46:10 -0700150 // Threshold for lateness that triggers a drift later in time.
151 int32_t mLatenessForDriftNanos;
152 clock_model_state_t mState; // State machine handles startup sequence.
Phil Burk204a1632017-01-03 17:23:43 -0800153
Phil Burk34e2d2d2019-09-26 12:46:10 -0700154 int32_t mTimestampCount = 0; // For logging.
Phil Burkfceeee72019-06-14 11:18:45 -0700155
Phil Burk204a1632017-01-03 17:23:43 -0800156 void update();
157};
158
Phil Burk5ed503c2017-02-01 09:38:15 -0800159} /* namespace aaudio */
Phil Burk204a1632017-01-03 17:23:43 -0800160
Phil Burk5204d312017-05-04 17:16:13 -0700161#endif //ANDROID_AAUDIO_ISOCHRONOUS_CLOCK_MODEL_H