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