1 /*
2 * Copyright (c) 2022-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
16 #include "dmic_dev.h"
17
18 #include <condition_variable>
19 #include <mutex>
20 #include <string>
21 #include <thread>
22
23 #include "daudio_constants.h"
24 #include "daudio_errorcode.h"
25 #include "daudio_hidumper.h"
26 #include "daudio_hisysevent.h"
27 #include "daudio_hitrace.h"
28 #include "daudio_log.h"
29 #include "daudio_source_manager.h"
30 #include "daudio_util.h"
31
32 #undef DH_LOG_TAG
33 #define DH_LOG_TAG "DMicDev"
34
35 namespace OHOS {
36 namespace DistributedHardware {
37 static constexpr size_t DATA_QUEUE_EXT_SIZE = 20;
OnEngineTransEvent(const AVTransEvent & event)38 void DMicDev::OnEngineTransEvent(const AVTransEvent &event)
39 {
40 if (event.type == EventType::EVENT_START_SUCCESS) {
41 OnStateChange(DATA_OPENED);
42 } else if ((event.type == EventType::EVENT_STOP_SUCCESS) ||
43 (event.type == EventType::EVENT_CHANNEL_CLOSED) ||
44 (event.type == EventType::EVENT_START_FAIL)) {
45 OnStateChange(DATA_CLOSED);
46 }
47 }
48
OnEngineTransMessage(const std::shared_ptr<AVTransMessage> & message)49 void DMicDev::OnEngineTransMessage(const std::shared_ptr<AVTransMessage> &message)
50 {
51 CHECK_NULL_VOID(message);
52 DHLOGI("On Engine message, type : %{public}s.", GetEventNameByType(message->type_).c_str());
53 DAudioSourceManager::GetInstance().HandleDAudioNotify(message->dstDevId_, message->dstDevId_,
54 message->type_, message->content_);
55 }
56
OnEngineTransDataAvailable(const std::shared_ptr<AudioData> & audioData)57 void DMicDev::OnEngineTransDataAvailable(const std::shared_ptr<AudioData> &audioData)
58 {
59 DHLOGD("On Engine Data available");
60 if (echoCannelOn_) {
61 #ifdef ECHO_CANNEL_ENABLE
62 if (echoManager_ == nullptr) {
63 DHLOGE("Echo manager is nullptr.");
64 return;
65 }
66 echoManager_->OnMicDataReceived(audioData);
67 #endif
68 } else {
69 OnDecodeTransDataDone(audioData);
70 }
71 }
72
InitReceiverEngine(IAVEngineProvider * providerPtr)73 int32_t DMicDev::InitReceiverEngine(IAVEngineProvider *providerPtr)
74 {
75 DHLOGI("InitReceiverEngine enter.");
76 if (micTrans_ == nullptr) {
77 micTrans_ = std::make_shared<AVTransReceiverTransport>(devId_, shared_from_this());
78 }
79 int32_t ret = micTrans_->InitEngine(providerPtr);
80 if (ret != DH_SUCCESS) {
81 DHLOGE("Mic dev initialize av receiver adapter failed.");
82 return ret;
83 }
84 ret = micTrans_->CreateCtrl();
85 if (ret != DH_SUCCESS) {
86 DHLOGE("Create ctrl channel failed. micdev");
87 return ret;
88 }
89 return DH_SUCCESS;
90 }
91
InitSenderEngine(IAVEngineProvider * providerPtr)92 int32_t DMicDev::InitSenderEngine(IAVEngineProvider *providerPtr)
93 {
94 DHLOGI("InitReceiverEngine enter.");
95 return DH_SUCCESS;
96 }
97
EnableDevice(const int32_t dhId,const std::string & capability)98 int32_t DMicDev::EnableDevice(const int32_t dhId, const std::string &capability)
99 {
100 DHLOGI("Enable IO device, device pin: %{public}d.", dhId);
101 int32_t ret = DAudioHdiHandler::GetInstance().RegisterAudioDevice(devId_, dhId, capability, shared_from_this());
102 if (ret != DH_SUCCESS) {
103 DHLOGE("Register device failed, ret: %{public}d.", ret);
104 DAudioHisysevent::GetInstance().SysEventWriteFault(DAUDIO_REGISTER_FAIL, devId_, std::to_string(dhId), ret,
105 "daudio register device failed.");
106 return ret;
107 }
108 dhId_ = dhId;
109 return DH_SUCCESS;
110 }
111
DisableDevice(const int32_t dhId)112 int32_t DMicDev::DisableDevice(const int32_t dhId)
113 {
114 DHLOGI("Disable IO device, device pin: %{public}d.", dhId);
115 int32_t ret = DAudioHdiHandler::GetInstance().UnRegisterAudioDevice(devId_, dhId);
116 if (ret != DH_SUCCESS) {
117 DHLOGE("UnRegister failed, ret: %{public}d.", ret);
118 DAudioHisysevent::GetInstance().SysEventWriteFault(DAUDIO_UNREGISTER_FAIL, devId_, std::to_string(dhId), ret,
119 "daudio unregister device failed.");
120 return ret;
121 }
122 return DH_SUCCESS;
123 }
124
CreateStream(const int32_t streamId)125 int32_t DMicDev::CreateStream(const int32_t streamId)
126 {
127 DHLOGI("Open stream of mic device streamId: %{public}d.", streamId);
128 std::shared_ptr<IAudioEventCallback> cbObj = audioEventCallback_.lock();
129 CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR);
130
131 cJSON *jParam = cJSON_CreateObject();
132 CHECK_NULL_RETURN(jParam, ERR_DH_AUDIO_NULLPTR);
133 cJSON_AddStringToObject(jParam, KEY_DH_ID, std::to_string(dhId_).c_str());
134 char *jsonData = cJSON_PrintUnformatted(jParam);
135 if (jsonData == nullptr) {
136 cJSON_Delete(jParam);
137 DHLOGE("Failed to create JSON data.");
138 return ERR_DH_AUDIO_NULLPTR;
139 }
140 std::string jsonDataStr(jsonData);
141 AudioEvent event(AudioEventType::OPEN_MIC, jsonDataStr);
142 cbObj->NotifyEvent(event);
143 DAudioHisysevent::GetInstance().SysEventWriteBehavior(DAUDIO_OPEN, devId_, std::to_string(dhId_),
144 "daudio mic device open success.");
145 streamId_ = streamId;
146 cJSON_Delete(jParam);
147 cJSON_free(jsonData);
148 return DH_SUCCESS;
149 }
150
DestroyStream(const int32_t streamId)151 int32_t DMicDev::DestroyStream(const int32_t streamId)
152 {
153 DHLOGI("Close stream of mic device streamId: %{public}d.", streamId);
154 std::shared_ptr<IAudioEventCallback> cbObj = audioEventCallback_.lock();
155 CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR);
156
157 cJSON *jParam = cJSON_CreateObject();
158 CHECK_NULL_RETURN(jParam, ERR_DH_AUDIO_NULLPTR);
159 cJSON_AddStringToObject(jParam, KEY_DH_ID, std::to_string(dhId_).c_str());
160 char *jsonData = cJSON_PrintUnformatted(jParam);
161 if (jsonData == nullptr) {
162 cJSON_Delete(jParam);
163 DHLOGE("Failed to create JSON data.");
164 return ERR_DH_AUDIO_NULLPTR;
165 }
166 std::string jsonDataStr(jsonData);
167 AudioEvent event(AudioEventType::CLOSE_MIC, jsonDataStr);
168 cbObj->NotifyEvent(event);
169 DAudioHisysevent::GetInstance().SysEventWriteBehavior(DAUDIO_CLOSE, devId_, std::to_string(dhId_),
170 "daudio mic device close success.");
171 cJSON_Delete(jParam);
172 cJSON_free(jsonData);
173 curPort_ = 0;
174 return DH_SUCCESS;
175 }
176
SetParameters(const int32_t streamId,const AudioParamHDF & param)177 int32_t DMicDev::SetParameters(const int32_t streamId, const AudioParamHDF ¶m)
178 {
179 DHLOGD("Set mic parameters {samplerate: %{public}d, channelmask: %{public}d, format: %{public}d, "
180 "period: %{public}d, framesize: %{public}d, ext{%{public}s}}.", param.sampleRate,
181 param.channelMask, param.bitFormat, param.period, param.frameSize, param.ext.c_str());
182 if (param.capturerFlags == MMAP_MODE && param.period != MMAP_NORMAL_PERIOD && param.period != MMAP_VOIP_PERIOD) {
183 DHLOGE("The period is invalid : %{public}" PRIu32, param.period);
184 return ERR_DH_AUDIO_SA_PARAM_INVALID;
185 }
186 curPort_ = dhId_;
187 paramHDF_ = param;
188
189 param_.comParam.sampleRate = paramHDF_.sampleRate;
190 param_.comParam.channelMask = paramHDF_.channelMask;
191 param_.comParam.bitFormat = paramHDF_.bitFormat;
192 param_.comParam.codecType = AudioCodecType::AUDIO_CODEC_AAC;
193 param_.comParam.frameSize = paramHDF_.frameSize;
194 if (paramHDF_.streamUsage == StreamUsage::STREAM_USAGE_VOICE_COMMUNICATION) {
195 param_.captureOpts.sourceType = SOURCE_TYPE_VOICE_COMMUNICATION;
196 } else {
197 param_.captureOpts.sourceType = SOURCE_TYPE_MIC;
198 }
199 param_.captureOpts.capturerFlags = paramHDF_.capturerFlags;
200 if (paramHDF_.capturerFlags == MMAP_MODE) {
201 lowLatencyHalfSize_ = LOW_LATENCY_JITTER_TIME_MS / paramHDF_.period;
202 lowLatencyMaxfSize_ = LOW_LATENCY_JITTER_MAX_TIME_MS / paramHDF_.period;
203 }
204 return DH_SUCCESS;
205 }
206
NotifyEvent(const int32_t streamId,const AudioEvent & event)207 int32_t DMicDev::NotifyEvent(const int32_t streamId, const AudioEvent &event)
208 {
209 DHLOGD("Notify mic event, type: %{public}d.", event.type);
210 std::shared_ptr<IAudioEventCallback> cbObj = audioEventCallback_.lock();
211 CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR);
212 switch (event.type) {
213 case AudioEventType::AUDIO_START:
214 curStatus_ = AudioStatus::STATUS_START;
215 isExistedEmpty_.store(false);
216 break;
217 case AudioEventType::AUDIO_STOP:
218 curStatus_ = AudioStatus::STATUS_STOP;
219 isExistedEmpty_.store(false);
220 break;
221 default:
222 break;
223 }
224 AudioEvent audioEvent(event.type, event.content);
225 cbObj->NotifyEvent(audioEvent);
226 return DH_SUCCESS;
227 }
228
SetUp()229 int32_t DMicDev::SetUp()
230 {
231 DHLOGI("Set up mic device.");
232 CHECK_NULL_RETURN(micTrans_, ERR_DH_AUDIO_NULLPTR);
233 int32_t ret = micTrans_->SetUp(param_, param_, shared_from_this(), CAP_MIC);
234 if (ret != DH_SUCCESS) {
235 DHLOGE("Mic trans set up failed. ret: %{public}d.", ret);
236 return ret;
237 }
238 echoCannelOn_ = true;
239 #ifdef ECHO_CANNEL_ENABLE
240 if (echoCannelOn_ && echoManager_ == nullptr) {
241 echoManager_ = std::make_shared<DAudioEchoCannelManager>();
242 }
243 AudioCommonParam info;
244 info.sampleRate = param_.comParam.sampleRate;
245 info.channelMask = param_.comParam.channelMask;
246 info.bitFormat = param_.comParam.bitFormat;
247 info.frameSize = param_.comParam.frameSize;
248 if (echoManager_ != nullptr) {
249 echoManager_->SetUp(info, shared_from_this());
250 }
251 #endif
252 DumpFileUtil::OpenDumpFile(DUMP_SERVER_PARA, DUMP_DAUDIO_MIC_READ_FROM_BUF_NAME, &dumpFileCommn_);
253 DumpFileUtil::OpenDumpFile(DUMP_SERVER_PARA, DUMP_DAUDIO_LOWLATENCY_MIC_FROM_BUF_NAME, &dumpFileFast_);
254 return DH_SUCCESS;
255 }
256
Start()257 int32_t DMicDev::Start()
258 {
259 DHLOGI("Start mic device.");
260 CHECK_NULL_RETURN(micTrans_, ERR_DH_AUDIO_NULLPTR);
261 int32_t ret = micTrans_->Start();
262 if (ret != DH_SUCCESS) {
263 DHLOGE("Mic trans start failed, ret: %{public}d.", ret);
264 return ret;
265 }
266 std::unique_lock<std::mutex> lck(channelWaitMutex_);
267 auto status = channelWaitCond_.wait_for(lck, std::chrono::seconds(CHANNEL_WAIT_SECONDS),
268 [this]() { return isTransReady_.load(); });
269 if (!status) {
270 DHLOGE("Wait channel open timeout(%{public}ds).", CHANNEL_WAIT_SECONDS);
271 return ERR_DH_AUDIO_SA_WAIT_TIMEOUT;
272 }
273 isOpened_.store(true);
274 return DH_SUCCESS;
275 }
276
Pause()277 int32_t DMicDev::Pause()
278 {
279 DHLOGI("Not support.");
280 return DH_SUCCESS;
281 }
282
Restart()283 int32_t DMicDev::Restart()
284 {
285 DHLOGI("Not surpport.");
286 return DH_SUCCESS;
287 }
288
Stop()289 int32_t DMicDev::Stop()
290 {
291 DHLOGI("Stop mic device.");
292 CHECK_NULL_RETURN(micTrans_, DH_SUCCESS);
293 isOpened_.store(false);
294 isTransReady_.store(false);
295 int32_t ret = micTrans_->Stop();
296 if (ret != DH_SUCCESS) {
297 DHLOGE("Stop mic trans failed, ret: %{public}d.", ret);
298 }
299 #ifdef ECHO_CANNEL_ENABLE
300 CHECK_NULL_RETURN(echoManager_, DH_SUCCESS);
301 ret = echoManager_->Stop();
302 if (ret != DH_SUCCESS) {
303 DHLOGE("Echo manager stop failed. ret: %{public}d.", ret);
304 return ret;
305 }
306 #endif
307 return DH_SUCCESS;
308 }
309
Release()310 int32_t DMicDev::Release()
311 {
312 DHLOGI("Release mic device.");
313 if (ashmem_ != nullptr) {
314 ashmem_->UnmapAshmem();
315 ashmem_->CloseAshmem();
316 ashmem_ = nullptr;
317 DHLOGI("UnInit ashmem success.");
318 }
319 CHECK_NULL_RETURN(micTrans_, DH_SUCCESS);
320
321 int32_t ret = micTrans_->Release();
322 if (ret != DH_SUCCESS) {
323 DHLOGE("Release mic trans failed, ret: %{public}d.", ret);
324 return ret;
325 }
326 #ifdef ECHO_CANNEL_ENABLE
327 if (echoManager_ != nullptr) {
328 echoManager_->Release();
329 echoManager_ = nullptr;
330 }
331 #endif
332 DumpFileUtil::CloseDumpFile(&dumpFileCommn_);
333 DumpFileUtil::CloseDumpFile(&dumpFileFast_);
334 return DH_SUCCESS;
335 }
336
IsOpened()337 bool DMicDev::IsOpened()
338 {
339 return isOpened_.load();
340 }
341
WriteStreamData(const int32_t streamId,std::shared_ptr<AudioData> & data)342 int32_t DMicDev::WriteStreamData(const int32_t streamId, std::shared_ptr<AudioData> &data)
343 {
344 (void)streamId;
345 (void)data;
346 return DH_SUCCESS;
347 }
348
ReadStreamData(const int32_t streamId,std::shared_ptr<AudioData> & data)349 int32_t DMicDev::ReadStreamData(const int32_t streamId, std::shared_ptr<AudioData> &data)
350 {
351 int64_t startTime = GetNowTimeUs();
352 if (curStatus_ != AudioStatus::STATUS_START) {
353 DHLOGE("Distributed audio is not starting status.");
354 return ERR_DH_AUDIO_FAILED;
355 }
356 std::lock_guard<std::mutex> lock(dataQueueMtx_);
357 uint32_t queSize = dataQueue_.size();
358 if (insertFrameCnt_ >= queSize || queSize == 0) {
359 ++insertFrameCnt_;
360 isExistedEmpty_.store(true);
361 DHLOGD("Data queue is empty, count :%{public}u.", insertFrameCnt_);
362 data = std::make_shared<AudioData>(param_.comParam.frameSize);
363 } else {
364 while (insertFrameCnt_ > 0) {
365 DHLOGD("Data discard, count: %{public}u", insertFrameCnt_);
366 dataQueue_.pop();
367 --insertFrameCnt_;
368 }
369 data = dataQueue_.front();
370 dataQueue_.pop();
371 }
372 CHECK_NULL_RETURN(data, ERR_DH_AUDIO_NULLPTR);
373 DumpFileUtil::WriteDumpFile(dumpFileCommn_, static_cast<void *>(data->Data()), data->Size());
374 int64_t endTime = GetNowTimeUs();
375 if (IsOutDurationRange(startTime, endTime, lastReadStartTime_)) {
376 DHLOGE("This time read data spend: %{public}" PRId64" us, The interval of read data this time and "
377 "the last time: %{public}" PRId64" us", endTime - startTime, startTime - lastReadStartTime_);
378 }
379 lastReadStartTime_ = startTime;
380 return DH_SUCCESS;
381 }
382
ReadMmapPosition(const int32_t streamId,uint64_t & frames,CurrentTimeHDF & time)383 int32_t DMicDev::ReadMmapPosition(const int32_t streamId, uint64_t &frames, CurrentTimeHDF &time)
384 {
385 DHLOGD("Read mmap position. frames: %{public}" PRIu64", tvsec: %{public}" PRId64", tvNSec:%{public}" PRId64,
386 writeNum_, writeTvSec_, writeTvNSec_);
387 frames = writeNum_;
388 time.tvSec = writeTvSec_;
389 time.tvNSec = writeTvNSec_;
390 return DH_SUCCESS;
391 }
392
RefreshAshmemInfo(const int32_t streamId,int32_t fd,int32_t ashmemLength,int32_t lengthPerTrans)393 int32_t DMicDev::RefreshAshmemInfo(const int32_t streamId,
394 int32_t fd, int32_t ashmemLength, int32_t lengthPerTrans)
395 {
396 DHLOGD("RefreshAshmemInfo: fd:%{public}d, ashmemLength: %{public}d, lengthPerTrans: %{public}d",
397 fd, ashmemLength, lengthPerTrans);
398 if (param_.captureOpts.capturerFlags == MMAP_MODE) {
399 DHLOGD("DMic dev low-latency mode");
400 if (ashmem_ != nullptr) {
401 return DH_SUCCESS;
402 }
403 if (ashmemLength < ASHMEM_MAX_LEN) {
404 ashmem_ = sptr<Ashmem>(new Ashmem(fd, ashmemLength));
405 ashmemLength_ = ashmemLength;
406 lengthPerTrans_ = lengthPerTrans;
407 DHLOGD("Create ashmem success. fd:%{public}d, ashmem length: %{public}d, lengthPreTrans: %{public}d",
408 fd, ashmemLength_, lengthPerTrans_);
409 bool mapRet = ashmem_->MapReadAndWriteAshmem();
410 if (!mapRet) {
411 DHLOGE("Mmap ashmem failed.");
412 return ERR_DH_AUDIO_NULLPTR;
413 }
414 }
415 }
416 return DH_SUCCESS;
417 }
418
MmapStart()419 int32_t DMicDev::MmapStart()
420 {
421 CHECK_NULL_RETURN(ashmem_, ERR_DH_AUDIO_NULLPTR);
422 std::lock_guard<std::mutex> lock(writeAshmemMutex_);
423 frameIndex_ = 0;
424 startTime_ = 0;
425 isEnqueueRunning_.store(true);
426 enqueueDataThread_ = std::thread([this]() { this->EnqueueThread(); });
427 if (pthread_setname_np(enqueueDataThread_.native_handle(), ENQUEUE_THREAD) != DH_SUCCESS) {
428 DHLOGE("Enqueue data thread setname failed.");
429 }
430 return DH_SUCCESS;
431 }
432
EnqueueThread()433 void DMicDev::EnqueueThread()
434 {
435 writeIndex_ = 0;
436 writeNum_ = 0;
437 int64_t timeIntervalns = static_cast<int64_t>(paramHDF_.period * AUDIO_NS_PER_SECOND / AUDIO_MS_PER_SECOND);
438 DHLOGD("Enqueue thread start, lengthPerWrite length: %{public}d, interval: %{public}d.", lengthPerTrans_,
439 paramHDF_.period);
440 FillJitterQueue();
441 while (ashmem_ != nullptr && isEnqueueRunning_.load()) {
442 int64_t timeOffset = UpdateTimeOffset(frameIndex_, timeIntervalns, startTime_);
443 DHLOGD("Write frameIndex: %{public}" PRId64", timeOffset: %{public}" PRId64, frameIndex_, timeOffset);
444 std::shared_ptr<AudioData> audioData = nullptr;
445 {
446 std::lock_guard<std::mutex> lock(dataQueueMtx_);
447 if (dataQueue_.empty()) {
448 DHLOGD("Data queue is Empty.");
449 audioData = std::make_shared<AudioData>(param_.comParam.frameSize);
450 } else {
451 audioData = dataQueue_.front();
452 dataQueue_.pop();
453 }
454 if (audioData == nullptr) {
455 DHLOGD("The audioData is nullptr.");
456 continue;
457 }
458 DumpFileUtil::WriteDumpFile(dumpFileFast_, static_cast<void *>(audioData->Data()), audioData->Size());
459 bool writeRet = ashmem_->WriteToAshmem(audioData->Data(), audioData->Size(), writeIndex_);
460 if (writeRet) {
461 DHLOGD("Write to ashmem success! write index: %{public}d, writeLength: %{public}d.",
462 writeIndex_, lengthPerTrans_);
463 } else {
464 DHLOGE("Write data to ashmem failed.");
465 }
466 }
467 writeIndex_ += lengthPerTrans_;
468 if (writeIndex_ >= ashmemLength_) {
469 writeIndex_ = 0;
470 }
471 writeNum_ += static_cast<uint64_t>(CalculateSampleNum(param_.comParam.sampleRate, paramHDF_.period));
472 GetCurrentTime(writeTvSec_, writeTvNSec_);
473 frameIndex_++;
474 AbsoluteSleep(startTime_ + frameIndex_ * timeIntervalns - timeOffset);
475 }
476 }
477
FillJitterQueue()478 void DMicDev::FillJitterQueue()
479 {
480 while (isEnqueueRunning_.load()) {
481 {
482 std::lock_guard<std::mutex> lock(dataQueueMtx_);
483 if (dataQueue_.size() >= (LOW_LATENCY_JITTER_TIME_MS / paramHDF_.period)) {
484 break;
485 }
486 }
487 usleep(MMAP_WAIT_FRAME_US);
488 }
489 DHLOGD("Mic jitter data queue fill end.");
490 }
491
MmapStop()492 int32_t DMicDev::MmapStop()
493 {
494 std::lock_guard<std::mutex> lock(writeAshmemMutex_);
495 isEnqueueRunning_.store(false);
496 if (enqueueDataThread_.joinable()) {
497 enqueueDataThread_.join();
498 }
499 DHLOGI("Mic mmap stop end.");
500 return DH_SUCCESS;
501 }
502
GetAudioParam() const503 AudioParam DMicDev::GetAudioParam() const
504 {
505 return param_;
506 }
507
NotifyHdfAudioEvent(const AudioEvent & event,const int32_t portId)508 int32_t DMicDev::NotifyHdfAudioEvent(const AudioEvent &event, const int32_t portId)
509 {
510 int32_t ret = DAudioHdiHandler::GetInstance().NotifyEvent(devId_, portId, streamId_, event);
511 if (ret != DH_SUCCESS) {
512 DHLOGE("Notify event: %{public}d, result: %{public}s, streamId: %{public}d.",
513 event.type, event.content.c_str(), streamId_);
514 }
515 return DH_SUCCESS;
516 }
517
OnStateChange(const AudioEventType type)518 int32_t DMicDev::OnStateChange(const AudioEventType type)
519 {
520 DHLOGD("On mic device state change, type: %{public}d", type);
521 AudioEvent event;
522 switch (type) {
523 case AudioEventType::DATA_OPENED:
524 isTransReady_.store(true);
525 channelWaitCond_.notify_one();
526 event.type = AudioEventType::MIC_OPENED;
527 break;
528 case AudioEventType::DATA_CLOSED:
529 isTransReady_.store(false);
530 event.type = AudioEventType::MIC_CLOSED;
531 break;
532 default:
533 break;
534 }
535 event.content = GetCJsonString(KEY_DH_ID, std::to_string(dhId_).c_str());
536 std::shared_ptr<IAudioEventCallback> cbObj = audioEventCallback_.lock();
537 CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR);
538 cbObj->NotifyEvent(event);
539 return DH_SUCCESS;
540 }
541
SendMessage(uint32_t type,std::string content,std::string dstDevId)542 int32_t DMicDev::SendMessage(uint32_t type, std::string content, std::string dstDevId)
543 {
544 DHLOGD("Send message to remote.");
545 if (type != static_cast<uint32_t>(OPEN_MIC) && type != static_cast<uint32_t>(CLOSE_MIC)) {
546 DHLOGE("Send message to remote. not OPEN_MIC or CLOSE_MIC. type: %{public}u", type);
547 return ERR_DH_AUDIO_NULLPTR;
548 }
549 CHECK_NULL_RETURN(micTrans_, ERR_DH_AUDIO_NULLPTR);
550 micTrans_->SendMessage(type, content, dstDevId);
551 return DH_SUCCESS;
552 }
553
OnDecodeTransDataDone(const std::shared_ptr<AudioData> & audioData)554 int32_t DMicDev::OnDecodeTransDataDone(const std::shared_ptr<AudioData> &audioData)
555 {
556 CHECK_NULL_RETURN(audioData, ERR_DH_AUDIO_NULLPTR);
557 std::lock_guard<std::mutex> lock(dataQueueMtx_);
558 dataQueSize_ = curStatus_ != AudioStatus::STATUS_START ?
559 (param_.captureOpts.capturerFlags == MMAP_MODE ? lowLatencyHalfSize_ : DATA_QUEUE_HALF_SIZE) :
560 (param_.captureOpts.capturerFlags == MMAP_MODE ? lowLatencyMaxfSize_ : DATA_QUEUE_MAX_SIZE);
561 if (isExistedEmpty_.load()) {
562 dataQueSize_ = param_.captureOpts.capturerFlags == MMAP_MODE ? dataQueSize_ : DATA_QUEUE_EXT_SIZE;
563 }
564 uint64_t queueSize;
565 while (dataQueue_.size() > dataQueSize_) {
566 queueSize = static_cast<uint64_t>(dataQueue_.size());
567 DHLOGD("Data queue overflow. buf current size: %{public}" PRIu64, queueSize);
568 dataQueue_.pop();
569 }
570 dataQueue_.push(audioData);
571 queueSize = static_cast<uint64_t>(dataQueue_.size());
572 DHLOGD("Push new mic data, buf len: %{public}" PRIu64, queueSize);
573 return DH_SUCCESS;
574 }
575 } // DistributedHardware
576 } // OHOS
577