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 "dspeaker_dev.h" 1750a07fd2Sopenharmony_ci 1850a07fd2Sopenharmony_ci#include <algorithm> 1950a07fd2Sopenharmony_ci#include <condition_variable> 2050a07fd2Sopenharmony_ci#include <mutex> 2150a07fd2Sopenharmony_ci#include <string> 2250a07fd2Sopenharmony_ci#include <thread> 2350a07fd2Sopenharmony_ci#include <securec.h> 2450a07fd2Sopenharmony_ci 2550a07fd2Sopenharmony_ci#include "daudio_constants.h" 2650a07fd2Sopenharmony_ci#include "daudio_errorcode.h" 2750a07fd2Sopenharmony_ci#include "daudio_hidumper.h" 2850a07fd2Sopenharmony_ci#include "daudio_hisysevent.h" 2950a07fd2Sopenharmony_ci#include "daudio_hitrace.h" 3050a07fd2Sopenharmony_ci#include "daudio_log.h" 3150a07fd2Sopenharmony_ci#include "daudio_source_manager.h" 3250a07fd2Sopenharmony_ci#include "daudio_util.h" 3350a07fd2Sopenharmony_ci 3450a07fd2Sopenharmony_ci#undef DH_LOG_TAG 3550a07fd2Sopenharmony_ci#define DH_LOG_TAG "DSpeakerDev" 3650a07fd2Sopenharmony_ci 3750a07fd2Sopenharmony_cinamespace OHOS { 3850a07fd2Sopenharmony_cinamespace DistributedHardware { 3950a07fd2Sopenharmony_ciint32_t DSpeakerDev::EnableDevice(const int32_t dhId, const std::string &capability) 4050a07fd2Sopenharmony_ci{ 4150a07fd2Sopenharmony_ci DHLOGI("Enable IO device, device pin: %{public}d.", dhId); 4250a07fd2Sopenharmony_ci int32_t ret = DAudioHdiHandler::GetInstance().RegisterAudioDevice(devId_, dhId, capability, shared_from_this()); 4350a07fd2Sopenharmony_ci if (ret != DH_SUCCESS) { 4450a07fd2Sopenharmony_ci DHLOGE("Register device failed, ret: %{public}d.", ret); 4550a07fd2Sopenharmony_ci DAudioHisysevent::GetInstance().SysEventWriteFault(DAUDIO_REGISTER_FAIL, devId_, std::to_string(dhId), ret, 4650a07fd2Sopenharmony_ci "daudio register device failed."); 4750a07fd2Sopenharmony_ci return ret; 4850a07fd2Sopenharmony_ci } 4950a07fd2Sopenharmony_ci dhId_ = dhId; 5050a07fd2Sopenharmony_ci return DH_SUCCESS; 5150a07fd2Sopenharmony_ci} 5250a07fd2Sopenharmony_ci 5350a07fd2Sopenharmony_ciint32_t DSpeakerDev::DisableDevice(const int32_t dhId) 5450a07fd2Sopenharmony_ci{ 5550a07fd2Sopenharmony_ci DHLOGI("Disable IO device, device pin: %{public}d.", dhId); 5650a07fd2Sopenharmony_ci int32_t ret = DAudioHdiHandler::GetInstance().UnRegisterAudioDevice(devId_, dhId); 5750a07fd2Sopenharmony_ci if (ret != DH_SUCCESS) { 5850a07fd2Sopenharmony_ci DHLOGE("UnRegister failed, ret: %{public}d.", ret); 5950a07fd2Sopenharmony_ci DAudioHisysevent::GetInstance().SysEventWriteFault(DAUDIO_UNREGISTER_FAIL, devId_, std::to_string(dhId), ret, 6050a07fd2Sopenharmony_ci "daudio unregister device failed."); 6150a07fd2Sopenharmony_ci return ret; 6250a07fd2Sopenharmony_ci } 6350a07fd2Sopenharmony_ci return DH_SUCCESS; 6450a07fd2Sopenharmony_ci} 6550a07fd2Sopenharmony_ci 6650a07fd2Sopenharmony_ciint32_t DSpeakerDev::InitReceiverEngine(IAVEngineProvider *providerPtr) 6750a07fd2Sopenharmony_ci{ 6850a07fd2Sopenharmony_ci DHLOGI("InitReceiverEngine enter."); 6950a07fd2Sopenharmony_ci return DH_SUCCESS; 7050a07fd2Sopenharmony_ci} 7150a07fd2Sopenharmony_ci 7250a07fd2Sopenharmony_ciint32_t DSpeakerDev::InitSenderEngine(IAVEngineProvider *providerPtr) 7350a07fd2Sopenharmony_ci{ 7450a07fd2Sopenharmony_ci DHLOGI("InitSenderEngine enter"); 7550a07fd2Sopenharmony_ci if (speakerTrans_ == nullptr) { 7650a07fd2Sopenharmony_ci speakerTrans_ = std::make_shared<AVTransSenderTransport>(devId_, shared_from_this()); 7750a07fd2Sopenharmony_ci } 7850a07fd2Sopenharmony_ci int32_t ret = speakerTrans_->InitEngine(providerPtr); 7950a07fd2Sopenharmony_ci if (ret != DH_SUCCESS) { 8050a07fd2Sopenharmony_ci DHLOGE("Speaker dev initialize av sender adapter failed."); 8150a07fd2Sopenharmony_ci return ret; 8250a07fd2Sopenharmony_ci } 8350a07fd2Sopenharmony_ci ret = speakerTrans_->CreateCtrl(); 8450a07fd2Sopenharmony_ci if (ret != DH_SUCCESS) { 8550a07fd2Sopenharmony_ci DHLOGE("Create ctrl channel failed."); 8650a07fd2Sopenharmony_ci } 8750a07fd2Sopenharmony_ci return ret; 8850a07fd2Sopenharmony_ci} 8950a07fd2Sopenharmony_ci 9050a07fd2Sopenharmony_civoid DSpeakerDev::OnEngineTransEvent(const AVTransEvent &event) 9150a07fd2Sopenharmony_ci{ 9250a07fd2Sopenharmony_ci if (event.type == EventType::EVENT_START_SUCCESS) { 9350a07fd2Sopenharmony_ci OnStateChange(DATA_OPENED); 9450a07fd2Sopenharmony_ci } else if ((event.type == EventType::EVENT_STOP_SUCCESS) || 9550a07fd2Sopenharmony_ci (event.type == EventType::EVENT_CHANNEL_CLOSED) || 9650a07fd2Sopenharmony_ci (event.type == EventType::EVENT_START_FAIL)) { 9750a07fd2Sopenharmony_ci OnStateChange(DATA_CLOSED); 9850a07fd2Sopenharmony_ci } 9950a07fd2Sopenharmony_ci} 10050a07fd2Sopenharmony_ci 10150a07fd2Sopenharmony_civoid DSpeakerDev::OnEngineTransMessage(const std::shared_ptr<AVTransMessage> &message) 10250a07fd2Sopenharmony_ci{ 10350a07fd2Sopenharmony_ci CHECK_NULL_VOID(message); 10450a07fd2Sopenharmony_ci DHLOGI("On Engine message, type : %{public}s.", GetEventNameByType(message->type_).c_str()); 10550a07fd2Sopenharmony_ci DAudioSourceManager::GetInstance().HandleDAudioNotify(message->dstDevId_, message->dstDevId_, 10650a07fd2Sopenharmony_ci message->type_, message->content_); 10750a07fd2Sopenharmony_ci} 10850a07fd2Sopenharmony_ci 10950a07fd2Sopenharmony_ciint32_t DSpeakerDev::CreateStream(const int32_t streamId) 11050a07fd2Sopenharmony_ci{ 11150a07fd2Sopenharmony_ci DHLOGI("Open stream of speaker device, streamId: %{public}d.", streamId); 11250a07fd2Sopenharmony_ci std::shared_ptr<IAudioEventCallback> cbObj = audioEventCallback_.lock(); 11350a07fd2Sopenharmony_ci CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR); 11450a07fd2Sopenharmony_ci 11550a07fd2Sopenharmony_ci cJSON *jParam = cJSON_CreateObject(); 11650a07fd2Sopenharmony_ci CHECK_NULL_RETURN(jParam, ERR_DH_AUDIO_NULLPTR); 11750a07fd2Sopenharmony_ci cJSON_AddStringToObject(jParam, KEY_DH_ID, std::to_string(dhId_).c_str()); 11850a07fd2Sopenharmony_ci char *jsonData = cJSON_PrintUnformatted(jParam); 11950a07fd2Sopenharmony_ci if (jsonData == nullptr) { 12050a07fd2Sopenharmony_ci DHLOGE("Failed to create JSON data."); 12150a07fd2Sopenharmony_ci cJSON_Delete(jParam); 12250a07fd2Sopenharmony_ci return ERR_DH_AUDIO_NULLPTR; 12350a07fd2Sopenharmony_ci } 12450a07fd2Sopenharmony_ci std::string jsonDataStr(jsonData); 12550a07fd2Sopenharmony_ci AudioEvent event(AudioEventType::OPEN_SPEAKER, jsonDataStr); 12650a07fd2Sopenharmony_ci cbObj->NotifyEvent(event); 12750a07fd2Sopenharmony_ci DAudioHisysevent::GetInstance().SysEventWriteBehavior(DAUDIO_OPEN, devId_, std::to_string(dhId_), 12850a07fd2Sopenharmony_ci "daudio spk device open success."); 12950a07fd2Sopenharmony_ci streamId_ = streamId; 13050a07fd2Sopenharmony_ci cJSON_Delete(jParam); 13150a07fd2Sopenharmony_ci cJSON_free(jsonData); 13250a07fd2Sopenharmony_ci return DH_SUCCESS; 13350a07fd2Sopenharmony_ci} 13450a07fd2Sopenharmony_ci 13550a07fd2Sopenharmony_ciint32_t DSpeakerDev::DestroyStream(const int32_t streamId) 13650a07fd2Sopenharmony_ci{ 13750a07fd2Sopenharmony_ci DHLOGI("Close stream of speaker device streamId: %{public}d.", streamId); 13850a07fd2Sopenharmony_ci std::shared_ptr<IAudioEventCallback> cbObj = audioEventCallback_.lock(); 13950a07fd2Sopenharmony_ci CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR); 14050a07fd2Sopenharmony_ci 14150a07fd2Sopenharmony_ci cJSON *jParam = cJSON_CreateObject(); 14250a07fd2Sopenharmony_ci CHECK_NULL_RETURN(jParam, ERR_DH_AUDIO_NULLPTR); 14350a07fd2Sopenharmony_ci cJSON_AddStringToObject(jParam, KEY_DH_ID, std::to_string(dhId_).c_str()); 14450a07fd2Sopenharmony_ci char *jsonData = cJSON_PrintUnformatted(jParam); 14550a07fd2Sopenharmony_ci if (jsonData == nullptr) { 14650a07fd2Sopenharmony_ci DHLOGE("Failed to create JSON data."); 14750a07fd2Sopenharmony_ci cJSON_Delete(jParam); 14850a07fd2Sopenharmony_ci return ERR_DH_AUDIO_NULLPTR; 14950a07fd2Sopenharmony_ci } 15050a07fd2Sopenharmony_ci std::string jsonDataStr(jsonData); 15150a07fd2Sopenharmony_ci AudioEvent event(AudioEventType::CLOSE_SPEAKER, jsonDataStr); 15250a07fd2Sopenharmony_ci cbObj->NotifyEvent(event); 15350a07fd2Sopenharmony_ci DAudioHisysevent::GetInstance().SysEventWriteBehavior(DAUDIO_CLOSE, devId_, std::to_string(dhId_), 15450a07fd2Sopenharmony_ci "daudio spk device close success."); 15550a07fd2Sopenharmony_ci curPort_ = 0; 15650a07fd2Sopenharmony_ci cJSON_Delete(jParam); 15750a07fd2Sopenharmony_ci cJSON_free(jsonData); 15850a07fd2Sopenharmony_ci return DH_SUCCESS; 15950a07fd2Sopenharmony_ci} 16050a07fd2Sopenharmony_ci 16150a07fd2Sopenharmony_ciint32_t DSpeakerDev::SetParameters(const int32_t streamId, const AudioParamHDF ¶m) 16250a07fd2Sopenharmony_ci{ 16350a07fd2Sopenharmony_ci DHLOGD("Set speaker parameters {samplerate: %{public}d, channelmask: %{public}d, format: %{public}d, " 16450a07fd2Sopenharmony_ci "streamusage: %{public}d, period: %{public}d, framesize: %{public}d, renderFlags: %{public}d, " 16550a07fd2Sopenharmony_ci "ext{%{public}s}}.", param.sampleRate, param.channelMask, param.bitFormat, param.streamUsage, 16650a07fd2Sopenharmony_ci param.period, param.frameSize, param.renderFlags, param.ext.c_str()); 16750a07fd2Sopenharmony_ci curPort_ = dhId_; 16850a07fd2Sopenharmony_ci paramHDF_ = param; 16950a07fd2Sopenharmony_ci 17050a07fd2Sopenharmony_ci param_.comParam.sampleRate = paramHDF_.sampleRate; 17150a07fd2Sopenharmony_ci param_.comParam.channelMask = paramHDF_.channelMask; 17250a07fd2Sopenharmony_ci param_.comParam.bitFormat = paramHDF_.bitFormat; 17350a07fd2Sopenharmony_ci param_.comParam.codecType = AudioCodecType::AUDIO_CODEC_AAC; 17450a07fd2Sopenharmony_ci param_.comParam.frameSize = paramHDF_.frameSize; 17550a07fd2Sopenharmony_ci param_.renderOpts.contentType = CONTENT_TYPE_MUSIC; 17650a07fd2Sopenharmony_ci param_.renderOpts.renderFlags = paramHDF_.renderFlags; 17750a07fd2Sopenharmony_ci param_.renderOpts.streamUsage = paramHDF_.streamUsage; 17850a07fd2Sopenharmony_ci return DH_SUCCESS; 17950a07fd2Sopenharmony_ci} 18050a07fd2Sopenharmony_ci 18150a07fd2Sopenharmony_ciint32_t DSpeakerDev::NotifyEvent(const int32_t streamId, const AudioEvent &event) 18250a07fd2Sopenharmony_ci{ 18350a07fd2Sopenharmony_ci DHLOGD("Notify speaker event."); 18450a07fd2Sopenharmony_ci std::shared_ptr<IAudioEventCallback> cbObj = audioEventCallback_.lock(); 18550a07fd2Sopenharmony_ci CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR); 18650a07fd2Sopenharmony_ci AudioEvent audioEvent(event.type, event.content); 18750a07fd2Sopenharmony_ci cbObj->NotifyEvent(audioEvent); 18850a07fd2Sopenharmony_ci return DH_SUCCESS; 18950a07fd2Sopenharmony_ci} 19050a07fd2Sopenharmony_ci 19150a07fd2Sopenharmony_ciint32_t DSpeakerDev::SetUp() 19250a07fd2Sopenharmony_ci{ 19350a07fd2Sopenharmony_ci DHLOGI("Set up speaker device."); 19450a07fd2Sopenharmony_ci CHECK_NULL_RETURN(speakerTrans_, ERR_DH_AUDIO_NULLPTR); 19550a07fd2Sopenharmony_ci 19650a07fd2Sopenharmony_ci int32_t ret = speakerTrans_->SetUp(param_, param_, shared_from_this(), CAP_SPK); 19750a07fd2Sopenharmony_ci if (ret != DH_SUCCESS) { 19850a07fd2Sopenharmony_ci DHLOGE("Speaker trans set up failed. ret:%{public}d", ret); 19950a07fd2Sopenharmony_ci return ret; 20050a07fd2Sopenharmony_ci } 20150a07fd2Sopenharmony_ci DumpFileUtil::OpenDumpFile(DUMP_SERVER_PARA, SPK_DEV_FILENAME, &dumpFileCommn_); 20250a07fd2Sopenharmony_ci DumpFileUtil::OpenDumpFile(DUMP_SERVER_PARA, SPK_LOWLATENCY_FILENAME, &dumpFileFast_); 20350a07fd2Sopenharmony_ci return DH_SUCCESS; 20450a07fd2Sopenharmony_ci} 20550a07fd2Sopenharmony_ci 20650a07fd2Sopenharmony_ciint32_t DSpeakerDev::Start() 20750a07fd2Sopenharmony_ci{ 20850a07fd2Sopenharmony_ci DHLOGI("Start speaker device."); 20950a07fd2Sopenharmony_ci CHECK_NULL_RETURN(speakerTrans_, ERR_DH_AUDIO_NULLPTR); 21050a07fd2Sopenharmony_ci int32_t ret = speakerTrans_->Start(); 21150a07fd2Sopenharmony_ci if (ret != DH_SUCCESS) { 21250a07fd2Sopenharmony_ci DHLOGE("Speaker trans start failed, ret: %{public}d.", ret); 21350a07fd2Sopenharmony_ci return ret; 21450a07fd2Sopenharmony_ci } 21550a07fd2Sopenharmony_ci std::unique_lock<std::mutex> lck(channelWaitMutex_); 21650a07fd2Sopenharmony_ci auto status = channelWaitCond_.wait_for(lck, std::chrono::seconds(CHANNEL_WAIT_SECONDS), 21750a07fd2Sopenharmony_ci [this]() { return isTransReady_.load(); }); 21850a07fd2Sopenharmony_ci if (!status) { 21950a07fd2Sopenharmony_ci DHLOGE("Wait channel open timeout(%{public}ds).", CHANNEL_WAIT_SECONDS); 22050a07fd2Sopenharmony_ci return ERR_DH_AUDIO_SA_WAIT_TIMEOUT; 22150a07fd2Sopenharmony_ci } 22250a07fd2Sopenharmony_ci isOpened_.store(true); 22350a07fd2Sopenharmony_ci return DH_SUCCESS; 22450a07fd2Sopenharmony_ci} 22550a07fd2Sopenharmony_ci 22650a07fd2Sopenharmony_ciint32_t DSpeakerDev::Stop() 22750a07fd2Sopenharmony_ci{ 22850a07fd2Sopenharmony_ci DHLOGI("Stop speaker device."); 22950a07fd2Sopenharmony_ci CHECK_NULL_RETURN(speakerTrans_, DH_SUCCESS); 23050a07fd2Sopenharmony_ci isOpened_.store(false); 23150a07fd2Sopenharmony_ci isTransReady_.store(false); 23250a07fd2Sopenharmony_ci int32_t ret = speakerTrans_->Stop(); 23350a07fd2Sopenharmony_ci if (ret != DH_SUCCESS) { 23450a07fd2Sopenharmony_ci DHLOGE("Stop speaker trans failed, ret: %{public}d.", ret); 23550a07fd2Sopenharmony_ci return ret; 23650a07fd2Sopenharmony_ci } 23750a07fd2Sopenharmony_ci return DH_SUCCESS; 23850a07fd2Sopenharmony_ci} 23950a07fd2Sopenharmony_ci 24050a07fd2Sopenharmony_ciint32_t DSpeakerDev::Release() 24150a07fd2Sopenharmony_ci{ 24250a07fd2Sopenharmony_ci DHLOGI("Release speaker device."); 24350a07fd2Sopenharmony_ci if (ashmem_ != nullptr) { 24450a07fd2Sopenharmony_ci ashmem_->UnmapAshmem(); 24550a07fd2Sopenharmony_ci ashmem_->CloseAshmem(); 24650a07fd2Sopenharmony_ci ashmem_ = nullptr; 24750a07fd2Sopenharmony_ci DHLOGI("UnInit ashmem success."); 24850a07fd2Sopenharmony_ci } 24950a07fd2Sopenharmony_ci CHECK_NULL_RETURN(speakerTrans_, DH_SUCCESS); 25050a07fd2Sopenharmony_ci int32_t ret = speakerTrans_->Release(); 25150a07fd2Sopenharmony_ci if (ret != DH_SUCCESS) { 25250a07fd2Sopenharmony_ci DHLOGE("Release speaker trans failed, ret: %{public}d.", ret); 25350a07fd2Sopenharmony_ci } 25450a07fd2Sopenharmony_ci DumpFileUtil::CloseDumpFile(&dumpFileCommn_); 25550a07fd2Sopenharmony_ci DumpFileUtil::CloseDumpFile(&dumpFileFast_); 25650a07fd2Sopenharmony_ci return DH_SUCCESS; 25750a07fd2Sopenharmony_ci} 25850a07fd2Sopenharmony_ci 25950a07fd2Sopenharmony_ciint32_t DSpeakerDev::Pause() 26050a07fd2Sopenharmony_ci{ 26150a07fd2Sopenharmony_ci DHLOGI("Pause."); 26250a07fd2Sopenharmony_ci CHECK_NULL_RETURN(speakerTrans_, ERR_DH_AUDIO_NULLPTR); 26350a07fd2Sopenharmony_ci int32_t ret = speakerTrans_->Pause(); 26450a07fd2Sopenharmony_ci if (ret != DH_SUCCESS) { 26550a07fd2Sopenharmony_ci DHLOGE("Pause speaker trans failed, ret: %{public}d.", ret); 26650a07fd2Sopenharmony_ci return ret; 26750a07fd2Sopenharmony_ci } 26850a07fd2Sopenharmony_ci DHLOGD("Pause success."); 26950a07fd2Sopenharmony_ci return DH_SUCCESS; 27050a07fd2Sopenharmony_ci} 27150a07fd2Sopenharmony_ci 27250a07fd2Sopenharmony_ciint32_t DSpeakerDev::Restart() 27350a07fd2Sopenharmony_ci{ 27450a07fd2Sopenharmony_ci DHLOGI("Restart."); 27550a07fd2Sopenharmony_ci CHECK_NULL_RETURN(speakerTrans_, ERR_DH_AUDIO_NULLPTR); 27650a07fd2Sopenharmony_ci int32_t ret = speakerTrans_->Restart(param_, param_); 27750a07fd2Sopenharmony_ci if (ret != DH_SUCCESS) { 27850a07fd2Sopenharmony_ci DHLOGE("Restart speaker trans failed, ret: %{public}d.", ret); 27950a07fd2Sopenharmony_ci return ret; 28050a07fd2Sopenharmony_ci } 28150a07fd2Sopenharmony_ci DHLOGD("Restart success."); 28250a07fd2Sopenharmony_ci return DH_SUCCESS; 28350a07fd2Sopenharmony_ci} 28450a07fd2Sopenharmony_ci 28550a07fd2Sopenharmony_cibool DSpeakerDev::IsOpened() 28650a07fd2Sopenharmony_ci{ 28750a07fd2Sopenharmony_ci return isOpened_.load(); 28850a07fd2Sopenharmony_ci} 28950a07fd2Sopenharmony_ci 29050a07fd2Sopenharmony_ciint32_t DSpeakerDev::ReadStreamData(const int32_t streamId, std::shared_ptr<AudioData> &data) 29150a07fd2Sopenharmony_ci{ 29250a07fd2Sopenharmony_ci (void)streamId; 29350a07fd2Sopenharmony_ci (void)data; 29450a07fd2Sopenharmony_ci DHLOGD("Dspeaker dev not support read stream data."); 29550a07fd2Sopenharmony_ci return DH_SUCCESS; 29650a07fd2Sopenharmony_ci} 29750a07fd2Sopenharmony_ci 29850a07fd2Sopenharmony_ciint32_t DSpeakerDev::WriteStreamData(const int32_t streamId, std::shared_ptr<AudioData> &data) 29950a07fd2Sopenharmony_ci{ 30050a07fd2Sopenharmony_ci DHLOGD("Write stream data, streamId:%{public}d", streamId); 30150a07fd2Sopenharmony_ci int64_t startTime = GetNowTimeUs(); 30250a07fd2Sopenharmony_ci CHECK_NULL_RETURN(speakerTrans_, ERR_DH_AUDIO_NULLPTR); 30350a07fd2Sopenharmony_ci CHECK_NULL_RETURN(data, ERR_DH_AUDIO_NULLPTR); 30450a07fd2Sopenharmony_ci DumpFileUtil::WriteDumpFile(dumpFileCommn_, static_cast<void *>(data->Data()), data->Size()); 30550a07fd2Sopenharmony_ci int32_t ret = speakerTrans_->FeedAudioData(data); 30650a07fd2Sopenharmony_ci if (ret != DH_SUCCESS) { 30750a07fd2Sopenharmony_ci DHLOGE("Write stream data failed, ret: %{public}d.", ret); 30850a07fd2Sopenharmony_ci return ret; 30950a07fd2Sopenharmony_ci } 31050a07fd2Sopenharmony_ci int64_t endTime = GetNowTimeUs(); 31150a07fd2Sopenharmony_ci if (IsOutDurationRange(startTime, endTime, lastwriteStartTime_)) { 31250a07fd2Sopenharmony_ci DHLOGE("This time write data spend: %{public}" PRId64" us, The interval of write data this time and " 31350a07fd2Sopenharmony_ci "the last time: %{public}" PRId64" us", endTime - startTime, startTime - lastwriteStartTime_); 31450a07fd2Sopenharmony_ci } 31550a07fd2Sopenharmony_ci lastwriteStartTime_ = startTime; 31650a07fd2Sopenharmony_ci return DH_SUCCESS; 31750a07fd2Sopenharmony_ci} 31850a07fd2Sopenharmony_ci 31950a07fd2Sopenharmony_ciint32_t DSpeakerDev::ReadMmapPosition(const int32_t streamId, 32050a07fd2Sopenharmony_ci uint64_t &frames, CurrentTimeHDF &time) 32150a07fd2Sopenharmony_ci{ 32250a07fd2Sopenharmony_ci DHLOGD("Read mmap position. frames: %{public}" PRIu64", tvsec: %{public}" PRId64", tvNSec:%{public}" PRId64, 32350a07fd2Sopenharmony_ci readNum_, readTvSec_, readTvNSec_); 32450a07fd2Sopenharmony_ci frames = readNum_; 32550a07fd2Sopenharmony_ci time.tvSec = readTvSec_; 32650a07fd2Sopenharmony_ci time.tvNSec = readTvNSec_; 32750a07fd2Sopenharmony_ci return DH_SUCCESS; 32850a07fd2Sopenharmony_ci} 32950a07fd2Sopenharmony_ci 33050a07fd2Sopenharmony_ciint32_t DSpeakerDev::RefreshAshmemInfo(const int32_t streamId, 33150a07fd2Sopenharmony_ci int32_t fd, int32_t ashmemLength, int32_t lengthPerTrans) 33250a07fd2Sopenharmony_ci{ 33350a07fd2Sopenharmony_ci DHLOGD("RefreshAshmemInfo: fd:%{public}d, ashmemLength: %{public}d, lengthPerTrans: %{public}d", 33450a07fd2Sopenharmony_ci fd, ashmemLength, lengthPerTrans); 33550a07fd2Sopenharmony_ci if (param_.renderOpts.renderFlags == MMAP_MODE) { 33650a07fd2Sopenharmony_ci DHLOGI("DSpeaker dev low-latency mode"); 33750a07fd2Sopenharmony_ci if (ashmem_ != nullptr) { 33850a07fd2Sopenharmony_ci return DH_SUCCESS; 33950a07fd2Sopenharmony_ci } 34050a07fd2Sopenharmony_ci if (ashmemLength < ASHMEM_MAX_LEN) { 34150a07fd2Sopenharmony_ci ashmem_ = sptr<Ashmem>(new Ashmem(fd, ashmemLength)); 34250a07fd2Sopenharmony_ci ashmemLength_ = ashmemLength; 34350a07fd2Sopenharmony_ci lengthPerTrans_ = lengthPerTrans; 34450a07fd2Sopenharmony_ci DHLOGI("Create ashmem success. fd:%{public}d, ashmem length: %{public}d, lengthPreTrans: %{public}d", 34550a07fd2Sopenharmony_ci fd, ashmemLength_, lengthPerTrans_); 34650a07fd2Sopenharmony_ci bool mapRet = ashmem_->MapReadAndWriteAshmem(); 34750a07fd2Sopenharmony_ci if (!mapRet) { 34850a07fd2Sopenharmony_ci DHLOGE("Mmap ashmem failed."); 34950a07fd2Sopenharmony_ci return ERR_DH_AUDIO_NULLPTR; 35050a07fd2Sopenharmony_ci } 35150a07fd2Sopenharmony_ci } 35250a07fd2Sopenharmony_ci } 35350a07fd2Sopenharmony_ci return DH_SUCCESS; 35450a07fd2Sopenharmony_ci} 35550a07fd2Sopenharmony_ci 35650a07fd2Sopenharmony_ciint32_t DSpeakerDev::MmapStart() 35750a07fd2Sopenharmony_ci{ 35850a07fd2Sopenharmony_ci CHECK_NULL_RETURN(ashmem_, ERR_DH_AUDIO_NULLPTR); 35950a07fd2Sopenharmony_ci isEnqueueRunning_.store(true); 36050a07fd2Sopenharmony_ci enqueueDataThread_ = std::thread([this]() { this->EnqueueThread(); }); 36150a07fd2Sopenharmony_ci if (pthread_setname_np(enqueueDataThread_.native_handle(), ENQUEUE_THREAD) != DH_SUCCESS) { 36250a07fd2Sopenharmony_ci DHLOGE("Enqueue data thread setname failed."); 36350a07fd2Sopenharmony_ci } 36450a07fd2Sopenharmony_ci return DH_SUCCESS; 36550a07fd2Sopenharmony_ci} 36650a07fd2Sopenharmony_ci 36750a07fd2Sopenharmony_civoid DSpeakerDev::EnqueueThread() 36850a07fd2Sopenharmony_ci{ 36950a07fd2Sopenharmony_ci readIndex_ = 0; 37050a07fd2Sopenharmony_ci readNum_ = 0; 37150a07fd2Sopenharmony_ci frameIndex_ = 0; 37250a07fd2Sopenharmony_ci int64_t timeIntervalns = static_cast<int64_t>(paramHDF_.period * AUDIO_NS_PER_SECOND / AUDIO_MS_PER_SECOND); 37350a07fd2Sopenharmony_ci DHLOGI("Enqueue thread start, lengthPerRead length: %{public}d, interval: %{pubic}d.", lengthPerTrans_, 37450a07fd2Sopenharmony_ci paramHDF_.period); 37550a07fd2Sopenharmony_ci while (ashmem_ != nullptr && isEnqueueRunning_.load()) { 37650a07fd2Sopenharmony_ci int64_t timeOffset = UpdateTimeOffset(frameIndex_, timeIntervalns, startTime_); 37750a07fd2Sopenharmony_ci DHLOGD("Read frameIndex: %{public}" PRId64", timeOffset: %{public}" PRId64, frameIndex_, timeOffset); 37850a07fd2Sopenharmony_ci auto readData = ashmem_->ReadFromAshmem(lengthPerTrans_, readIndex_); 37950a07fd2Sopenharmony_ci DHLOGD("Read from ashmem success! read index: %{public}d, readLength: %{public}d.", 38050a07fd2Sopenharmony_ci readIndex_, lengthPerTrans_); 38150a07fd2Sopenharmony_ci std::shared_ptr<AudioData> audioData = std::make_shared<AudioData>(lengthPerTrans_); 38250a07fd2Sopenharmony_ci if (readData != nullptr) { 38350a07fd2Sopenharmony_ci const uint8_t *readAudioData = reinterpret_cast<const uint8_t *>(readData); 38450a07fd2Sopenharmony_ci if (memcpy_s(audioData->Data(), audioData->Capacity(), readAudioData, param_.comParam.frameSize) != EOK) { 38550a07fd2Sopenharmony_ci DHLOGE("Copy audio data failed."); 38650a07fd2Sopenharmony_ci } 38750a07fd2Sopenharmony_ci } 38850a07fd2Sopenharmony_ci CHECK_NULL_VOID(speakerTrans_); 38950a07fd2Sopenharmony_ci DumpFileUtil::WriteDumpFile(dumpFileFast_, static_cast<void *>(audioData->Data()), audioData->Size()); 39050a07fd2Sopenharmony_ci int32_t ret = speakerTrans_->FeedAudioData(audioData); 39150a07fd2Sopenharmony_ci if (ret != DH_SUCCESS) { 39250a07fd2Sopenharmony_ci DHLOGE("Speaker enqueue thread, write stream data failed, ret: %{public}d.", ret); 39350a07fd2Sopenharmony_ci } 39450a07fd2Sopenharmony_ci readIndex_ += lengthPerTrans_; 39550a07fd2Sopenharmony_ci if (readIndex_ >= ashmemLength_) { 39650a07fd2Sopenharmony_ci readIndex_ = 0; 39750a07fd2Sopenharmony_ci } 39850a07fd2Sopenharmony_ci readNum_ += static_cast<uint64_t>(CalculateSampleNum(param_.comParam.sampleRate, paramHDF_.period)); 39950a07fd2Sopenharmony_ci GetCurrentTime(readTvSec_, readTvNSec_); 40050a07fd2Sopenharmony_ci frameIndex_++; 40150a07fd2Sopenharmony_ci AbsoluteSleep(startTime_ + frameIndex_ * timeIntervalns - timeOffset); 40250a07fd2Sopenharmony_ci } 40350a07fd2Sopenharmony_ci} 40450a07fd2Sopenharmony_ci 40550a07fd2Sopenharmony_ciint32_t DSpeakerDev::MmapStop() 40650a07fd2Sopenharmony_ci{ 40750a07fd2Sopenharmony_ci isEnqueueRunning_.store(false); 40850a07fd2Sopenharmony_ci if (enqueueDataThread_.joinable()) { 40950a07fd2Sopenharmony_ci enqueueDataThread_.join(); 41050a07fd2Sopenharmony_ci } 41150a07fd2Sopenharmony_ci DHLOGI("Spk mmap stop end."); 41250a07fd2Sopenharmony_ci return DH_SUCCESS; 41350a07fd2Sopenharmony_ci} 41450a07fd2Sopenharmony_ci 41550a07fd2Sopenharmony_ciAudioParam DSpeakerDev::GetAudioParam() const 41650a07fd2Sopenharmony_ci{ 41750a07fd2Sopenharmony_ci return param_; 41850a07fd2Sopenharmony_ci} 41950a07fd2Sopenharmony_ci 42050a07fd2Sopenharmony_ciint32_t DSpeakerDev::SendMessage(uint32_t type, std::string content, std::string dstDevId) 42150a07fd2Sopenharmony_ci{ 42250a07fd2Sopenharmony_ci DHLOGD("Send message to remote."); 42350a07fd2Sopenharmony_ci if (type != static_cast<uint32_t>(OPEN_SPEAKER) && type != static_cast<uint32_t>(CLOSE_SPEAKER) && 42450a07fd2Sopenharmony_ci type != static_cast<uint32_t>(CHANGE_PLAY_STATUS) && type != static_cast<uint32_t>(VOLUME_SET) && 42550a07fd2Sopenharmony_ci type != static_cast<uint32_t>(VOLUME_MUTE_SET)) { 42650a07fd2Sopenharmony_ci DHLOGE("Send message to remote. not OPEN_SPK or CLOSE_SPK. type: %{public}u", type); 42750a07fd2Sopenharmony_ci return ERR_DH_AUDIO_NULLPTR; 42850a07fd2Sopenharmony_ci } 42950a07fd2Sopenharmony_ci CHECK_NULL_RETURN(speakerTrans_, ERR_DH_AUDIO_NULLPTR); 43050a07fd2Sopenharmony_ci speakerTrans_->SendMessage(type, content, dstDevId); 43150a07fd2Sopenharmony_ci return DH_SUCCESS; 43250a07fd2Sopenharmony_ci} 43350a07fd2Sopenharmony_ci 43450a07fd2Sopenharmony_ciint32_t DSpeakerDev::NotifyHdfAudioEvent(const AudioEvent &event, const int32_t portId) 43550a07fd2Sopenharmony_ci{ 43650a07fd2Sopenharmony_ci int32_t ret = DAudioHdiHandler::GetInstance().NotifyEvent(devId_, portId, streamId_, event); 43750a07fd2Sopenharmony_ci if (ret != DH_SUCCESS) { 43850a07fd2Sopenharmony_ci DHLOGE("Notify event: %{public}d, result: %{public}s, streamId: %{public}d.", 43950a07fd2Sopenharmony_ci event.type, event.content.c_str(), streamId_); 44050a07fd2Sopenharmony_ci } 44150a07fd2Sopenharmony_ci return DH_SUCCESS; 44250a07fd2Sopenharmony_ci} 44350a07fd2Sopenharmony_ci 44450a07fd2Sopenharmony_ciint32_t DSpeakerDev::OnStateChange(const AudioEventType type) 44550a07fd2Sopenharmony_ci{ 44650a07fd2Sopenharmony_ci DHLOGI("On speaker device state change, type: %{public}d.", type); 44750a07fd2Sopenharmony_ci AudioEvent event; 44850a07fd2Sopenharmony_ci switch (type) { 44950a07fd2Sopenharmony_ci case AudioEventType::DATA_OPENED: 45050a07fd2Sopenharmony_ci isTransReady_.store(true); 45150a07fd2Sopenharmony_ci channelWaitCond_.notify_all(); 45250a07fd2Sopenharmony_ci event.type = AudioEventType::SPEAKER_OPENED; 45350a07fd2Sopenharmony_ci break; 45450a07fd2Sopenharmony_ci case AudioEventType::DATA_CLOSED: 45550a07fd2Sopenharmony_ci isOpened_.store(false); 45650a07fd2Sopenharmony_ci isTransReady_.store(false); 45750a07fd2Sopenharmony_ci event.type = AudioEventType::SPEAKER_CLOSED; 45850a07fd2Sopenharmony_ci break; 45950a07fd2Sopenharmony_ci default: 46050a07fd2Sopenharmony_ci break; 46150a07fd2Sopenharmony_ci } 46250a07fd2Sopenharmony_ci event.content = GetCJsonString(KEY_DH_ID, std::to_string(dhId_).c_str()); 46350a07fd2Sopenharmony_ci std::shared_ptr<IAudioEventCallback> cbObj = audioEventCallback_.lock(); 46450a07fd2Sopenharmony_ci CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR); 46550a07fd2Sopenharmony_ci cbObj->NotifyEvent(event); 46650a07fd2Sopenharmony_ci return DH_SUCCESS; 46750a07fd2Sopenharmony_ci} 46850a07fd2Sopenharmony_ci 46950a07fd2Sopenharmony_ciint32_t DSpeakerDev::OnDecodeTransDataDone(const std::shared_ptr<AudioData> &audioData) 47050a07fd2Sopenharmony_ci{ 47150a07fd2Sopenharmony_ci (void) audioData; 47250a07fd2Sopenharmony_ci return DH_SUCCESS; 47350a07fd2Sopenharmony_ci} 47450a07fd2Sopenharmony_ci} // DistributedHardware 47550a07fd2Sopenharmony_ci} // OHOS 476