1 /*
2 * Copyright (c) 2021-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 <chrono>
17 #include <cstdint>
18 #include <cstdio>
19 #include <cstring>
20 #include <vector>
21 #include <cstdlib>
22 #include <memory>
23 #include "unistd.h"
24 #include "audio_capturer.h"
25 #include "audio_info.h"
26 #include "audio_log.h"
27
28 using namespace std;
29 using namespace std::chrono;
30 using namespace OHOS;
31 using namespace OHOS::AudioStandard;
32 int32_t bufferMsec = 0;
33 namespace AudioTestConstants {
34 constexpr int32_t FIRST_ARG_IDX = 1;
35 constexpr int32_t SECOND_ARG_IDX = 2;
36 constexpr int32_t THIRD_ARG_IDX = 3;
37 constexpr int32_t FOURTH_ARG_IDX = 4;
38 constexpr int32_t NUM_BASE = 10;
39 constexpr int32_t PAUSE_BUFFER_POSITION = 128;
40 constexpr int32_t PAUSE_READ_TIME_SECONDS = 2;
41 constexpr int32_t SUCCESS = 0;
42 }
43
44 class AudioCapturerCallbackTestImpl : public AudioCapturerCallback {
45 public:
OnStateChange(const CapturerState state)46 void OnStateChange(const CapturerState state) override
47 {
48 AUDIO_DEBUG_LOG("AudioCapturerCallbackTestImpl:: OnStateChange");
49
50 switch (state) {
51 case CAPTURER_PREPARED:
52 AUDIO_DEBUG_LOG("AudioCapturerCallbackTestImpl: OnStateChange CAPTURER_PREPARED");
53 break;
54 case CAPTURER_RUNNING:
55 AUDIO_DEBUG_LOG("AudioCapturerCallbackTestImpl: OnStateChange CAPTURER_RUNNING");
56 break;
57 case CAPTURER_STOPPED:
58 AUDIO_DEBUG_LOG("AudioCapturerCallbackTestImpl: OnStateChange CAPTURER_STOPPED");
59 break;
60 case CAPTURER_RELEASED:
61 AUDIO_DEBUG_LOG("AudioCapturerCallbackTestImpl: OnStateChange CAPTURER_RELEASED");
62 break;
63 default:
64 AUDIO_ERR_LOG("AudioCapturerCallbackTestImpl: OnStateChange NOT A VALID state");
65 break;
66 }
67 }
68 };
69
70 class AudioCapturerTest {
71 public:
CheckSupportedParams() const72 void CheckSupportedParams() const
73 {
74 vector<AudioSampleFormat> supportedFormatList = AudioCapturer::GetSupportedFormats();
75 AUDIO_INFO_LOG("Supported formats:");
76 for (auto i = supportedFormatList.begin(); i != supportedFormatList.end(); ++i) {
77 AUDIO_INFO_LOG("Format %{public}d", *i);
78 }
79
80 vector<AudioChannel> supportedChannelList = AudioCapturer::GetSupportedChannels();
81 AUDIO_INFO_LOG("Supported channels:");
82 for (auto i = supportedChannelList.begin(); i != supportedChannelList.end(); ++i) {
83 AUDIO_INFO_LOG("channel %{public}d", *i);
84 }
85
86 vector<AudioEncodingType> supportedEncodingTypes
87 = AudioCapturer::GetSupportedEncodingTypes();
88 AUDIO_INFO_LOG("Supported encoding types:");
89 for (auto i = supportedEncodingTypes.begin(); i != supportedEncodingTypes.end(); ++i) {
90 AUDIO_INFO_LOG("encoding type %{public}d", *i);
91 }
92
93 vector<AudioSamplingRate> supportedSamplingRates = AudioCapturer::GetSupportedSamplingRates();
94 AUDIO_INFO_LOG("Supported sampling rates:");
95 for (auto i = supportedSamplingRates.begin(); i != supportedSamplingRates.end(); ++i) {
96 AUDIO_INFO_LOG("sampling rate %{public}d", *i);
97 }
98 }
99
InitCapture(const unique_ptr<AudioCapturer> & audioCapturer) const100 bool InitCapture(const unique_ptr<AudioCapturer> &audioCapturer) const
101 {
102 AUDIO_INFO_LOG("Starting Stream");
103 if (!audioCapturer->Start()) {
104 AUDIO_ERR_LOG("Start stream failed");
105 audioCapturer->Release();
106 return false;
107 }
108 AUDIO_INFO_LOG("Capturing started");
109
110 AUDIO_INFO_LOG("Get Audio parameters:");
111 AudioCapturerParams getCapturerParams;
112 if (audioCapturer->GetParams(getCapturerParams) == AudioTestConstants::SUCCESS) {
113 AUDIO_INFO_LOG("Get Audio format: %{public}d", getCapturerParams.audioSampleFormat);
114 AUDIO_INFO_LOG("Get Audio sampling rate: %{public}d", getCapturerParams.samplingRate);
115 AUDIO_INFO_LOG("Get Audio channels: %{public}d", getCapturerParams.audioChannel);
116 }
117
118 return true;
119 }
120
StartCapture(const unique_ptr<AudioCapturer> & audioCapturer,bool isBlocking,FILE * pFile) const121 bool StartCapture(const unique_ptr<AudioCapturer> &audioCapturer, bool isBlocking, FILE *pFile) const
122 {
123 size_t bufferLen;
124 if (audioCapturer->GetBufferSize(bufferLen) < 0) {
125 AUDIO_ERR_LOG(" GetMinimumBufferSize failed");
126 return false;
127 }
128
129 auto buffer = std::make_unique<uint8_t[]>(bufferLen);
130 if (buffer == nullptr) {
131 AUDIO_ERR_LOG("AudioCapturerTest: Failed to allocate buffer");
132 return false;
133 }
134 AUDIO_INFO_LOG("AudioPerf Capturer First Frame Read, BUFFER_LEN = %{public}zu", bufferLen);
135 size_t size = 1;
136 size_t numBuffersToCapture = 256;
137 while (numBuffersToCapture) {
138 size_t bytesRead = 0;
139 while (bytesRead < bufferLen) {
140 auto start = high_resolution_clock::now();
141 int32_t len = audioCapturer->Read(*(buffer.get() + bytesRead), bufferLen - bytesRead, isBlocking);
142 auto stop = high_resolution_clock::now();
143 auto duration = duration_cast<microseconds>(stop - start);
144 AUDIO_INFO_LOG("AudioPerf Capturer Read in microseconds TimeTaken =%{public}lld",
145 (long long)duration.count());
146 if (len >= 0) {
147 bytesRead += len;
148 } else {
149 bytesRead = len;
150 break;
151 }
152 }
153 if (bytesRead < 0) {
154 AUDIO_ERR_LOG("Bytes read failed. error code %{public}zu", bytesRead);
155 break;
156 } else if (bytesRead == 0) {
157 continue;
158 }
159
160 if (fwrite(buffer.get(), size, bytesRead, pFile) != bytesRead) {
161 AUDIO_ERR_LOG("error occurred in fwrite");
162 }
163 numBuffersToCapture--;
164 if ((numBuffersToCapture == AudioTestConstants::PAUSE_BUFFER_POSITION)
165 && (audioCapturer->Stop())) {
166 AUDIO_INFO_LOG("Audio capture stopped for %{public}d seconds",
167 AudioTestConstants::PAUSE_READ_TIME_SECONDS);
168 sleep(AudioTestConstants::PAUSE_READ_TIME_SECONDS);
169 if (!audioCapturer->Start()) {
170 AUDIO_ERR_LOG("resume stream failed");
171 audioCapturer->Release();
172 break;
173 }
174 AUDIO_INFO_LOG("AudioPerf Capturer Read after stop and start");
175 }
176 }
177
178 return true;
179 }
180
TestRecording(int32_t samplingRate,bool isBlocking,string filePath) const181 bool TestRecording(int32_t samplingRate, bool isBlocking, string filePath) const
182 {
183 AUDIO_INFO_LOG("TestCapture start ");
184 AudioCapturerOptions capturerOptions;
185 capturerOptions.streamInfo.samplingRate = static_cast<AudioSamplingRate>(samplingRate);
186 capturerOptions.streamInfo.encoding = AudioEncodingType::ENCODING_PCM;
187 capturerOptions.streamInfo.format = AudioSampleFormat::SAMPLE_S16LE;
188 capturerOptions.streamInfo.channels = AudioChannel::STEREO;
189 capturerOptions.capturerInfo.sourceType = SourceType::SOURCE_TYPE_MIC;
190 capturerOptions.capturerInfo.capturerFlags = 0;
191
192 unique_ptr<AudioCapturer> audioCapturer = AudioCapturer::Create(capturerOptions);
193
194 int32_t ret = 0;
195 shared_ptr<AudioCapturerCallback> cb1 = make_shared<AudioCapturerCallbackTestImpl>();
196 ret = audioCapturer->SetCapturerCallback(cb1);
197 if (ret) {
198 AUDIO_ERR_LOG("AudioCapturerTest: SetCapturerCallback failed %{public}d", ret);
199 return false;
200 }
201
202 CheckSupportedParams();
203 AUDIO_ERR_LOG("AudioCaptruerTest: buffermsec = %{public}d", bufferMsec);
204 int32_t status = audioCapturer->SetBufferDuration(bufferMsec);
205 if (status) {
206 AUDIO_ERR_LOG("Failed to set buffer duration");
207 }
208
209 if (!InitCapture(audioCapturer)) {
210 AUDIO_ERR_LOG("Initialize capturer failed");
211 return false;
212 }
213
214 AUDIO_INFO_LOG("Is blocking read: %{public}s", isBlocking ? "true" : "false");
215 FILE *pFile = fopen(filePath.c_str(), "wb");
216 if (pFile == nullptr) {
217 AUDIO_INFO_LOG("AudioCapturerTest: Unable to open file");
218 return false;
219 }
220
221 if (!StartCapture(audioCapturer, isBlocking, pFile)) {
222 AUDIO_ERR_LOG("Start capturer failed");
223 fclose(pFile);
224 return false;
225 }
226
227 fflush(pFile);
228 if (!audioCapturer->Flush()) {
229 AUDIO_ERR_LOG("AudioCapturerTest: flush failed");
230 }
231
232 if (!audioCapturer->Stop()) {
233 AUDIO_ERR_LOG("AudioCapturerTest: Stop failed");
234 }
235
236 if (!audioCapturer->Release()) {
237 AUDIO_ERR_LOG("AudioCapturerTest: Release failed");
238 }
239 fclose(pFile);
240 AUDIO_INFO_LOG("TestCapture end");
241
242 return true;
243 }
244 };
245
main(int argc,char * argv[])246 int main(int argc, char *argv[])
247 {
248 AUDIO_INFO_LOG("capture test in");
249
250 if ((argv == nullptr) || (argc <= AudioTestConstants::THIRD_ARG_IDX)) {
251 AUDIO_ERR_LOG("argv is null");
252 return 0;
253 }
254
255 AUDIO_INFO_LOG("argc=%d", argc);
256 AUDIO_INFO_LOG("argv[1]=%{public}s", argv[AudioTestConstants::FIRST_ARG_IDX]);
257 AUDIO_INFO_LOG("argv[2]=%{public}s", argv[AudioTestConstants::SECOND_ARG_IDX]);
258 AUDIO_INFO_LOG("argv[3]=%{public}s", argv[AudioTestConstants::THIRD_ARG_IDX]);
259
260 int32_t samplingRate = atoi(argv[AudioTestConstants::SECOND_ARG_IDX]);
261 bool isBlocking = (atoi(argv[AudioTestConstants::THIRD_ARG_IDX]) == 1);
262 string filePath = argv[AudioTestConstants::FIRST_ARG_IDX];
263 if (argc > AudioTestConstants::FOURTH_ARG_IDX) {
264 bufferMsec = strtol(argv[AudioTestConstants::FOURTH_ARG_IDX], nullptr, AudioTestConstants::NUM_BASE);
265 }
266 AudioCapturerTest testObj;
267 bool ret = testObj.TestRecording(samplingRate, isBlocking, filePath);
268
269 return ret;
270 }
271