blob: 531b5487157109a86ff1a5f9b8cb7b706194dcd9 [file] [log] [blame]
Glenn Kastence703742013-07-19 16:33:58 -07001/*
2 * Copyright (C) 2013 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
17#ifndef ANDROID_AUDIO_TIMESTAMP_H
18#define ANDROID_AUDIO_TIMESTAMP_H
19
Andy Hung3f0c9022016-01-15 17:49:46 -080020#include <string>
21#include <sstream>
Glenn Kastence703742013-07-19 16:33:58 -070022#include <time.h>
23
Glenn Kasten71de2f22013-09-23 14:30:36 -070024namespace android {
25
Glenn Kastence703742013-07-19 16:33:58 -070026class AudioTimestamp {
27public:
28 AudioTimestamp() : mPosition(0) {
29 mTime.tv_sec = 0;
30 mTime.tv_nsec = 0;
31 }
32 // FIXME change type to match android.media.AudioTrack
33 uint32_t mPosition; // a frame position in AudioTrack::getPosition() units
34 struct timespec mTime; // corresponding CLOCK_MONOTONIC when frame is expected to present
35};
36
Andy Hung3f0c9022016-01-15 17:49:46 -080037struct ExtendedTimestamp {
38 enum Location {
39 LOCATION_CLIENT, // timestamp of last read frame from client-server track buffer
40 LOCATION_SERVER, // timestamp of newest frame from client-server track buffer
41 LOCATION_KERNEL, // timestamp of newest frame in the kernel (alsa) buffer.
42 LOCATION_MAX // for sizing arrays only
43 };
44
45 // This needs to be kept in sync with android.media.AudioTimestamp
46 enum Timebase {
47 TIMEBASE_MONOTONIC, // Clock monotonic offset (generally 0)
48 TIMEBASE_BOOTTIME,
49 TIMEBASE_MAX,
50 };
51
52 ExtendedTimestamp() {
53 clear();
54 }
55
56 // mPosition is expressed in frame units.
57 // It is generally nonnegative, though we keep this signed for
58 // to potentially express algorithmic latency at the start of the stream
59 // and to prevent unintentional unsigned integer underflow.
60 int64_t mPosition[LOCATION_MAX];
61
62 // mTimeNs is in nanoseconds for the default timebase, monotonic.
63 // If this value is -1, then both time and position are invalid.
64 // If this value is 0, then the time is not valid but the position is valid.
65 int64_t mTimeNs[LOCATION_MAX];
66
67 // mTimebaseOffset is the offset in ns from monotonic when the
68 // timestamp was taken. This may vary due to suspend time
69 // or NTP adjustment.
70 int64_t mTimebaseOffset[TIMEBASE_MAX];
71
72 void clear() {
73 memset(mPosition, 0, sizeof(mPosition)); // actually not necessary if time is -1
74 for (int i = 0; i < LOCATION_MAX; ++i) {
75 mTimeNs[i] = -1;
76 }
77 memset(mTimebaseOffset, 0, sizeof(mTimebaseOffset));
78 }
79
80 // Returns the best timestamp as judged from the closest-to-hw stage in the
81 // pipeline with a valid timestamp.
Andy Hung6ae58432016-02-16 18:32:24 -080082 status_t getBestTimestamp(int64_t *position, int64_t *time, int timebase) const {
Andy Hung3f0c9022016-01-15 17:49:46 -080083 if (position == nullptr || time == nullptr
84 || timebase < 0 || timebase >= TIMEBASE_MAX) {
85 return BAD_VALUE;
86 }
87 // look for the closest-to-hw stage in the pipeline with a valid timestamp.
88 // We omit LOCATION_CLIENT as we prefer at least LOCATION_SERVER based accuracy
89 // when getting the best timestamp.
90 for (int i = LOCATION_MAX - 1; i >= LOCATION_SERVER; --i) {
91 if (mTimeNs[i] > 0) {
92 *position = mPosition[i];
93 *time = mTimeNs[i] + mTimebaseOffset[timebase];
94 return OK;
95 }
96 }
97 return INVALID_OPERATION;
98 }
99
Andy Hung6ae58432016-02-16 18:32:24 -0800100 status_t getBestTimestamp(AudioTimestamp *timestamp) const {
101 if (timestamp == nullptr) {
102 return BAD_VALUE;
103 }
104 int64_t position, time;
105 if (getBestTimestamp(&position, &time, TIMEBASE_MONOTONIC) == OK) {
106 timestamp->mPosition = position;
107 timestamp->mTime.tv_sec = time / 1000000000;
108 timestamp->mTime.tv_nsec = time - timestamp->mTime.tv_sec * 1000000000LL;
109 return OK;
110 }
111 return INVALID_OPERATION;
112 }
113
Andy Hung3f0c9022016-01-15 17:49:46 -0800114 // convert fields to a printable string
115 std::string toString() {
116 std::stringstream ss;
117
118 ss << "BOOTTIME offset " << mTimebaseOffset[TIMEBASE_BOOTTIME] << "\n";
119 for (int i = 0; i < LOCATION_MAX; ++i) {
120 ss << "ExtendedTimestamp[" << i << "] position: "
121 << mPosition[i] << " time: " << mTimeNs[i] << "\n";
122 }
123 return ss.str();
124 }
125 // TODO:
126 // Consider adding buffer status:
127 // size, available, algorithmic latency
128};
129
Glenn Kasten71de2f22013-09-23 14:30:36 -0700130} // namespace
131
Glenn Kastence703742013-07-19 16:33:58 -0700132#endif // ANDROID_AUDIO_TIMESTAMP_H