1*05767d91SRobert Wu /*
2*05767d91SRobert Wu * Copyright 2017 The Android Open Source Project
3*05767d91SRobert Wu *
4*05767d91SRobert Wu * Licensed under the Apache License, Version 2.0 (the "License");
5*05767d91SRobert Wu * you may not use this file except in compliance with the License.
6*05767d91SRobert Wu * You may obtain a copy of the License at
7*05767d91SRobert Wu *
8*05767d91SRobert Wu * http://www.apache.org/licenses/LICENSE-2.0
9*05767d91SRobert Wu *
10*05767d91SRobert Wu * Unless required by applicable law or agreed to in writing, software
11*05767d91SRobert Wu * distributed under the License is distributed on an "AS IS" BASIS,
12*05767d91SRobert Wu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*05767d91SRobert Wu * See the License for the specific language governing permissions and
14*05767d91SRobert Wu * limitations under the License.
15*05767d91SRobert Wu */
16*05767d91SRobert Wu
17*05767d91SRobert Wu #include <dlfcn.h>
18*05767d91SRobert Wu #include "common/OboeDebug.h"
19*05767d91SRobert Wu #include "EngineOpenSLES.h"
20*05767d91SRobert Wu #include "OpenSLESUtilities.h"
21*05767d91SRobert Wu
22*05767d91SRobert Wu using namespace oboe;
23*05767d91SRobert Wu
24*05767d91SRobert Wu // OpenSL ES is deprecated in SDK 30.
25*05767d91SRobert Wu // So we use custom dynamic linking to access the library.
26*05767d91SRobert Wu #define LIB_OPENSLES_NAME "libOpenSLES.so"
27*05767d91SRobert Wu typedef SLresult (*prototype_slCreateEngine)(
28*05767d91SRobert Wu SLObjectItf *pEngine,
29*05767d91SRobert Wu SLuint32 numOptions,
30*05767d91SRobert Wu const SLEngineOption *pEngineOptions,
31*05767d91SRobert Wu SLuint32 numInterfaces,
32*05767d91SRobert Wu const SLInterfaceID *pInterfaceIds,
33*05767d91SRobert Wu const SLboolean *pInterfaceRequired
34*05767d91SRobert Wu );
35*05767d91SRobert Wu static prototype_slCreateEngine gFunction_slCreateEngine = nullptr;
36*05767d91SRobert Wu static void *gLibOpenSlesLibraryHandle = nullptr;
37*05767d91SRobert Wu
38*05767d91SRobert Wu // Load the OpenSL ES library and the one primary entry point.
39*05767d91SRobert Wu // @return true if linked OK
linkOpenSLES()40*05767d91SRobert Wu static bool linkOpenSLES() {
41*05767d91SRobert Wu if (gLibOpenSlesLibraryHandle == nullptr && gFunction_slCreateEngine == nullptr) {
42*05767d91SRobert Wu // Use RTLD_NOW to avoid the unpredictable behavior that RTLD_LAZY can cause.
43*05767d91SRobert Wu // Also resolving all the links now will prevent a run-time penalty later.
44*05767d91SRobert Wu gLibOpenSlesLibraryHandle = dlopen(LIB_OPENSLES_NAME, RTLD_NOW);
45*05767d91SRobert Wu if (gLibOpenSlesLibraryHandle == nullptr) {
46*05767d91SRobert Wu LOGE("linkOpenSLES() could not find " LIB_OPENSLES_NAME);
47*05767d91SRobert Wu } else {
48*05767d91SRobert Wu gFunction_slCreateEngine = (prototype_slCreateEngine) dlsym(
49*05767d91SRobert Wu gLibOpenSlesLibraryHandle,
50*05767d91SRobert Wu "slCreateEngine");
51*05767d91SRobert Wu LOGD("linkOpenSLES(): dlsym(%s) returned %p", "slCreateEngine",
52*05767d91SRobert Wu gFunction_slCreateEngine);
53*05767d91SRobert Wu }
54*05767d91SRobert Wu }
55*05767d91SRobert Wu return gFunction_slCreateEngine != nullptr;
56*05767d91SRobert Wu }
57*05767d91SRobert Wu
getInstance()58*05767d91SRobert Wu EngineOpenSLES &EngineOpenSLES::getInstance() {
59*05767d91SRobert Wu static EngineOpenSLES sInstance;
60*05767d91SRobert Wu return sInstance;
61*05767d91SRobert Wu }
62*05767d91SRobert Wu
open()63*05767d91SRobert Wu SLresult EngineOpenSLES::open() {
64*05767d91SRobert Wu std::lock_guard<std::mutex> lock(mLock);
65*05767d91SRobert Wu
66*05767d91SRobert Wu SLresult result = SL_RESULT_SUCCESS;
67*05767d91SRobert Wu if (mOpenCount++ == 0) {
68*05767d91SRobert Wu // load the library and link to it
69*05767d91SRobert Wu if (!linkOpenSLES()) {
70*05767d91SRobert Wu result = SL_RESULT_FEATURE_UNSUPPORTED;
71*05767d91SRobert Wu goto error;
72*05767d91SRobert Wu };
73*05767d91SRobert Wu
74*05767d91SRobert Wu // create engine
75*05767d91SRobert Wu result = (*gFunction_slCreateEngine)(&mEngineObject, 0, NULL, 0, NULL, NULL);
76*05767d91SRobert Wu if (SL_RESULT_SUCCESS != result) {
77*05767d91SRobert Wu LOGE("EngineOpenSLES - slCreateEngine() result:%s", getSLErrStr(result));
78*05767d91SRobert Wu goto error;
79*05767d91SRobert Wu }
80*05767d91SRobert Wu
81*05767d91SRobert Wu // realize the engine
82*05767d91SRobert Wu result = (*mEngineObject)->Realize(mEngineObject, SL_BOOLEAN_FALSE);
83*05767d91SRobert Wu if (SL_RESULT_SUCCESS != result) {
84*05767d91SRobert Wu LOGE("EngineOpenSLES - Realize() engine result:%s", getSLErrStr(result));
85*05767d91SRobert Wu goto error;
86*05767d91SRobert Wu }
87*05767d91SRobert Wu
88*05767d91SRobert Wu // get the engine interface, which is needed in order to create other objects
89*05767d91SRobert Wu result = (*mEngineObject)->GetInterface(mEngineObject, SL_IID_ENGINE, &mEngineInterface);
90*05767d91SRobert Wu if (SL_RESULT_SUCCESS != result) {
91*05767d91SRobert Wu LOGE("EngineOpenSLES - GetInterface() engine result:%s", getSLErrStr(result));
92*05767d91SRobert Wu goto error;
93*05767d91SRobert Wu }
94*05767d91SRobert Wu }
95*05767d91SRobert Wu
96*05767d91SRobert Wu return result;
97*05767d91SRobert Wu
98*05767d91SRobert Wu error:
99*05767d91SRobert Wu close();
100*05767d91SRobert Wu return result;
101*05767d91SRobert Wu }
102*05767d91SRobert Wu
close()103*05767d91SRobert Wu void EngineOpenSLES::close() {
104*05767d91SRobert Wu std::lock_guard<std::mutex> lock(mLock);
105*05767d91SRobert Wu if (--mOpenCount == 0) {
106*05767d91SRobert Wu if (mEngineObject != nullptr) {
107*05767d91SRobert Wu (*mEngineObject)->Destroy(mEngineObject);
108*05767d91SRobert Wu mEngineObject = nullptr;
109*05767d91SRobert Wu mEngineInterface = nullptr;
110*05767d91SRobert Wu }
111*05767d91SRobert Wu }
112*05767d91SRobert Wu }
113*05767d91SRobert Wu
createOutputMix(SLObjectItf * objectItf)114*05767d91SRobert Wu SLresult EngineOpenSLES::createOutputMix(SLObjectItf *objectItf) {
115*05767d91SRobert Wu return (*mEngineInterface)->CreateOutputMix(mEngineInterface, objectItf, 0, 0, 0);
116*05767d91SRobert Wu }
117*05767d91SRobert Wu
createAudioPlayer(SLObjectItf * objectItf,SLDataSource * audioSource,SLDataSink * audioSink)118*05767d91SRobert Wu SLresult EngineOpenSLES::createAudioPlayer(SLObjectItf *objectItf,
119*05767d91SRobert Wu SLDataSource *audioSource,
120*05767d91SRobert Wu SLDataSink *audioSink) {
121*05767d91SRobert Wu
122*05767d91SRobert Wu const SLInterfaceID ids[] = {SL_IID_BUFFERQUEUE, SL_IID_ANDROIDCONFIGURATION};
123*05767d91SRobert Wu const SLboolean reqs[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
124*05767d91SRobert Wu
125*05767d91SRobert Wu return (*mEngineInterface)->CreateAudioPlayer(mEngineInterface, objectItf, audioSource,
126*05767d91SRobert Wu audioSink,
127*05767d91SRobert Wu sizeof(ids) / sizeof(ids[0]), ids, reqs);
128*05767d91SRobert Wu }
129*05767d91SRobert Wu
createAudioRecorder(SLObjectItf * objectItf,SLDataSource * audioSource,SLDataSink * audioSink)130*05767d91SRobert Wu SLresult EngineOpenSLES::createAudioRecorder(SLObjectItf *objectItf,
131*05767d91SRobert Wu SLDataSource *audioSource,
132*05767d91SRobert Wu SLDataSink *audioSink) {
133*05767d91SRobert Wu
134*05767d91SRobert Wu const SLInterfaceID ids[] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_ANDROIDCONFIGURATION };
135*05767d91SRobert Wu const SLboolean reqs[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
136*05767d91SRobert Wu
137*05767d91SRobert Wu return (*mEngineInterface)->CreateAudioRecorder(mEngineInterface, objectItf, audioSource,
138*05767d91SRobert Wu audioSink,
139*05767d91SRobert Wu sizeof(ids) / sizeof(ids[0]), ids, reqs);
140*05767d91SRobert Wu }
141*05767d91SRobert Wu
142