blob: e6ca225f5a522034deb23e5817a2c8decfeb713a [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.
82 int getBestTimestamp(int64_t *position, int64_t *time, int timebase) {
83 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
100 // convert fields to a printable string
101 std::string toString() {
102 std::stringstream ss;
103
104 ss << "BOOTTIME offset " << mTimebaseOffset[TIMEBASE_BOOTTIME] << "\n";
105 for (int i = 0; i < LOCATION_MAX; ++i) {
106 ss << "ExtendedTimestamp[" << i << "] position: "
107 << mPosition[i] << " time: " << mTimeNs[i] << "\n";
108 }
109 return ss.str();
110 }
111 // TODO:
112 // Consider adding buffer status:
113 // size, available, algorithmic latency
114};
115
Glenn Kasten71de2f22013-09-23 14:30:36 -0700116} // namespace
117
Glenn Kastence703742013-07-19 16:33:58 -0700118#endif // ANDROID_AUDIO_TIMESTAMP_H