summaryrefslogtreecommitdiff
path: root/audio_proxy
diff options
context:
space:
mode:
authoryucliu <yucliu@google.com>2022-03-09 10:59:11 -0800
committerYuchen Liu <yucliu@google.com>2022-03-25 17:02:29 +0000
commit5dd30deaae4457f42a60252d4ca6f9da78bc5833 (patch)
tree167f9679fdb43c38a51a50893cc45951d1687d89 /audio_proxy
parent3af881dd3ea1d369d0a401cf85d506f0f64cfa3b (diff)
downloadatv-5dd30deaae4457f42a60252d4ca6f9da78bc5833.tar.gz
[AudioProxy] PcmOnlyConfigOutputStreamTest
VTS test runs without the audio proxy client app. So audio proxy will use the DummyBusOutputStream. Change the write behavior to actually consume the PCMs in realtime. Bug: 219879559 Test: VtsHalAudioV7_0TargetTest Change-Id: I904da685f3aafd72d0fb3f22923a9471ae841230 (cherry picked from commit 63c4ab65b17908d056c60e9087923d50c312c7b8)
Diffstat (limited to 'audio_proxy')
-rw-r--r--audio_proxy/service/DummyBusOutputStream.cpp75
-rw-r--r--audio_proxy/service/DummyBusOutputStream.h19
-rw-r--r--audio_proxy/service/main.cpp2
3 files changed, 90 insertions, 6 deletions
diff --git a/audio_proxy/service/DummyBusOutputStream.cpp b/audio_proxy/service/DummyBusOutputStream.cpp
index 7a626c9..b18728f 100644
--- a/audio_proxy/service/DummyBusOutputStream.cpp
+++ b/audio_proxy/service/DummyBusOutputStream.cpp
@@ -14,9 +14,34 @@
#include "DummyBusOutputStream.h"
+#include <algorithm>
+
+#include <aidl/device/google/atv/audio_proxy/TimeSpec.h>
#include <android-base/logging.h>
+#include <unistd.h>
+
+using aidl::device::google::atv::audio_proxy::TimeSpec;
namespace audio_proxy::service {
+namespace {
+constexpr int64_t kOneSecInNs = 1'000'000'000;
+constexpr int64_t kOneSecInUs = 1'000'000;
+constexpr int64_t kOneUSecInNs = 1'000;
+
+int64_t timespecDelta(const timespec& newTime, const timespec& oldTime) {
+ int64_t deltaSec = 0;
+ int64_t deltaNSec = 0;
+ if (newTime.tv_nsec >= oldTime.tv_nsec) {
+ deltaSec = newTime.tv_sec - oldTime.tv_sec;
+ deltaNSec = newTime.tv_nsec - oldTime.tv_nsec;
+ } else {
+ deltaSec = newTime.tv_sec - oldTime.tv_sec - 1;
+ deltaNSec = kOneSecInNs + newTime.tv_nsec - oldTime.tv_nsec;
+ }
+
+ return deltaSec * kOneSecInUs + deltaNSec / kOneUSecInNs;
+}
+} // namespace
DummyBusOutputStream::DummyBusOutputStream(const std::string& address,
const AidlAudioConfig& config,
@@ -32,18 +57,62 @@ bool DummyBusOutputStream::flush() { return true; }
bool DummyBusOutputStream::close() { return true; }
bool DummyBusOutputStream::setVolume(float left, float right) { return true; }
-size_t DummyBusOutputStream::availableToWrite() { return 0; }
+size_t DummyBusOutputStream::availableToWrite() {
+ return mWritingFrameSize * mWritingFrameCount;
+}
AidlWriteStatus DummyBusOutputStream::writeRingBuffer(const uint8_t* firstMem,
size_t firstLength,
const uint8_t* secondMem,
size_t secondLength) {
- return {};
+ size_t bufferBytes = firstLength + secondLength;
+ int64_t numFrames = bufferBytes / getFrameSize();
+ int64_t durationUs = numFrames * kOneSecInUs / mConfig.sampleRateHz;
+
+ timespec now = {0, 0};
+ clock_gettime(CLOCK_MONOTONIC, &now);
+ if (mStartTime.tv_sec == 0) {
+ mStartTime = now;
+ }
+
+ // Check underrun
+ int64_t elapsedTimeUs = timespecDelta(now, mStartTime);
+ if (elapsedTimeUs > mInputUsSinceStart) {
+ // Underrun
+ mPlayedUsBeforeUnderrun += mInputUsSinceStart;
+ mStartTime = now;
+ mInputUsSinceStart = 0;
+ }
+
+ // Wait if buffer full.
+ mInputUsSinceStart += durationUs;
+ int64_t waitTimeUs = mInputUsSinceStart - elapsedTimeUs - mMaxBufferUs;
+ if (waitTimeUs > 0) {
+ usleep(waitTimeUs);
+ clock_gettime(CLOCK_MONOTONIC, &now);
+ }
+
+ // Calculate played frames.
+ int64_t playedUs =
+ mPlayedUsBeforeUnderrun +
+ std::min(timespecDelta(now, mStartTime), mInputUsSinceStart);
+
+ TimeSpec timeSpec = {now.tv_sec, now.tv_nsec};
+
+ AidlWriteStatus status;
+ status.written = bufferBytes;
+ status.position = {playedUs * mConfig.sampleRateHz / kOneSecInUs, timeSpec};
+
+ return status;
}
bool DummyBusOutputStream::prepareForWritingImpl(uint32_t frameSize,
uint32_t frameCount) {
+ // The `frame` here is not audio frame, it doesn't count the sample format and
+ // channel layout.
+ mMaxBufferUs = frameSize * frameCount * 10 * kOneSecInUs /
+ (mConfig.sampleRateHz * getFrameSize());
return true;
}
-} // namespace audio_proxy::service \ No newline at end of file
+} // namespace audio_proxy::service
diff --git a/audio_proxy/service/DummyBusOutputStream.h b/audio_proxy/service/DummyBusOutputStream.h
index 400ccf2..c5ca47e 100644
--- a/audio_proxy/service/DummyBusOutputStream.h
+++ b/audio_proxy/service/DummyBusOutputStream.h
@@ -16,10 +16,12 @@
#include "BusOutputStream.h"
+#include <time.h>
+
namespace audio_proxy::service {
-// Impl of BusOutputStream which blocks the write, a.k.a, it always has
-// 0 available write space.
+// Impl of BusOutputStream which has a small buffer and consumes the audio data
+// in real time.
class DummyBusOutputStream : public BusOutputStream {
public:
DummyBusOutputStream(const std::string& address,
@@ -41,6 +43,19 @@ class DummyBusOutputStream : public BusOutputStream {
protected:
bool prepareForWritingImpl(uint32_t frameSize, uint32_t frameCount) override;
+
+ private:
+ // Buffer capacity.
+ int64_t mMaxBufferUs = 0;
+
+ // Timestamp for the first played frame. Underrun will reset it.
+ timespec mStartTime = {0, 0};
+
+ // Total written buffer size in us after `mStartTime` reset.
+ int64_t mInputUsSinceStart = 0;
+
+ // Total played buffer size in us before underrun.
+ int64_t mPlayedUsBeforeUnderrun = 0;
};
} // namespace audio_proxy::service \ No newline at end of file
diff --git a/audio_proxy/service/main.cpp b/audio_proxy/service/main.cpp
index a277dd3..352ff0d 100644
--- a/audio_proxy/service/main.cpp
+++ b/audio_proxy/service/main.cpp
@@ -36,7 +36,7 @@ int main(int argc, char** argv) {
}
// Default stream config.
- StreamConfig defaultStreamConfig = {100, 100};
+ StreamConfig defaultStreamConfig = {10, 10};
config->streams.emplace("default", defaultStreamConfig);
// Config thread pool.