mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Oboe: Updated to release 1.5.1
This commit is contained in:
parent
433750941b
commit
8aa84abd7c
9 changed files with 249 additions and 20 deletions
|
|
@ -429,7 +429,8 @@ public:
|
|||
/**
|
||||
* Create and open a stream object based on the current settings.
|
||||
*
|
||||
* The caller owns the pointer to the AudioStream object.
|
||||
* The caller owns the pointer to the AudioStream object
|
||||
* and must delete it when finished.
|
||||
*
|
||||
* @deprecated Use openStream(std::shared_ptr<oboe::AudioStream> &stream) instead.
|
||||
* @param stream pointer to a variable to receive the stream address
|
||||
|
|
@ -455,6 +456,8 @@ public:
|
|||
* The caller must create a unique ptr, and pass by reference so it can be
|
||||
* modified to point to an opened stream. The caller owns the unique ptr,
|
||||
* and it will be automatically closed and deleted when going out of scope.
|
||||
*
|
||||
* @deprecated Use openStream(std::shared_ptr<oboe::AudioStream> &stream) instead.
|
||||
* @param stream Reference to the ManagedStream (uniqueptr) used to keep track of stream
|
||||
* @return OBOE_OK if successful or a negative error code.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
#define OBOE_VERSION_MINOR 5
|
||||
|
||||
// Type: 16-bit unsigned int. Min value: 0 Max value: 65535. See below for description.
|
||||
#define OBOE_VERSION_PATCH 0
|
||||
#define OBOE_VERSION_PATCH 1
|
||||
|
||||
#define OBOE_STRINGIFY(x) #x
|
||||
#define OBOE_TOSTRING(x) OBOE_STRINGIFY(x)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
* Copyright 2019 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 OBOE_AAUDIO_EXTENSIONS_H
|
||||
#define OBOE_AAUDIO_EXTENSIONS_H
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <sys/system_properties.h>
|
||||
|
||||
#include "common/OboeDebug.h"
|
||||
#include "oboe/Oboe.h"
|
||||
#include "AAudioLoader.h"
|
||||
|
||||
namespace oboe {
|
||||
|
||||
#define LIB_AAUDIO_NAME "libaaudio.so"
|
||||
#define FUNCTION_IS_MMAP "AAudioStream_isMMapUsed"
|
||||
#define FUNCTION_SET_MMAP_POLICY "AAudio_setMMapPolicy"
|
||||
#define FUNCTION_GET_MMAP_POLICY "AAudio_getMMapPolicy"
|
||||
|
||||
#define AAUDIO_ERROR_UNAVAILABLE static_cast<aaudio_result_t>(Result::ErrorUnavailable)
|
||||
|
||||
typedef struct AAudioStreamStruct AAudioStream;
|
||||
|
||||
/**
|
||||
* Call some AAudio test routines that are not part of the normal API.
|
||||
*/
|
||||
class AAudioExtensions {
|
||||
public:
|
||||
AAudioExtensions() {
|
||||
int32_t policy = getIntegerProperty("aaudio.mmap_policy", 0);
|
||||
mMMapSupported = isPolicyEnabled(policy);
|
||||
|
||||
policy = getIntegerProperty("aaudio.mmap_exclusive_policy", 0);
|
||||
mMMapExclusiveSupported = isPolicyEnabled(policy);
|
||||
}
|
||||
|
||||
static bool isPolicyEnabled(int32_t policy) {
|
||||
return (policy == AAUDIO_POLICY_AUTO || policy == AAUDIO_POLICY_ALWAYS);
|
||||
}
|
||||
|
||||
static AAudioExtensions &getInstance() {
|
||||
static AAudioExtensions instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
bool isMMapUsed(oboe::AudioStream *oboeStream) {
|
||||
AAudioStream *aaudioStream = (AAudioStream *) oboeStream->getUnderlyingStream();
|
||||
return isMMapUsed(aaudioStream);
|
||||
}
|
||||
|
||||
bool isMMapUsed(AAudioStream *aaudioStream) {
|
||||
if (loadSymbols()) return false;
|
||||
if (mAAudioStream_isMMap == nullptr) return false;
|
||||
return mAAudioStream_isMMap(aaudioStream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Controls whether the MMAP data path can be selected when opening a stream.
|
||||
* It has no effect after the stream has been opened.
|
||||
* It only affects the application that calls it. Other apps are not affected.
|
||||
*
|
||||
* @param enabled
|
||||
* @return 0 or a negative error code
|
||||
*/
|
||||
int32_t setMMapEnabled(bool enabled) {
|
||||
if (loadSymbols()) return AAUDIO_ERROR_UNAVAILABLE;
|
||||
if (mAAudio_setMMapPolicy == nullptr) return false;
|
||||
return mAAudio_setMMapPolicy(enabled ? AAUDIO_POLICY_AUTO : AAUDIO_POLICY_NEVER);
|
||||
}
|
||||
|
||||
bool isMMapEnabled() {
|
||||
if (loadSymbols()) return false;
|
||||
if (mAAudio_getMMapPolicy == nullptr) return false;
|
||||
int32_t policy = mAAudio_getMMapPolicy();
|
||||
return isPolicyEnabled(policy);
|
||||
}
|
||||
|
||||
bool isMMapSupported() {
|
||||
return mMMapSupported;
|
||||
}
|
||||
|
||||
bool isMMapExclusiveSupported() {
|
||||
return mMMapExclusiveSupported;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
enum {
|
||||
AAUDIO_POLICY_NEVER = 1,
|
||||
AAUDIO_POLICY_AUTO,
|
||||
AAUDIO_POLICY_ALWAYS
|
||||
};
|
||||
typedef int32_t aaudio_policy_t;
|
||||
|
||||
int getIntegerProperty(const char *name, int defaultValue) {
|
||||
int result = defaultValue;
|
||||
char valueText[PROP_VALUE_MAX] = {0};
|
||||
if (__system_property_get(name, valueText) != 0) {
|
||||
result = atoi(valueText);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the function pointers.
|
||||
* This can be called multiple times.
|
||||
* It should only be called from one thread.
|
||||
*
|
||||
* @return 0 if successful or negative error.
|
||||
*/
|
||||
aaudio_result_t loadSymbols() {
|
||||
if (mAAudio_getMMapPolicy != nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *libHandle = AAudioLoader::getInstance()->getLibHandle();
|
||||
if (libHandle == nullptr) {
|
||||
LOGI("%s() could not find " LIB_AAUDIO_NAME, __func__);
|
||||
return AAUDIO_ERROR_UNAVAILABLE;
|
||||
}
|
||||
|
||||
mAAudioStream_isMMap = (bool (*)(AAudioStream *stream))
|
||||
dlsym(libHandle, FUNCTION_IS_MMAP);
|
||||
if (mAAudioStream_isMMap == nullptr) {
|
||||
LOGI("%s() could not find " FUNCTION_IS_MMAP, __func__);
|
||||
return AAUDIO_ERROR_UNAVAILABLE;
|
||||
}
|
||||
|
||||
mAAudio_setMMapPolicy = (int32_t (*)(aaudio_policy_t policy))
|
||||
dlsym(libHandle, FUNCTION_SET_MMAP_POLICY);
|
||||
if (mAAudio_setMMapPolicy == nullptr) {
|
||||
LOGI("%s() could not find " FUNCTION_SET_MMAP_POLICY, __func__);
|
||||
return AAUDIO_ERROR_UNAVAILABLE;
|
||||
}
|
||||
|
||||
mAAudio_getMMapPolicy = (aaudio_policy_t (*)())
|
||||
dlsym(libHandle, FUNCTION_GET_MMAP_POLICY);
|
||||
if (mAAudio_getMMapPolicy == nullptr) {
|
||||
LOGI("%s() could not find " FUNCTION_GET_MMAP_POLICY, __func__);
|
||||
return AAUDIO_ERROR_UNAVAILABLE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool mMMapSupported = false;
|
||||
bool mMMapExclusiveSupported = false;
|
||||
|
||||
bool (*mAAudioStream_isMMap)(AAudioStream *stream) = nullptr;
|
||||
int32_t (*mAAudio_setMMapPolicy)(aaudio_policy_t policy) = nullptr;
|
||||
aaudio_policy_t (*mAAudio_getMMapPolicy)() = nullptr;
|
||||
};
|
||||
|
||||
} // namespace oboe
|
||||
|
||||
#endif //OBOE_AAUDIO_EXTENSIONS_H
|
||||
|
|
@ -24,10 +24,17 @@
|
|||
namespace oboe {
|
||||
|
||||
AAudioLoader::~AAudioLoader() {
|
||||
if (mLibHandle != nullptr) {
|
||||
dlclose(mLibHandle);
|
||||
mLibHandle = nullptr;
|
||||
}
|
||||
// Issue 360: thread_local variables with non-trivial destructors
|
||||
// will cause segfaults if the containing library is dlclose()ed on
|
||||
// devices running M or newer, or devices before M when using a static STL.
|
||||
// The simple workaround is to not call dlclose.
|
||||
// https://github.com/android/ndk/wiki/Changelog-r22#known-issues
|
||||
//
|
||||
// The libaaudio and libaaudioclient do not use thread_local.
|
||||
// But, to be safe, we should avoid dlclose() if possible.
|
||||
// Because AAudioLoader is a static Singleton, we can safely skip
|
||||
// calling dlclose() without causing a resource leak.
|
||||
LOGI("%s() dlclose(%s) not called, OK", __func__, LIB_AAUDIO_NAME);
|
||||
}
|
||||
|
||||
AAudioLoader* AAudioLoader::getInstance() {
|
||||
|
|
@ -90,8 +97,6 @@ int AAudioLoader::open() {
|
|||
|
||||
stream_getTimestamp = load_I_PSKPLPL("AAudioStream_getTimestamp");
|
||||
|
||||
stream_isMMapUsed = load_B_PS("AAudioStream_isMMapUsed");
|
||||
|
||||
stream_getChannelCount = load_I_PS("AAudioStream_getChannelCount");
|
||||
if (stream_getChannelCount == nullptr) {
|
||||
// Use old alias if needed.
|
||||
|
|
@ -304,7 +309,6 @@ AAudioLoader::signature_I_PSKPLPL AAudioLoader::load_I_PSKPLPL(const char *funct
|
|||
== AAUDIO_PERFORMANCE_MODE_POWER_SAVING, ERRMSG);
|
||||
static_assert((int32_t)PerformanceMode::LowLatency
|
||||
== AAUDIO_PERFORMANCE_MODE_LOW_LATENCY, ERRMSG);
|
||||
#endif
|
||||
|
||||
// The aaudio_ usage, content and input_preset types were added in NDK 17,
|
||||
// which is the first version to support Android Pie (API 28).
|
||||
|
|
@ -343,6 +347,9 @@ AAudioLoader::signature_I_PSKPLPL AAudioLoader::load_I_PSKPLPL(const char *funct
|
|||
|
||||
static_assert((int32_t)SessionId::None == AAUDIO_SESSION_ID_NONE, ERRMSG);
|
||||
static_assert((int32_t)SessionId::Allocate == AAUDIO_SESSION_ID_ALLOCATE, ERRMSG);
|
||||
#endif
|
||||
|
||||
#endif // __NDK_MAJOR__ >= 17
|
||||
|
||||
#endif // AAUDIO_AAUDIO_H
|
||||
|
||||
} // namespace oboe
|
||||
|
|
|
|||
|
|
@ -52,6 +52,12 @@ typedef int32_t aaudio_usage_t;
|
|||
typedef int32_t aaudio_content_type_t;
|
||||
typedef int32_t aaudio_input_preset_t;
|
||||
typedef int32_t aaudio_session_id_t;
|
||||
|
||||
// There are a few definitions used by Oboe.
|
||||
#define AAUDIO_OK static_cast<aaudio_result_t>(Result::OK)
|
||||
#define AAUDIO_ERROR_TIMEOUT static_cast<aaudio_result_t>(Result::ErrorTimeout)
|
||||
#define AAUDIO_STREAM_STATE_STARTING static_cast<aaudio_stream_state_t>(StreamState::Starting)
|
||||
#define AAUDIO_STREAM_STATE_STARTED static_cast<aaudio_stream_state_t>(StreamState::Started)
|
||||
#else
|
||||
#include <aaudio/AAudio.h>
|
||||
#include <android/ndk-version.h>
|
||||
|
|
@ -63,7 +69,6 @@ typedef int32_t aaudio_session_id_t;
|
|||
|
||||
namespace oboe {
|
||||
|
||||
|
||||
/**
|
||||
* The AAudio API was not available in early versions of Android.
|
||||
* To avoid linker errors, we dynamically link with the functions by name using dlsym().
|
||||
|
|
@ -133,6 +138,8 @@ class AAudioLoader {
|
|||
*/
|
||||
int open();
|
||||
|
||||
void *getLibHandle() const { return mLibHandle; }
|
||||
|
||||
// Function pointers into the AAudio shared library.
|
||||
signature_I_PPB createStreamBuilder = nullptr;
|
||||
|
||||
|
|
@ -167,8 +174,6 @@ class AAudioLoader {
|
|||
|
||||
signature_I_PSKPLPL stream_getTimestamp = nullptr;
|
||||
|
||||
signature_B_PS stream_isMMapUsed = nullptr;
|
||||
|
||||
signature_I_PS stream_close = nullptr;
|
||||
|
||||
signature_I_PS stream_getChannelCount = nullptr;
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include "common/AudioClock.h"
|
||||
#include "common/OboeDebug.h"
|
||||
#include "oboe/Utilities.h"
|
||||
#include "AAudioExtensions.h"
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <sys/system_properties.h>
|
||||
|
|
@ -677,7 +678,7 @@ ResultWithValue<double> AudioStreamAAudio::calculateLatencyMillis() {
|
|||
bool AudioStreamAAudio::isMMapUsed() {
|
||||
AAudioStream *stream = mAAudioStream.load();
|
||||
if (stream != nullptr) {
|
||||
return mLibLoader->stream_isMMapUsed(stream);
|
||||
return AAudioExtensions::getInstance().isMMapUsed(stream);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
#include <sys/types.h>
|
||||
|
||||
|
||||
#include "aaudio/AAudioExtensions.h"
|
||||
#include "aaudio/AudioStreamAAudio.h"
|
||||
#include "FilterAudioStream.h"
|
||||
#include "OboeDebug.h"
|
||||
|
|
@ -109,7 +111,6 @@ Result AudioStreamBuilder::openStream(AudioStream **streamPP) {
|
|||
// Do we need to make a child stream and convert.
|
||||
if (conversionNeeded) {
|
||||
AudioStream *tempStream;
|
||||
|
||||
result = childBuilder.openStream(&tempStream);
|
||||
if (result != Result::OK) {
|
||||
return result;
|
||||
|
|
@ -156,7 +157,20 @@ Result AudioStreamBuilder::openStream(AudioStream **streamPP) {
|
|||
}
|
||||
}
|
||||
|
||||
result = streamP->open(); // TODO review API
|
||||
// If MMAP has a problem in this case then disable it temporarily.
|
||||
bool wasMMapOriginallyEnabled = AAudioExtensions::getInstance().isMMapEnabled();
|
||||
bool wasMMapTemporarilyDisabled = false;
|
||||
if (wasMMapOriginallyEnabled) {
|
||||
bool isMMapSafe = QuirksManager::getInstance().isMMapSafe(childBuilder);
|
||||
if (!isMMapSafe) {
|
||||
AAudioExtensions::getInstance().setMMapEnabled(false);
|
||||
wasMMapTemporarilyDisabled = true;
|
||||
}
|
||||
}
|
||||
result = streamP->open();
|
||||
if (wasMMapTemporarilyDisabled) {
|
||||
AAudioExtensions::getInstance().setMMapEnabled(wasMMapOriginallyEnabled); // restore original
|
||||
}
|
||||
if (result == Result::OK) {
|
||||
|
||||
int32_t optimalBufferSize = -1;
|
||||
|
|
|
|||
|
|
@ -20,10 +20,6 @@
|
|||
#include "OboeDebug.h"
|
||||
#include "QuirksManager.h"
|
||||
|
||||
#ifndef __ANDROID_API_R__
|
||||
#define __ANDROID_API_R__ 30
|
||||
#endif
|
||||
|
||||
using namespace oboe;
|
||||
|
||||
int32_t QuirksManager::DeviceQuirks::clipBufferSize(AudioStream &stream,
|
||||
|
|
@ -74,6 +70,9 @@ public:
|
|||
|
||||
std::string chipname = getPropertyString("ro.hardware.chipname");
|
||||
isExynos9810 = (chipname == "exynos9810");
|
||||
isExynos990 = (chipname == "exynos990");
|
||||
|
||||
mBuildChangelist = getPropertyInteger("ro.build.changelist", 0);
|
||||
}
|
||||
|
||||
virtual ~SamsungDeviceQuirks() = default;
|
||||
|
|
@ -98,6 +97,17 @@ public:
|
|||
&& builder.getInputPreset() != oboe::InputPreset::Camcorder;
|
||||
}
|
||||
|
||||
bool isMMapSafe(const AudioStreamBuilder &builder) override {
|
||||
const bool isInput = builder.getDirection() == Direction::Input;
|
||||
// This detects b/159066712 , S20 LSI has corrupt low latency audio recording
|
||||
// and turns off MMAP.
|
||||
// See also https://github.com/google/oboe/issues/892
|
||||
bool mRecordingCorrupted = isInput
|
||||
&& isExynos990
|
||||
&& mBuildChangelist < 19350896;
|
||||
return !mRecordingCorrupted;
|
||||
}
|
||||
|
||||
private:
|
||||
// Stay farther away from DSP position on Exynos devices.
|
||||
static constexpr int32_t kBottomMarginExynos = 2;
|
||||
|
|
@ -105,6 +115,8 @@ private:
|
|||
static constexpr int32_t kTopMargin = 1;
|
||||
bool isExynos = false;
|
||||
bool isExynos9810 = false;
|
||||
bool isExynos990 = false;
|
||||
int mBuildChangelist = 0;
|
||||
};
|
||||
|
||||
QuirksManager::QuirksManager() {
|
||||
|
|
@ -203,3 +215,8 @@ bool QuirksManager::isConversionNeeded(
|
|||
|
||||
return conversionNeeded;
|
||||
}
|
||||
|
||||
bool QuirksManager::isMMapSafe(AudioStreamBuilder &builder) {
|
||||
if (!OboeGlobals::areWorkaroundsEnabled()) return true;
|
||||
return mDeviceQuirks->isMMapSafe(builder);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,10 @@
|
|||
#include <oboe/AudioStreamBuilder.h>
|
||||
#include <aaudio/AudioStreamAAudio.h>
|
||||
|
||||
#ifndef __ANDROID_API_R__
|
||||
#define __ANDROID_API_R__ 30
|
||||
#endif
|
||||
|
||||
namespace oboe {
|
||||
|
||||
/**
|
||||
|
|
@ -98,6 +102,10 @@ public:
|
|||
|
||||
virtual bool isAAudioMMapPossible(const AudioStreamBuilder &builder) const;
|
||||
|
||||
virtual bool isMMapSafe(const AudioStreamBuilder & /* builder */ ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static constexpr int32_t kDefaultBottomMarginInBursts = 0;
|
||||
static constexpr int32_t kDefaultTopMarginInBursts = 0;
|
||||
|
||||
|
|
@ -108,6 +116,8 @@ public:
|
|||
static constexpr int32_t kCommonNativeRate = 48000; // very typical native sample rate
|
||||
};
|
||||
|
||||
bool isMMapSafe(AudioStreamBuilder &builder);
|
||||
|
||||
private:
|
||||
|
||||
static constexpr int32_t kChannelCountMono = 1;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue