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