libaaudio: implement callback
Use AudioTrack and AudioRecord TRANSFER_CALLBACK.
Add FixedBlockAdapter to provide fixed size callbacks.
Bug: 36489240
Test: CTS test_aaudio.cpp
Change-Id: Id2034dd640f878dd27fee6b43ad80a01c627dfd6
Signed-off-by: Phil Burk <philburk@google.com>
diff --git a/media/libaaudio/src/legacy/AudioStreamLegacy.cpp b/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
new file mode 100644
index 0000000..baa24c9
--- /dev/null
+++ b/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AudioStreamLegacy"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include <stdint.h>
+#include <utils/String16.h>
+#include <media/AudioTrack.h>
+#include <aaudio/AAudio.h>
+
+#include "core/AudioStream.h"
+#include "legacy/AudioStreamLegacy.h"
+
+using namespace android;
+using namespace aaudio;
+
+AudioStreamLegacy::AudioStreamLegacy()
+ : AudioStream() {
+}
+
+AudioStreamLegacy::~AudioStreamLegacy() {
+}
+
+// Called from AudioTrack.cpp or AudioRecord.cpp
+static void AudioStreamLegacy_callback(int event, void* userData, void *info) {
+ AudioStreamLegacy *streamLegacy = (AudioStreamLegacy *) userData;
+ streamLegacy->processCallback(event, info);
+}
+
+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();
+ // Call using the AAudio callback interface.
+ AAudioStream_dataCallback appCallback = getDataCallbackProc();
+ return (*appCallback)(
+ (AAudioStream *) this,
+ getDataCallbackUserData(),
+ buffer,
+ frameCount);
+}
+
+void AudioStreamLegacy::processCallbackCommon(aaudio_callback_operation_t opcode, void *info) {
+ aaudio_data_callback_result_t callbackResult;
+ switch (opcode) {
+ case AAUDIO_CALLBACK_OPERATION_PROCESS_DATA: {
+ // Note that this code assumes an AudioTrack::Buffer is the same as AudioRecord::Buffer
+ // TODO define our own AudioBuffer and pass it from the subclasses.
+ AudioTrack::Buffer *audioBuffer = static_cast<AudioTrack::Buffer *>(info);
+ if (audioBuffer->frameCount == 0) return;
+
+ // If the caller specified an exact size then use a block size adapter.
+ if (mBlockAdapter != nullptr) {
+ int32_t byteCount = audioBuffer->frameCount * getBytesPerFrame();
+ callbackResult = mBlockAdapter->processVariableBlock((uint8_t *) audioBuffer->raw,
+ byteCount);
+ } else {
+ // Call using the AAudio callback interface.
+ callbackResult = (*getDataCallbackProc())(
+ (AAudioStream *) this,
+ getDataCallbackUserData(),
+ audioBuffer->raw,
+ audioBuffer->frameCount
+ );
+ }
+ if (callbackResult == AAUDIO_CALLBACK_RESULT_CONTINUE) {
+ audioBuffer->size = audioBuffer->frameCount * getBytesPerFrame();
+ } else {
+ audioBuffer->size = 0;
+ }
+ }
+ break;
+
+ // Stream got rerouted so we disconnect.
+ case AAUDIO_CALLBACK_OPERATION_DISCONNECTED: {
+ ALOGD("AudioStreamAAudio(): callbackLoop() stream disconnected");
+ if (getErrorCallbackProc() != nullptr) {
+ (*getErrorCallbackProc())(
+ (AAudioStream *) this,
+ getErrorCallbackUserData(),
+ AAUDIO_OK
+ );
+ }
+ mCallbackEnabled.store(false);
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
diff --git a/media/libaaudio/src/legacy/AudioStreamLegacy.h b/media/libaaudio/src/legacy/AudioStreamLegacy.h
new file mode 100644
index 0000000..c109ee7
--- /dev/null
+++ b/media/libaaudio/src/legacy/AudioStreamLegacy.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LEGACY_AUDIO_STREAM_LEGACY_H
+#define LEGACY_AUDIO_STREAM_LEGACY_H
+
+
+#include <aaudio/AAudio.h>
+
+#include "AudioStream.h"
+#include "AAudioLegacy.h"
+#include "utility/FixedBlockAdapter.h"
+
+namespace aaudio {
+
+
+typedef void (*aaudio_legacy_callback_t)(int event, void* user, void *info);
+
+enum {
+ /**
+ * Request that the callback function should fill the data buffer of an output stream,
+ * or process the data of an input stream.
+ * The address parameter passed to the callback function will point to a data buffer.
+ * For an input stream, the data is read-only.
+ * The value1 parameter will be the number of frames.
+ * The value2 parameter is reserved and will be set to zero.
+ * The callback should return AAUDIO_CALLBACK_RESULT_CONTINUE or AAUDIO_CALLBACK_RESULT_STOP.
+ */
+ AAUDIO_CALLBACK_OPERATION_PROCESS_DATA,
+
+ /**
+ * Inform the callback function that the stream was disconnected.
+ * The address parameter passed to the callback function will be NULL.
+ * The value1 will be an error code or AAUDIO_OK.
+ * The value2 parameter is reserved and will be set to zero.
+ * The callback return value will be ignored.
+ */
+ AAUDIO_CALLBACK_OPERATION_DISCONNECTED,
+};
+typedef int32_t aaudio_callback_operation_t;
+
+
+class AudioStreamLegacy : public AudioStream, public FixedBlockProcessor {
+public:
+ AudioStreamLegacy();
+
+ virtual ~AudioStreamLegacy();
+
+ aaudio_legacy_callback_t getLegacyCallback();
+
+ // 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;
+
+ void processCallbackCommon(aaudio_callback_operation_t opcode, void *info);
+
+ // Implement FixedBlockProcessor
+ int32_t onProcessFixedBlock(uint8_t *buffer, int32_t numBytes) override;
+
+protected:
+ FixedBlockAdapter *mBlockAdapter = nullptr;
+ aaudio_wrapping_frames_t mPositionWhenStarting = 0;
+ int32_t mCallbackBufferSize = 0;
+};
+
+} /* namespace aaudio */
+
+#endif //LEGACY_AUDIO_STREAM_LEGACY_H
diff --git a/media/libaaudio/src/legacy/AudioStreamRecord.cpp b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
index 78c68ae..f0a6ceb 100644
--- a/media/libaaudio/src/legacy/AudioStreamRecord.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
@@ -24,14 +24,16 @@
#include <aaudio/AAudio.h>
#include "AudioClock.h"
-#include "AudioStreamRecord.h"
-#include "utility/AAudioUtilities.h"
+#include "legacy/AudioStreamLegacy.h"
+#include "legacy/AudioStreamRecord.h"
+#include "utility/FixedBlockWriter.h"
using namespace android;
using namespace aaudio;
AudioStreamRecord::AudioStreamRecord()
- : AudioStream()
+ : AudioStreamLegacy()
+ , mFixedBlockWriter(*this)
{
}
@@ -58,7 +60,6 @@
? 2 : getSamplesPerFrame();
audio_channel_mask_t channelMask = audio_channel_in_mask_from_count(samplesPerFrame);
- AudioRecord::callback_t callback = nullptr;
audio_input_flags_t flags = (audio_input_flags_t) AUDIO_INPUT_FLAG_NONE;
size_t frameCount = (builder.getBufferCapacity() == AAUDIO_UNSPECIFIED) ? 0
@@ -68,6 +69,17 @@
? AUDIO_FORMAT_PCM_FLOAT
: AAudioConvert_aaudioToAndroidDataFormat(getFormat());
+ // Setup the callback if there is one.
+ AudioRecord::callback_t callback = nullptr;
+ void *callbackData = nullptr;
+ AudioRecord::transfer_type streamTransferType = AudioRecord::transfer_type::TRANSFER_SYNC;
+ if (builder.getDataCallbackProc() != nullptr) {
+ streamTransferType = AudioRecord::transfer_type::TRANSFER_CALLBACK;
+ callback = getLegacyCallback();
+ callbackData = this;
+ }
+ mCallbackBufferSize = builder.getFramesPerDataCallback();
+
mAudioRecord = new AudioRecord(
AUDIO_SOURCE_DEFAULT,
getSampleRate(),
@@ -76,10 +88,10 @@
mOpPackageName, // const String16& opPackageName TODO does not compile
frameCount,
callback,
- nullptr, // void* user = nullptr,
+ callbackData,
0, // uint32_t notificationFrames = 0,
AUDIO_SESSION_ALLOCATE,
- AudioRecord::TRANSFER_DEFAULT,
+ streamTransferType,
flags
// int uid = -1,
// pid_t pid = -1,
@@ -99,6 +111,15 @@
setSamplesPerFrame(mAudioRecord->channelCount());
setFormat(AAudioConvert_androidToAAudioDataFormat(mAudioRecord->format()));
+ // We may need to pass the data through a block size adapter to guarantee constant size.
+ if (mCallbackBufferSize != AAUDIO_UNSPECIFIED) {
+ int callbackSizeBytes = getBytesPerFrame() * mCallbackBufferSize;
+ mFixedBlockWriter.open(callbackSizeBytes);
+ mBlockAdapter = &mFixedBlockWriter;
+ } else {
+ mBlockAdapter = nullptr;
+ }
+
setState(AAUDIO_STREAM_STATE_OPEN);
return AAUDIO_OK;
@@ -111,9 +132,29 @@
mAudioRecord.clear();
setState(AAUDIO_STREAM_STATE_CLOSED);
}
+ mFixedBlockWriter.close();
return AAUDIO_OK;
}
+void AudioStreamRecord::processCallback(int event, void *info) {
+
+ ALOGD("AudioStreamRecord::processCallback(), event %d", event);
+ switch (event) {
+ case AudioRecord::EVENT_MORE_DATA:
+ processCallbackCommon(AAUDIO_CALLBACK_OPERATION_PROCESS_DATA, info);
+ break;
+
+ // Stream got rerouted so we disconnect.
+ case AudioRecord::EVENT_NEW_IAUDIORECORD:
+ processCallbackCommon(AAUDIO_CALLBACK_OPERATION_DISCONNECTED, info);
+ break;
+
+ default:
+ break;
+ }
+ return;
+}
+
aaudio_result_t AudioStreamRecord::requestStart()
{
if (mAudioRecord.get() == nullptr) {
@@ -124,6 +165,7 @@
if (err != OK) {
return AAudioConvert_androidToAAudioResult(err);
}
+
err = mAudioRecord->start();
if (err != OK) {
return AAudioConvert_androidToAAudioResult(err);
@@ -151,7 +193,7 @@
return AAUDIO_OK;
}
-aaudio_result_t AudioStreamRecord::updateState()
+aaudio_result_t AudioStreamRecord::updateStateWhileWaiting()
{
aaudio_result_t result = AAUDIO_OK;
aaudio_wrapping_frames_t position;
diff --git a/media/libaaudio/src/legacy/AudioStreamRecord.h b/media/libaaudio/src/legacy/AudioStreamRecord.h
index 4667f05..897a5b3 100644
--- a/media/libaaudio/src/legacy/AudioStreamRecord.h
+++ b/media/libaaudio/src/legacy/AudioStreamRecord.h
@@ -23,51 +23,58 @@
#include "AudioStreamBuilder.h"
#include "AudioStream.h"
#include "AAudioLegacy.h"
+#include "legacy/AudioStreamLegacy.h"
+#include "utility/FixedBlockWriter.h"
namespace aaudio {
/**
* Internal stream that uses the legacy AudioTrack path.
*/
-class AudioStreamRecord : public AudioStream {
+class AudioStreamRecord : public AudioStreamLegacy {
public:
AudioStreamRecord();
virtual ~AudioStreamRecord();
- virtual aaudio_result_t open(const AudioStreamBuilder & builder) override;
- virtual aaudio_result_t close() override;
+ aaudio_result_t open(const AudioStreamBuilder & builder) override;
+ aaudio_result_t close() override;
- virtual aaudio_result_t requestStart() override;
- virtual aaudio_result_t requestPause() override;
- virtual aaudio_result_t requestFlush() override;
- virtual aaudio_result_t requestStop() override;
+ aaudio_result_t requestStart() override;
+ aaudio_result_t requestPause() override;
+ aaudio_result_t requestFlush() override;
+ aaudio_result_t requestStop() override;
virtual aaudio_result_t getTimestamp(clockid_t clockId,
int64_t *framePosition,
int64_t *timeNanoseconds) override;
- virtual aaudio_result_t read(void *buffer,
+ aaudio_result_t read(void *buffer,
int32_t numFrames,
int64_t timeoutNanoseconds) override;
- virtual aaudio_result_t setBufferSize(int32_t requestedFrames) override;
+ aaudio_result_t setBufferSize(int32_t requestedFrames) override;
- virtual int32_t getBufferSize() const override;
+ int32_t getBufferSize() const override;
- virtual int32_t getBufferCapacity() const override;
+ int32_t getBufferCapacity() const override;
- virtual int32_t getXRunCount() const override;
+ int32_t getXRunCount() const override;
- virtual int32_t getFramesPerBurst() const override;
+ int32_t getFramesPerBurst() const override;
- virtual aaudio_result_t updateState() override;
+ aaudio_result_t updateStateWhileWaiting() override;
+
+ // This is public so it can be called from the C callback function.
+ void processCallback(int event, void *info) override;
private:
android::sp<android::AudioRecord> mAudioRecord;
+ // adapts between variable sized blocks and fixed size blocks
+ FixedBlockWriter mFixedBlockWriter;
+
// TODO add 64-bit position reporting to AudioRecord and use it.
- aaudio_wrapping_frames_t mPositionWhenStarting = 0;
- android::String16 mOpPackageName;
+ android::String16 mOpPackageName;
};
} /* namespace aaudio */
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.cpp b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
index a7c0677..ff87c28 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
@@ -20,20 +20,25 @@
#include <stdint.h>
#include <media/AudioTrack.h>
-#include <aaudio/AAudio.h>
-#include "utility/AudioClock.h"
-#include "AudioStreamTrack.h"
-#include "utility/AAudioUtilities.h"
+#include <aaudio/AAudio.h>
+#include "AudioClock.h"
+#include "legacy/AudioStreamLegacy.h"
+#include "legacy/AudioStreamTrack.h"
+#include "utility/FixedBlockReader.h"
using namespace android;
using namespace aaudio;
+// Arbitrary and somewhat generous number of bursts.
+#define DEFAULT_BURSTS_PER_BUFFER_CAPACITY 8
+
/*
* Create a stream that uses the AudioTrack.
*/
AudioStreamTrack::AudioStreamTrack()
- : AudioStream()
+ : AudioStreamLegacy()
+ , mFixedBlockReader(*this)
{
}
@@ -53,6 +58,8 @@
return result;
}
+ ALOGD("AudioStreamTrack::open = %p", this);
+
// Try to create an AudioTrack
// TODO Support UNSPECIFIED in AudioTrack. For now, use stereo if unspecified.
int32_t samplesPerFrame = (getSamplesPerFrame() == AAUDIO_UNSPECIFIED)
@@ -61,16 +68,40 @@
ALOGD("AudioStreamTrack::open(), samplesPerFrame = %d, channelMask = 0x%08x",
samplesPerFrame, channelMask);
- AudioTrack::callback_t callback = nullptr;
// TODO add more performance options
audio_output_flags_t flags = (audio_output_flags_t) AUDIO_OUTPUT_FLAG_FAST;
- size_t frameCount = (builder.getBufferCapacity() == AAUDIO_UNSPECIFIED) ? 0
- : builder.getBufferCapacity();
+
+ int32_t frameCount = builder.getBufferCapacity();
+ ALOGD("AudioStreamTrack::open(), requested buffer capacity %d", frameCount);
+
+ int32_t notificationFrames = 0;
+
// TODO implement an unspecified AudioTrack format then use that.
- audio_format_t format = (getFormat() == AAUDIO_UNSPECIFIED)
+ audio_format_t format = (getFormat() == AAUDIO_FORMAT_UNSPECIFIED)
? AUDIO_FORMAT_PCM_FLOAT
: AAudioConvert_aaudioToAndroidDataFormat(getFormat());
+ // Setup the callback if there is one.
+ AudioTrack::callback_t callback = nullptr;
+ void *callbackData = nullptr;
+ // Note that TRANSFER_SYNC does not allow FAST track
+ AudioTrack::transfer_type streamTransferType = AudioTrack::transfer_type::TRANSFER_SYNC;
+ if (builder.getDataCallbackProc() != nullptr) {
+ streamTransferType = AudioTrack::transfer_type::TRANSFER_CALLBACK;
+ callback = getLegacyCallback();
+ callbackData = this;
+
+ notificationFrames = builder.getFramesPerDataCallback();
+ // If the total buffer size is unspecified then base the size on the burst size.
+ if (frameCount == AAUDIO_UNSPECIFIED) {
+ // Take advantage of a special trick that allows us to create a buffer
+ // that is some multiple of the burst size.
+ notificationFrames = 0 - DEFAULT_BURSTS_PER_BUFFER_CAPACITY;
+ }
+ }
+ mCallbackBufferSize = builder.getFramesPerDataCallback();
+
+ ALOGD("AudioStreamTrack::open(), notificationFrames = %d", notificationFrames);
mAudioTrack = new AudioTrack(
(audio_stream_type_t) AUDIO_STREAM_MUSIC,
getSampleRate(),
@@ -79,10 +110,10 @@
frameCount,
flags,
callback,
- nullptr, // user callback data
- 0, // notificationFrames
+ callbackData,
+ notificationFrames,
AUDIO_SESSION_ALLOCATE,
- AudioTrack::transfer_type::TRANSFER_SYNC // TODO - this does not allow FAST
+ streamTransferType
);
// Did we get a valid track?
@@ -97,7 +128,18 @@
// Get the actual values from the AudioTrack.
setSamplesPerFrame(mAudioTrack->channelCount());
setSampleRate(mAudioTrack->getSampleRate());
- setFormat(AAudioConvert_androidToAAudioDataFormat(mAudioTrack->format()));
+ aaudio_audio_format_t aaudioFormat =
+ AAudioConvert_androidToAAudioDataFormat(mAudioTrack->format());
+ setFormat(aaudioFormat);
+
+ // We may need to pass the data through a block size adapter to guarantee constant size.
+ if (mCallbackBufferSize != AAUDIO_UNSPECIFIED) {
+ int callbackSizeBytes = getBytesPerFrame() * mCallbackBufferSize;
+ mFixedBlockReader.open(callbackSizeBytes);
+ mBlockAdapter = &mFixedBlockReader;
+ } else {
+ mBlockAdapter = nullptr;
+ }
setState(AAUDIO_STREAM_STATE_OPEN);
@@ -111,11 +153,32 @@
mAudioTrack.clear(); // TODO is this right?
setState(AAUDIO_STREAM_STATE_CLOSED);
}
+ mFixedBlockReader.close();
return AAUDIO_OK;
}
+void AudioStreamTrack::processCallback(int event, void *info) {
+
+ switch (event) {
+ case AudioTrack::EVENT_MORE_DATA:
+ processCallbackCommon(AAUDIO_CALLBACK_OPERATION_PROCESS_DATA, info);
+ break;
+
+ // Stream got rerouted so we disconnect.
+ case AudioTrack::EVENT_NEW_IAUDIOTRACK:
+ processCallbackCommon(AAUDIO_CALLBACK_OPERATION_DISCONNECTED, info);
+ break;
+
+ default:
+ break;
+ }
+ return;
+}
+
aaudio_result_t AudioStreamTrack::requestStart()
{
+ std::lock_guard<std::mutex> lock(mStreamMutex);
+
if (mAudioTrack.get() == nullptr) {
return AAUDIO_ERROR_INVALID_STATE;
}
@@ -124,6 +187,7 @@
if (err != OK) {
return AAudioConvert_androidToAAudioResult(err);
}
+
err = mAudioTrack->start();
if (err != OK) {
return AAudioConvert_androidToAAudioResult(err);
@@ -135,11 +199,14 @@
aaudio_result_t AudioStreamTrack::requestPause()
{
+ std::lock_guard<std::mutex> lock(mStreamMutex);
+
if (mAudioTrack.get() == nullptr) {
return AAUDIO_ERROR_INVALID_STATE;
} else if (getState() != AAUDIO_STREAM_STATE_STARTING
&& getState() != AAUDIO_STREAM_STATE_STARTED) {
- ALOGE("requestPause(), called when state is %s", AAudio_convertStreamStateToText(getState()));
+ ALOGE("requestPause(), called when state is %s",
+ AAudio_convertStreamStateToText(getState()));
return AAUDIO_ERROR_INVALID_STATE;
}
setState(AAUDIO_STREAM_STATE_PAUSING);
@@ -152,6 +219,8 @@
}
aaudio_result_t AudioStreamTrack::requestFlush() {
+ std::lock_guard<std::mutex> lock(mStreamMutex);
+
if (mAudioTrack.get() == nullptr) {
return AAUDIO_ERROR_INVALID_STATE;
} else if (getState() != AAUDIO_STREAM_STATE_PAUSED) {
@@ -165,6 +234,8 @@
}
aaudio_result_t AudioStreamTrack::requestStop() {
+ std::lock_guard<std::mutex> lock(mStreamMutex);
+
if (mAudioTrack.get() == nullptr) {
return AAUDIO_ERROR_INVALID_STATE;
}
@@ -175,7 +246,7 @@
return AAUDIO_OK;
}
-aaudio_result_t AudioStreamTrack::updateState()
+aaudio_result_t AudioStreamTrack::updateStateWhileWaiting()
{
status_t err;
aaudio_wrapping_frames_t position;
@@ -303,7 +374,7 @@
}
// TODO Merge common code into AudioStreamLegacy after rebasing.
int timebase;
- switch(clockId) {
+ switch (clockId) {
case CLOCK_BOOTTIME:
timebase = ExtendedTimestamp::TIMEBASE_BOOTTIME;
break;
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.h b/media/libaaudio/src/legacy/AudioStreamTrack.h
index 7a53022..29f5d15 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.h
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.h
@@ -17,54 +17,63 @@
#ifndef LEGACY_AUDIO_STREAM_TRACK_H
#define LEGACY_AUDIO_STREAM_TRACK_H
+#include <math.h>
#include <media/AudioTrack.h>
#include <aaudio/AAudio.h>
#include "AudioStreamBuilder.h"
#include "AudioStream.h"
-#include "AAudioLegacy.h"
+#include "legacy/AAudioLegacy.h"
+#include "legacy/AudioStreamLegacy.h"
+#include "utility/FixedBlockReader.h"
namespace aaudio {
-
/**
* Internal stream that uses the legacy AudioTrack path.
*/
-class AudioStreamTrack : public AudioStream {
+class AudioStreamTrack : public AudioStreamLegacy {
public:
AudioStreamTrack();
virtual ~AudioStreamTrack();
- virtual aaudio_result_t open(const AudioStreamBuilder & builder) override;
- virtual aaudio_result_t close() override;
+ aaudio_result_t open(const AudioStreamBuilder & builder) override;
+ aaudio_result_t close() override;
- virtual aaudio_result_t requestStart() override;
- virtual aaudio_result_t requestPause() override;
- virtual aaudio_result_t requestFlush() override;
- virtual aaudio_result_t requestStop() override;
+ aaudio_result_t requestStart() override;
+ aaudio_result_t requestPause() override;
+ aaudio_result_t requestFlush() override;
+ aaudio_result_t requestStop() override;
- virtual aaudio_result_t getTimestamp(clockid_t clockId,
+ aaudio_result_t getTimestamp(clockid_t clockId,
int64_t *framePosition,
int64_t *timeNanoseconds) override;
- virtual aaudio_result_t write(const void *buffer,
+ aaudio_result_t write(const void *buffer,
int32_t numFrames,
int64_t timeoutNanoseconds) override;
- virtual aaudio_result_t setBufferSize(int32_t requestedFrames) override;
- virtual int32_t getBufferSize() const override;
- virtual int32_t getBufferCapacity() const override;
- virtual int32_t getFramesPerBurst()const override;
- virtual int32_t getXRunCount() const override;
+ aaudio_result_t setBufferSize(int32_t requestedFrames) override;
+ int32_t getBufferSize() const override;
+ int32_t getBufferCapacity() const override;
+ int32_t getFramesPerBurst()const override;
+ int32_t getXRunCount() const override;
- virtual int64_t getFramesRead() override;
+ int64_t getFramesRead() override;
- virtual aaudio_result_t updateState() override;
+ aaudio_result_t updateStateWhileWaiting() override;
+
+ // This is public so it can be called from the C callback function.
+ void processCallback(int event, void *info) override;
private:
+
android::sp<android::AudioTrack> mAudioTrack;
+ // adapts between variable sized blocks and fixed size blocks
+ FixedBlockReader mFixedBlockReader;
+
// TODO add 64-bit position reporting to AudioRecord and use it.
aaudio_wrapping_frames_t mPositionWhenStarting = 0;
aaudio_wrapping_frames_t mPositionWhenPausing = 0;