• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020-2021 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 <ctime>
17 #include <iostream>
18 #include <string>
19 #include <thread>
20 #include <unistd.h>
21 #include "audio_capturer.h"
22 #include "media_errors.h"
23 #include "securec.h"
24 
25 using namespace OHOS;
26 using namespace OHOS::Audio;
27 using namespace OHOS::Media;
28 using namespace std;
29 
30 struct AudioSourceInput {
31     size_t framesize;
32     uint8_t *buffer;
33     AudioCapturer *audioCap;
34     AudioCodecFormat audioFormat;
35     std::thread processThread;
36     bool bThreadRun;
37 };
38 
39 enum AppState {
40     AV_ON,
41     AV_OFF
42 };
43 
44 static AudioSourceInput g_audioSourceProcessInput;
45 
GernerateFileName(AudioCodecFormat format)46 static char *GernerateFileName(AudioCodecFormat format)
47 {
48     time_t stCurrent;
49     char aszDatetime[0x100];
50     (void)time(&stCurrent);
51     struct tm *pstCurrentTime = localtime(&(stCurrent));
52     if (pstCurrentTime == nullptr) {
53         return nullptr;
54     }
55     if (strftime(aszDatetime, 0x100, "%Y-%m-%d-%H-%M-%S", pstCurrentTime) > 0) {
56         std::cout << "Current Time: " << aszDatetime << std::endl;
57     }
58 
59     string postfix;
60     switch (format) {
61         case PCM:
62             postfix = "pcm";
63             break;
64         case AAC_LC:
65             postfix = "aac";
66             break;
67         case G711A:
68             postfix = "g711a";
69             break;
70         case G711U:
71             postfix = "g711u";
72             break;
73         case G726:
74             postfix = "g726";
75             break;
76         default:
77             return nullptr;
78     }
79 
80     const int32_t size = 0x180;
81     char *name = static_cast<char *>(malloc(size));
82     if (name == nullptr) {
83         return nullptr;
84     }
85     (void)memset_s(name, size, 0, size);
86     /* create file for save stream */
87     if (snprintf_s(name, size, size - 1, "/userdata/audio_%s.%s", aszDatetime, postfix.c_str()) < 0) {
88         std::cout << "snprintf_s failed " << std::endl;
89         free(name);
90         return nullptr;
91     }
92     return name;
93 }
94 
AudioInputSourceProcess(AudioSourceInput * audioSourceInput)95 static void AudioInputSourceProcess(AudioSourceInput *audioSourceInput)
96 {
97     const int32_t waitTimeUs = 20000;
98     std::cout << "audioSourceInput: " << audioSourceInput << std::endl;
99     if (audioSourceInput == nullptr) {
100         return;
101     }
102 
103     char *fileName = GernerateFileName(audioSourceInput->audioFormat);
104     if (fileName == nullptr) {
105         return;
106     }
107 
108     FILE *pfd = fopen(fileName, "w+");
109     if (pfd == nullptr) {
110         std::cout << "open file  failed " << fileName << std::endl;
111         free(fileName);
112         return;
113     }
114     std::cout << "Open  SUCCESS " << fileName << std::endl;
115     int readCnt = 0;
116     while (audioSourceInput->bThreadRun) {
117         int ret = audioSourceInput->audioCap->Read(audioSourceInput->buffer,
118             audioSourceInput->framesize, false);
119         if (ret <= 0) {
120             std::cout << "audioCap Read failed ret:" << ret << std::endl;
121             usleep(waitTimeUs);
122             continue;
123         }
124         if (fwrite(audioSourceInput->buffer, 1, ret, pfd) != ret) {
125             std::cout << "fwrite failed errno:"<< errno << std::endl;
126             break;
127         }
128         readCnt++;
129         std::cout << "audioCap Read readCnt:  "<< readCnt << " size: " << ret << std::endl;
130     }
131     (void)fclose(pfd);
132     free(fileName);
133 }
134 
135 struct CapturerInfo {
136     AudioCodecFormat audioFormat;
137     int32_t sampleRate;
138     int32_t bitRate;
139 };
140 
GetAudioFormat(void)141 static AudioCodecFormat GetAudioFormat(void)
142 {
143     std::cout << "*******************************************" << endl;
144     std::cout << "SetCapturerInfo (PCM:1, AAC_LC:2, G711A:7, G711U:8, G726:9)" << endl;
145     std::cout << "*******************************************" << endl;
146     int32_t audioFormat;
147     std::cin >> audioFormat;
148     cout << "input  audioFormat:" << audioFormat << endl;
149     if (audioFormat != 1 && audioFormat != 0x2 && audioFormat != 0x7 &&
150         audioFormat != 0x8 && audioFormat != 0x9) {
151         std::cout << "Can't support input format:" << static_cast<int32_t> (audioFormat) << std::endl;
152         return FORMAT_BUTT;
153     }
154     return static_cast<AudioCodecFormat> (audioFormat);
155 }
156 
GetDefaultSampleRateAndRateBaseFormat(AudioCodecFormat format,int32_t & sr,int32_t & rate)157 static void GetDefaultSampleRateAndRateBaseFormat(AudioCodecFormat format, int32_t &sr, int32_t &rate)
158 {
159     const CapturerInfo audioCapturerInfo[] = {
160         {PCM, 16000, 128000},
161         {AAC_LC, 48000, 128000},
162         {G711A, 8000, 64000},
163         {G711U, 8000, 64000},
164         {G726, 8000, 24000}
165     };
166 
167     int validCapInfoNum = sizeof(audioCapturerInfo) / sizeof(audioCapturerInfo[0]);
168     for (int i = 0; i < validCapInfoNum; i++) {
169         if (format == audioCapturerInfo[i].audioFormat) {
170             sr = audioCapturerInfo[i].sampleRate;
171             rate = audioCapturerInfo[i].bitRate;
172         }
173     }
174 }
175 
GetChannelCount(void)176 static int32_t GetChannelCount(void)
177 {
178     std::cout << "*******************************************" << endl;
179     std::cout << "SetCapturerInfo (channelCount:1, channelCount:2)" << endl;
180     std::cout << "*******************************************" << endl;
181     int32_t channelCount;
182     std::cin >> channelCount;
183     if (channelCount != 1 && channelCount != 0x2) {
184         std::cout << "Can't support input channelCount:" << channelCount << std::endl;
185         return -1;
186     }
187     return channelCount;
188 }
189 
ShowCmdInfo(void)190 static void ShowCmdInfo(void)
191 {
192     cout << "*******************************************" << endl;
193     cout << "Select the behavior of audio capturer." << endl;
194     cout << "s or S-----start audio capturer" << endl;
195     cout << "p or P-----stop audio capturer" << endl;
196     cout << "q or Q-----quit audio capturer" << endl;
197     cout << "*******************************************" << endl;
198 }
199 
TaskQuit(AudioCapturer & audioCap,AppState & state)200 static void TaskQuit(AudioCapturer &audioCap, AppState &state)
201 {
202     if (state == AV_ON) {
203         g_audioSourceProcessInput.bThreadRun = false;
204         g_audioSourceProcessInput.processThread.join();
205         if (!audioCap.Stop()) {
206             std::cout << "Stop audioCap failed, quit record\n" << endl;
207         }
208         state = AV_OFF;
209     }
210 }
211 
TaskStop(AudioCapturer & audioCap,AppState & state)212 static int32_t TaskStop(AudioCapturer &audioCap, AppState &state)
213 {
214     if (state == AV_ON) {
215         g_audioSourceProcessInput.bThreadRun = false;
216         g_audioSourceProcessInput.processThread.join();
217         if (!audioCap.Stop()) {
218             std::cout << "Stop audioCap fialed, stop record " << endl;
219             return -1;
220         }
221         state = AV_OFF;
222     } else {
223         std::cout << "Start recorder first." << endl;
224     }
225     return 0;
226 }
227 
TaskStart(AudioCapturer & audioCap,AppState & state)228 static int32_t TaskStart(AudioCapturer &audioCap, AppState &state)
229 {
230     if (state == AV_ON) {
231         return 0;
232     }
233 
234     if (!audioCap.Start()) {
235         std::cout << "Can't Start..." << endl;
236         delete g_audioSourceProcessInput.buffer;
237         return -1;
238     }
239     g_audioSourceProcessInput.audioCap = &audioCap;
240     g_audioSourceProcessInput.bThreadRun = true;
241     g_audioSourceProcessInput.processThread = std::thread(AudioInputSourceProcess,
242         &g_audioSourceProcessInput);
243     state = AV_ON;
244     std::cout << "Recording..." << endl;
245     return 0;
246 }
247 
RumCmd(AudioCapturer & audioCap)248 static void RumCmd(AudioCapturer &audioCap)
249 {
250     ShowCmdInfo();
251     char input;
252     AppState state = AV_OFF;
253     while (std::cin >> input) {
254         switch (input) {
255             case 's':
256             case 'S':
257                 if (TaskStart(audioCap, state) != 0) {
258                     return;
259                 }
260                 break;
261             case 'p':
262             case 'P':
263                 if (TaskStop(audioCap, state) != 0) {
264                     return;
265                 }
266                 break;
267             case 'q':
268             case 'Q':
269                 TaskQuit(audioCap, state);
270                 return;
271             default:
272                 break;
273         }
274     }
275 }
276 
main(int argc,char * argv[])277 int main(int argc, char *argv[])
278 {
279     std::cout << "audio_capture_sample " << std::endl;
280     int ret = 0;
281     size_t frameCount;
282     AudioCapturer audioCap;
283 
284     AudioCapturerInfo info;
285     info.inputSource = AUDIO_MIC;
286     info.bitWidth = BIT_WIDTH_16;
287     AudioCodecFormat audioFormat = GetAudioFormat();
288     if (audioFormat == FORMAT_BUTT) {
289         return -1;
290     }
291     info.audioFormat = audioFormat;
292     g_audioSourceProcessInput.audioFormat = audioFormat;
293     GetDefaultSampleRateAndRateBaseFormat(audioFormat, info.sampleRate, info.bitRate);
294 
295     info.channelCount = GetChannelCount();
296     if (info.channelCount == -1) {
297         return -1;
298     }
299 
300     std::cout << " SetCapturerInfo" << std::endl;
301     if ((ret = audioCap.SetCapturerInfo(info)) != 0) {
302         std::cout << "Can't SetCapturerInfo " << std::endl;
303         delete g_audioSourceProcessInput.buffer;
304         return -1;
305     }
306     frameCount = audioCap.GetFrameCount();
307     std::cout << "GetFrameCount  " << frameCount << std::endl;
308     g_audioSourceProcessInput.framesize = frameCount * 0x400;
309     g_audioSourceProcessInput.buffer = new uint8_t[g_audioSourceProcessInput.framesize];
310 
311     RumCmd(audioCap);
312 
313     audioCap.Release();
314     delete g_audioSourceProcessInput.buffer;
315     g_audioSourceProcessInput.buffer = nullptr;
316     return 0;
317 }
318