• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #ifndef LOG_TAG
16 #define LOG_TAG "AudioOpenslesPlayerTest"
17 #endif
18 
19 #include <OpenSLES.h>
20 #include <OpenSLES_OpenHarmony.h>
21 
22 #include <cstdio>
23 #include <climits>
24 #include <cstdlib>
25 #include <cstring>
26 #include <unistd.h>
27 
28 #include "audio_renderer_log.h"
29 #include "pcm2wav.h"
30 
31 using namespace std;
32 
33 static void BufferQueueCallback(SLOHBufferQueueItf bufferQueueItf, void *pContext, SLuint32 size);
34 
35 static void PlayerStart(SLPlayItf playItf, SLOHBufferQueueItf bufferQueueItf, FILE *wavFile);
36 
37 static void PlayerStop(SLPlayItf playItf, SLOHBufferQueueItf bufferQueueItf);
38 
39 static void OpenSlTest();
40 
41 static void OpenSlTestConcurrent();
42 
43 const SLuint32 number = 3;
44 FILE *wavFile_ = nullptr;
45 FILE *wavFile1_ = nullptr;
46 FILE *wavFile2_ = nullptr;
47 wav_hdr wavHeader_;
48 wav_hdr wavHeader1_;
49 wav_hdr wavHeader2_;
50 SLObjectItf engineObject = nullptr;
51 SLObjectItf outputMixObject = nullptr;
52 SLPlayItf playItf;
53 SLPlayItf playItf1;
54 SLPlayItf playItf2;
55 SLVolumeItf volumeItf1;
56 SLVolumeItf volumeItf2;
57 SLOHBufferQueueItf bufferQueueItf;
58 SLOHBufferQueueItf bufferQueueItf1;
59 SLOHBufferQueueItf bufferQueueItf2;
60 SLObjectItf pcmPlayerObject = nullptr;
61 SLObjectItf pcmPlayerObject1 = nullptr;
62 SLObjectItf pcmPlayerObject2 = nullptr;
63 
main(int argc,char * argv[])64 int main(int argc, char *argv[])
65 {
66     if (argc == 4) {
67         size_t headerSize = sizeof(wav_hdr);
68         char *inputPath = argv[1];
69         char path[PATH_MAX + 1] = {0x00};
70         if ((strlen(inputPath) > PATH_MAX) || (realpath(inputPath, path) == nullptr)) {
71             AUDIO_ERR_LOG("Invalid path");
72             return -1;
73         }
74         wavFile1_ = fopen(path, "rb");
75         if (wavFile1_ == nullptr) {
76             AUDIO_INFO_LOG("AudioRendererTest: Unable to open wave file");
77             return -1;
78         }
79         fread(&wavHeader1_, 1, headerSize, wavFile1_);
80 
81         headerSize = sizeof(wav_hdr);
82         inputPath = argv[2];
83         if ((strlen(inputPath) > PATH_MAX) || (realpath(inputPath, path) == nullptr)) {
84             AUDIO_ERR_LOG("Invalid path");
85             fclose(wavFile1_);
86             wavFile1_ = nullptr;
87             return -1;
88         }
89         wavFile2_ = fopen(path, "rb");
90         if (wavFile2_ == nullptr) {
91             fclose(wavFile1_);
92             wavFile1_ = nullptr;
93             AUDIO_INFO_LOG("AudioRendererTest: Unable to open wave file");
94             return -1;
95         }
96         fread(&wavHeader2_, 1, headerSize, wavFile2_);
97 
98         OpenSlTestConcurrent();
99 
100         while (!feof(wavFile1_) || !feof(wavFile2_)) {
101             sleep(1);
102         }
103 
104         PlayerStop(playItf1, bufferQueueItf1);
105         PlayerStop(playItf2, bufferQueueItf2);
106         (*pcmPlayerObject1)->Destroy(pcmPlayerObject1);
107         (*pcmPlayerObject2)->Destroy(pcmPlayerObject2);
108         (*engineObject)->Destroy(engineObject);
109         (*outputMixObject)->Destroy(outputMixObject);
110         fclose(wavFile1_);
111         wavFile1_ = nullptr;
112         fclose(wavFile2_);
113         wavFile2_ = nullptr;
114         return 0;
115     } else {
116         if (argc < 2) {
117             return -1;
118         }
119         size_t headerSize = sizeof(wav_hdr);
120         char *inputPath = argv[1];
121         char path[PATH_MAX + 1] = {0x00};
122         if ((strlen(inputPath) > PATH_MAX) || (realpath(inputPath, path) == nullptr)) {
123             AUDIO_ERR_LOG("Invalid path");
124             return -1;
125         }
126         wavFile_ = fopen(path, "rb");
127         if (wavFile_ == nullptr) {
128             AUDIO_INFO_LOG("AudioRendererTest: Unable to open wave file");
129             return -1;
130         }
131         fread(&wavHeader_, 1, headerSize, wavFile_);
132 
133         OpenSlTest();
134 
135         while (!feof(wavFile_)) {
136             sleep(1);
137         }
138         PlayerStop(playItf, bufferQueueItf);
139         (*pcmPlayerObject)->Destroy(pcmPlayerObject);
140         fclose(wavFile_);
141         wavFile_ = nullptr;
142 
143         if (argc < 3) {
144             return 0;
145         }
146         char *inputPath2 = argv[2];
147         char path2[PATH_MAX + 1] = {0x00};
148         if ((strlen(inputPath2) > PATH_MAX) || (realpath(inputPath2, path2) == nullptr)) {
149             AUDIO_ERR_LOG("Invalid path");
150             return -1;
151         }
152         wavFile_ = fopen(path2, "rb");
153         if (wavFile_ == nullptr) {
154             AUDIO_INFO_LOG("AudioRendererTest: Unable to open wave file");
155             return -1;
156         }
157         fread(&wavHeader_, 1, headerSize, wavFile_);
158 
159         OpenSlTest();
160 
161         while (!feof(wavFile_)) {
162             sleep(1);
163         }
164         PlayerStop(playItf, bufferQueueItf);
165         (*pcmPlayerObject)->Destroy(pcmPlayerObject);
166         fclose(wavFile_);
167         wavFile_ = nullptr;
168         return 0;
169     }
170 }
171 
OpenSlTest()172 static void OpenSlTest()
173 {
174     AUDIO_INFO_LOG("OpenSlTest");
175     engineObject = nullptr;
176     SLEngineItf engineEngine = nullptr;
177     slCreateEngine(&engineObject, 0, nullptr, 0, nullptr, nullptr);
178     (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
179     (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
180 
181     outputMixObject = nullptr;
182     (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, nullptr, nullptr);
183     (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
184 
185     SLDataLocator_OutputMix slOutputMix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject};
186     SLDataSink slSink = {&slOutputMix, nullptr};
187     SLDataLocator_BufferQueue slBufferQueue = {
188         SL_DATALOCATOR_BUFFERQUEUE,
189         0
190     };
191     SLDataFormat_PCM pcmFormat = {
192         SL_DATAFORMAT_PCM,
193         wavHeader_.NumOfChan,
194         wavHeader_.SamplesPerSec * 1000,
195         wavHeader_.bitsPerSample,
196         0,
197         0,
198         0
199     };
200     SLDataSource slSource = {&slBufferQueue, &pcmFormat};
201     (*engineEngine)->CreateAudioPlayer(engineEngine, &pcmPlayerObject, &slSource, &slSink, number, nullptr, nullptr);
202     (*pcmPlayerObject)->Realize(pcmPlayerObject, SL_BOOLEAN_FALSE);
203 
204     (*pcmPlayerObject)->GetInterface(pcmPlayerObject, SL_IID_PLAY, &playItf);
205     SLVolumeItf volumeItf;
206     (*pcmPlayerObject)->GetInterface(pcmPlayerObject, SL_IID_VOLUME, &volumeItf);
207     SLmillibel pLevel = 0;
208     (*volumeItf)->GetVolumeLevel(volumeItf, &pLevel);
209     (*pcmPlayerObject)->GetInterface(pcmPlayerObject, SL_IID_OH_BUFFERQUEUE, &bufferQueueItf);
210     (*bufferQueueItf)->RegisterCallback(bufferQueueItf, BufferQueueCallback, wavFile_);
211 
212     PlayerStart(playItf, bufferQueueItf, wavFile_);
213 }
214 
OpenSlTestConcurrent()215 static void OpenSlTestConcurrent()
216 {
217     AUDIO_INFO_LOG("OpenSlTestConcurrent");
218     engineObject = nullptr;
219     SLEngineItf engineEngine = nullptr;
220 
221     slCreateEngine(&engineObject, 0, nullptr, 0, nullptr, nullptr);
222     (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
223     (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
224 
225     outputMixObject = nullptr;
226     (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, nullptr, nullptr);
227     (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
228 
229     SLDataLocator_OutputMix slOutputMix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject};
230     SLDataSink slSink = {&slOutputMix, nullptr};
231     SLDataLocator_BufferQueue slBufferQueue = {
232         SL_DATALOCATOR_BUFFERQUEUE,
233         0
234     };
235     SLDataFormat_PCM pcmFormat1 = {
236         SL_DATAFORMAT_PCM,
237         wavHeader1_.NumOfChan,
238         wavHeader1_.SamplesPerSec * 1000,
239         wavHeader1_.bitsPerSample,
240         0,
241         0,
242         0
243     };
244     SLDataFormat_PCM pcmFormat2 = {
245         SL_DATAFORMAT_PCM,
246         wavHeader2_.NumOfChan,
247         wavHeader2_.SamplesPerSec * 1000,
248         wavHeader2_.bitsPerSample,
249         0,
250         0,
251         0
252     };
253     SLDataSource slSource1 = {&slBufferQueue, &pcmFormat1};
254     SLDataSource slSource2 = {&slBufferQueue, &pcmFormat2};
255 
256     (*engineEngine)->CreateAudioPlayer(engineEngine, &pcmPlayerObject1, &slSource1, &slSink, number, nullptr, nullptr);
257     (*pcmPlayerObject1)->Realize(pcmPlayerObject1, SL_BOOLEAN_FALSE);
258 
259     (*engineEngine)->CreateAudioPlayer(engineEngine, &pcmPlayerObject2, &slSource2, &slSink, number, nullptr, nullptr);
260     (*pcmPlayerObject2)->Realize(pcmPlayerObject2, SL_BOOLEAN_FALSE);
261 
262     (*pcmPlayerObject1)->GetInterface(pcmPlayerObject1, SL_IID_PLAY, &playItf1);
263     (*pcmPlayerObject2)->GetInterface(pcmPlayerObject2, SL_IID_PLAY, &playItf2);
264     (*pcmPlayerObject1)->GetInterface(pcmPlayerObject1, SL_IID_VOLUME, &volumeItf1);
265 
266     SLmillibel level1 = 0;
267     (*volumeItf1)->GetMaxVolumeLevel(volumeItf1, &level1);
268     SLmillibel temp = 2;
269     level1 = (SLmillibel) (level1 / temp);
270     (*volumeItf1)->SetVolumeLevel(volumeItf1, level1);
271     (*pcmPlayerObject2)->GetInterface(pcmPlayerObject2, SL_IID_VOLUME, &volumeItf2);
272     SLmillibel level2 = 0;
273     (*volumeItf2)->GetMaxVolumeLevel(volumeItf2, &level2);
274     temp = 15; // MaxVolumeLevel
275     level2 = (SLmillibel) (level2 / temp);
276     (*volumeItf2)->SetVolumeLevel(volumeItf2, level2);
277 
278     (*pcmPlayerObject1)->GetInterface(pcmPlayerObject1, SL_IID_OH_BUFFERQUEUE, &bufferQueueItf1);
279     (*pcmPlayerObject2)->GetInterface(pcmPlayerObject2, SL_IID_OH_BUFFERQUEUE, &bufferQueueItf2);
280     (*bufferQueueItf1)->RegisterCallback(bufferQueueItf1, BufferQueueCallback, wavFile1_);
281     (*bufferQueueItf2)->RegisterCallback(bufferQueueItf2, BufferQueueCallback, wavFile2_);
282     PlayerStart(playItf1, bufferQueueItf1, wavFile1_);
283     PlayerStart(playItf2, bufferQueueItf2, wavFile2_);
284 }
285 
BufferQueueCallback(SLOHBufferQueueItf bufferQueueItf,void * pContext,SLuint32 size)286 static void BufferQueueCallback(SLOHBufferQueueItf bufferQueueItf, void *pContext, SLuint32 size)
287 {
288     FILE *wavFile = (FILE *)pContext;
289     if (!feof(wavFile)) {
290         SLuint8 *buffer = nullptr;
291         SLuint32 bufferSize = 0;
292         (*bufferQueueItf)->GetBuffer(bufferQueueItf, &buffer, &bufferSize);
293         if (buffer != nullptr) {
294             fread(buffer, 1, size, wavFile);
295             (*bufferQueueItf)->Enqueue(bufferQueueItf, buffer, size);
296         }
297     }
298     return;
299 }
300 
PlayerStart(SLPlayItf playItf,SLOHBufferQueueItf bufferQueueItf,FILE * wavFile)301 static void PlayerStart(SLPlayItf playItf, SLOHBufferQueueItf bufferQueueItf, FILE *wavFile)
302 {
303     AUDIO_INFO_LOG("PlayerStart");
304     (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PLAYING);
305     return;
306 }
307 
PlayerStop(SLPlayItf playItf,SLOHBufferQueueItf bufferQueueItf)308 static void PlayerStop(SLPlayItf playItf, SLOHBufferQueueItf bufferQueueItf)
309 {
310     AUDIO_INFO_LOG("PlayerStop");
311     (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_STOPPED);
312     return;
313 }
314