Merge "Enable FastTrack timestamps" into nyc-dev
diff --git a/include/media/AudioTimestamp.h b/include/media/AudioTimestamp.h
index e6ca225..531b548 100644
--- a/include/media/AudioTimestamp.h
+++ b/include/media/AudioTimestamp.h
@@ -79,7 +79,7 @@
// 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) {
+ status_t getBestTimestamp(int64_t *position, int64_t *time, int timebase) const {
if (position == nullptr || time == nullptr
|| timebase < 0 || timebase >= TIMEBASE_MAX) {
return BAD_VALUE;
@@ -97,6 +97,20 @@
return INVALID_OPERATION;
}
+ status_t getBestTimestamp(AudioTimestamp *timestamp) const {
+ if (timestamp == nullptr) {
+ return BAD_VALUE;
+ }
+ int64_t position, time;
+ if (getBestTimestamp(&position, &time, TIMEBASE_MONOTONIC) == OK) {
+ timestamp->mPosition = position;
+ timestamp->mTime.tv_sec = time / 1000000000;
+ timestamp->mTime.tv_nsec = time - timestamp->mTime.tv_sec * 1000000000LL;
+ return OK;
+ }
+ return INVALID_OPERATION;
+ }
+
// convert fields to a printable string
std::string toString() {
std::stringstream ss;
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index 2270c85..aa9e98c 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -315,6 +315,19 @@
// See documentation for AudioTrack.setBufferSizeInFrames()
size_t setBufferSizeInFrames(size_t requestedSize);
+ status_t getTimestamp(ExtendedTimestamp *timestamp) {
+ if (timestamp == nullptr) {
+ return BAD_VALUE;
+ }
+ (void) mTimestampObserver.poll(mTimestamp);
+ *timestamp = mTimestamp;
+ return OK;
+ }
+
+ void clearTimestamp() {
+ mTimestamp.clear();
+ }
+
protected:
// This is set by AudioTrack.setBufferSizeInFrames().
// A write will not fill the buffer above this limit.
@@ -322,6 +335,12 @@
private:
Modulo<uint32_t> mEpoch;
+
+ // The shared buffer contents referred to by the timestamp observer
+ // is initialized when the server proxy created. A local zero timestamp
+ // is initialized by the client constructor.
+ ExtendedTimestampQueue::Observer mTimestampObserver;
+ ExtendedTimestamp mTimestamp; // initialized by constructor
};
// ----------------------------------------------------------------------------
@@ -333,7 +352,9 @@
size_t frameSize, bool clientInServer = false)
: ClientProxy(cblk, buffers, frameCount, frameSize, true /*isOut*/,
clientInServer),
- mPlaybackRateMutator(&cblk->mPlaybackRateQueue) { }
+ mPlaybackRateMutator(&cblk->mPlaybackRateQueue) {
+ }
+
virtual ~AudioTrackClientProxy() { }
// No barriers on the following operations, so the ordering of loads/stores
@@ -431,23 +452,9 @@
AudioRecordClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
size_t frameSize)
: ClientProxy(cblk, buffers, frameCount, frameSize,
- false /*isOut*/, false /*clientInServer*/)
- , mTimestampObserver(&cblk->mExtendedTimestampQueue) { }
+ false /*isOut*/, false /*clientInServer*/) { }
~AudioRecordClientProxy() { }
- status_t getTimestamp(ExtendedTimestamp *timestamp) {
- if (timestamp == nullptr) {
- return BAD_VALUE;
- }
- (void) mTimestampObserver.poll(mTimestamp);
- *timestamp = mTimestamp;
- return OK;
- }
-
- void clearTimestamp() {
- mTimestamp.clear();
- }
-
// Advances the client read pointer to the server write head pointer
// effectively flushing the client read buffer. The effect is
// instantaneous. Returns the number of frames flushed.
@@ -457,13 +464,6 @@
android_atomic_release_store(rear, &mCblk->u.mStreaming.mFront);
return (Modulo<int32_t>(rear) - front).unsignedValue();
}
-
-private:
- // The shared buffer contents referred to by the timestamp observer
- // is initialized when the server proxy created. A local zero timestamp
- // is initialized by the client constructor.
- ExtendedTimestampQueue::Observer mTimestampObserver;
- ExtendedTimestamp mTimestamp; // initialized by constructor
};
// ----------------------------------------------------------------------------
@@ -509,10 +509,20 @@
// buffer->mRaw is NULL.
virtual void releaseBuffer(Buffer* buffer);
+ // Return the total number of frames that AudioFlinger has obtained and released
+ virtual int64_t framesReleased() const { return mReleased; }
+
+ // Expose timestamp to client proxy. Should only be called by a single thread.
+ virtual void setTimestamp(const ExtendedTimestamp ×tamp) {
+ mTimestampMutator.push(timestamp);
+ }
+
protected:
size_t mAvailToClient; // estimated frames available to client prior to releaseBuffer()
int32_t mFlush; // our copy of cblk->u.mStreaming.mFlush, for streaming output only
int64_t mReleased; // our copy of cblk->mServer, at 64 bit resolution
+
+ ExtendedTimestampQueue::Mutator mTimestampMutator;
};
// Proxy used by AudioFlinger for servicing AudioTrack
@@ -556,9 +566,6 @@
// and thus which resulted in an underrun.
virtual uint32_t getUnderrunFrames() const { return mCblk->u.mStreaming.mUnderrunFrames; }
- // Return the total number of frames that AudioFlinger has obtained and released
- virtual size_t framesReleased() const { return mReleased; }
-
// Return the playback speed and pitch read atomically. Not multi-thread safe on server side.
AudioPlaybackRate getPlaybackRate();
@@ -611,20 +618,10 @@
public:
AudioRecordServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
size_t frameSize, bool clientInServer)
- : ServerProxy(cblk, buffers, frameCount, frameSize, false /*isOut*/, clientInServer)
- , mTimestampMutator(&cblk->mExtendedTimestampQueue) { }
+ : ServerProxy(cblk, buffers, frameCount, frameSize, false /*isOut*/, clientInServer) { }
- // Return the total number of frames that AudioFlinger has obtained and released
- virtual int64_t framesReleased() const { return mReleased; }
-
- // Expose timestamp to client proxy. Should only be called by a single thread.
- virtual void setExtendedTimestamp(const ExtendedTimestamp ×tamp) {
- mTimestampMutator.push(timestamp);
- }
protected:
virtual ~AudioRecordServerProxy() { }
-
- ExtendedTimestampQueue::Mutator mTimestampMutator;
};
// ----------------------------------------------------------------------------
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index b2a5f14..33dcc57 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -528,12 +528,14 @@
mTimestampStartupGlitchReported = false;
mRetrogradeMotionReported = false;
- // If previousState == STATE_STOPPED, we reactivate markers (mMarkerPosition != 0)
+ // If previousState == STATE_STOPPED, we clear the timestamp so that it
+ // needs a new server push. We also reactivate markers (mMarkerPosition != 0)
// as the position is reset to 0. This is legacy behavior. This is not done
// in stop() to avoid a race condition where the last marker event is issued twice.
// Note: the if is technically unnecessary because previousState == STATE_FLUSHED
// is only for streaming tracks, and mMarkerReached is already set to false.
if (previousState == STATE_STOPPED) {
+ mProxy->clearTimestamp(); // need new server push for valid timestamp
mMarkerReached = false;
}
@@ -2169,11 +2171,6 @@
// Set false here to cover all the error return cases.
mPreviousTimestampValid = false;
- // FIXME not implemented for fast tracks; should use proxy and SSQ
- if (mFlags & AUDIO_OUTPUT_FLAG_FAST) {
- return INVALID_OPERATION;
- }
-
switch (mState) {
case STATE_ACTIVE:
case STATE_PAUSED:
@@ -2203,7 +2200,22 @@
// The presented frame count must always lag behind the consumed frame count.
// To avoid a race, read the presented frames first. This ensures that presented <= consumed.
- status_t status = mAudioTrack->getTimestamp(timestamp);
+
+ status_t status;
+ if (!(mFlags & AUDIO_OUTPUT_FLAG_FAST)) {
+ // use Binder to get timestamp
+ status = mAudioTrack->getTimestamp(timestamp);
+ } else {
+ // read timestamp from shared memory
+ ExtendedTimestamp ets;
+ status = mProxy->getTimestamp(&ets);
+ if (status == OK) {
+ status = ets.getBestTimestamp(×tamp);
+ }
+ if (status == INVALID_OPERATION) {
+ status = WOULD_BLOCK;
+ }
+ }
if (status != NO_ERROR) {
ALOGV_IF(status != WOULD_BLOCK, "getTimestamp error:%#x", status);
return status;
diff --git a/media/libmedia/AudioTrackShared.cpp b/media/libmedia/AudioTrackShared.cpp
index 988386e..1d15495 100644
--- a/media/libmedia/AudioTrackShared.cpp
+++ b/media/libmedia/AudioTrackShared.cpp
@@ -69,6 +69,7 @@
: Proxy(cblk, buffers, frameCount, frameSize, isOut, clientInServer)
, mBufferSizeInFrames(frameCount)
, mEpoch(0)
+ , mTimestampObserver(&cblk->mExtendedTimestampQueue)
{
}
@@ -598,6 +599,7 @@
size_t frameSize, bool isOut, bool clientInServer)
: Proxy(cblk, buffers, frameCount, frameSize, isOut, clientInServer),
mAvailToClient(0), mFlush(0), mReleased(0)
+ , mTimestampMutator(&cblk->mExtendedTimestampQueue)
{
}
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index c81bbf9..fe3cc53 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -89,6 +89,7 @@
// ExtendedAudioBufferProvider interface
virtual size_t framesReady() const;
virtual size_t framesReleased() const;
+ virtual void onTimestamp(const AudioTimestamp ×tamp);
bool isPausing() const { return mState == PAUSING; }
bool isPaused() const { return mState == PAUSED; }
diff --git a/services/audioflinger/RecordTracks.h b/services/audioflinger/RecordTracks.h
index 5f70479..6f84af1 100644
--- a/services/audioflinger/RecordTracks.h
+++ b/services/audioflinger/RecordTracks.h
@@ -76,8 +76,6 @@
// be dropped and therefore not read by the application.
sp<SyncEvent> mSyncStartEvent;
- AudioRecordServerProxy *mAudioRecordServerProxy;
-
// number of captured frames to drop after the start sync event has been received.
// when < 0, maximum frames to drop before starting capture even if sync event is
// not received
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 5aff394..4807400 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -6157,7 +6157,7 @@
// update frame information and push timestamp out
activeTrack->updateTrackFrameInfo(
- activeTrack->mAudioRecordServerProxy->framesReleased(),
+ activeTrack->mServerProxy->framesReleased(),
mTimestamp.mPosition[ExtendedTimestamp::LOCATION_SERVER],
mSampleRate, mTimestamp);
}
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index b719046..536581c 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -596,6 +596,20 @@
return mAudioTrackServerProxy->framesReleased();
}
+void AudioFlinger::PlaybackThread::Track::onTimestamp(const AudioTimestamp ×tamp)
+{
+ // This call comes from a FastTrack and should be kept lockless.
+ // The server side frames are already translated to client frames.
+
+ ExtendedTimestamp ets;
+ ets.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] =
+ timestamp.mTime.tv_sec * 1000000000LL + timestamp.mTime.tv_nsec;
+ ets.mPosition[ExtendedTimestamp::LOCATION_KERNEL] = timestamp.mPosition;
+
+ // Caution, this doesn't set the timebase for BOOTTIME properly, but is ignored right now.
+ mAudioTrackServerProxy->setTimestamp(ets);
+}
+
// Don't call for fast tracks; the framesReady() could result in priority inversion
bool AudioFlinger::PlaybackThread::Track::isReady() const {
if (mFillingUpStatus != FS_FILLING || isStopped() || isPausing()) {
@@ -1438,9 +1452,8 @@
return;
}
- mAudioRecordServerProxy = new AudioRecordServerProxy(mCblk, mBuffer, frameCount,
+ mServerProxy = new AudioRecordServerProxy(mCblk, mBuffer, frameCount,
mFrameSize, !isExternalTrack());
- mServerProxy = mAudioRecordServerProxy;
mResamplerBufferProvider = new ResamplerBufferProvider(this);
@@ -1594,7 +1607,7 @@
local.mPosition[i] = relativeTrackFrames + trackFramesReleased;
}
}
- mAudioRecordServerProxy->setExtendedTimestamp(local);
+ mServerProxy->setTimestamp(local);
}
AudioFlinger::RecordThread::PatchRecord::PatchRecord(RecordThread *recordThread,