1 /*
2  * Copyright (c) 2024 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 "InnerCapTest"
17 #endif
18 
19 #include <chrono>
20 #include <cstdio>
21 #include <cstdlib>
22 #include <cinttypes>
23 #include <unistd.h>
24 #include <thread>
25 #include <random>
26 #include <iostream>
27 #include "securec.h"
28 #include <map>
29 
30 #include "audio_capturer_log.h"
31 #include "audio_capturer.h"
32 
33 using namespace std;
34 namespace OHOS {
35 namespace AudioStandard {
36 enum CapturerMode : int32_t {
37     DIRECTLY_READ = 0,
38     READ_AFTER_CALLBACK = 1,
39 };
40 
41 enum OperationCode : int32_t {
42     CODE_INVALID = -1,
43     CAPTURER_CODE_INIT = 0,
44     CAPTURER_CODE_START = 1,
45     CAPTURER_CODE_PAUSE = 2,
46     CAPTURER_CODE_FLUSH = 3,
47     CAPTURER_CODE_STOP = 4,
48     CAPTURER_CODE_RELEASE = 5,
49     EXIT_DEMO = 1000,
50     CAPTURER_CODE_MAX
51 };
52 
53 class PaCapturerTest : public AudioCapturerReadCallback, public enable_shared_from_this<PaCapturerTest> {
54 public:
~PaCapturerTest()55     virtual ~PaCapturerTest() {};
56 
57     int32_t InitCapturer(CapturerMode capturerMode);
58     int32_t StartRecorder();
59     int32_t PauseRecorder();
60     int32_t FlushRecorder();
61     int32_t StopRecorder();
62     int32_t ReleaseRecorder();
63     void OnReadData(size_t length) override;
64 
65 private:
66     std::unique_ptr<AudioCapturer> audioCapturer_ = nullptr;
67     std::condition_variable enableReadCv_;
68     bool enableRead_ = false;
69     FILE *pfd_ = nullptr;
70     CapturerMode capturerMode_ = READ_AFTER_CALLBACK;
71 };
72 
OnReadData(size_t length)73 void PaCapturerTest::OnReadData(size_t length)
74 {
75     int32_t ret = -1;
76     AUDIO_INFO_LOG("PaCapturerTest::OnReadData, length: %{public}zu", length);
77     BufferDesc bufferDesc = { nullptr, 0, 0 };
78     audioCapturer_->GetBufferDesc(bufferDesc);
79 
80     ret = fwrite(reinterpret_cast<void *>(bufferDesc.buffer), 1, bufferDesc.bufLength, pfd_);
81     if (ret != 0) { AUDIO_ERR_LOG(" something wrong when writing pcm! "); }
82 
83     audioCapturer_->Enqueue(bufferDesc);
84 }
85 
InitCapturer(CapturerMode capturerMode)86 int32_t PaCapturerTest::InitCapturer(CapturerMode capturerMode)
87 {
88     AUDIO_INFO_LOG("Start InitCapturer");
89     capturerMode_ = capturerMode;
90     AudioCapturerOptions capturerOptions;
91     capturerOptions.streamInfo.samplingRate = SAMPLE_RATE_48000;
92     capturerOptions.streamInfo.encoding = AudioEncodingType::ENCODING_PCM;
93     capturerOptions.streamInfo.format = AudioSampleFormat::SAMPLE_S16LE;
94     capturerOptions.streamInfo.channels = AudioChannel::STEREO;
95     capturerOptions.capturerInfo.sourceType = SourceType::SOURCE_TYPE_PLAYBACK_CAPTURE;
96     capturerOptions.capturerInfo.capturerFlags = 0;
97 
98     audioCapturer_ = AudioCapturer::Create(capturerOptions);
99     if (audioCapturer_ == nullptr) {
100         AUDIO_ERR_LOG("Create audioCapturer failed");
101         return -1;
102     }
103     if (capturerMode_ == READ_AFTER_CALLBACK) {
104         if (audioCapturer_->SetCaptureMode(CAPTURE_MODE_CALLBACK)) {
105             AUDIO_ERR_LOG("SetCaptureMode failed");
106             return -1;
107         }
108         if (audioCapturer_->SetCapturerReadCallback(shared_from_this())) {
109             AUDIO_ERR_LOG("SetCapturerReadCallback failed");
110             return -1;
111         }
112     }
113     AUDIO_INFO_LOG("Audio capturer create success.");
114     pfd_ = fopen("/data/data/.pulse_dir/capturer.pcm", "wb+");
115     return 0;
116 }
117 
StartRecorder()118 int32_t PaCapturerTest::StartRecorder()
119 {
120     AUDIO_INFO_LOG("StartRecorder");
121     if (audioCapturer_ == nullptr) {
122         AUDIO_ERR_LOG("audioCapturer_ init failed.");
123         return -1;
124     }
125     enableRead_ = true;
126     enableReadCv_.notify_all();
127     if (!audioCapturer_->Start()) {
128         AUDIO_ERR_LOG("Audio capturer start failed.");
129         return -1;
130     }
131     return 0;
132 }
133 
PauseRecorder()134 int32_t PaCapturerTest::PauseRecorder()
135 {
136     if (audioCapturer_ == nullptr) {
137         AUDIO_ERR_LOG("audioCapturer_ init failed.");
138         return -1;
139     }
140     enableRead_ = false;
141     if (!audioCapturer_->Pause()) {
142         AUDIO_ERR_LOG("Audio capturer start failed.");
143         return -1;
144     }
145     return 0;
146 }
147 
FlushRecorder()148 int32_t PaCapturerTest::FlushRecorder()
149 {
150     if (audioCapturer_ == nullptr) {
151         AUDIO_ERR_LOG("audioCapturer_ init failed.");
152         return -1;
153     }
154     if (!audioCapturer_->Flush()) {
155         AUDIO_ERR_LOG("Audio capturer start failed.");
156         return -1;
157     }
158     return 0;
159 }
160 
StopRecorder()161 int32_t PaCapturerTest::StopRecorder()
162 {
163     if (audioCapturer_ == nullptr) {
164         AUDIO_ERR_LOG("audioCapturer_ init failed.");
165         return -1;
166     }
167     if (!audioCapturer_->Stop()) {
168         AUDIO_ERR_LOG("Audio capturer stop failed.");
169         return -1;
170     }
171     return 0;
172 }
173 
ReleaseRecorder()174 int32_t PaCapturerTest::ReleaseRecorder()
175 {
176     int32_t ret = -1;
177     if (audioCapturer_ == nullptr) {
178         AUDIO_ERR_LOG("audioCapturer_ init failed.");
179         return -1;
180     }
181     enableRead_ = false;
182     if (!audioCapturer_->Release()) {
183         AUDIO_ERR_LOG("Audio capturer stop failed.");
184         return -1;
185     }
186     audioCapturer_ = nullptr;
187     ret = fclose(pfd_);
188     if (ret != 0) { AUDIO_ERR_LOG(" something wrong when fclose! "); }
189     pfd_ = nullptr;
190     return 0;
191 }
192 
GetUserInput()193 int32_t GetUserInput()
194 {
195     int32_t res = -1; // result
196     size_t count = 3; // try three time
197     int32_t ret = -1;
198     cout << ">> >> >>";
199 
200     ret = scanf_s("%d", &res);
201     if (ret != 0) { AUDIO_ERR_LOG(" something wrong when scanf_s! "); }
202     while (res < 0 && count-- > 0) {
203         cout << "invalid input, not a number! Please retry with a number." << endl;
204         cout << ">> >> >>";
205         ret = scanf_s("%d", &res);
206         if (ret != 0) { AUDIO_ERR_LOG(" something wrong when scanf_s! "); }
207     }
208 
209     return res;
210 }
211 
PrintUsage()212 void PrintUsage()
213 {
214     cout << "[inner capturer Test App]" << endl << endl;
215     cout << "Supported Functionalities:" << endl;
216     cout << "================================Usage=======================================" << endl << endl;
217     cout << "  0: Init Capturer." << endl;
218     cout << "  1: Start read." << endl;
219     cout << "  2: Pause read." << endl;
220     cout << "  3: Flush read." << endl;
221     cout << "  4: Stop read." << endl;
222     cout << "  5: Release read." << endl;
223 
224     cout << "  1000: exit demo." << endl;
225     cout << " Please input your choice: " << endl;
226     cout << "================================Usage=======================================" << endl << endl;
227 }
228 
InitRecorder(std::shared_ptr<PaCapturerTest> capturerTest,CapturerMode capturerMode)229 int32_t InitRecorder(std::shared_ptr<PaCapturerTest> capturerTest, CapturerMode capturerMode)
230 {
231     if (capturerTest == nullptr) {
232         cout << "PaCapturerTest obj is nullptr, init recorder error." << endl;
233         return -1;
234     }
235     int32_t ret = capturerTest->InitCapturer(capturerMode);
236     if (ret != 0) {
237         cout << "Init capturer error!" << endl;
238         return -1;
239     }
240     return 0;
241 }
242 
StartRecorder(std::shared_ptr<PaCapturerTest> capturerTest)243 int32_t StartRecorder(std::shared_ptr<PaCapturerTest> capturerTest)
244 {
245     if (capturerTest == nullptr) {
246         cout << "PaCapturerTest obj is nullptr, start recorder error." << endl;
247         return -1;
248     }
249     int32_t ret = capturerTest->StartRecorder();
250     if (ret != 0) {
251         cout << "Start recorder error!" << endl;
252         return -1;
253     }
254     return 0;
255 }
256 
PauseRecorder(std::shared_ptr<PaCapturerTest> capturerTest)257 int32_t PauseRecorder(std::shared_ptr<PaCapturerTest> capturerTest)
258 {
259     if (capturerTest == nullptr) {
260         cout << "PaCapturerTest obj is nullptr, pause recorder error." << endl;
261         return -1;
262     }
263     int32_t ret = capturerTest->PauseRecorder();
264     if (ret != 0) {
265         cout << "Pause recorder error!" << endl;
266         return -1;
267     }
268     return 0;
269 }
270 
FlushRecorder(std::shared_ptr<PaCapturerTest> capturerTest)271 int32_t FlushRecorder(std::shared_ptr<PaCapturerTest> capturerTest)
272 {
273     if (capturerTest == nullptr) {
274         cout << "PaCapturerTest obj is nullptr, Flush recorder error." << endl;
275         return -1;
276     }
277     int32_t ret = capturerTest->FlushRecorder();
278     if (ret != 0) {
279         cout << "Flush recorder error!" << endl;
280         return -1;
281     }
282     return 0;
283 }
284 
StopRecorder(std::shared_ptr<PaCapturerTest> capturerTest)285 int32_t StopRecorder(std::shared_ptr<PaCapturerTest> capturerTest)
286 {
287     if (capturerTest == nullptr) {
288         cout << "PaCapturerTest obj is nullptr, stop recorder error." << endl;
289         return -1;
290     }
291     int32_t ret = capturerTest->StopRecorder();
292     if (ret != 0) {
293         cout << "Stop recorder error!" << endl;
294         return -1;
295     }
296     return 0;
297 }
298 
ReleaseRecorder(std::shared_ptr<PaCapturerTest> capturerTest)299 int32_t ReleaseRecorder(std::shared_ptr<PaCapturerTest> capturerTest)
300 {
301     if (capturerTest == nullptr) {
302         cout << "PaCapturerTest obj is nullptr, stop recorder error." << endl;
303         return -1;
304     }
305     int32_t ret = capturerTest->ReleaseRecorder();
306     if (ret != 0) {
307         cout << "Stop recorder error!" << endl;
308         return -1;
309     }
310     return 0;
311 }
312 
HandleCapturerCode(OperationCode optCode,std::shared_ptr<PaCapturerTest> capturerTest)313 void HandleCapturerCode(OperationCode optCode, std::shared_ptr<PaCapturerTest> capturerTest)
314 {
315     switch (optCode) {
316         case CAPTURER_CODE_START:
317             StartRecorder(capturerTest);
318             break;
319         case CAPTURER_CODE_PAUSE:
320             PauseRecorder(capturerTest);
321             break;
322         case CAPTURER_CODE_FLUSH:
323             FlushRecorder(capturerTest);
324             break;
325         case CAPTURER_CODE_STOP:
326             StopRecorder(capturerTest);
327             break;
328         case CAPTURER_CODE_RELEASE:
329             ReleaseRecorder(capturerTest);
330             break;
331         default:
332             cout << "Invalid input: " << optCode << endl;
333             break;
334     }
335 }
336 
Loop(std::shared_ptr<PaCapturerTest> capturerTest)337 void Loop(std::shared_ptr<PaCapturerTest> capturerTest)
338 {
339     bool isProcTestRun = true;
340     while (isProcTestRun) {
341         PrintUsage();
342         OperationCode optCode = CODE_INVALID;
343         int32_t res = GetUserInput();
344         int32_t capturerMode = 1; // default callback
345 
346         if (res < 0 && res >= OperationCode::CAPTURER_CODE_MAX) {
347             cout << "OperationCode is INVALID!" << endl;
348             return;
349         }
350         optCode = static_cast<OperationCode>(res);
351         switch (optCode) {
352             // Capturer
353             case CAPTURER_CODE_INIT:
354                 cout << " ==== Recorder has been inited, use callback mode ==== " << endl;
355                 InitRecorder(capturerTest, static_cast<CapturerMode>(capturerMode));
356                 break;
357             case EXIT_DEMO:
358                 isProcTestRun = false;
359                 break;
360             default:
361                 HandleCapturerCode(optCode, capturerTest);
362                 break;
363         }
364     }
365 }
366 }
367 }
368 
369 using namespace OHOS::AudioStandard;
370 using namespace std;
main(int argc,char * argv[])371 int main(int argc, char* argv[])
372 {
373     cout << "oh inner capturer test." << endl;
374     std::shared_ptr<PaCapturerTest> capturerTest = std::make_shared<PaCapturerTest>();
375     Loop(capturerTest);
376     return 0;
377 }
378