150a07fd2Sopenharmony_ci/* 250a07fd2Sopenharmony_ci * Copyright (c) 2022-2024 Huawei Device Co., Ltd. 350a07fd2Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 450a07fd2Sopenharmony_ci * you may not use this file except in compliance with the License. 550a07fd2Sopenharmony_ci * You may obtain a copy of the License at 650a07fd2Sopenharmony_ci * 750a07fd2Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 850a07fd2Sopenharmony_ci * 950a07fd2Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1050a07fd2Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1150a07fd2Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1250a07fd2Sopenharmony_ci * See the License for the specific language governing permissions and 1350a07fd2Sopenharmony_ci * limitations under the License. 1450a07fd2Sopenharmony_ci */ 1550a07fd2Sopenharmony_ci 1650a07fd2Sopenharmony_ci#include "dmic_dev.h" 1750a07fd2Sopenharmony_ci 1850a07fd2Sopenharmony_ci#include <condition_variable> 1950a07fd2Sopenharmony_ci#include <mutex> 2050a07fd2Sopenharmony_ci#include <string> 2150a07fd2Sopenharmony_ci#include <thread> 2250a07fd2Sopenharmony_ci 2350a07fd2Sopenharmony_ci#include "daudio_constants.h" 2450a07fd2Sopenharmony_ci#include "daudio_errorcode.h" 2550a07fd2Sopenharmony_ci#include "daudio_hidumper.h" 2650a07fd2Sopenharmony_ci#include "daudio_hisysevent.h" 2750a07fd2Sopenharmony_ci#include "daudio_hitrace.h" 2850a07fd2Sopenharmony_ci#include "daudio_log.h" 2950a07fd2Sopenharmony_ci#include "daudio_source_manager.h" 3050a07fd2Sopenharmony_ci#include "daudio_util.h" 3150a07fd2Sopenharmony_ci 3250a07fd2Sopenharmony_ci#undef DH_LOG_TAG 3350a07fd2Sopenharmony_ci#define DH_LOG_TAG "DMicDev" 3450a07fd2Sopenharmony_ci 3550a07fd2Sopenharmony_cinamespace OHOS { 3650a07fd2Sopenharmony_cinamespace DistributedHardware { 3750a07fd2Sopenharmony_cistatic constexpr size_t DATA_QUEUE_EXT_SIZE = 20; 3850a07fd2Sopenharmony_civoid DMicDev::OnEngineTransEvent(const AVTransEvent &event) 3950a07fd2Sopenharmony_ci{ 4050a07fd2Sopenharmony_ci if (event.type == EventType::EVENT_START_SUCCESS) { 4150a07fd2Sopenharmony_ci OnStateChange(DATA_OPENED); 4250a07fd2Sopenharmony_ci } else if ((event.type == EventType::EVENT_STOP_SUCCESS) || 4350a07fd2Sopenharmony_ci (event.type == EventType::EVENT_CHANNEL_CLOSED) || 4450a07fd2Sopenharmony_ci (event.type == EventType::EVENT_START_FAIL)) { 4550a07fd2Sopenharmony_ci OnStateChange(DATA_CLOSED); 4650a07fd2Sopenharmony_ci } 4750a07fd2Sopenharmony_ci} 4850a07fd2Sopenharmony_ci 4950a07fd2Sopenharmony_civoid DMicDev::OnEngineTransMessage(const std::shared_ptr<AVTransMessage> &message) 5050a07fd2Sopenharmony_ci{ 5150a07fd2Sopenharmony_ci CHECK_NULL_VOID(message); 5250a07fd2Sopenharmony_ci DHLOGI("On Engine message, type : %{public}s.", GetEventNameByType(message->type_).c_str()); 5350a07fd2Sopenharmony_ci DAudioSourceManager::GetInstance().HandleDAudioNotify(message->dstDevId_, message->dstDevId_, 5450a07fd2Sopenharmony_ci message->type_, message->content_); 5550a07fd2Sopenharmony_ci} 5650a07fd2Sopenharmony_ci 5750a07fd2Sopenharmony_civoid DMicDev::OnEngineTransDataAvailable(const std::shared_ptr<AudioData> &audioData) 5850a07fd2Sopenharmony_ci{ 5950a07fd2Sopenharmony_ci DHLOGD("On Engine Data available"); 6050a07fd2Sopenharmony_ci if (echoCannelOn_) { 6150a07fd2Sopenharmony_ci#ifdef ECHO_CANNEL_ENABLE 6250a07fd2Sopenharmony_ci if (echoManager_ == nullptr) { 6350a07fd2Sopenharmony_ci DHLOGE("Echo manager is nullptr."); 6450a07fd2Sopenharmony_ci return; 6550a07fd2Sopenharmony_ci } 6650a07fd2Sopenharmony_ci echoManager_->OnMicDataReceived(audioData); 6750a07fd2Sopenharmony_ci#endif 6850a07fd2Sopenharmony_ci } else { 6950a07fd2Sopenharmony_ci OnDecodeTransDataDone(audioData); 7050a07fd2Sopenharmony_ci } 7150a07fd2Sopenharmony_ci} 7250a07fd2Sopenharmony_ci 7350a07fd2Sopenharmony_ciint32_t DMicDev::InitReceiverEngine(IAVEngineProvider *providerPtr) 7450a07fd2Sopenharmony_ci{ 7550a07fd2Sopenharmony_ci DHLOGI("InitReceiverEngine enter."); 7650a07fd2Sopenharmony_ci if (micTrans_ == nullptr) { 7750a07fd2Sopenharmony_ci micTrans_ = std::make_shared<AVTransReceiverTransport>(devId_, shared_from_this()); 7850a07fd2Sopenharmony_ci } 7950a07fd2Sopenharmony_ci int32_t ret = micTrans_->InitEngine(providerPtr); 8050a07fd2Sopenharmony_ci if (ret != DH_SUCCESS) { 8150a07fd2Sopenharmony_ci DHLOGE("Mic dev initialize av receiver adapter failed."); 8250a07fd2Sopenharmony_ci return ret; 8350a07fd2Sopenharmony_ci } 8450a07fd2Sopenharmony_ci ret = micTrans_->CreateCtrl(); 8550a07fd2Sopenharmony_ci if (ret != DH_SUCCESS) { 8650a07fd2Sopenharmony_ci DHLOGE("Create ctrl channel failed. micdev"); 8750a07fd2Sopenharmony_ci return ret; 8850a07fd2Sopenharmony_ci } 8950a07fd2Sopenharmony_ci return DH_SUCCESS; 9050a07fd2Sopenharmony_ci} 9150a07fd2Sopenharmony_ci 9250a07fd2Sopenharmony_ciint32_t DMicDev::InitSenderEngine(IAVEngineProvider *providerPtr) 9350a07fd2Sopenharmony_ci{ 9450a07fd2Sopenharmony_ci DHLOGI("InitReceiverEngine enter."); 9550a07fd2Sopenharmony_ci return DH_SUCCESS; 9650a07fd2Sopenharmony_ci} 9750a07fd2Sopenharmony_ci 9850a07fd2Sopenharmony_ciint32_t DMicDev::EnableDevice(const int32_t dhId, const std::string &capability) 9950a07fd2Sopenharmony_ci{ 10050a07fd2Sopenharmony_ci DHLOGI("Enable IO device, device pin: %{public}d.", dhId); 10150a07fd2Sopenharmony_ci int32_t ret = DAudioHdiHandler::GetInstance().RegisterAudioDevice(devId_, dhId, capability, shared_from_this()); 10250a07fd2Sopenharmony_ci if (ret != DH_SUCCESS) { 10350a07fd2Sopenharmony_ci DHLOGE("Register device failed, ret: %{public}d.", ret); 10450a07fd2Sopenharmony_ci DAudioHisysevent::GetInstance().SysEventWriteFault(DAUDIO_REGISTER_FAIL, devId_, std::to_string(dhId), ret, 10550a07fd2Sopenharmony_ci "daudio register device failed."); 10650a07fd2Sopenharmony_ci return ret; 10750a07fd2Sopenharmony_ci } 10850a07fd2Sopenharmony_ci dhId_ = dhId; 10950a07fd2Sopenharmony_ci return DH_SUCCESS; 11050a07fd2Sopenharmony_ci} 11150a07fd2Sopenharmony_ci 11250a07fd2Sopenharmony_ciint32_t DMicDev::DisableDevice(const int32_t dhId) 11350a07fd2Sopenharmony_ci{ 11450a07fd2Sopenharmony_ci DHLOGI("Disable IO device, device pin: %{public}d.", dhId); 11550a07fd2Sopenharmony_ci int32_t ret = DAudioHdiHandler::GetInstance().UnRegisterAudioDevice(devId_, dhId); 11650a07fd2Sopenharmony_ci if (ret != DH_SUCCESS) { 11750a07fd2Sopenharmony_ci DHLOGE("UnRegister failed, ret: %{public}d.", ret); 11850a07fd2Sopenharmony_ci DAudioHisysevent::GetInstance().SysEventWriteFault(DAUDIO_UNREGISTER_FAIL, devId_, std::to_string(dhId), ret, 11950a07fd2Sopenharmony_ci "daudio unregister device failed."); 12050a07fd2Sopenharmony_ci return ret; 12150a07fd2Sopenharmony_ci } 12250a07fd2Sopenharmony_ci return DH_SUCCESS; 12350a07fd2Sopenharmony_ci} 12450a07fd2Sopenharmony_ci 12550a07fd2Sopenharmony_ciint32_t DMicDev::CreateStream(const int32_t streamId) 12650a07fd2Sopenharmony_ci{ 12750a07fd2Sopenharmony_ci DHLOGI("Open stream of mic device streamId: %{public}d.", streamId); 12850a07fd2Sopenharmony_ci std::shared_ptr<IAudioEventCallback> cbObj = audioEventCallback_.lock(); 12950a07fd2Sopenharmony_ci CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR); 13050a07fd2Sopenharmony_ci 13150a07fd2Sopenharmony_ci cJSON *jParam = cJSON_CreateObject(); 13250a07fd2Sopenharmony_ci CHECK_NULL_RETURN(jParam, ERR_DH_AUDIO_NULLPTR); 13350a07fd2Sopenharmony_ci cJSON_AddStringToObject(jParam, KEY_DH_ID, std::to_string(dhId_).c_str()); 13450a07fd2Sopenharmony_ci char *jsonData = cJSON_PrintUnformatted(jParam); 13550a07fd2Sopenharmony_ci if (jsonData == nullptr) { 13650a07fd2Sopenharmony_ci cJSON_Delete(jParam); 13750a07fd2Sopenharmony_ci DHLOGE("Failed to create JSON data."); 13850a07fd2Sopenharmony_ci return ERR_DH_AUDIO_NULLPTR; 13950a07fd2Sopenharmony_ci } 14050a07fd2Sopenharmony_ci std::string jsonDataStr(jsonData); 14150a07fd2Sopenharmony_ci AudioEvent event(AudioEventType::OPEN_MIC, jsonDataStr); 14250a07fd2Sopenharmony_ci cbObj->NotifyEvent(event); 14350a07fd2Sopenharmony_ci DAudioHisysevent::GetInstance().SysEventWriteBehavior(DAUDIO_OPEN, devId_, std::to_string(dhId_), 14450a07fd2Sopenharmony_ci "daudio mic device open success."); 14550a07fd2Sopenharmony_ci streamId_ = streamId; 14650a07fd2Sopenharmony_ci cJSON_Delete(jParam); 14750a07fd2Sopenharmony_ci cJSON_free(jsonData); 14850a07fd2Sopenharmony_ci return DH_SUCCESS; 14950a07fd2Sopenharmony_ci} 15050a07fd2Sopenharmony_ci 15150a07fd2Sopenharmony_ciint32_t DMicDev::DestroyStream(const int32_t streamId) 15250a07fd2Sopenharmony_ci{ 15350a07fd2Sopenharmony_ci DHLOGI("Close stream of mic device streamId: %{public}d.", streamId); 15450a07fd2Sopenharmony_ci std::shared_ptr<IAudioEventCallback> cbObj = audioEventCallback_.lock(); 15550a07fd2Sopenharmony_ci CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR); 15650a07fd2Sopenharmony_ci 15750a07fd2Sopenharmony_ci cJSON *jParam = cJSON_CreateObject(); 15850a07fd2Sopenharmony_ci CHECK_NULL_RETURN(jParam, ERR_DH_AUDIO_NULLPTR); 15950a07fd2Sopenharmony_ci cJSON_AddStringToObject(jParam, KEY_DH_ID, std::to_string(dhId_).c_str()); 16050a07fd2Sopenharmony_ci char *jsonData = cJSON_PrintUnformatted(jParam); 16150a07fd2Sopenharmony_ci if (jsonData == nullptr) { 16250a07fd2Sopenharmony_ci cJSON_Delete(jParam); 16350a07fd2Sopenharmony_ci DHLOGE("Failed to create JSON data."); 16450a07fd2Sopenharmony_ci return ERR_DH_AUDIO_NULLPTR; 16550a07fd2Sopenharmony_ci } 16650a07fd2Sopenharmony_ci std::string jsonDataStr(jsonData); 16750a07fd2Sopenharmony_ci AudioEvent event(AudioEventType::CLOSE_MIC, jsonDataStr); 16850a07fd2Sopenharmony_ci cbObj->NotifyEvent(event); 16950a07fd2Sopenharmony_ci DAudioHisysevent::GetInstance().SysEventWriteBehavior(DAUDIO_CLOSE, devId_, std::to_string(dhId_), 17050a07fd2Sopenharmony_ci "daudio mic device close success."); 17150a07fd2Sopenharmony_ci cJSON_Delete(jParam); 17250a07fd2Sopenharmony_ci cJSON_free(jsonData); 17350a07fd2Sopenharmony_ci curPort_ = 0; 17450a07fd2Sopenharmony_ci return DH_SUCCESS; 17550a07fd2Sopenharmony_ci} 17650a07fd2Sopenharmony_ci 17750a07fd2Sopenharmony_ciint32_t DMicDev::SetParameters(const int32_t streamId, const AudioParamHDF ¶m) 17850a07fd2Sopenharmony_ci{ 17950a07fd2Sopenharmony_ci DHLOGD("Set mic parameters {samplerate: %{public}d, channelmask: %{public}d, format: %{public}d, " 18050a07fd2Sopenharmony_ci "period: %{public}d, framesize: %{public}d, ext{%{public}s}}.", param.sampleRate, 18150a07fd2Sopenharmony_ci param.channelMask, param.bitFormat, param.period, param.frameSize, param.ext.c_str()); 18250a07fd2Sopenharmony_ci if (param.capturerFlags == MMAP_MODE && param.period != MMAP_NORMAL_PERIOD && param.period != MMAP_VOIP_PERIOD) { 18350a07fd2Sopenharmony_ci DHLOGE("The period is invalid : %{public}" PRIu32, param.period); 18450a07fd2Sopenharmony_ci return ERR_DH_AUDIO_SA_PARAM_INVALID; 18550a07fd2Sopenharmony_ci } 18650a07fd2Sopenharmony_ci curPort_ = dhId_; 18750a07fd2Sopenharmony_ci paramHDF_ = param; 18850a07fd2Sopenharmony_ci 18950a07fd2Sopenharmony_ci param_.comParam.sampleRate = paramHDF_.sampleRate; 19050a07fd2Sopenharmony_ci param_.comParam.channelMask = paramHDF_.channelMask; 19150a07fd2Sopenharmony_ci param_.comParam.bitFormat = paramHDF_.bitFormat; 19250a07fd2Sopenharmony_ci param_.comParam.codecType = AudioCodecType::AUDIO_CODEC_AAC; 19350a07fd2Sopenharmony_ci param_.comParam.frameSize = paramHDF_.frameSize; 19450a07fd2Sopenharmony_ci if (paramHDF_.streamUsage == StreamUsage::STREAM_USAGE_VOICE_COMMUNICATION) { 19550a07fd2Sopenharmony_ci param_.captureOpts.sourceType = SOURCE_TYPE_VOICE_COMMUNICATION; 19650a07fd2Sopenharmony_ci } else { 19750a07fd2Sopenharmony_ci param_.captureOpts.sourceType = SOURCE_TYPE_MIC; 19850a07fd2Sopenharmony_ci } 19950a07fd2Sopenharmony_ci param_.captureOpts.capturerFlags = paramHDF_.capturerFlags; 20050a07fd2Sopenharmony_ci if (paramHDF_.capturerFlags == MMAP_MODE) { 20150a07fd2Sopenharmony_ci lowLatencyHalfSize_ = LOW_LATENCY_JITTER_TIME_MS / paramHDF_.period; 20250a07fd2Sopenharmony_ci lowLatencyMaxfSize_ = LOW_LATENCY_JITTER_MAX_TIME_MS / paramHDF_.period; 20350a07fd2Sopenharmony_ci } 20450a07fd2Sopenharmony_ci return DH_SUCCESS; 20550a07fd2Sopenharmony_ci} 20650a07fd2Sopenharmony_ci 20750a07fd2Sopenharmony_ciint32_t DMicDev::NotifyEvent(const int32_t streamId, const AudioEvent &event) 20850a07fd2Sopenharmony_ci{ 20950a07fd2Sopenharmony_ci DHLOGD("Notify mic event, type: %{public}d.", event.type); 21050a07fd2Sopenharmony_ci std::shared_ptr<IAudioEventCallback> cbObj = audioEventCallback_.lock(); 21150a07fd2Sopenharmony_ci CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR); 21250a07fd2Sopenharmony_ci switch (event.type) { 21350a07fd2Sopenharmony_ci case AudioEventType::AUDIO_START: 21450a07fd2Sopenharmony_ci curStatus_ = AudioStatus::STATUS_START; 21550a07fd2Sopenharmony_ci isExistedEmpty_.store(false); 21650a07fd2Sopenharmony_ci break; 21750a07fd2Sopenharmony_ci case AudioEventType::AUDIO_STOP: 21850a07fd2Sopenharmony_ci curStatus_ = AudioStatus::STATUS_STOP; 21950a07fd2Sopenharmony_ci isExistedEmpty_.store(false); 22050a07fd2Sopenharmony_ci break; 22150a07fd2Sopenharmony_ci default: 22250a07fd2Sopenharmony_ci break; 22350a07fd2Sopenharmony_ci } 22450a07fd2Sopenharmony_ci AudioEvent audioEvent(event.type, event.content); 22550a07fd2Sopenharmony_ci cbObj->NotifyEvent(audioEvent); 22650a07fd2Sopenharmony_ci return DH_SUCCESS; 22750a07fd2Sopenharmony_ci} 22850a07fd2Sopenharmony_ci 22950a07fd2Sopenharmony_ciint32_t DMicDev::SetUp() 23050a07fd2Sopenharmony_ci{ 23150a07fd2Sopenharmony_ci DHLOGI("Set up mic device."); 23250a07fd2Sopenharmony_ci CHECK_NULL_RETURN(micTrans_, ERR_DH_AUDIO_NULLPTR); 23350a07fd2Sopenharmony_ci int32_t ret = micTrans_->SetUp(param_, param_, shared_from_this(), CAP_MIC); 23450a07fd2Sopenharmony_ci if (ret != DH_SUCCESS) { 23550a07fd2Sopenharmony_ci DHLOGE("Mic trans set up failed. ret: %{public}d.", ret); 23650a07fd2Sopenharmony_ci return ret; 23750a07fd2Sopenharmony_ci } 23850a07fd2Sopenharmony_ci echoCannelOn_ = true; 23950a07fd2Sopenharmony_ci#ifdef ECHO_CANNEL_ENABLE 24050a07fd2Sopenharmony_ci if (echoCannelOn_ && echoManager_ == nullptr) { 24150a07fd2Sopenharmony_ci echoManager_ = std::make_shared<DAudioEchoCannelManager>(); 24250a07fd2Sopenharmony_ci } 24350a07fd2Sopenharmony_ci AudioCommonParam info; 24450a07fd2Sopenharmony_ci info.sampleRate = param_.comParam.sampleRate; 24550a07fd2Sopenharmony_ci info.channelMask = param_.comParam.channelMask; 24650a07fd2Sopenharmony_ci info.bitFormat = param_.comParam.bitFormat; 24750a07fd2Sopenharmony_ci info.frameSize = param_.comParam.frameSize; 24850a07fd2Sopenharmony_ci if (echoManager_ != nullptr) { 24950a07fd2Sopenharmony_ci echoManager_->SetUp(info, shared_from_this()); 25050a07fd2Sopenharmony_ci } 25150a07fd2Sopenharmony_ci#endif 25250a07fd2Sopenharmony_ci DumpFileUtil::OpenDumpFile(DUMP_SERVER_PARA, DUMP_DAUDIO_MIC_READ_FROM_BUF_NAME, &dumpFileCommn_); 25350a07fd2Sopenharmony_ci DumpFileUtil::OpenDumpFile(DUMP_SERVER_PARA, DUMP_DAUDIO_LOWLATENCY_MIC_FROM_BUF_NAME, &dumpFileFast_); 25450a07fd2Sopenharmony_ci return DH_SUCCESS; 25550a07fd2Sopenharmony_ci} 25650a07fd2Sopenharmony_ci 25750a07fd2Sopenharmony_ciint32_t DMicDev::Start() 25850a07fd2Sopenharmony_ci{ 25950a07fd2Sopenharmony_ci DHLOGI("Start mic device."); 26050a07fd2Sopenharmony_ci CHECK_NULL_RETURN(micTrans_, ERR_DH_AUDIO_NULLPTR); 26150a07fd2Sopenharmony_ci int32_t ret = micTrans_->Start(); 26250a07fd2Sopenharmony_ci if (ret != DH_SUCCESS) { 26350a07fd2Sopenharmony_ci DHLOGE("Mic trans start failed, ret: %{public}d.", ret); 26450a07fd2Sopenharmony_ci return ret; 26550a07fd2Sopenharmony_ci } 26650a07fd2Sopenharmony_ci std::unique_lock<std::mutex> lck(channelWaitMutex_); 26750a07fd2Sopenharmony_ci auto status = channelWaitCond_.wait_for(lck, std::chrono::seconds(CHANNEL_WAIT_SECONDS), 26850a07fd2Sopenharmony_ci [this]() { return isTransReady_.load(); }); 26950a07fd2Sopenharmony_ci if (!status) { 27050a07fd2Sopenharmony_ci DHLOGE("Wait channel open timeout(%{public}ds).", CHANNEL_WAIT_SECONDS); 27150a07fd2Sopenharmony_ci return ERR_DH_AUDIO_SA_WAIT_TIMEOUT; 27250a07fd2Sopenharmony_ci } 27350a07fd2Sopenharmony_ci isOpened_.store(true); 27450a07fd2Sopenharmony_ci return DH_SUCCESS; 27550a07fd2Sopenharmony_ci} 27650a07fd2Sopenharmony_ci 27750a07fd2Sopenharmony_ciint32_t DMicDev::Pause() 27850a07fd2Sopenharmony_ci{ 27950a07fd2Sopenharmony_ci DHLOGI("Not support."); 28050a07fd2Sopenharmony_ci return DH_SUCCESS; 28150a07fd2Sopenharmony_ci} 28250a07fd2Sopenharmony_ci 28350a07fd2Sopenharmony_ciint32_t DMicDev::Restart() 28450a07fd2Sopenharmony_ci{ 28550a07fd2Sopenharmony_ci DHLOGI("Not surpport."); 28650a07fd2Sopenharmony_ci return DH_SUCCESS; 28750a07fd2Sopenharmony_ci} 28850a07fd2Sopenharmony_ci 28950a07fd2Sopenharmony_ciint32_t DMicDev::Stop() 29050a07fd2Sopenharmony_ci{ 29150a07fd2Sopenharmony_ci DHLOGI("Stop mic device."); 29250a07fd2Sopenharmony_ci CHECK_NULL_RETURN(micTrans_, DH_SUCCESS); 29350a07fd2Sopenharmony_ci isOpened_.store(false); 29450a07fd2Sopenharmony_ci isTransReady_.store(false); 29550a07fd2Sopenharmony_ci int32_t ret = micTrans_->Stop(); 29650a07fd2Sopenharmony_ci if (ret != DH_SUCCESS) { 29750a07fd2Sopenharmony_ci DHLOGE("Stop mic trans failed, ret: %{public}d.", ret); 29850a07fd2Sopenharmony_ci } 29950a07fd2Sopenharmony_ci#ifdef ECHO_CANNEL_ENABLE 30050a07fd2Sopenharmony_ci CHECK_NULL_RETURN(echoManager_, DH_SUCCESS); 30150a07fd2Sopenharmony_ci ret = echoManager_->Stop(); 30250a07fd2Sopenharmony_ci if (ret != DH_SUCCESS) { 30350a07fd2Sopenharmony_ci DHLOGE("Echo manager stop failed. ret: %{public}d.", ret); 30450a07fd2Sopenharmony_ci return ret; 30550a07fd2Sopenharmony_ci } 30650a07fd2Sopenharmony_ci#endif 30750a07fd2Sopenharmony_ci return DH_SUCCESS; 30850a07fd2Sopenharmony_ci} 30950a07fd2Sopenharmony_ci 31050a07fd2Sopenharmony_ciint32_t DMicDev::Release() 31150a07fd2Sopenharmony_ci{ 31250a07fd2Sopenharmony_ci DHLOGI("Release mic device."); 31350a07fd2Sopenharmony_ci if (ashmem_ != nullptr) { 31450a07fd2Sopenharmony_ci ashmem_->UnmapAshmem(); 31550a07fd2Sopenharmony_ci ashmem_->CloseAshmem(); 31650a07fd2Sopenharmony_ci ashmem_ = nullptr; 31750a07fd2Sopenharmony_ci DHLOGI("UnInit ashmem success."); 31850a07fd2Sopenharmony_ci } 31950a07fd2Sopenharmony_ci CHECK_NULL_RETURN(micTrans_, DH_SUCCESS); 32050a07fd2Sopenharmony_ci 32150a07fd2Sopenharmony_ci int32_t ret = micTrans_->Release(); 32250a07fd2Sopenharmony_ci if (ret != DH_SUCCESS) { 32350a07fd2Sopenharmony_ci DHLOGE("Release mic trans failed, ret: %{public}d.", ret); 32450a07fd2Sopenharmony_ci return ret; 32550a07fd2Sopenharmony_ci } 32650a07fd2Sopenharmony_ci#ifdef ECHO_CANNEL_ENABLE 32750a07fd2Sopenharmony_ci if (echoManager_ != nullptr) { 32850a07fd2Sopenharmony_ci echoManager_->Release(); 32950a07fd2Sopenharmony_ci echoManager_ = nullptr; 33050a07fd2Sopenharmony_ci } 33150a07fd2Sopenharmony_ci#endif 33250a07fd2Sopenharmony_ci DumpFileUtil::CloseDumpFile(&dumpFileCommn_); 33350a07fd2Sopenharmony_ci DumpFileUtil::CloseDumpFile(&dumpFileFast_); 33450a07fd2Sopenharmony_ci return DH_SUCCESS; 33550a07fd2Sopenharmony_ci} 33650a07fd2Sopenharmony_ci 33750a07fd2Sopenharmony_cibool DMicDev::IsOpened() 33850a07fd2Sopenharmony_ci{ 33950a07fd2Sopenharmony_ci return isOpened_.load(); 34050a07fd2Sopenharmony_ci} 34150a07fd2Sopenharmony_ci 34250a07fd2Sopenharmony_ciint32_t DMicDev::WriteStreamData(const int32_t streamId, std::shared_ptr<AudioData> &data) 34350a07fd2Sopenharmony_ci{ 34450a07fd2Sopenharmony_ci (void)streamId; 34550a07fd2Sopenharmony_ci (void)data; 34650a07fd2Sopenharmony_ci return DH_SUCCESS; 34750a07fd2Sopenharmony_ci} 34850a07fd2Sopenharmony_ci 34950a07fd2Sopenharmony_ciint32_t DMicDev::ReadStreamData(const int32_t streamId, std::shared_ptr<AudioData> &data) 35050a07fd2Sopenharmony_ci{ 35150a07fd2Sopenharmony_ci int64_t startTime = GetNowTimeUs(); 35250a07fd2Sopenharmony_ci if (curStatus_ != AudioStatus::STATUS_START) { 35350a07fd2Sopenharmony_ci DHLOGE("Distributed audio is not starting status."); 35450a07fd2Sopenharmony_ci return ERR_DH_AUDIO_FAILED; 35550a07fd2Sopenharmony_ci } 35650a07fd2Sopenharmony_ci std::lock_guard<std::mutex> lock(dataQueueMtx_); 35750a07fd2Sopenharmony_ci uint32_t queSize = dataQueue_.size(); 35850a07fd2Sopenharmony_ci if (insertFrameCnt_ >= queSize || queSize == 0) { 35950a07fd2Sopenharmony_ci ++insertFrameCnt_; 36050a07fd2Sopenharmony_ci isExistedEmpty_.store(true); 36150a07fd2Sopenharmony_ci DHLOGD("Data queue is empty, count :%{public}u.", insertFrameCnt_); 36250a07fd2Sopenharmony_ci data = std::make_shared<AudioData>(param_.comParam.frameSize); 36350a07fd2Sopenharmony_ci } else { 36450a07fd2Sopenharmony_ci while (insertFrameCnt_ > 0) { 36550a07fd2Sopenharmony_ci DHLOGD("Data discard, count: %{public}u", insertFrameCnt_); 36650a07fd2Sopenharmony_ci dataQueue_.pop(); 36750a07fd2Sopenharmony_ci --insertFrameCnt_; 36850a07fd2Sopenharmony_ci } 36950a07fd2Sopenharmony_ci data = dataQueue_.front(); 37050a07fd2Sopenharmony_ci dataQueue_.pop(); 37150a07fd2Sopenharmony_ci } 37250a07fd2Sopenharmony_ci CHECK_NULL_RETURN(data, ERR_DH_AUDIO_NULLPTR); 37350a07fd2Sopenharmony_ci DumpFileUtil::WriteDumpFile(dumpFileCommn_, static_cast<void *>(data->Data()), data->Size()); 37450a07fd2Sopenharmony_ci int64_t endTime = GetNowTimeUs(); 37550a07fd2Sopenharmony_ci if (IsOutDurationRange(startTime, endTime, lastReadStartTime_)) { 37650a07fd2Sopenharmony_ci DHLOGE("This time read data spend: %{public}" PRId64" us, The interval of read data this time and " 37750a07fd2Sopenharmony_ci "the last time: %{public}" PRId64" us", endTime - startTime, startTime - lastReadStartTime_); 37850a07fd2Sopenharmony_ci } 37950a07fd2Sopenharmony_ci lastReadStartTime_ = startTime; 38050a07fd2Sopenharmony_ci return DH_SUCCESS; 38150a07fd2Sopenharmony_ci} 38250a07fd2Sopenharmony_ci 38350a07fd2Sopenharmony_ciint32_t DMicDev::ReadMmapPosition(const int32_t streamId, uint64_t &frames, CurrentTimeHDF &time) 38450a07fd2Sopenharmony_ci{ 38550a07fd2Sopenharmony_ci DHLOGD("Read mmap position. frames: %{public}" PRIu64", tvsec: %{public}" PRId64", tvNSec:%{public}" PRId64, 38650a07fd2Sopenharmony_ci writeNum_, writeTvSec_, writeTvNSec_); 38750a07fd2Sopenharmony_ci frames = writeNum_; 38850a07fd2Sopenharmony_ci time.tvSec = writeTvSec_; 38950a07fd2Sopenharmony_ci time.tvNSec = writeTvNSec_; 39050a07fd2Sopenharmony_ci return DH_SUCCESS; 39150a07fd2Sopenharmony_ci} 39250a07fd2Sopenharmony_ci 39350a07fd2Sopenharmony_ciint32_t DMicDev::RefreshAshmemInfo(const int32_t streamId, 39450a07fd2Sopenharmony_ci int32_t fd, int32_t ashmemLength, int32_t lengthPerTrans) 39550a07fd2Sopenharmony_ci{ 39650a07fd2Sopenharmony_ci DHLOGD("RefreshAshmemInfo: fd:%{public}d, ashmemLength: %{public}d, lengthPerTrans: %{public}d", 39750a07fd2Sopenharmony_ci fd, ashmemLength, lengthPerTrans); 39850a07fd2Sopenharmony_ci if (param_.captureOpts.capturerFlags == MMAP_MODE) { 39950a07fd2Sopenharmony_ci DHLOGD("DMic dev low-latency mode"); 40050a07fd2Sopenharmony_ci if (ashmem_ != nullptr) { 40150a07fd2Sopenharmony_ci return DH_SUCCESS; 40250a07fd2Sopenharmony_ci } 40350a07fd2Sopenharmony_ci if (ashmemLength < ASHMEM_MAX_LEN) { 40450a07fd2Sopenharmony_ci ashmem_ = sptr<Ashmem>(new Ashmem(fd, ashmemLength)); 40550a07fd2Sopenharmony_ci ashmemLength_ = ashmemLength; 40650a07fd2Sopenharmony_ci lengthPerTrans_ = lengthPerTrans; 40750a07fd2Sopenharmony_ci DHLOGD("Create ashmem success. fd:%{public}d, ashmem length: %{public}d, lengthPreTrans: %{public}d", 40850a07fd2Sopenharmony_ci fd, ashmemLength_, lengthPerTrans_); 40950a07fd2Sopenharmony_ci bool mapRet = ashmem_->MapReadAndWriteAshmem(); 41050a07fd2Sopenharmony_ci if (!mapRet) { 41150a07fd2Sopenharmony_ci DHLOGE("Mmap ashmem failed."); 41250a07fd2Sopenharmony_ci return ERR_DH_AUDIO_NULLPTR; 41350a07fd2Sopenharmony_ci } 41450a07fd2Sopenharmony_ci } 41550a07fd2Sopenharmony_ci } 41650a07fd2Sopenharmony_ci return DH_SUCCESS; 41750a07fd2Sopenharmony_ci} 41850a07fd2Sopenharmony_ci 41950a07fd2Sopenharmony_ciint32_t DMicDev::MmapStart() 42050a07fd2Sopenharmony_ci{ 42150a07fd2Sopenharmony_ci CHECK_NULL_RETURN(ashmem_, ERR_DH_AUDIO_NULLPTR); 42250a07fd2Sopenharmony_ci std::lock_guard<std::mutex> lock(writeAshmemMutex_); 42350a07fd2Sopenharmony_ci frameIndex_ = 0; 42450a07fd2Sopenharmony_ci startTime_ = 0; 42550a07fd2Sopenharmony_ci isEnqueueRunning_.store(true); 42650a07fd2Sopenharmony_ci enqueueDataThread_ = std::thread([this]() { this->EnqueueThread(); }); 42750a07fd2Sopenharmony_ci if (pthread_setname_np(enqueueDataThread_.native_handle(), ENQUEUE_THREAD) != DH_SUCCESS) { 42850a07fd2Sopenharmony_ci DHLOGE("Enqueue data thread setname failed."); 42950a07fd2Sopenharmony_ci } 43050a07fd2Sopenharmony_ci return DH_SUCCESS; 43150a07fd2Sopenharmony_ci} 43250a07fd2Sopenharmony_ci 43350a07fd2Sopenharmony_civoid DMicDev::EnqueueThread() 43450a07fd2Sopenharmony_ci{ 43550a07fd2Sopenharmony_ci writeIndex_ = 0; 43650a07fd2Sopenharmony_ci writeNum_ = 0; 43750a07fd2Sopenharmony_ci int64_t timeIntervalns = static_cast<int64_t>(paramHDF_.period * AUDIO_NS_PER_SECOND / AUDIO_MS_PER_SECOND); 43850a07fd2Sopenharmony_ci DHLOGD("Enqueue thread start, lengthPerWrite length: %{public}d, interval: %{public}d.", lengthPerTrans_, 43950a07fd2Sopenharmony_ci paramHDF_.period); 44050a07fd2Sopenharmony_ci FillJitterQueue(); 44150a07fd2Sopenharmony_ci while (ashmem_ != nullptr && isEnqueueRunning_.load()) { 44250a07fd2Sopenharmony_ci int64_t timeOffset = UpdateTimeOffset(frameIndex_, timeIntervalns, startTime_); 44350a07fd2Sopenharmony_ci DHLOGD("Write frameIndex: %{public}" PRId64", timeOffset: %{public}" PRId64, frameIndex_, timeOffset); 44450a07fd2Sopenharmony_ci std::shared_ptr<AudioData> audioData = nullptr; 44550a07fd2Sopenharmony_ci { 44650a07fd2Sopenharmony_ci std::lock_guard<std::mutex> lock(dataQueueMtx_); 44750a07fd2Sopenharmony_ci if (dataQueue_.empty()) { 44850a07fd2Sopenharmony_ci DHLOGD("Data queue is Empty."); 44950a07fd2Sopenharmony_ci audioData = std::make_shared<AudioData>(param_.comParam.frameSize); 45050a07fd2Sopenharmony_ci } else { 45150a07fd2Sopenharmony_ci audioData = dataQueue_.front(); 45250a07fd2Sopenharmony_ci dataQueue_.pop(); 45350a07fd2Sopenharmony_ci } 45450a07fd2Sopenharmony_ci if (audioData == nullptr) { 45550a07fd2Sopenharmony_ci DHLOGD("The audioData is nullptr."); 45650a07fd2Sopenharmony_ci continue; 45750a07fd2Sopenharmony_ci } 45850a07fd2Sopenharmony_ci DumpFileUtil::WriteDumpFile(dumpFileFast_, static_cast<void *>(audioData->Data()), audioData->Size()); 45950a07fd2Sopenharmony_ci bool writeRet = ashmem_->WriteToAshmem(audioData->Data(), audioData->Size(), writeIndex_); 46050a07fd2Sopenharmony_ci if (writeRet) { 46150a07fd2Sopenharmony_ci DHLOGD("Write to ashmem success! write index: %{public}d, writeLength: %{public}d.", 46250a07fd2Sopenharmony_ci writeIndex_, lengthPerTrans_); 46350a07fd2Sopenharmony_ci } else { 46450a07fd2Sopenharmony_ci DHLOGE("Write data to ashmem failed."); 46550a07fd2Sopenharmony_ci } 46650a07fd2Sopenharmony_ci } 46750a07fd2Sopenharmony_ci writeIndex_ += lengthPerTrans_; 46850a07fd2Sopenharmony_ci if (writeIndex_ >= ashmemLength_) { 46950a07fd2Sopenharmony_ci writeIndex_ = 0; 47050a07fd2Sopenharmony_ci } 47150a07fd2Sopenharmony_ci writeNum_ += static_cast<uint64_t>(CalculateSampleNum(param_.comParam.sampleRate, paramHDF_.period)); 47250a07fd2Sopenharmony_ci GetCurrentTime(writeTvSec_, writeTvNSec_); 47350a07fd2Sopenharmony_ci frameIndex_++; 47450a07fd2Sopenharmony_ci AbsoluteSleep(startTime_ + frameIndex_ * timeIntervalns - timeOffset); 47550a07fd2Sopenharmony_ci } 47650a07fd2Sopenharmony_ci} 47750a07fd2Sopenharmony_ci 47850a07fd2Sopenharmony_civoid DMicDev::FillJitterQueue() 47950a07fd2Sopenharmony_ci{ 48050a07fd2Sopenharmony_ci while (isEnqueueRunning_.load()) { 48150a07fd2Sopenharmony_ci { 48250a07fd2Sopenharmony_ci std::lock_guard<std::mutex> lock(dataQueueMtx_); 48350a07fd2Sopenharmony_ci if (dataQueue_.size() >= (LOW_LATENCY_JITTER_TIME_MS / paramHDF_.period)) { 48450a07fd2Sopenharmony_ci break; 48550a07fd2Sopenharmony_ci } 48650a07fd2Sopenharmony_ci } 48750a07fd2Sopenharmony_ci usleep(MMAP_WAIT_FRAME_US); 48850a07fd2Sopenharmony_ci } 48950a07fd2Sopenharmony_ci DHLOGD("Mic jitter data queue fill end."); 49050a07fd2Sopenharmony_ci} 49150a07fd2Sopenharmony_ci 49250a07fd2Sopenharmony_ciint32_t DMicDev::MmapStop() 49350a07fd2Sopenharmony_ci{ 49450a07fd2Sopenharmony_ci std::lock_guard<std::mutex> lock(writeAshmemMutex_); 49550a07fd2Sopenharmony_ci isEnqueueRunning_.store(false); 49650a07fd2Sopenharmony_ci if (enqueueDataThread_.joinable()) { 49750a07fd2Sopenharmony_ci enqueueDataThread_.join(); 49850a07fd2Sopenharmony_ci } 49950a07fd2Sopenharmony_ci DHLOGI("Mic mmap stop end."); 50050a07fd2Sopenharmony_ci return DH_SUCCESS; 50150a07fd2Sopenharmony_ci} 50250a07fd2Sopenharmony_ci 50350a07fd2Sopenharmony_ciAudioParam DMicDev::GetAudioParam() const 50450a07fd2Sopenharmony_ci{ 50550a07fd2Sopenharmony_ci return param_; 50650a07fd2Sopenharmony_ci} 50750a07fd2Sopenharmony_ci 50850a07fd2Sopenharmony_ciint32_t DMicDev::NotifyHdfAudioEvent(const AudioEvent &event, const int32_t portId) 50950a07fd2Sopenharmony_ci{ 51050a07fd2Sopenharmony_ci int32_t ret = DAudioHdiHandler::GetInstance().NotifyEvent(devId_, portId, streamId_, event); 51150a07fd2Sopenharmony_ci if (ret != DH_SUCCESS) { 51250a07fd2Sopenharmony_ci DHLOGE("Notify event: %{public}d, result: %{public}s, streamId: %{public}d.", 51350a07fd2Sopenharmony_ci event.type, event.content.c_str(), streamId_); 51450a07fd2Sopenharmony_ci } 51550a07fd2Sopenharmony_ci return DH_SUCCESS; 51650a07fd2Sopenharmony_ci} 51750a07fd2Sopenharmony_ci 51850a07fd2Sopenharmony_ciint32_t DMicDev::OnStateChange(const AudioEventType type) 51950a07fd2Sopenharmony_ci{ 52050a07fd2Sopenharmony_ci DHLOGD("On mic device state change, type: %{public}d", type); 52150a07fd2Sopenharmony_ci AudioEvent event; 52250a07fd2Sopenharmony_ci switch (type) { 52350a07fd2Sopenharmony_ci case AudioEventType::DATA_OPENED: 52450a07fd2Sopenharmony_ci isTransReady_.store(true); 52550a07fd2Sopenharmony_ci channelWaitCond_.notify_one(); 52650a07fd2Sopenharmony_ci event.type = AudioEventType::MIC_OPENED; 52750a07fd2Sopenharmony_ci break; 52850a07fd2Sopenharmony_ci case AudioEventType::DATA_CLOSED: 52950a07fd2Sopenharmony_ci isTransReady_.store(false); 53050a07fd2Sopenharmony_ci event.type = AudioEventType::MIC_CLOSED; 53150a07fd2Sopenharmony_ci break; 53250a07fd2Sopenharmony_ci default: 53350a07fd2Sopenharmony_ci break; 53450a07fd2Sopenharmony_ci } 53550a07fd2Sopenharmony_ci event.content = GetCJsonString(KEY_DH_ID, std::to_string(dhId_).c_str()); 53650a07fd2Sopenharmony_ci std::shared_ptr<IAudioEventCallback> cbObj = audioEventCallback_.lock(); 53750a07fd2Sopenharmony_ci CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR); 53850a07fd2Sopenharmony_ci cbObj->NotifyEvent(event); 53950a07fd2Sopenharmony_ci return DH_SUCCESS; 54050a07fd2Sopenharmony_ci} 54150a07fd2Sopenharmony_ci 54250a07fd2Sopenharmony_ciint32_t DMicDev::SendMessage(uint32_t type, std::string content, std::string dstDevId) 54350a07fd2Sopenharmony_ci{ 54450a07fd2Sopenharmony_ci DHLOGD("Send message to remote."); 54550a07fd2Sopenharmony_ci if (type != static_cast<uint32_t>(OPEN_MIC) && type != static_cast<uint32_t>(CLOSE_MIC)) { 54650a07fd2Sopenharmony_ci DHLOGE("Send message to remote. not OPEN_MIC or CLOSE_MIC. type: %{public}u", type); 54750a07fd2Sopenharmony_ci return ERR_DH_AUDIO_NULLPTR; 54850a07fd2Sopenharmony_ci } 54950a07fd2Sopenharmony_ci CHECK_NULL_RETURN(micTrans_, ERR_DH_AUDIO_NULLPTR); 55050a07fd2Sopenharmony_ci micTrans_->SendMessage(type, content, dstDevId); 55150a07fd2Sopenharmony_ci return DH_SUCCESS; 55250a07fd2Sopenharmony_ci} 55350a07fd2Sopenharmony_ci 55450a07fd2Sopenharmony_ciint32_t DMicDev::OnDecodeTransDataDone(const std::shared_ptr<AudioData> &audioData) 55550a07fd2Sopenharmony_ci{ 55650a07fd2Sopenharmony_ci CHECK_NULL_RETURN(audioData, ERR_DH_AUDIO_NULLPTR); 55750a07fd2Sopenharmony_ci std::lock_guard<std::mutex> lock(dataQueueMtx_); 55850a07fd2Sopenharmony_ci dataQueSize_ = curStatus_ != AudioStatus::STATUS_START ? 55950a07fd2Sopenharmony_ci (param_.captureOpts.capturerFlags == MMAP_MODE ? lowLatencyHalfSize_ : DATA_QUEUE_HALF_SIZE) : 56050a07fd2Sopenharmony_ci (param_.captureOpts.capturerFlags == MMAP_MODE ? lowLatencyMaxfSize_ : DATA_QUEUE_MAX_SIZE); 56150a07fd2Sopenharmony_ci if (isExistedEmpty_.load()) { 56250a07fd2Sopenharmony_ci dataQueSize_ = param_.captureOpts.capturerFlags == MMAP_MODE ? dataQueSize_ : DATA_QUEUE_EXT_SIZE; 56350a07fd2Sopenharmony_ci } 56450a07fd2Sopenharmony_ci uint64_t queueSize; 56550a07fd2Sopenharmony_ci while (dataQueue_.size() > dataQueSize_) { 56650a07fd2Sopenharmony_ci queueSize = static_cast<uint64_t>(dataQueue_.size()); 56750a07fd2Sopenharmony_ci DHLOGD("Data queue overflow. buf current size: %{public}" PRIu64, queueSize); 56850a07fd2Sopenharmony_ci dataQueue_.pop(); 56950a07fd2Sopenharmony_ci } 57050a07fd2Sopenharmony_ci dataQueue_.push(audioData); 57150a07fd2Sopenharmony_ci queueSize = static_cast<uint64_t>(dataQueue_.size()); 57250a07fd2Sopenharmony_ci DHLOGD("Push new mic data, buf len: %{public}" PRIu64, queueSize); 57350a07fd2Sopenharmony_ci return DH_SUCCESS; 57450a07fd2Sopenharmony_ci} 57550a07fd2Sopenharmony_ci} // DistributedHardware 57650a07fd2Sopenharmony_ci} // OHOS 577