Skip to content

Commit

Permalink
Add offload support.
Browse files Browse the repository at this point in the history
Fixes #2154.
  • Loading branch information
flamme committed Feb 20, 2025
1 parent a231d4b commit 7df9038
Show file tree
Hide file tree
Showing 12 changed files with 305 additions and 0 deletions.
16 changes: 16 additions & 0 deletions apps/OboeTester/app/src/main/cpp/FormatConverterBox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ FormatConverterBox::FormatConverterBox(int32_t maxSamples,
case oboe::AudioFormat::Unspecified:
mSource = std::make_unique<oboe::flowgraph::SourceFloat>(1);
break;
case oboe::AudioFormat::MP3:
case oboe::AudioFormat::AAC_LC:
case oboe::AudioFormat::AAC_HE_V1:
case oboe::AudioFormat::AAC_HE_V2:
case oboe::AudioFormat::AAC_ELD:
case oboe::AudioFormat::AAC_XHE:
case oboe::AudioFormat::OPUS:
break;
}

mSink.reset();
Expand All @@ -62,6 +70,14 @@ FormatConverterBox::FormatConverterBox(int32_t maxSamples,
case oboe::AudioFormat::Unspecified:
mSink = std::make_unique<oboe::flowgraph::SinkFloat>(1);
break;
case oboe::AudioFormat::MP3:
case oboe::AudioFormat::AAC_LC:
case oboe::AudioFormat::AAC_HE_V1:
case oboe::AudioFormat::AAC_HE_V2:
case oboe::AudioFormat::AAC_ELD:
case oboe::AudioFormat::AAC_XHE:
case oboe::AudioFormat::OPUS:
break;
}

if (mSource && mSink) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public class StreamConfiguration {
public static final int PERFORMANCE_MODE_NONE = 10; // must match AAUDIO
public static final int PERFORMANCE_MODE_POWER_SAVING = 11; // must match AAUDIO
public static final int PERFORMANCE_MODE_LOW_LATENCY = 12; // must match AAUDIO
public static final int PERFORMANCE_MODE_POWER_SAVING_OFFLOAD = 13; // must match AAUDIO

public static final int RATE_CONVERSION_QUALITY_NONE = 0; // must match Oboe
public static final int RATE_CONVERSION_QUALITY_FASTEST = 1; // must match Oboe
Expand Down Expand Up @@ -401,6 +402,8 @@ static String convertPerformanceModeToText(int performanceMode) {
return "PS";
case PERFORMANCE_MODE_LOW_LATENCY:
return "LL";
case PERFORMANCE_MODE_POWER_SAVING_OFFLOAD:
return "PSO";
default:
return "??";
}
Expand Down
1 change: 1 addition & 0 deletions apps/OboeTester/app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@
<item>NONE</item>
<item>POWER_SAVING</item>
<item>LOW_LATENCY</item>
<item>POWER_SAVING_OFFLOAD</item>
</string-array>

<!--Must match SignalType in NativeAudioContext.h-->
Expand Down
16 changes: 16 additions & 0 deletions include/oboe/AudioStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,22 @@ class AudioStream : public AudioStreamBase {
return oboe::Result::ErrorUnimplemented;
}

virtual oboe::Result setOffloadDelayPadding(int32_t delayInFrames, int32_t paddingInFrames) {
return Result::ErrorUnimplemented;
}

virtual ResultWithValue<int32_t> getOffloadDelay() {
return ResultWithValue<int32_t>(Result::ErrorUnimplemented);
}

virtual ResultWithValue<int32_t> getOffloadPadding() {
return ResultWithValue<int32_t>(Result::ErrorUnimplemented);
}

virtual oboe::Result setOffloadEndOfStream() {
return Result::ErrorUnimplemented;
}

protected:

/**
Expand Down
17 changes: 17 additions & 0 deletions include/oboe/AudioStreamBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,14 @@ class AudioStreamBase {
return mErrorCallback;
}

/**
* For internal use only.
* @return the presentation callback object for this stream, if set.
*/
std::shared_ptr<AudioStreamPresentationCallback> getPresentationCallback() const {
return mSharedPresentationCallback;
}

/**
* @return true if a data callback was set for this stream
*/
Expand All @@ -137,6 +145,13 @@ class AudioStreamBase {
return mErrorCallback != nullptr;
}

/**
* @return true if a presentation callback was set for this stream
*/
bool isPresentationCallbackSpecified() const {
return mSharedPresentationCallback != nullptr;
}

/**
* @return the usage for this stream.
*/
Expand Down Expand Up @@ -244,6 +259,8 @@ class AudioStreamBase {
AudioStreamErrorCallback *mErrorCallback = nullptr;
std::shared_ptr<AudioStreamErrorCallback> mSharedErrorCallback;

std::shared_ptr<AudioStreamPresentationCallback> mSharedPresentationCallback;

/** Number of audio frames which will be requested in each callback */
int32_t mFramesPerCallback = kUnspecified;
/** Stream channel count */
Expand Down
24 changes: 24 additions & 0 deletions include/oboe/AudioStreamBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,30 @@ class AudioStreamBuilder : public AudioStreamBase {
return this;
}

/**
* Specifies an object to handle data presentation related callbacks from the underlying API.
* This can occur when all data queued in the audio system for an offload stream has been
* played.
*
* Note that presentation callbacks will only be called when a data callback has been specified
* and the stream is started.
*
* <strong>Important: See AudioStreamCallback for restrictions on what may be called
* from the callback methods.</strong>
*
* We pass a shared_ptr so that the presentationCallback object cannot be deleted before the
* stream is deleted. If the stream was created using a shared_ptr then the stream cannot be
* deleted before the presentation callback has finished running.
*
* @param sharedPresentationCallback
* @return pointer to the builder so calls can be chained
*/
AudioStreamBuilder *setPresentationCallback(
std::shared_ptr<AudioStreamPresentationCallback> sharedPresentationCallback) {
mSharedPresentationCallback = sharedPresentationCallback;
return this;
}

/**
* Specifies an object to handle data or error related callbacks from the underlying API.
*
Expand Down
21 changes: 21 additions & 0 deletions include/oboe/AudioStreamCallback.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,27 @@ class AudioStreamErrorCallback {

};

/**
* AudioStreamPresentationCallback defines a callback interface for
* being notified when a data presentation event is filed.
*
* It is used with AudioStreamBuilder::setPresentationCallback().
*/
class AudioStreamPresentationCallback {
public:
virtual ~AudioStreamPresentationCallback() = default;

/**
* This will be called when all the buffers of an offloaded
* stream that were queued in the audio system (e.g. the
* combination of the Android audio framework and the device's
* audio hardware) have been played.
*
* @param audioStream pointer to the associated stream
*/
virtual void onPresentationEnd(AudioStream* /* audioStream */) {}
};

/**
* AudioStreamCallback defines a callback interface for:
*
Expand Down
43 changes: 43 additions & 0 deletions include/oboe/Definitions.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,41 @@ namespace oboe {
* Available since API 34 (U).
*/
IEC61937 = 5, // AAUDIO_FORMAT_IEC61937

/**
* This format is used for audio compressed in MP3 format.
*/
MP3 = 6, // AAUDIO_FORMAT_MP3

/**
* This format is used for audio compressed in AAC LC format.
*/
AAC_LC, // AAUDIO_FORMAT_AAC_LC

/**
* This format is used for audio compressed in AAC HE V1 format.
*/
AAC_HE_V1, // AAUDIO_FORMAT_AAC_HE_V1,

/**
* This format is used for audio compressed in AAC HE V2 format.
*/
AAC_HE_V2, // AAUDIO_FORMAT_AAC_HE_V2

/**
* This format is used for audio compressed in AAC ELD format.
*/
AAC_ELD, // AAUDIO_FORMAT_AAC_ELD

/**
* This format is used for audio compressed in AAC XHE format.
*/
AAC_XHE, // AAUDIO_FORMAT_AAC_XHE

/**
* This format is used for audio compressed in OPUS.
*/
OPUS, // AAUDIO_FORMAT_OPUS
};

/**
Expand Down Expand Up @@ -246,6 +281,14 @@ namespace oboe {
* Reducing latency is most important.
*/
LowLatency = 12, // AAUDIO_PERFORMANCE_MODE_LOW_LATENCY

/**
* Extending battery life is more important than low latency.
*
* This mode is not supported in input streams.
* This mode will play through the offloaded audio path to save battery life.
*/
POWER_SAVING_OFFLOADED = 13, // AAUDIO_PERFORMANCE_MODE_POWER_SAVING_OFFLOADED
};

/**
Expand Down
25 changes: 25 additions & 0 deletions src/aaudio/AAudioLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ AAudioLoader* AAudioLoader::getInstance() {
}

int AAudioLoader::open() {
LOGD("flamme sdk version=%d", getSdkVersion());
if (mLibHandle != nullptr) {
return 0;
}
Expand Down Expand Up @@ -102,6 +103,10 @@ int AAudioLoader::open() {
builder_setSpatializationBehavior = load_V_PBI("AAudioStreamBuilder_setSpatializationBehavior");
}

if (getSdkVersion() >= __ANDROID_API_W__) {
builder_setPresentationEndCallback = load_V_PBPRPV("AAudioStreamBuilder_setPresentationEndCallback");
}

builder_delete = load_I_PB("AAudioStreamBuilder_delete");


Expand Down Expand Up @@ -177,6 +182,14 @@ int AAudioLoader::open() {
stream_getHardwareFormat = load_F_PS("AAudioStream_getHardwareFormat");
}

if (getSdkVersion() >= __ANDROID_API_W__) {
LOGD("flamme version greater than w");
stream_setOffloadDelayPadding = load_I_PSII("AAudioStream_setOffloadDelayPadding");
stream_getOffloadDelay = load_I_PS("AAudioStream_getOffloadDelay");
stream_getOffloadPadding = load_I_PS("AAudioStream_getOffloadPadding");
stream_setOffloadEndOfStream = load_I_PS("AAudioStream_setOffloadEndOfStream");
}

return 0;
}

Expand Down Expand Up @@ -306,6 +319,18 @@ AAudioLoader::signature_V_PBO AAudioLoader::load_V_PBO(const char *functionName)
return reinterpret_cast<signature_V_PBO>(proc);
}

AAudioLoader::signature_V_PBPRPV AAudioLoader::load_V_PBPRPV(const char *functionName) {
void *proc = dlsym(mLibHandle, functionName);
AAudioLoader_check(proc, functionName);
return reinterpret_cast<signature_V_PBPRPV>(proc);
}

AAudioLoader::signature_I_PSII AAudioLoader::load_I_PSII(const char *functionName) {
void *proc = dlsym(mLibHandle, functionName);
AAudioLoader_check(proc, functionName);
return reinterpret_cast<signature_I_PSII>(proc);
}

// Ensure that all AAudio primitive data types are int32_t
#define ASSERT_INT32(type) static_assert(std::is_same<int32_t, type>::value, \
#type" must be int32_t")
Expand Down
26 changes: 26 additions & 0 deletions src/aaudio/AAudioLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,13 @@ typedef uint32_t aaudio_channel_mask_t;
typedef int32_t aaudio_spatialization_behavior_t;
#endif

#if __NDK_MAJOR__ < 36
// Defined in W
typedef void (*AAudioStream_presentationEndCallback)(
AAudioStream* stream,
void* userData);
#endif

#ifndef __ANDROID_API_Q__
#define __ANDROID_API_Q__ 29
#endif
Expand All @@ -92,6 +99,10 @@ typedef int32_t aaudio_spatialization_behavior_t;
#define __ANDROID_API_U__ 34
#endif

#ifndef __ANDROID_API_W__
#define __ANDROID_API_W__ 36
#endif

namespace oboe {

/**
Expand All @@ -114,6 +125,7 @@ class AAudioLoader {
// H = cHar
// U = uint32_t
// O = bOol
// R = pResentation end callback

typedef int32_t (*signature_I_PPB)(AAudioStreamBuilder **builder);

Expand Down Expand Up @@ -147,6 +159,10 @@ class AAudioLoader {
AAudioStream_errorCallback,
void *);

typedef void (*signature_V_PBPRPV)(AAudioStreamBuilder *,
AAudioStream_presentationEndCallback,
void *);

typedef aaudio_format_t (*signature_F_PS)(AAudioStream *stream);

typedef int32_t (*signature_I_PSPVIL)(AAudioStream *, void *, int32_t, int64_t);
Expand All @@ -163,6 +179,8 @@ class AAudioLoader {

typedef uint32_t (*signature_U_PS)(AAudioStream *);

typedef int32_t (*signature_I_PSII)(AAudioStream *, int32_t, int32_t);

static AAudioLoader* getInstance(); // singleton

/**
Expand Down Expand Up @@ -210,6 +228,7 @@ class AAudioLoader {

signature_V_PBPDPV builder_setDataCallback = nullptr;
signature_V_PBPEPV builder_setErrorCallback = nullptr;
signature_V_PBPRPV builder_setPresentationEndCallback = nullptr;

signature_I_PB builder_delete = nullptr;

Expand Down Expand Up @@ -265,6 +284,11 @@ class AAudioLoader {
signature_I_PS stream_getHardwareSampleRate = nullptr;
signature_F_PS stream_getHardwareFormat = nullptr;

signature_I_PSII stream_setOffloadDelayPadding = nullptr;
signature_I_PS stream_getOffloadDelay = nullptr;
signature_I_PS stream_getOffloadPadding = nullptr;
signature_I_PS stream_setOffloadEndOfStream = nullptr;

private:
AAudioLoader() {}
~AAudioLoader();
Expand All @@ -290,6 +314,8 @@ class AAudioLoader {
signature_V_PBU load_V_PBU(const char *name);
signature_U_PS load_U_PS(const char *name);
signature_V_PBO load_V_PBO(const char *name);
signature_V_PBPRPV load_V_PBPRPV(const char *name);
signature_I_PSII load_I_PSII(const char *name);

void *mLibHandle = nullptr;
};
Expand Down
Loading

0 comments on commit 7df9038

Please sign in to comment.