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