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