• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <cstdio>
18 #include <cstring>
19 #include <cstdlib>
20 #include <unistd.h>
21 #include <cerrno>
22 #include <fcntl.h>
23 #include <csignal>
24 #include <sys/stat.h>
25 
26 #include <iostream>
27 #include <string>
28 
29 #include <securec.h>
30 #include "unistd.h"
31 #include "./distributedaudiotest.h"
32 
33 std::string deviceId;
34 
35 struct Request {
36     pid_t pid;
37     int commandNum;
38     char reqString[70];
39     int seqLen;
40 };
41 
42 struct Response {
43     int seqNum;
44     char resString[CMD_EXECUTING_RETURN_LENGHT_MAX];
45 };
46 
47 using namespace OHOS::DistributedHardware;
48 static AudioManager *g_manager = nullptr;
49 static AudioAdapter *g_adapter = nullptr;
50 static AudioRender *g_render = nullptr;
51 static AudioCapture *g_capture = nullptr;
52 static AudioAdapterDescriptor *g_devices = nullptr;
53 
54 static constexpr const char* PLAY_THREAD = "playThread";
55 static constexpr const char* CAPTURE_THREAD = "captureThread";
56 
57 int32_t g_deviceNum = 0;
58 int32_t g_frameNum = 0;
59 int32_t g_frameIndex = 0;
60 int32_t g_micFrameNum = 0;
61 bool g_isInitRenderData = false;
62 static std::vector<uint8_t*> renderData;
63 
64 static DeviceStatus g_spkStatus = DEVICE_IDLE;
65 static DeviceStatus g_micStatus = DEVICE_IDLE;
66 
67 static std::thread g_palyingThread;
68 static std::thread g_capingThread;
69 FILE *g_micFile = nullptr;
70 
GetNowTimeUs()71 static int64_t GetNowTimeUs()
72 {
73     std::chrono::microseconds nowUs =
74         std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch());
75     return nowUs.count();
76 }
77 
InitTestDemo()78 int32_t InitTestDemo()
79 {
80     DHLOGI("**********************************************************************************");
81     DHLOGI("Distributed Audio Test Demo Bin v1.3.");
82     DHLOGI("**********************************************************************************");
83     DHLOGI("Init distributed audio hdf service.");
84     g_manager = GetAudioManagerFuncs();
85     if (g_manager == nullptr) {
86         DHLOGI("Distributed audio manager is null, quit!");
87         return ERR_DH_AUDIO_HDF_FAIL;
88     }
89     DHLOGI("Load audio manager success.");
90     return DH_SUCCESS;
91 }
92 
FindAudioDevice()93 std::string FindAudioDevice()
94 {
95     if (g_manager == nullptr) {
96         return "false";
97     }
98     int32_t ret = g_manager->GetAllAdapters(g_manager, &g_devices, &g_deviceNum);
99     if (ret != DH_SUCCESS) {
100         DHLOGI("Get audio devices failed!");
101         return "false";
102     }
103     std::string res = "true";
104     std::cout << "Get audio devices success, adapter size: " << g_deviceNum << std::endl;
105     for (int32_t index = 0; index < g_deviceNum; index++) {
106         const AudioAdapterDescriptor &desc = g_devices[index];
107         std::cout << "Device[" << index << "] ID: " << desc.adapterName << std::endl;
108         deviceId = deviceId +  desc.adapterName;
109         DHLOGI("demo test: Device [%s] ID", desc.adapterName);
110         if (index != g_deviceNum - 1) {
111         }
112         std::cout << "pin list: ";
113         for (uint32_t i = 0; i < desc.portNum; i++) {
114             std::cout << desc.ports[i].portId << ", ";
115         }
116         std::cout << std::endl;
117     }
118     return res;
119 }
120 
HandleDevError(const char * condition,const char * value)121 static void HandleDevError(const char *condition, const char *value)
122 {
123     if (condition[TYPE_OFFSET] == DEV_TYPE_SPK && g_spkStatus != DEVICE_IDLE) {
124         CloseSpk();
125     }
126 
127     if (condition[TYPE_OFFSET] == DEV_TYPE_MIC && g_micStatus == DEVICE_IDLE) {
128         CloseMic();
129     }
130 
131     DHLOGI("Receive abnormal event, Demo quit.");
132 }
133 
ParamEventCallback(AudioExtParamKey key,const char * condition,const char * value,void * reserved,void * cookie)134 static int32_t ParamEventCallback(AudioExtParamKey key, const char *condition, const char *value, void *reserved,
135     void *cookie)
136 {
137     std::string val(value);
138     std::string con(condition);
139     std::cout << std::endl;
140     DHLOGI("**********************************************************************************");
141     std::cout << "Event recived: " << key << std::endl;
142     std::cout << "Condition: " << con << std::endl;
143     std::cout << "Value: " << val << std::endl;
144     std::cout << std::endl;
145     DHLOGI("**********************************************************************************");
146 
147     if (key == AudioExtParamKey::AUDIO_EXT_PARAM_KEY_STATUS && con.rfind("ERR_EVENT", 0) == 0) {
148         HandleDevError(condition, value);
149     }
150     return DH_SUCCESS;
151 }
152 
LoadSpkDev(const std::string & devId)153 static int32_t LoadSpkDev(const std::string &devId)
154 {
155     std::cout << "Open SPK device , device Id:" << devId << std::endl;
156 
157     struct AudioAdapterDescriptor *dev = nullptr;
158     for (int32_t index = 0; index < g_deviceNum; index++) {
159         struct AudioAdapterDescriptor &desc = g_devices[index];
160         if (desc.adapterName == devId) {
161             dev = &desc;
162             break;
163         }
164     }
165     if (dev == nullptr) {
166         DHLOGI("Input device id is wrong.");
167         FindAudioDevice();
168         return ERR_DH_AUDIO_HDF_FAIL;
169     }
170     if (g_manager == nullptr) {
171         return ERR_DH_AUDIO_HDF_FAIL;
172     }
173     if (g_adapter == nullptr) {
174         int32_t ret = g_manager->LoadAdapter(g_manager, dev, &g_adapter);
175         if (ret != DH_SUCCESS || g_adapter == nullptr) {
176             std::cout << "Load audio device failed, ret: " << ret << std::endl;
177             return ERR_DH_AUDIO_HDF_FAIL;
178         }
179     }
180     DHLOGI("Load audio device success.");
181     return DH_SUCCESS;
182 }
183 
OpenSpk()184 std::string OpenSpk()
185 {
186     if (g_spkStatus != DEVICE_IDLE) {
187         DHLOGI("Speaker device is already opened.");
188         return "true";
189     }
190     if (LoadSpkDev(deviceId) != DH_SUCCESS) {
191         return "true";
192     }
193     ParamCallback callback = ParamEventCallback;
194     int32_t ret = g_adapter->RegExtraParamObserver(g_adapter, callback, nullptr);
195     if (ret != DH_SUCCESS) {
196         std::cout << "Register observer failed, ret: " << ret << std::endl;
197         return "true";
198     }
199 
200     struct AudioDeviceDescriptor renderDesc;
201     renderDesc.pins = AudioPortPin::PIN_OUT_SPEAKER;
202     renderDesc.desc = nullptr;
203     AudioSampleAttributes g_rattrs = {};
204     g_rattrs.type = AUDIO_IN_MEDIA;
205     g_rattrs.interleaved = RENDER_INTER_LEAVED;
206     g_rattrs.streamId = RENDER_STREAM_ID;
207     g_rattrs.channelCount = RENDER_CHANNEL_MASK;
208     g_rattrs.sampleRate = AUDIO_SAMPLE_RATE;
209     g_rattrs.format = AudioFormat::AUDIO_FORMAT_TYPE_PCM_16_BIT;
210     ret = g_adapter->CreateRender(g_adapter, &renderDesc, &g_rattrs, &g_render);
211     if (ret != DH_SUCCESS || g_render == nullptr) {
212         std::cout << "Open SPK device failed, ret: " << ret << std::endl;
213         return "true";
214     }
215     g_spkStatus = DEVICE_OPEN;
216     DHLOGI("Open SPK device success.");
217     return "true";
218 }
219 
WriteStreamWait(const int64_t & startTime)220 static void WriteStreamWait(const int64_t &startTime)
221 {
222     int64_t endTime = GetNowTimeUs();
223     int64_t passTime = endTime - startTime;
224 
225     if (passTime > AUDIO_FRAME_TIME_INTERFAL_DEFAULT) {
226         return;
227     }
228     int64_t remainTime = AUDIO_FRAME_TIME_INTERFAL_DEFAULT - passTime;
229     std::this_thread::sleep_for(std::chrono::microseconds(remainTime));
230 }
231 
Play()232 static void Play()
233 {
234     if (g_render == nullptr) {
235         DHLOGI("SPK device is null.");
236         return;
237     }
238     if (pthread_setname_np(pthread_self(), PLAY_THREAD) != DH_SUCCESS) {
239         DHLOGI("Play thread setname failed.");
240     }
241     DHLOGI("Playing thread started.");
242     g_render->control.Start((AudioHandle)g_render);
243     g_spkStatus = DEVICE_START;
244 
245     uint64_t size = 0;
246     while (g_spkStatus == DEVICE_START) {
247         int64_t startTime = GetNowTimeUs();
248         int32_t ret = g_render->RenderFrame(g_render, renderData[g_frameIndex], RENDER_FRAME_SIZE, &size);
249         if (ret != DH_SUCCESS) {
250             std::cout<<"RenderFrame failed, index: "<< g_frameIndex << ", ret:  " << ret << std::endl;
251         }
252         g_frameIndex++;
253         if (g_frameNum != 0 && g_frameIndex == g_frameNum) {
254             g_frameIndex = 0;
255         }
256         WriteStreamWait(startTime);
257     }
258     DHLOGI("Playing thread stopped.");
259 }
260 
StartRender()261 std::string StartRender()
262 {
263     if (g_spkStatus == DEVICE_IDLE || g_spkStatus == DEVICE_OPEN) {
264         return "true";
265     }
266 
267     if (g_spkStatus == DEVICE_OPEN) {
268         WavHdr wavHeader;
269         size_t headerSize = sizeof(WavHdr);
270         if (!g_isInitRenderData) {
271             struct stat statbuf;
272             stat(SPK_FILE_PATH, &statbuf);
273             int32_t size = statbuf.st_size;
274             g_frameNum = (size - headerSize) / RENDER_FRAME_SIZE;
275             std::cout << "Audio file frame num: " << g_frameNum << std::endl;
276             for (int32_t j = 0; j < g_frameNum; j++) {
277                 uint8_t *frame = new uint8_t[RENDER_FRAME_SIZE]();
278                 renderData.push_back(frame);
279             }
280             g_isInitRenderData = true;
281         }
282         FILE *wavFile = fopen(SPK_FILE_PATH, "rb");
283         fread(&wavHeader, 1, headerSize, wavFile);
284         for (int32_t i = 0; i < g_frameNum; i++) {
285             fread(renderData[i], 1, RENDER_FRAME_SIZE, wavFile);
286         }
287         fclose(wavFile);
288         g_frameIndex = 0;
289         g_palyingThread = std::thread(Play);
290         return "true";
291     }
292     if (g_spkStatus == DEVICE_START) {
293         return "Speaker device is started.";
294     }
295     if (g_spkStatus == DEVICE_STOP) {
296         g_palyingThread = std::thread(Play);
297     }
298     return "true";
299 }
300 
StopRender()301 std::string StopRender()
302 {
303     if (g_render == nullptr || g_spkStatus == DEVICE_OPEN) {
304         return "true";
305     }
306 
307     if (g_spkStatus == DEVICE_IDLE) {
308         return "Speaker device is not opened.";
309     }
310 
311     if (g_spkStatus == DEVICE_OPEN) {
312         return "Speaker device is not started.";
313     }
314 
315     if (g_spkStatus == DEVICE_STOP) {
316         return "Speaker device is already stoped.";
317     }
318 
319     g_spkStatus = DEVICE_STOP;
320     if (g_palyingThread.joinable()) {
321         g_palyingThread.join();
322     }
323     g_render->control.Stop((AudioHandle)g_render);
324     return "true";
325 }
326 
CloseSpk()327 std::string CloseSpk()
328 {
329     if (g_spkStatus == DEVICE_IDLE) {
330         return "true";
331     }
332 
333     if (g_spkStatus == DEVICE_START) {
334         StopRender();
335     }
336 
337     int32_t ret = g_adapter->DestroyRender(g_adapter, g_render);
338     if (ret != DH_SUCCESS) {
339         return "Close speaker failed";
340     }
341     if (g_micStatus == DEVICE_IDLE) {
342         g_manager->UnloadAdapter(g_manager, g_adapter);
343         g_adapter = nullptr;
344     }
345     g_spkStatus = DEVICE_IDLE;
346 
347     if (g_isInitRenderData) {
348         for (auto &p : renderData) {
349             delete[] p;
350         }
351         renderData.clear();
352         g_isInitRenderData = false;
353     }
354     return "true";
355 }
356 
LoadMicDev(const std::string & devId)357 static int32_t LoadMicDev(const std::string &devId)
358 {
359     std::cout << "Open MIC device ,input device Id:" << devId << std::endl;
360 
361     struct AudioAdapterDescriptor *dev = nullptr;
362     for (int32_t index = 0; index < g_deviceNum; index++) {
363         struct AudioAdapterDescriptor &desc = g_devices[index];
364         if (desc.adapterName == devId) {
365             dev = &desc;
366             break;
367         }
368     }
369     if (dev == nullptr) {
370         DHLOGI("Input device id is wrong.");
371         FindAudioDevice();
372         return ERR_DH_AUDIO_HDF_FAIL;
373     }
374     if (g_manager == nullptr) {
375         return ERR_DH_AUDIO_HDF_FAIL;
376     }
377     if (g_adapter == nullptr) {
378         int32_t ret = g_manager->LoadAdapter(g_manager, dev, &g_adapter);
379         if (ret != DH_SUCCESS || g_adapter == nullptr) {
380             std::cout << "Load audio device failed, ret: " << ret << std::endl;
381             return ERR_DH_AUDIO_HDF_FAIL;
382         }
383     }
384     DHLOGI("Load audio device success.");
385     return DH_SUCCESS;
386 }
387 
OpenMic()388 std::string OpenMic()
389 {
390     if (g_micStatus != DEVICE_IDLE) {
391         return "true";
392     }
393     if (LoadMicDev(deviceId) != DH_SUCCESS) {
394         return "true";
395     }
396 
397     AudioDeviceDescriptor captureDesc;
398     captureDesc.pins = AudioPortPin::PIN_IN_MIC;
399     captureDesc.desc = nullptr;
400     AudioSampleAttributes captureAttr;
401     captureAttr.type = AUDIO_IN_MEDIA;
402     captureAttr.interleaved = CAPTURE_INTER_LEAVED;
403     captureAttr.streamId = CAPTURE_STREAM_ID;
404     captureAttr.channelCount = CAPTURE_CHANNEL_MASK;
405     captureAttr.sampleRate = AUDIO_SAMPLE_RATE;
406     captureAttr.format = AudioFormat::AUDIO_FORMAT_TYPE_PCM_16_BIT;
407     int32_t ret = g_adapter->CreateCapture(g_adapter, &captureDesc, &captureAttr, &g_capture);
408     if (ret != DH_SUCCESS || g_capture == nullptr) {
409         return "true";
410     }
411     g_micStatus = DEVICE_OPEN;
412     return "true";
413 }
414 
ReadStreamWait(const int64_t & startTime)415 static void ReadStreamWait(const int64_t &startTime)
416 {
417     int64_t endTime = GetNowTimeUs();
418     int32_t passTime = endTime - startTime;
419 
420     if (passTime > AUDIO_FRAME_TIME_INTERFAL_DEFAULT) {
421         return;
422     }
423     int64_t remainTime = AUDIO_FRAME_TIME_INTERFAL_DEFAULT - passTime;
424     std::this_thread::sleep_for(std::chrono::microseconds(remainTime));
425 }
426 
Capture()427 static void Capture()
428 {
429     if (g_capture == nullptr) {
430         DHLOGI("MIC device is null.");
431         return;
432     }
433     if (pthread_setname_np(pthread_self(), CAPTURE_THREAD) != DH_SUCCESS) {
434         DHLOGI("Capture thread setname failed.");
435     }
436     DHLOGI("Capturing thread started.");
437     g_capture->control.Start((AudioHandle)g_capture);
438     g_micStatus = DEVICE_START;
439 
440     uint64_t size = 0;
441     while (g_micStatus == DEVICE_START) {
442         uint8_t *data[RENDER_FRAME_SIZE];
443         int64_t startTime = GetNowTimeUs();
444         int32_t ret = g_capture->CaptureFrame(g_capture, data, RENDER_FRAME_SIZE, &size);
445         if (ret != DH_SUCCESS) {
446             std::cout << "CaptureFrame failed, ret: " << ret << std::endl;
447             return;
448         }
449         size_t res = fwrite(data, 1, RENDER_FRAME_SIZE, g_micFile);
450         if (res < DH_SUCCESS) {
451             std::cout << "fwrite failed, res: " << res << std::endl;
452             return;
453         }
454         g_micFrameNum++;
455         ReadStreamWait(startTime);
456     }
457     DHLOGI("Capturing thread stopped.");
458 }
459 
StartCapture()460 std::string StartCapture()
461 {
462     if (g_micStatus == DEVICE_IDLE) {
463         return "true";
464     }
465 
466     if (g_micStatus == DEVICE_OPEN) {
467         g_micFile = fopen(MIC_FILE_PATH, "ab+");
468         if (g_micFile == nullptr) {
469             return "Open pcm file failed.";
470         }
471         g_capingThread = std::thread(Capture);
472         return "true";
473     }
474 
475     if (g_micStatus == DEVICE_START) {
476         return "Mic device is already started.";
477     }
478 
479     if (g_micStatus == DEVICE_STOP) {
480         g_capingThread = std::thread(Capture);
481     }
482     return "true";
483 }
484 
StopCapture()485 std::string StopCapture()
486 {
487     if (g_capture == nullptr) {
488         return "true";
489     }
490 
491     if (g_micStatus == DEVICE_IDLE) {
492         return "Mic device is not opened.";
493     }
494 
495     if (g_micStatus == DEVICE_OPEN) {
496         return "Mic device is not started.";
497     }
498 
499     if (g_micStatus == DEVICE_STOP) {
500         return "Mic device is already started.";
501     }
502 
503     g_micStatus = DEVICE_STOP;
504     if (g_capingThread.joinable()) {
505         g_capingThread.join();
506     }
507     g_capture->control.Stop((AudioHandle)g_capture);
508     return "true";
509 }
510 
CloseMic()511 std::string CloseMic()
512 {
513     if (g_micStatus == DEVICE_IDLE) {
514         return "true";
515     }
516 
517     if (g_micStatus == DEVICE_START) {
518         StopCapture();
519     }
520 
521     int32_t ret = g_adapter->DestroyCapture(g_adapter, g_capture);
522     if (ret != DH_SUCCESS) {
523         return "Close mic failed.";
524     }
525     if (g_spkStatus == DEVICE_IDLE) {
526         g_manager->UnloadAdapter(g_manager, g_adapter);
527         g_adapter = nullptr;
528     }
529     if (g_micFile != nullptr) {
530         fclose(g_micFile);
531         g_micFile = nullptr;
532     }
533     g_micStatus = DEVICE_IDLE;
534     return "true";
535 }
536 
SetVolume(std::string vol)537 std::string SetVolume(std::string vol)
538 {
539     if (g_spkStatus == DEVICE_IDLE) {
540         return "true";
541     }
542     int32_t volInt = std::stoi(vol);
543     if (volInt < VOLUME_MIN || volInt > VOLUME_MAX) {
544         return "Volume is invalid";
545     }
546     enum AudioExtParamKey key = AudioExtParamKey::AUDIO_EXT_PARAM_KEY_VOLUME;
547     std::string condition = "EVENT_TYPE=1;VOLUME_GROUP_ID=1;AUDIO_VOLUME_TYPE=1;";
548     int32_t ret = g_adapter->SetExtraParams(g_adapter, key, condition.c_str(), vol.c_str());
549     if (ret != DH_SUCCESS) {
550         return "Set volume failed";
551     }
552     return "true";
553 }
554 
GetVolume()555 std::string GetVolume()
556 {
557     if (g_spkStatus == DEVICE_IDLE) {
558         return "true";
559     }
560     enum AudioExtParamKey key = AudioExtParamKey::AUDIO_EXT_PARAM_KEY_VOLUME;
561     std::string condition = "EVENT_TYPE=1;VOLUME_GROUP_ID=1;AUDIO_VOLUME_TYPE=1;";
562     char vol[VOLUME_BIT];
563     int32_t ret = g_adapter->GetExtraParams(g_adapter, key, condition.c_str(), vol, VOLUME_BIT);
564     if (ret != DH_SUCCESS) {
565         return "Get Volume failed.";
566     }
567     DHLOGI("demo test:GetVolume = %s", vol);
568     return "true";
569 }