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