1 /*
2 * Copyright (c) 2022 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
16 #include <OpenSLES.h>
17 #include <OpenSLES_OpenHarmony.h>
18 #include <OpenSLES_Platform.h>
19 #include "media_log.h"
20 #include <iostream>
21 #include "pcm2wav.h"
22 #include <unistd.h>
23
24 using namespace std;
25
26 static void BuqqerQueueCallback (SLOHBufferQueueItf bufferQueueItf, void *pContext, SLuint32 size);
27
28 static void PlayerStart (SLPlayItf playItf, SLOHBufferQueueItf bufferQueueItf, FILE *wavFile);
29
30 static void PlayerStop (SLPlayItf playItf, SLOHBufferQueueItf bufferQueueItf);
31
32 static void OpenSlTest();
33
34 static void OpenSlTestConcurrent();
35
36 FILE *wavFile_ = nullptr;
37 FILE *wavFile1_ = nullptr;
38 FILE *wavFile2_ = nullptr;
39 wav_hdr wavHeader_;
40 wav_hdr wavHeader1_;
41 wav_hdr wavHeader2_;
42 SLObjectItf engineObject = nullptr;
43 SLObjectItf outputMixObject = nullptr;
44 SLPlayItf playItf;
45 SLPlayItf playItf1;
46 SLPlayItf playItf2;
47 SLVolumeItf volumeItf1;
48 SLVolumeItf volumeItf2;
49 SLOHBufferQueueItf bufferQueueItf;
50 SLOHBufferQueueItf bufferQueueItf1;
51 SLOHBufferQueueItf bufferQueueItf2;
52 SLObjectItf pcmPlayerObject = nullptr;
53 SLObjectItf pcmPlayerObject1 = nullptr;
54 SLObjectItf pcmPlayerObject2 = nullptr;
55
main(int argc,char * argv[])56 int main(int argc, char *argv[])
57 {
58 if (argc == 4) {
59 size_t headerSize = sizeof(wav_hdr);
60 char *inputPath = argv[1];
61 char path[PATH_MAX + 1] = {0x00};
62 if ((strlen(inputPath) > PATH_MAX) || (realpath(inputPath, path) == nullptr)) {
63 MEDIA_ERR_LOG("Invalid path");
64 return -1;
65 }
66 wavFile1_ = fopen(path, "rb");
67 if (wavFile1_ == nullptr) {
68 MEDIA_INFO_LOG("AudioRendererTest: Unable to open wave file");
69 return -1;
70 }
71 fread(&wavHeader1_, 1, headerSize, wavFile1_);
72
73 headerSize = sizeof(wav_hdr);
74 inputPath = argv[2];
75 if ((strlen(inputPath) > PATH_MAX) || (realpath(inputPath, path) == nullptr)) {
76 MEDIA_ERR_LOG("Invalid path");
77 return -1;
78 }
79 wavFile2_ = fopen(path, "rb");
80 if (wavFile2_ == nullptr) {
81 MEDIA_INFO_LOG("AudioRendererTest: Unable to open wave file");
82 return -1;
83 }
84 fread(&wavHeader2_, 1, headerSize, wavFile2_);
85
86 OpenSlTestConcurrent();
87
88 while (!feof(wavFile1_) || !feof(wavFile2_)) {
89 sleep(1);
90 }
91
92 PlayerStop(playItf1, bufferQueueItf1);
93 PlayerStop(playItf2, bufferQueueItf2);
94 (*pcmPlayerObject1)->Destroy(pcmPlayerObject1);
95 (*pcmPlayerObject2)->Destroy(pcmPlayerObject2);
96 (*engineObject)->Destroy(engineObject);
97 (*outputMixObject)->Destroy(outputMixObject);
98 return 0;
99 } else {
100 if (argc < 2) {
101 return -1;
102 }
103 size_t headerSize = sizeof(wav_hdr);
104 char *inputPath = argv[1];
105 char path[PATH_MAX + 1] = {0x00};
106 if ((strlen(inputPath) > PATH_MAX) || (realpath(inputPath, path) == nullptr)) {
107 MEDIA_ERR_LOG("Invalid path");
108 return -1;
109 }
110 wavFile_ = fopen(path, "rb");
111 if (wavFile_ == nullptr) {
112 MEDIA_INFO_LOG("AudioRendererTest: Unable to open wave file");
113 return -1;
114 }
115 fread(&wavHeader_, 1, headerSize, wavFile_);
116
117 OpenSlTest();
118
119 while (!feof(wavFile_)) {
120 sleep(1);
121 }
122 PlayerStop(playItf, bufferQueueItf);
123 (*pcmPlayerObject)->Destroy(pcmPlayerObject);
124
125 if (argc < 3) {
126 return 0;
127 }
128 char *inputPath2 = argv[2];
129 char path2[PATH_MAX + 1] = {0x00};
130 if ((strlen(inputPath2) > PATH_MAX) || (realpath(inputPath2, path2) == nullptr)) {
131 MEDIA_ERR_LOG("Invalid path");
132 return -1;
133 }
134 wavFile_ = fopen(path2, "rb");
135 if (wavFile_ == nullptr) {
136 MEDIA_INFO_LOG("AudioRendererTest: Unable to open wave file");
137 return -1;
138 }
139 fread(&wavHeader_, 1, headerSize, wavFile_);
140
141 OpenSlTest();
142
143 while (!feof(wavFile_)) {
144 sleep(1);
145 }
146 PlayerStop(playItf, bufferQueueItf);
147 (*pcmPlayerObject)->Destroy(pcmPlayerObject);
148 return 0;
149 }
150 }
151
OpenSlTest()152 static void OpenSlTest()
153 {
154 MEDIA_INFO_LOG("OpenSlTest");
155 engineObject = nullptr;
156 SLEngineItf engineEngine = nullptr;
157 SLresult result;
158 result = slCreateEngine(&engineObject, 0, nullptr, 0, nullptr, nullptr);
159 result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
160 result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
161
162 outputMixObject = nullptr;
163 result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, nullptr, nullptr);
164 (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
165
166 SLDataLocator_OutputMix slOutputMix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject};
167 SLDataSink slSink = {&slOutputMix, nullptr};
168 SLDataLocator_BufferQueue slBufferQueue = {
169 SL_DATALOCATOR_BUFFERQUEUE,
170 0
171 };
172 SLDataFormat_PCM pcmFormat = {
173 SL_DATAFORMAT_PCM,
174 wavHeader_.NumOfChan,
175 wavHeader_.SamplesPerSec * 1000,
176 wavHeader_.bitsPerSample,
177 0,
178 0,
179 0
180 };
181 SLDataSource slSource = {&slBufferQueue, &pcmFormat};
182 result = (*engineEngine)->CreateAudioPlayer(engineEngine, &pcmPlayerObject, &slSource, &slSink, 3, nullptr, nullptr);
183 (*pcmPlayerObject)->Realize(pcmPlayerObject, SL_BOOLEAN_FALSE);
184
185 (*pcmPlayerObject)->GetInterface(pcmPlayerObject, SL_IID_PLAY, &playItf);
186 SLVolumeItf volumeItf;
187 (*pcmPlayerObject)->GetInterface(pcmPlayerObject, SL_IID_VOLUME, &volumeItf);
188 SLmillibel pLevel = 0;
189 (*volumeItf)->GetVolumeLevel(volumeItf, &pLevel);
190 (*pcmPlayerObject)->GetInterface(pcmPlayerObject, SL_IID_OH_BUFFERQUEUE, &bufferQueueItf);
191 (*bufferQueueItf)->RegisterCallback(bufferQueueItf, BuqqerQueueCallback, wavFile_);
192
193 PlayerStart(playItf, bufferQueueItf, wavFile_);
194 }
195
OpenSlTestConcurrent()196 static void OpenSlTestConcurrent()
197 {
198 MEDIA_INFO_LOG("OpenSlTestConcurrent");
199 engineObject = nullptr;
200 SLEngineItf engineEngine = nullptr;
201 SLresult result;
202
203 result = slCreateEngine(&engineObject, 0, nullptr, 0, nullptr, nullptr);
204 result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
205 result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
206
207 outputMixObject = nullptr;
208 result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, nullptr, nullptr);
209 (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
210
211 SLDataLocator_OutputMix slOutputMix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject};
212 SLDataSink slSink = {&slOutputMix, nullptr};
213 SLDataLocator_BufferQueue slBufferQueue = {
214 SL_DATALOCATOR_BUFFERQUEUE,
215 0
216 };
217 SLDataFormat_PCM pcmFormat1 = {
218 SL_DATAFORMAT_PCM,
219 wavHeader1_.NumOfChan,
220 wavHeader1_.SamplesPerSec * 1000,
221 wavHeader1_.bitsPerSample,
222 0,
223 0,
224 0
225 };
226 SLDataFormat_PCM pcmFormat2 = {
227 SL_DATAFORMAT_PCM,
228 wavHeader2_.NumOfChan,
229 wavHeader2_.SamplesPerSec * 1000,
230 wavHeader2_.bitsPerSample,
231 0,
232 0,
233 0
234 };
235 SLDataSource slSource1 = {&slBufferQueue, &pcmFormat1};
236 SLDataSource slSource2 = {&slBufferQueue, &pcmFormat2};
237
238 result = (*engineEngine)->CreateAudioPlayer(engineEngine, &pcmPlayerObject1, &slSource1, &slSink, 3, nullptr, nullptr);
239 (*pcmPlayerObject1)->Realize(pcmPlayerObject1, SL_BOOLEAN_FALSE);
240
241 result = (*engineEngine)->CreateAudioPlayer(engineEngine, &pcmPlayerObject2, &slSource2, &slSink, 3, nullptr, nullptr);
242 (*pcmPlayerObject2)->Realize(pcmPlayerObject2, SL_BOOLEAN_FALSE);
243
244 (*pcmPlayerObject1)->GetInterface(pcmPlayerObject1, SL_IID_PLAY, &playItf1);
245 (*pcmPlayerObject2)->GetInterface(pcmPlayerObject2, SL_IID_PLAY, &playItf2);
246 (*pcmPlayerObject1)->GetInterface(pcmPlayerObject1, SL_IID_VOLUME, &volumeItf1);
247
248 SLmillibel level1 = 0;
249 (*volumeItf1)->GetMaxVolumeLevel(volumeItf1, &level1);
250 SLmillibel temp = 2;
251 level1 = (SLmillibel) (level1 / temp);
252 (*volumeItf1)->SetVolumeLevel(volumeItf1, level1);
253 (*pcmPlayerObject2)->GetInterface(pcmPlayerObject2, SL_IID_VOLUME, &volumeItf2);
254 SLmillibel level2 = 0;
255 (*volumeItf2)->GetMaxVolumeLevel(volumeItf2, &level2);
256 temp = 15;
257 level2 = (SLmillibel) (level2 / temp);
258 (*volumeItf2)->SetVolumeLevel(volumeItf2, level2);
259
260 (*pcmPlayerObject1)->GetInterface(pcmPlayerObject1, SL_IID_OH_BUFFERQUEUE, &bufferQueueItf1);
261 (*pcmPlayerObject2)->GetInterface(pcmPlayerObject2, SL_IID_OH_BUFFERQUEUE, &bufferQueueItf2);
262 (*bufferQueueItf1)->RegisterCallback(bufferQueueItf1, BuqqerQueueCallback, wavFile1_);
263 (*bufferQueueItf2)->RegisterCallback(bufferQueueItf2, BuqqerQueueCallback, wavFile2_);
264 PlayerStart(playItf1, bufferQueueItf1, wavFile1_);
265 PlayerStart(playItf2, bufferQueueItf2, wavFile2_);
266 }
267
BuqqerQueueCallback(SLOHBufferQueueItf bufferQueueItf,void * pContext,SLuint32 size)268 static void BuqqerQueueCallback (SLOHBufferQueueItf bufferQueueItf, void *pContext, SLuint32 size)
269 {
270 FILE *wavFile = (FILE *)pContext;
271 if (!feof(wavFile)) {
272 SLuint8 *buffer = nullptr;
273 SLuint32 pSize = 0;
274 (*bufferQueueItf)->GetBuffer(bufferQueueItf, &buffer, pSize);
275 fread(buffer, 1, size, wavFile);
276 (*bufferQueueItf)->Enqueue(bufferQueueItf, buffer, size);
277 }
278 return;
279 }
280
PlayerStart(SLPlayItf playItf,SLOHBufferQueueItf bufferQueueItf,FILE * wavFile)281 static void PlayerStart (SLPlayItf playItf, SLOHBufferQueueItf bufferQueueItf, FILE *wavFile)
282 {
283 MEDIA_INFO_LOG("PlayerStart");
284 (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PLAYING);
285 if (!feof(wavFile)) {
286 SLuint8* buffer = nullptr;
287 SLuint32 pSize = 0;
288 (*bufferQueueItf)->GetBuffer(bufferQueueItf, &buffer, pSize);
289 fread(buffer, 1, pSize, wavFile);
290 (*bufferQueueItf)->Enqueue(bufferQueueItf, buffer, pSize);
291 }
292 return;
293 }
294
PlayerStop(SLPlayItf playItf,SLOHBufferQueueItf bufferQueueItf)295 static void PlayerStop (SLPlayItf playItf, SLOHBufferQueueItf bufferQueueItf)
296 {
297 MEDIA_INFO_LOG("PlayerStop");
298 (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_STOPPED);
299 return;
300 }
301
302