OSDN Git Service

aaudio: prevent retrograde motion in Legacy timestamps
authorPhil Burk <philburk@google.com>
Wed, 30 Aug 2017 16:29:48 +0000 (09:29 -0700)
committerPhil Burk <philburk@google.com>
Thu, 7 Sep 2017 00:08:19 +0000 (17:08 -0700)
Use MonotonicCounter for timestamp position.

Bug: 63918065
Test: write_sine_callback.cpp and test_timestamps.cpp
Change-Id: Iea58384e2d96adcfad586e8c522024baaecccb8c

media/libaaudio/src/legacy/AudioStreamLegacy.cpp
media/libaaudio/src/legacy/AudioStreamLegacy.h
media/libaaudio/src/legacy/AudioStreamRecord.cpp
media/libaaudio/src/legacy/AudioStreamTrack.cpp
media/libaaudio/src/utility/MonotonicCounter.h

index 2816bac..ee29177 100644 (file)
@@ -21,6 +21,7 @@
 #include <stdint.h>
 #include <utils/String16.h>
 #include <media/AudioTrack.h>
+#include <media/AudioTimestamp.h>
 #include <aaudio/AAudio.h>
 
 #include "core/AudioStream.h"
@@ -46,16 +47,32 @@ aaudio_legacy_callback_t AudioStreamLegacy::getLegacyCallback() {
     return AudioStreamLegacy_callback;
 }
 
-// Implement FixedBlockProcessor
-int32_t AudioStreamLegacy::onProcessFixedBlock(uint8_t *buffer, int32_t numBytes) {
-    int32_t frameCount = numBytes / getBytesPerFrame();
+int32_t AudioStreamLegacy::callDataCallbackFrames(uint8_t *buffer, int32_t numFrames) {
+    if (getDirection() == AAUDIO_DIRECTION_INPUT) {
+        // Increment before because we already got the data from the device.
+        incrementFramesRead(numFrames);
+    }
+
     // Call using the AAudio callback interface.
     AAudioStream_dataCallback appCallback = getDataCallbackProc();
-    return (*appCallback)(
+    aaudio_data_callback_result_t callbackResult = (*appCallback)(
             (AAudioStream *) this,
             getDataCallbackUserData(),
             buffer,
-            frameCount);
+            numFrames);
+
+    if (callbackResult == AAUDIO_CALLBACK_RESULT_CONTINUE
+            && getDirection() == AAUDIO_DIRECTION_OUTPUT) {
+        // Increment after because we are going to write the data to the device.
+        incrementFramesWritten(numFrames);
+    }
+    return callbackResult;
+}
+
+// Implement FixedBlockProcessor
+int32_t AudioStreamLegacy::onProcessFixedBlock(uint8_t *buffer, int32_t numBytes) {
+    int32_t numFrames = numBytes / getBytesPerFrame();
+    return callDataCallbackFrames(buffer, numFrames);
 }
 
 void AudioStreamLegacy::processCallbackCommon(aaudio_callback_operation_t opcode, void *info) {
@@ -81,16 +98,11 @@ void AudioStreamLegacy::processCallbackCommon(aaudio_callback_operation_t opcode
                             (uint8_t *) audioBuffer->raw, byteCount);
                 } else {
                     // Call using the AAudio callback interface.
-                    callbackResult = (*getDataCallbackProc())(
-                            (AAudioStream *) this,
-                            getDataCallbackUserData(),
-                            audioBuffer->raw,
-                            audioBuffer->frameCount
-                            );
+                    callbackResult = callDataCallbackFrames((uint8_t *)audioBuffer->raw,
+                                                            audioBuffer->frameCount);
                 }
                 if (callbackResult == AAUDIO_CALLBACK_RESULT_CONTINUE) {
                     audioBuffer->size = audioBuffer->frameCount * getBytesPerFrame();
-                    incrementClientFrameCounter(audioBuffer->frameCount);
                 } else {
                     audioBuffer->size = 0;
                 }
@@ -139,7 +151,18 @@ aaudio_result_t AudioStreamLegacy::getBestTimestamp(clockid_t clockId,
             return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
             break;
     }
-    status_t status = extendedTimestamp->getBestTimestamp(framePosition, timeNanoseconds, timebase);
+    ExtendedTimestamp::Location location = ExtendedTimestamp::Location::LOCATION_INVALID;
+    int64_t localPosition;
+    status_t status = extendedTimestamp->getBestTimestamp(&localPosition, timeNanoseconds,
+                                                          timebase, &location);
+    // use MonotonicCounter to prevent retrograde motion.
+    mTimestampPosition.update32((int32_t)localPosition);
+    *framePosition = mTimestampPosition.get();
+
+//    ALOGD("getBestTimestamp() fposition: server = %6lld, kernel = %6lld, location = %d",
+//          (long long) extendedTimestamp->mPosition[ExtendedTimestamp::Location::LOCATION_SERVER],
+//          (long long) extendedTimestamp->mPosition[ExtendedTimestamp::Location::LOCATION_KERNEL],
+//          (int)location);
     return AAudioConvert_androidToAAudioResult(status);
 }
 
index d2ef3c7..66c216c 100644 (file)
@@ -63,6 +63,8 @@ public:
 
     aaudio_legacy_callback_t getLegacyCallback();
 
+    int32_t callDataCallbackFrames(uint8_t *buffer, int32_t numFrames);
+
     // This is public so it can be called from the C callback function.
     // This is called from the AudioTrack/AudioRecord client.
     virtual void processCallback(int event, void *info) = 0;
@@ -122,6 +124,7 @@ protected:
 
     MonotonicCounter           mFramesWritten;
     MonotonicCounter           mFramesRead;
+    MonotonicCounter           mTimestampPosition;
 
     FixedBlockAdapter         *mBlockAdapter = nullptr;
     aaudio_wrapping_frames_t   mPositionWhenStarting = 0;
index 041280d..c8b94ae 100644 (file)
@@ -233,8 +233,10 @@ aaudio_result_t AudioStreamRecord::requestStop() {
     onStop();
     setState(AAUDIO_STREAM_STATE_STOPPING);
     incrementFramesWritten(getFramesRead() - getFramesWritten()); // TODO review
+    mTimestampPosition.set(getFramesRead());
     mAudioRecord->stop();
     mFramesRead.reset32();
+    mTimestampPosition.reset32();
     return AAUDIO_OK;
 }
 
index 155362c..702b12a 100644 (file)
@@ -285,6 +285,7 @@ aaudio_result_t AudioStreamTrack::requestFlush() {
     incrementFramesRead(getFramesWritten() - getFramesRead());
     mAudioTrack->flush();
     mFramesWritten.reset32();
+    mTimestampPosition.reset32();
     return AAUDIO_OK;
 }
 
@@ -298,8 +299,10 @@ aaudio_result_t AudioStreamTrack::requestStop() {
     onStop();
     setState(AAUDIO_STREAM_STATE_STOPPING);
     incrementFramesRead(getFramesWritten() - getFramesRead()); // TODO review
+    mTimestampPosition.set(getFramesWritten());
     stop();
     mFramesWritten.reset32();
+    mTimestampPosition.reset32();
     return AAUDIO_OK;
 }
 
@@ -447,5 +450,18 @@ aaudio_result_t AudioStreamTrack::getTimestamp(clockid_t clockId,
     if (status != NO_ERROR) {
         return AAudioConvert_androidToAAudioResult(status);
     }
-    return getBestTimestamp(clockId, framePosition, timeNanoseconds, &extendedTimestamp);
+    int64_t position = 0;
+    int64_t nanoseconds = 0;
+    aaudio_result_t result = getBestTimestamp(clockId, &position,
+                                              &nanoseconds, &extendedTimestamp);
+    if (result == AAUDIO_OK) {
+        if (position < getFramesWritten()) {
+            *framePosition = position;
+            *timeNanoseconds = nanoseconds;
+            return result;
+        } else {
+            return AAUDIO_ERROR_INVALID_STATE; // TODO review, documented but not consistent
+        }
+    }
+    return result;
 }
index 81d7f89..13c92a2 100644 (file)
@@ -41,6 +41,13 @@ public:
     }
 
     /**
+     * set the current value of the counter
+     */
+    void set(int64_t counter) {
+        mCounter64 = counter;
+    }
+
+    /**
      * Advance the counter if delta is positive.
      * @return current value of the counter
      */