Skip to content

Commit 7752557

Browse files
authored
Add offload support. (#2165)
* Add offload support. Fixes #2154.
1 parent 1b42b73 commit 7752557

12 files changed

Lines changed: 299 additions & 0 deletions

File tree

apps/OboeTester/app/src/main/cpp/FormatConverterBox.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,14 @@ FormatConverterBox::FormatConverterBox(int32_t maxSamples,
4343
case oboe::AudioFormat::Unspecified:
4444
mSource = std::make_unique<oboe::flowgraph::SourceFloat>(1);
4545
break;
46+
case oboe::AudioFormat::MP3:
47+
case oboe::AudioFormat::AAC_LC:
48+
case oboe::AudioFormat::AAC_HE_V1:
49+
case oboe::AudioFormat::AAC_HE_V2:
50+
case oboe::AudioFormat::AAC_ELD:
51+
case oboe::AudioFormat::AAC_XHE:
52+
case oboe::AudioFormat::OPUS:
53+
break;
4654
}
4755

4856
mSink.reset();
@@ -62,6 +70,14 @@ FormatConverterBox::FormatConverterBox(int32_t maxSamples,
6270
case oboe::AudioFormat::Unspecified:
6371
mSink = std::make_unique<oboe::flowgraph::SinkFloat>(1);
6472
break;
73+
case oboe::AudioFormat::MP3:
74+
case oboe::AudioFormat::AAC_LC:
75+
case oboe::AudioFormat::AAC_HE_V1:
76+
case oboe::AudioFormat::AAC_HE_V2:
77+
case oboe::AudioFormat::AAC_ELD:
78+
case oboe::AudioFormat::AAC_XHE:
79+
case oboe::AudioFormat::OPUS:
80+
break;
6581
}
6682

6783
if (mSource && mSink) {

apps/OboeTester/app/src/main/java/com/mobileer/oboetester/StreamConfiguration.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ public class StreamConfiguration {
5454
public static final int PERFORMANCE_MODE_NONE = 10; // must match AAUDIO
5555
public static final int PERFORMANCE_MODE_POWER_SAVING = 11; // must match AAUDIO
5656
public static final int PERFORMANCE_MODE_LOW_LATENCY = 12; // must match AAUDIO
57+
public static final int PERFORMANCE_MODE_POWER_SAVING_OFFLOAD = 13; // must match AAUDIO
5758

5859
public static final int RATE_CONVERSION_QUALITY_NONE = 0; // must match Oboe
5960
public static final int RATE_CONVERSION_QUALITY_FASTEST = 1; // must match Oboe
@@ -406,6 +407,8 @@ static String convertPerformanceModeToText(int performanceMode) {
406407
return "PS";
407408
case PERFORMANCE_MODE_LOW_LATENCY:
408409
return "LL";
410+
case PERFORMANCE_MODE_POWER_SAVING_OFFLOAD:
411+
return "PSO";
409412
default:
410413
return "??";
411414
}

apps/OboeTester/app/src/main/res/values/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@
191191
<item>NONE</item>
192192
<item>POWER_SAVING</item>
193193
<item>LOW_LATENCY</item>
194+
<item>POWER_SAVING_OFFLOAD</item>
194195
</string-array>
195196

196197
<!--Must match SignalType in NativeAudioContext.h-->

include/oboe/AudioStream.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,22 @@ class AudioStream : public AudioStreamBase {
572572
return oboe::Result::ErrorUnimplemented;
573573
}
574574

575+
virtual oboe::Result setOffloadDelayPadding(int32_t delayInFrames, int32_t paddingInFrames) {
576+
return Result::ErrorUnimplemented;
577+
}
578+
579+
virtual ResultWithValue<int32_t> getOffloadDelay() {
580+
return ResultWithValue<int32_t>(Result::ErrorUnimplemented);
581+
}
582+
583+
virtual ResultWithValue<int32_t> getOffloadPadding() {
584+
return ResultWithValue<int32_t>(Result::ErrorUnimplemented);
585+
}
586+
587+
virtual oboe::Result setOffloadEndOfStream() {
588+
return Result::ErrorUnimplemented;
589+
}
590+
575591
protected:
576592

577593
/**

include/oboe/AudioStreamBase.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,14 @@ class AudioStreamBase {
121121
return mErrorCallback;
122122
}
123123

124+
/**
125+
* For internal use only.
126+
* @return the presentation callback object for this stream, if set.
127+
*/
128+
std::shared_ptr<AudioStreamPresentationCallback> getPresentationCallback() const {
129+
return mSharedPresentationCallback;
130+
}
131+
124132
/**
125133
* @return true if a data callback was set for this stream
126134
*/
@@ -137,6 +145,13 @@ class AudioStreamBase {
137145
return mErrorCallback != nullptr;
138146
}
139147

148+
/**
149+
* @return true if a presentation callback was set for this stream
150+
*/
151+
bool isPresentationCallbackSpecified() const {
152+
return mSharedPresentationCallback != nullptr;
153+
}
154+
140155
/**
141156
* @return the usage for this stream.
142157
*/
@@ -244,6 +259,8 @@ class AudioStreamBase {
244259
AudioStreamErrorCallback *mErrorCallback = nullptr;
245260
std::shared_ptr<AudioStreamErrorCallback> mSharedErrorCallback;
246261

262+
std::shared_ptr<AudioStreamPresentationCallback> mSharedPresentationCallback;
263+
247264
/** Number of audio frames which will be requested in each callback */
248265
int32_t mFramesPerCallback = kUnspecified;
249266
/** Stream channel count */

include/oboe/AudioStreamBuilder.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,30 @@ class AudioStreamBuilder : public AudioStreamBase {
505505
return this;
506506
}
507507

508+
/**
509+
* Specifies an object to handle data presentation related callbacks from the underlying API.
510+
* This can occur when all data queued in the audio system for an offload stream has been
511+
* played.
512+
*
513+
* Note that presentation callbacks will only be called when a data callback has been specified
514+
* and the stream is started.
515+
*
516+
* <strong>Important: See AudioStreamCallback for restrictions on what may be called
517+
* from the callback methods.</strong>
518+
*
519+
* We pass a shared_ptr so that the presentationCallback object cannot be deleted before the
520+
* stream is deleted. If the stream was created using a shared_ptr then the stream cannot be
521+
* deleted before the presentation callback has finished running.
522+
*
523+
* @param sharedPresentationCallback
524+
* @return pointer to the builder so calls can be chained
525+
*/
526+
AudioStreamBuilder *setPresentationCallback(
527+
std::shared_ptr<AudioStreamPresentationCallback> sharedPresentationCallback) {
528+
mSharedPresentationCallback = sharedPresentationCallback;
529+
return this;
530+
}
531+
508532
/**
509533
* Specifies an object to handle data or error related callbacks from the underlying API.
510534
*

include/oboe/AudioStreamCallback.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,27 @@ class AudioStreamErrorCallback {
169169

170170
};
171171

172+
/**
173+
* AudioStreamPresentationCallback defines a callback interface for
174+
* being notified when a data presentation event is filed.
175+
*
176+
* It is used with AudioStreamBuilder::setPresentationCallback().
177+
*/
178+
class AudioStreamPresentationCallback {
179+
public:
180+
virtual ~AudioStreamPresentationCallback() = default;
181+
182+
/**
183+
* This will be called when all the buffers of an offloaded
184+
* stream that were queued in the audio system (e.g. the
185+
* combination of the Android audio framework and the device's
186+
* audio hardware) have been played.
187+
*
188+
* @param audioStream pointer to the associated stream
189+
*/
190+
virtual void onPresentationEnded(AudioStream* /* audioStream */) {}
191+
};
192+
172193
/**
173194
* AudioStreamCallback defines a callback interface for:
174195
*

include/oboe/Definitions.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,41 @@ namespace oboe {
152152
* Available since API 34 (U).
153153
*/
154154
IEC61937 = 5, // AAUDIO_FORMAT_IEC61937
155+
156+
/**
157+
* This format is used for audio compressed in MP3 format.
158+
*/
159+
MP3 = 6, // AAUDIO_FORMAT_MP3
160+
161+
/**
162+
* This format is used for audio compressed in AAC LC format.
163+
*/
164+
AAC_LC, // AAUDIO_FORMAT_AAC_LC
165+
166+
/**
167+
* This format is used for audio compressed in AAC HE V1 format.
168+
*/
169+
AAC_HE_V1, // AAUDIO_FORMAT_AAC_HE_V1,
170+
171+
/**
172+
* This format is used for audio compressed in AAC HE V2 format.
173+
*/
174+
AAC_HE_V2, // AAUDIO_FORMAT_AAC_HE_V2
175+
176+
/**
177+
* This format is used for audio compressed in AAC ELD format.
178+
*/
179+
AAC_ELD, // AAUDIO_FORMAT_AAC_ELD
180+
181+
/**
182+
* This format is used for audio compressed in AAC XHE format.
183+
*/
184+
AAC_XHE, // AAUDIO_FORMAT_AAC_XHE
185+
186+
/**
187+
* This format is used for audio compressed in OPUS.
188+
*/
189+
OPUS, // AAUDIO_FORMAT_OPUS
155190
};
156191

157192
/**
@@ -246,6 +281,16 @@ namespace oboe {
246281
* Reducing latency is most important.
247282
*/
248283
LowLatency = 12, // AAUDIO_PERFORMANCE_MODE_LOW_LATENCY
284+
285+
/**
286+
* Extending battery life is more important than low latency.
287+
*
288+
* This mode is not supported in input streams.
289+
* This mode will play through the offloaded audio path to save battery life.
290+
* With the offload playback, the default data callback size will be large and it
291+
* allows data feeding thread to sleep longer time after sending enough data.
292+
*/
293+
POWER_SAVING_OFFLOADED = 13, // AAUDIO_PERFORMANCE_MODE_POWER_SAVING_OFFLOADED
249294
};
250295

251296
/**

src/aaudio/AAudioLoader.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@ int AAudioLoader::open() {
102102
builder_setSpatializationBehavior = load_V_PBI("AAudioStreamBuilder_setSpatializationBehavior");
103103
}
104104

105+
if (getSdkVersion() >= __ANDROID_API_B__) {
106+
builder_setPresentationEndCallback = load_V_PBPRPV("AAudioStreamBuilder_setPresentationEndCallback");
107+
}
108+
105109
builder_delete = load_I_PB("AAudioStreamBuilder_delete");
106110

107111

@@ -183,6 +187,11 @@ int AAudioLoader::open() {
183187
aaudio_setMMapPolicy = load_I_I("AAudio_setMMapPolicy");
184188
aaudio_getMMapPolicy = load_I("AAudio_getMMapPolicy");
185189
stream_isMMapUsed = load_O_PS("AAudioStream_isMMapUsed");
190+
191+
stream_setOffloadDelayPadding = load_I_PSII("AAudioStream_setOffloadDelayPadding");
192+
stream_getOffloadDelay = load_I_PS("AAudioStream_getOffloadDelay");
193+
stream_getOffloadPadding = load_I_PS("AAudioStream_getOffloadPadding");
194+
stream_setOffloadEndOfStream = load_I_PS("AAudioStream_setOffloadEndOfStream");
186195
}
187196

188197
return 0;
@@ -332,6 +341,18 @@ AAudioLoader::signature_I AAudioLoader::load_I(const char *functionName) {
332341
return reinterpret_cast<signature_I>(proc);
333342
}
334343

344+
AAudioLoader::signature_V_PBPRPV AAudioLoader::load_V_PBPRPV(const char *functionName) {
345+
void *proc = dlsym(mLibHandle, functionName);
346+
AAudioLoader_check(proc, functionName);
347+
return reinterpret_cast<signature_V_PBPRPV>(proc);
348+
}
349+
350+
AAudioLoader::signature_I_PSII AAudioLoader::load_I_PSII(const char *functionName) {
351+
void *proc = dlsym(mLibHandle, functionName);
352+
AAudioLoader_check(proc, functionName);
353+
return reinterpret_cast<signature_I_PSII>(proc);
354+
}
355+
335356
// Ensure that all AAudio primitive data types are int32_t
336357
#define ASSERT_INT32(type) static_assert(std::is_same<int32_t, type>::value, \
337358
#type" must be int32_t")

src/aaudio/AAudioLoader.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,13 @@ typedef uint32_t aaudio_channel_mask_t;
7272
typedef int32_t aaudio_spatialization_behavior_t;
7373
#endif
7474

75+
#if __NDK_MAJOR__ < 36
76+
// Defined in W
77+
typedef void (*AAudioStream_presentationEndCallback)(
78+
AAudioStream* stream,
79+
void* userData);
80+
#endif
81+
7582
#ifndef __ANDROID_API_Q__
7683
#define __ANDROID_API_Q__ 29
7784
#endif
@@ -124,6 +131,7 @@ class AAudioLoader {
124131
// H = cHar
125132
// U = uint32_t
126133
// O = bOol
134+
// R = pResentation end callback
127135

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

@@ -157,6 +165,10 @@ class AAudioLoader {
157165
AAudioStream_errorCallback,
158166
void *);
159167

168+
typedef void (*signature_V_PBPRPV)(AAudioStreamBuilder *,
169+
AAudioStream_presentationEndCallback,
170+
void *);
171+
160172
typedef aaudio_format_t (*signature_F_PS)(AAudioStream *stream);
161173

162174
typedef int32_t (*signature_I_PSPVIL)(AAudioStream *, void *, int32_t, int64_t);
@@ -176,6 +188,7 @@ class AAudioLoader {
176188
typedef int32_t (*signature_I_II)(int32_t, int32_t);
177189
typedef int32_t (*signature_I_I)(int32_t);
178190
typedef int32_t (*signature_I)();
191+
typedef int32_t (*signature_I_PSII)(AAudioStream *, int32_t, int32_t);
179192

180193
static AAudioLoader* getInstance(); // singleton
181194

@@ -224,6 +237,7 @@ class AAudioLoader {
224237

225238
signature_V_PBPDPV builder_setDataCallback = nullptr;
226239
signature_V_PBPEPV builder_setErrorCallback = nullptr;
240+
signature_V_PBPRPV builder_setPresentationEndCallback = nullptr;
227241

228242
signature_I_PB builder_delete = nullptr;
229243

@@ -279,12 +293,18 @@ class AAudioLoader {
279293
signature_I_PS stream_getHardwareSampleRate = nullptr;
280294
signature_F_PS stream_getHardwareFormat = nullptr;
281295

296+
282297
signature_I_II aaudio_getPlatformMMapPolicy = nullptr;
283298
signature_I_II aaudio_getPlatformMMapExclusivePolicy = nullptr;
284299
signature_I_I aaudio_setMMapPolicy = nullptr;
285300
signature_I aaudio_getMMapPolicy = nullptr;
286301
signature_O_PS stream_isMMapUsed = nullptr;
287302

303+
signature_I_PSII stream_setOffloadDelayPadding = nullptr;
304+
signature_I_PS stream_getOffloadDelay = nullptr;
305+
signature_I_PS stream_getOffloadPadding = nullptr;
306+
signature_I_PS stream_setOffloadEndOfStream = nullptr;
307+
288308
private:
289309
AAudioLoader() {}
290310
~AAudioLoader();
@@ -313,6 +333,8 @@ class AAudioLoader {
313333
signature_I_II load_I_II(const char *name);
314334
signature_I_I load_I_I(const char *name);
315335
signature_I load_I(const char *name);
336+
signature_V_PBPRPV load_V_PBPRPV(const char *name);
337+
signature_I_PSII load_I_PSII(const char *name);
316338

317339
void *mLibHandle = nullptr;
318340
};

0 commit comments

Comments
 (0)