1 /*
2 * Copyright (c) 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
16 #include <cstdio>
17 #include <cstdlib>
18 #include <cstring>
19 #include <securec.h>
20 #include <iostream>
21 #include <unistd.h>
22 #include <OpenSLES.h>
23 #include <OpenSLES_OpenHarmony.h>
24 #include <OpenSLES_Platform.h>
25 #include "audio_info.h"
26 #include "audio_log.h"
27 #include "gtest/gtest.h"
28
29 using namespace std;
30 using namespace testing::ext;
31
32 namespace {
33 class ActsOpenslesRecoderNdkTest : public testing::Test {
34 public:
35 static void SetUpTestCase();
36 static void TearDownTestCase();
37 void SetUp() override;
38 void TearDown() override;
39 };
40
SetUpTestCase()41 void ActsOpenslesRecoderNdkTest::SetUpTestCase() {}
TearDownTestCase()42 void ActsOpenslesRecoderNdkTest::TearDownTestCase() {}
SetUp()43 void ActsOpenslesRecoderNdkTest::SetUp() {}
TearDown()44 void ActsOpenslesRecoderNdkTest::TearDown() {}
45
46 static void BufferQueueCallback(SLOHBufferQueueItf sBufferQueueItf, void *pContext, SLuint32 size);
47
48 static SLresult CaptureStart(SLRecordItf sRecordItf, SLOHBufferQueueItf sBufferQueueItf, FILE *wavFile);
49
50 static SLresult CapturePause(SLRecordItf sRecordItf);
51
52 static SLresult CaptureStop(SLRecordItf sRecordItf);
53
54 static SLresult OpenSLESCaptureTest();
55
56 FILE *wavFile_ = nullptr;
57 SLObjectItf engineObject = nullptr;
58 SLRecordItf recordItf;
59 SLOHBufferQueueItf bufferQueueItf;
60 SLObjectItf pcmCapturerObject = nullptr;
61
OpenSLESCaptureTest()62 static SLresult OpenSLESCaptureTest()
63 {
64 AUDIO_INFO_LOG("Enter OpenSLESCaptureTest");
65 engineObject = nullptr;
66 SLEngineItf engineItf = nullptr;
67
68 SLresult result = slCreateEngine(&engineObject, 0, nullptr, 0, nullptr, nullptr);
69 if (SL_RESULT_SUCCESS != result) {
70 AUDIO_INFO_LOG("OpenSLESCaptureTest slCreateEngine result: %{public}lu", result);
71 return result;
72 }
73 result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
74 if (SL_RESULT_SUCCESS != result) {
75 AUDIO_INFO_LOG("OpenSLESCaptureTest Realize result: %{public}lu", result);
76 return result;
77 }
78 result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineItf);
79 if (SL_RESULT_SUCCESS != result) {
80 AUDIO_INFO_LOG("OpenSLESCaptureTest get engineItf result: %{public}lu", result);
81 return result;
82 }
83
84 SLDataLocator_IODevice io_device = {
85 SL_DATALOCATOR_IODEVICE,
86 SL_IODEVICE_AUDIOINPUT,
87 SL_DEFAULTDEVICEID_AUDIOINPUT,
88 NULL
89 };
90
91 SLDataSource audioSource = {
92 &io_device,
93 NULL
94 };
95
96 SLDataLocator_BufferQueue buffer_queue = {
97 SL_DATALOCATOR_BUFFERQUEUE,
98 3
99 };
100
101 SLDataFormat_PCM format_pcm = {
102 SL_DATAFORMAT_PCM,
103 OHOS::AudioStandard::AudioChannel::MONO,
104 OHOS::AudioStandard::AudioSamplingRate::SAMPLE_RATE_44100,
105 SL_PCMSAMPLEFORMAT_FIXED_16,
106 0,
107 0,
108 0
109 };
110 SLDataSink audioSink = {
111 &buffer_queue,
112 &format_pcm
113 };
114
115 result = (*engineItf)->CreateAudioRecorder(engineItf, &pcmCapturerObject,
116 &audioSource, &audioSink, 0, nullptr, nullptr);
117 if (SL_RESULT_SUCCESS != result) {
118 AUDIO_INFO_LOG("OpenSLESCaptureTest CreateAudioRecorder result: %{public}lu", result);
119 return result;
120 }
121 result = (*pcmCapturerObject)->Realize(pcmCapturerObject, SL_BOOLEAN_FALSE);
122 if (SL_RESULT_SUCCESS != result) {
123 AUDIO_INFO_LOG("OpenSLESCaptureTest Realize result: %{public}lu", result);
124 return result;
125 }
126 result = (*pcmCapturerObject)->GetInterface(pcmCapturerObject, SL_IID_RECORD, &recordItf);
127 if (SL_RESULT_SUCCESS != result) {
128 AUDIO_INFO_LOG("OpenSLESCaptureTest get recordItf result: %{public}lu", result);
129 return result;
130 }
131 result = (*pcmCapturerObject)->GetInterface(pcmCapturerObject, SL_IID_OH_BUFFERQUEUE, &bufferQueueItf);
132 if (SL_RESULT_SUCCESS != result) {
133 AUDIO_INFO_LOG("OpenSLESCaptureTest get bufferQueueItf result: %{public}lu", result);
134 return result;
135 }
136 result = (*bufferQueueItf)->RegisterCallback(bufferQueueItf, BufferQueueCallback, wavFile_);
137 if (SL_RESULT_SUCCESS != result) {
138 AUDIO_INFO_LOG("OpenSLESCaptureTest RegisterCallback result: %{public}lu", result);
139 return result;
140 }
141 AUDIO_INFO_LOG("OpenSLESCaptureTest end");
142 return result;
143 }
144
BufferQueueCallback(SLOHBufferQueueItf sBufferQueueItf,void * pContext,SLuint32 size)145 static void BufferQueueCallback(SLOHBufferQueueItf sBufferQueueItf, void *pContext, SLuint32 size)
146 {
147 AUDIO_INFO_LOG("Enter BufferQueueCallback");
148 FILE *wavFile = (FILE *)pContext;
149 if (wavFile != nullptr) {
150 SLuint8 *buffer = nullptr;
151 SLuint32 pSize = 0;
152 SLresult result = (*bufferQueueItf)->GetBuffer(sBufferQueueItf, &buffer, &pSize);
153 if (SL_RESULT_SUCCESS != result) {
154 AUDIO_INFO_LOG("BufferQueueCallback GetBuffer result: %{public}lu", result);
155 return ;
156 }
157 if (buffer != nullptr) {
158 AUDIO_INFO_LOG("BufferQueueCallback, length, pSize:%{public}lu, size: %{public}lu.",
159 pSize, size);
160 fwrite(buffer, 1, pSize, wavFile);
161 result = (*bufferQueueItf)->Enqueue(sBufferQueueItf, buffer, size);
162 if (SL_RESULT_SUCCESS != result) {
163 AUDIO_INFO_LOG("BufferQueueCallback Enqueue result: %{public}lu", result);
164 return ;
165 }
166 } else {
167 AUDIO_INFO_LOG("BufferQueueCallback, buffer is null or pSize: %{public}lu, size: %{public}lu.",
168 pSize, size);
169 }
170 }
171 AUDIO_INFO_LOG("BufferQueueCallback end");
172 return;
173 }
174
CaptureStart(SLRecordItf sRecordItf,SLOHBufferQueueItf sBufferQueueItf,FILE * wavFile)175 static SLresult CaptureStart(SLRecordItf sRecordItf, SLOHBufferQueueItf sBufferQueueItf, FILE *wavFile)
176 {
177 AUDIO_INFO_LOG("Enter CaptureStart");
178 SLresult result = (*recordItf)->SetRecordState(sRecordItf, SL_RECORDSTATE_RECORDING);
179 if (SL_RESULT_SUCCESS != result) {
180 AUDIO_INFO_LOG("CaptureStart SetRecordState result: %{public}lu", result);
181 return result;
182 }
183 SLuint32 state = SL_RECORDSTATE_RECORDING;
184 result = (*recordItf)->GetRecordState(sRecordItf, &state);
185 if (SL_RESULT_SUCCESS != result) {
186 AUDIO_INFO_LOG("CaptureStart GetRecordState result: %{public}lu", result);
187 return result;
188 }
189 if (wavFile != nullptr) {
190 SLuint8* buffer = nullptr;
191 SLuint32 pSize = 0;
192 result = (*bufferQueueItf)->GetBuffer(sBufferQueueItf, &buffer, &pSize);
193 if (SL_RESULT_SUCCESS != result) {
194 AUDIO_INFO_LOG("CaptureStart GetBuffer result: %{public}lu", result);
195 return result;
196 }
197 if (buffer != nullptr) {
198 AUDIO_INFO_LOG("CaptureStart, enqueue buffer length: %{public}lu.", pSize);
199 fwrite(buffer, 1, pSize, wavFile);
200 result = (*bufferQueueItf)->Enqueue(sBufferQueueItf, buffer, pSize);
201 if (SL_RESULT_SUCCESS != result) {
202 AUDIO_INFO_LOG("CaptureStart Enqueue result: %{public}lu", result);
203 return result;
204 }
205 } else {
206 AUDIO_INFO_LOG("CaptureStart, buffer is null or pSize: %{public}lu.", pSize);
207 }
208 }
209 AUDIO_INFO_LOG("CaptureStart return result: %{public}lu", result);
210 return result;
211 }
212
CapturePause(SLRecordItf sRecordItf)213 static SLresult CapturePause(SLRecordItf sRecordItf)
214 {
215 AUDIO_INFO_LOG("Enter CapturePause");
216 SLresult result = (*recordItf)->SetRecordState(sRecordItf, SL_RECORDSTATE_PAUSED);
217 if (SL_RESULT_SUCCESS != result) {
218 AUDIO_INFO_LOG("CapturePause SetRecordState result: %{public}lu", result);
219 return result;
220 }
221 AUDIO_INFO_LOG("CapturePause return result: %{public}lu", result);
222 return result;
223 }
224
CaptureStop(SLRecordItf sRecordItf)225 static SLresult CaptureStop(SLRecordItf sRecordItf)
226 {
227 AUDIO_INFO_LOG("Enter CaptureStop");
228 fflush(wavFile_);
229 SLresult result = (*recordItf)->SetRecordState(sRecordItf, SL_RECORDSTATE_STOPPED);
230 if (SL_RESULT_SUCCESS != result) {
231 AUDIO_INFO_LOG("CapturePause SetRecordState result: %{public}lu", result);
232 return result;
233 }
234 (*pcmCapturerObject)->Destroy(pcmCapturerObject);
235 fclose(wavFile_);
236 wavFile_ = nullptr;
237 AUDIO_INFO_LOG("CaptureStop return result: %{public}lu", result);
238 return result;
239 }
240 }
241
242 /**
243 * @tc.number : SUB_MULTIMEDIA_AUDIO_OPENSELES_RECODER_FUNCTION_0100
244 * @tc.name : stop at end of stream
245 * @tc.desc : Basic function test
246 */
247 HWTEST_F(ActsOpenslesRecoderNdkTest, SUB_MULTIMEDIA_AUDIO_OPENSELES_RECODER_FUNCTION_0100, TestSize.Level1)
248 {
249 string filePath = "/data/test.pcm";
250 wavFile_ = fopen(filePath.c_str(), "wb");
251 if (wavFile_ == nullptr) {
252 AUDIO_INFO_LOG("OpenSL ES capture: Unable to open file");
253 return ;
254 }
255 SLresult result = OpenSLESCaptureTest();
256 ASSERT_EQ(SL_RESULT_SUCCESS, result);
257 result = CaptureStart(recordItf, bufferQueueItf, wavFile_);
258 ASSERT_EQ(SL_RESULT_SUCCESS, result);
259 result = CapturePause(recordItf);
260 ASSERT_EQ(SL_RESULT_SUCCESS, result);
261 result = CaptureStop(recordItf);
262 ASSERT_EQ(SL_RESULT_SUCCESS, result);
263 }
264
265 /**
266 * @tc.number : SUB_MULTIMEDIA_AUDIO_OPENSELES_RECODER_INVALID_FUNCTION_0100
267 * @tc.name : record invalid 001
268 * @tc.desc : Basic function test
269 */
270 HWTEST_F(ActsOpenslesRecoderNdkTest, SUB_MULTIMEDIA_AUDIO_OPENSELES_RECODER_INVALID_FUNCTION_0100, TestSize.Level1)
271 {
272 SLresult result1 = (*recordItf)->SetDurationLimit(nullptr, 0);
273 EXPECT_TRUE(result1 == SL_RESULT_FEATURE_UNSUPPORTED);
274
275 SLresult result2 = (*recordItf)->GetPosition(nullptr, 0);
276 EXPECT_TRUE(result2 == SL_RESULT_FEATURE_UNSUPPORTED);
277
278 SLresult result3 = (*recordItf)->RegisterCallback(recordItf, nullptr, wavFile_);
279 EXPECT_TRUE(result3 == SL_RESULT_FEATURE_UNSUPPORTED);
280
281 SLresult result4 = (*recordItf)->SetCallbackEventsMask(nullptr, 0);
282 EXPECT_TRUE(result4 == SL_RESULT_FEATURE_UNSUPPORTED);
283
284 SLresult result5 = (*recordItf)->GetCallbackEventsMask(nullptr, nullptr);
285 EXPECT_TRUE(result5 == SL_RESULT_FEATURE_UNSUPPORTED);
286
287 SLresult result6 = (*recordItf)->SetMarkerPosition(nullptr, 0);
288 EXPECT_TRUE(result6 == SL_RESULT_FEATURE_UNSUPPORTED);
289
290 SLresult result7 = (*recordItf)->ClearMarkerPosition(nullptr);
291 EXPECT_TRUE(result7 == SL_RESULT_FEATURE_UNSUPPORTED);
292
293 SLresult result8 = (*recordItf)->GetMarkerPosition(nullptr, nullptr);
294 EXPECT_TRUE(result8 == SL_RESULT_FEATURE_UNSUPPORTED);
295
296 SLresult result9 = (*recordItf)->SetPositionUpdatePeriod(nullptr, 0);
297 EXPECT_TRUE(result9 == SL_RESULT_FEATURE_UNSUPPORTED);
298
299 SLresult result10 = (*recordItf)->GetPositionUpdatePeriod(nullptr, nullptr);
300 EXPECT_TRUE(result10 == SL_RESULT_FEATURE_UNSUPPORTED);
301 }