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 <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
28 using namespace std;
29
30 static void BufferQueueCallback(SLOHBufferQueueItf bufferQueueItf, void *pContext, SLuint32 size);
31
32 static void CaptureOption(void);
33
34 static void OperationTime(uint64_t time);
35
36 static void CaptureStart(SLRecordItf recordItf, SLOHBufferQueueItf bufferQueueItf, FILE *wavFile);
37
38 static void CapturePause(SLRecordItf recordItf);
39
40 static void CaptureStop(SLRecordItf recordItf);
41
42 static void OpenSLESCaptureTest();
43
44 const int PARAMETERS = 8;
45 FILE *wavFile_ = nullptr;
46 SLObjectItf engineObject = nullptr;
47 SLRecordItf recordItf;
48 SLOHBufferQueueItf bufferQueueItf;
49 SLObjectItf pcmCapturerObject = nullptr;
50 struct timespec tv1 = {0};
51 struct timespec tv2 = {0};
52
main(int argc,char * argv[])53 int main(int argc, char *argv[])
54 {
55 AUDIO_INFO_LOG("OpenSL ES capture test in");
56 if (argc > PARAMETERS) {
57 AUDIO_ERR_LOG("Incorrect number(%{public}d) of parameters", argc);
58 return -1;
59 }
60
61 int opt = 0;
62 string filePath = "/data/test.pcm";
63 wavFile_ = fopen(filePath.c_str(), "wb");
64 if (wavFile_ == nullptr) {
65 AUDIO_INFO_LOG("OpenSL ES capture: Unable to open file");
66 return -1;
67 }
68
69 OpenSLESCaptureTest();
70 while ((opt = getopt(argc, argv, "s:p:S")) != -1) {
71 switch (opt) {
72 case 's':
73 CaptureOption();
74 break;
75 case 'p':
76 CapturePause(recordItf);
77 break;
78 case 'S':
79 default:
80 CaptureStop(recordItf);
81 break;
82 }
83 }
84 }
85
CaptureOption(void)86 static void CaptureOption(void)
87 {
88 AUDIO_INFO_LOG("Enter CaptureOption.");
89 uint64_t totalTime = strtoull(optarg, nullptr, 10);
90 CaptureStart(recordItf, bufferQueueItf, wavFile_);
91 OperationTime(totalTime);
92 }
93
OpenSLESCaptureTest()94 static void OpenSLESCaptureTest()
95 {
96 AUDIO_INFO_LOG("Enter OpenSLESCaptureTest");
97 engineObject = nullptr;
98 SLEngineItf engineItf = nullptr;
99
100 slCreateEngine(&engineObject, 0, nullptr, 0, nullptr, nullptr);
101 (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
102 (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineItf);
103
104 SLDataLocator_IODevice io_device = {
105 SL_DATALOCATOR_IODEVICE,
106 SL_IODEVICE_AUDIOINPUT,
107 SL_DEFAULTDEVICEID_AUDIOINPUT,
108 NULL
109 };
110
111 SLDataSource audioSource = {
112 &io_device,
113 NULL
114 };
115
116 SLDataLocator_BufferQueue buffer_queue = {
117 SL_DATALOCATOR_BUFFERQUEUE,
118 3
119 };
120
121 SLDataFormat_PCM format_pcm = {
122 SL_DATAFORMAT_PCM,
123 OHOS::AudioStandard::AudioChannel::MONO,
124 OHOS::AudioStandard::AudioSamplingRate::SAMPLE_RATE_44100,
125 SL_PCMSAMPLEFORMAT_FIXED_16,
126 0,
127 0,
128 0
129 };
130 SLDataSink audioSink = {
131 &buffer_queue,
132 &format_pcm
133 };
134
135 (*engineItf)->CreateAudioRecorder(engineItf, &pcmCapturerObject,
136 &audioSource, &audioSink, 0, nullptr, nullptr);
137 (*pcmCapturerObject)->Realize(pcmCapturerObject, SL_BOOLEAN_FALSE);
138
139 (*pcmCapturerObject)->GetInterface(pcmCapturerObject, SL_IID_RECORD, &recordItf);
140 (*pcmCapturerObject)->GetInterface(pcmCapturerObject, SL_IID_OH_BUFFERQUEUE, &bufferQueueItf);
141 (*bufferQueueItf)->RegisterCallback(bufferQueueItf, BufferQueueCallback, wavFile_);
142
143 return;
144 }
145
BufferQueueCallback(SLOHBufferQueueItf bufferQueueItf,void * pContext,SLuint32 size)146 static void BufferQueueCallback(SLOHBufferQueueItf bufferQueueItf, void *pContext, SLuint32 size)
147 {
148 AUDIO_INFO_LOG("Enter BufferQueueCallback");
149 FILE *wavFile = (FILE *)pContext;
150 if (wavFile != nullptr) {
151 SLuint8 *buffer = nullptr;
152 SLuint32 pSize = 0;
153 (*bufferQueueItf)->GetBuffer(bufferQueueItf, &buffer, pSize);
154 if (buffer != nullptr) {
155 AUDIO_INFO_LOG("BufferQueueCallback, length, pSize:%{public}lu, size: %{public}lu.",
156 pSize, size);
157 fwrite(buffer, 1, pSize, wavFile);
158 (*bufferQueueItf)->Enqueue(bufferQueueItf, buffer, size);
159 } else {
160 AUDIO_INFO_LOG("BufferQueueCallback, buffer is null or pSize: %{public}lu, size: %{public}lu.",
161 pSize, size);
162 }
163 }
164
165 return;
166 }
167
CaptureStart(SLRecordItf recordItf,SLOHBufferQueueItf bufferQueueItf,FILE * wavFile)168 static void CaptureStart(SLRecordItf recordItf, SLOHBufferQueueItf bufferQueueItf, FILE *wavFile)
169 {
170 AUDIO_INFO_LOG("Enter CaptureStart");
171 (*recordItf)->SetRecordState(recordItf, SL_RECORDSTATE_RECORDING);
172 if (wavFile != nullptr) {
173 SLuint8* buffer = nullptr;
174 SLuint32 pSize = 0;
175 (*bufferQueueItf)->GetBuffer(bufferQueueItf, &buffer, pSize);
176 if (buffer != nullptr) {
177 AUDIO_INFO_LOG("CaptureStart, enqueue buffer length: %{public}lu.", pSize);
178 fwrite(buffer, 1, pSize, wavFile);
179 (*bufferQueueItf)->Enqueue(bufferQueueItf, buffer, pSize);
180 } else {
181 AUDIO_INFO_LOG("CaptureStart, buffer is null or pSize: %{public}lu.", pSize);
182 }
183 }
184
185 return;
186 }
187
CapturePause(SLRecordItf recordItf)188 static void CapturePause(SLRecordItf recordItf)
189 {
190 AUDIO_INFO_LOG("Enter CapturePause");
191 uint64_t totalTime = strtoull(optarg, nullptr, 10);
192 (*recordItf)->SetRecordState(recordItf, SL_RECORDSTATE_PAUSED);
193 OperationTime(totalTime);
194
195 return;
196 }
197
CaptureStop(SLRecordItf recordItf)198 static void CaptureStop(SLRecordItf recordItf)
199 {
200 AUDIO_INFO_LOG("Enter CaptureStop");
201 fflush(wavFile_);
202 (*recordItf)->SetRecordState(recordItf, SL_RECORDSTATE_STOPPED);
203 (*pcmCapturerObject)->Destroy(pcmCapturerObject);
204 fclose(wavFile_);
205 wavFile_ = nullptr;
206 return;
207 }
208
OperationTime(uint64_t time)209 static void OperationTime(uint64_t time)
210 {
211 uint64_t usecTimes = 1000000000;
212 time *= usecTimes;
213 clock_gettime(CLOCK_REALTIME, &tv1);
214 clock_gettime(CLOCK_REALTIME, &tv2);
215 while (((tv2.tv_sec * usecTimes + tv2.tv_nsec) - (tv1.tv_sec * usecTimes + tv1.tv_nsec)) <= time) {
216 sleep(1);
217 clock_gettime(CLOCK_REALTIME, &tv2);
218 }
219
220 return;
221 }
222