Add AudioRecord timestamps
Bug: 13569372
Bug: 22886739
Change-Id: Ibc81afefb733d23676a632a0f2da31163fdbe05f
diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h
index c47a4e7..521557d 100644
--- a/include/media/AudioRecord.h
+++ b/include/media/AudioRecord.h
@@ -19,6 +19,7 @@
#include <cutils/sched_policy.h>
#include <media/AudioSystem.h>
+#include <media/AudioTimestamp.h>
#include <media/IAudioRecord.h>
#include <media/Modulo.h>
#include <utils/threads.h>
@@ -314,6 +315,17 @@
*/
status_t getPosition(uint32_t *position) const;
+ /* Return the record timestamp.
+ *
+ * Parameters:
+ * timestamp: A pointer to the timestamp to be filled.
+ *
+ * Returned status (from utils/Errors.h) can be:
+ * - NO_ERROR: successful operation
+ * - BAD_VALUE: timestamp is NULL
+ */
+ status_t getTimestamp(ExtendedTimestamp *timestamp);
+
/* Returns a handle on the audio input used by this AudioRecord.
*
* Parameters:
@@ -571,6 +583,11 @@
size_t mReqFrameCount; // frame count to request the first or next time
// a new IAudioRecord is needed, non-decreasing
+ int64_t mFramesRead; // total frames read. reset to zero after
+ // the start() following stop(). It is not
+ // changed after restoring the track.
+ int64_t mFramesReadServerOffset; // An offset to server frames read due to
+ // restoring AudioRecord, or stop/start.
// constant after constructor or set()
uint32_t mSampleRate;
audio_format_t mFormat;
diff --git a/include/media/AudioTimestamp.h b/include/media/AudioTimestamp.h
index 99e9c3e..e6ca225 100644
--- a/include/media/AudioTimestamp.h
+++ b/include/media/AudioTimestamp.h
@@ -17,6 +17,8 @@
#ifndef ANDROID_AUDIO_TIMESTAMP_H
#define ANDROID_AUDIO_TIMESTAMP_H
+#include <string>
+#include <sstream>
#include <time.h>
namespace android {
@@ -32,6 +34,85 @@
struct timespec mTime; // corresponding CLOCK_MONOTONIC when frame is expected to present
};
+struct ExtendedTimestamp {
+ enum Location {
+ LOCATION_CLIENT, // timestamp of last read frame from client-server track buffer
+ LOCATION_SERVER, // timestamp of newest frame from client-server track buffer
+ LOCATION_KERNEL, // timestamp of newest frame in the kernel (alsa) buffer.
+ LOCATION_MAX // for sizing arrays only
+ };
+
+ // This needs to be kept in sync with android.media.AudioTimestamp
+ enum Timebase {
+ TIMEBASE_MONOTONIC, // Clock monotonic offset (generally 0)
+ TIMEBASE_BOOTTIME,
+ TIMEBASE_MAX,
+ };
+
+ ExtendedTimestamp() {
+ clear();
+ }
+
+ // mPosition is expressed in frame units.
+ // It is generally nonnegative, though we keep this signed for
+ // to potentially express algorithmic latency at the start of the stream
+ // and to prevent unintentional unsigned integer underflow.
+ int64_t mPosition[LOCATION_MAX];
+
+ // mTimeNs is in nanoseconds for the default timebase, monotonic.
+ // If this value is -1, then both time and position are invalid.
+ // If this value is 0, then the time is not valid but the position is valid.
+ int64_t mTimeNs[LOCATION_MAX];
+
+ // mTimebaseOffset is the offset in ns from monotonic when the
+ // timestamp was taken. This may vary due to suspend time
+ // or NTP adjustment.
+ int64_t mTimebaseOffset[TIMEBASE_MAX];
+
+ void clear() {
+ memset(mPosition, 0, sizeof(mPosition)); // actually not necessary if time is -1
+ for (int i = 0; i < LOCATION_MAX; ++i) {
+ mTimeNs[i] = -1;
+ }
+ memset(mTimebaseOffset, 0, sizeof(mTimebaseOffset));
+ }
+
+ // Returns the best timestamp as judged from the closest-to-hw stage in the
+ // pipeline with a valid timestamp.
+ int getBestTimestamp(int64_t *position, int64_t *time, int timebase) {
+ if (position == nullptr || time == nullptr
+ || timebase < 0 || timebase >= TIMEBASE_MAX) {
+ return BAD_VALUE;
+ }
+ // look for the closest-to-hw stage in the pipeline with a valid timestamp.
+ // We omit LOCATION_CLIENT as we prefer at least LOCATION_SERVER based accuracy
+ // when getting the best timestamp.
+ for (int i = LOCATION_MAX - 1; i >= LOCATION_SERVER; --i) {
+ if (mTimeNs[i] > 0) {
+ *position = mPosition[i];
+ *time = mTimeNs[i] + mTimebaseOffset[timebase];
+ return OK;
+ }
+ }
+ return INVALID_OPERATION;
+ }
+
+ // convert fields to a printable string
+ std::string toString() {
+ std::stringstream ss;
+
+ ss << "BOOTTIME offset " << mTimebaseOffset[TIMEBASE_BOOTTIME] << "\n";
+ for (int i = 0; i < LOCATION_MAX; ++i) {
+ ss << "ExtendedTimestamp[" << i << "] position: "
+ << mPosition[i] << " time: " << mTimeNs[i] << "\n";
+ }
+ return ss.str();
+ }
+ // TODO:
+ // Consider adding buffer status:
+ // size, available, algorithmic latency
+};
+
} // namespace
#endif // ANDROID_AUDIO_TIMESTAMP_H