From 492104d3f7930e3ee6393e3b575f7baeb5565f14 Mon Sep 17 00:00:00 2001 From: byndyx Date: Mon, 17 Feb 2025 19:35:38 +0800 Subject: [PATCH] add ringbuffer Signed-off-by: byndyx --- audiohandler/include/daudio_handler.h | 3 + audiohandler/src/daudio_handler.cpp | 82 ++++---- common/include/daudio_constants.h | 15 +- common/include/daudio_ringbuffer.h | 53 +++++ common/src/daudio_ringbuffer.cpp | 187 ++++++++++++++++++ common/src/daudio_util.cpp | 1 + .../audioclient/micclient/src/dmic_client.cpp | 4 +- .../spkclient/src/dspeaker_client.cpp | 8 +- .../managersink/src/daudio_sink_dev.cpp | 6 + .../managersource/include/dmic_dev.h | 12 +- .../managersource/include/dspeaker_dev.h | 1 + .../managersource/src/daudio_source_dev.cpp | 2 +- .../managersource/src/dmic_dev.cpp | 82 +++++++- .../managersource/src/dspeaker_dev.cpp | 11 ++ .../sourcedevice/src/dmic_dev_test.cpp | 2 - .../src/av_receiver_engine_transport.cpp | 2 +- services/common/BUILD.gn | 1 + services/common/audioparam/audio_param.h | 3 +- .../test_example/distributedaudiotest.cpp | 2 +- 19 files changed, 414 insertions(+), 63 deletions(-) create mode 100644 common/include/daudio_ringbuffer.h create mode 100644 common/src/daudio_ringbuffer.cpp diff --git a/audiohandler/include/daudio_handler.h b/audiohandler/include/daudio_handler.h index fb9b6dff..a7933d0d 100644 --- a/audiohandler/include/daudio_handler.h +++ b/audiohandler/include/daudio_handler.h @@ -52,10 +52,13 @@ private: ~DAudioHandler(); int32_t QueryAudioInfo(); bool AddItemsToObject(DHItem &dhItem, cJSON *infoJson, const int32_t &dhId); + bool AddParamsToJson(DHItem &dhItem, cJSON* infoJson, const std::string &subtype, const AudioInfo &infos); std::vector RealQuery(const std::string &dataType); private: AudioInfo spkInfos_; AudioInfo micInfos_; + std::vector supportedStream_; + std::vector codec_; std::shared_ptr listener_ = nullptr; }; diff --git a/audiohandler/src/daudio_handler.cpp b/audiohandler/src/daudio_handler.cpp index 45fac2bb..c1f270b2 100644 --- a/audiohandler/src/daudio_handler.cpp +++ b/audiohandler/src/daudio_handler.cpp @@ -53,50 +53,47 @@ bool DAudioHandler::AddItemsToObject(DHItem &dhItem, cJSON* infoJson, const int3 DHLOGD("Get dhId and then add other items into cjson object"); int32_t deviceType = GetDevTypeByDHId(dhId); if (deviceType == AUDIO_DEVICE_TYPE_MIC) { - dhItem.subtype = "mic"; - cJSON *sampleArray = cJSON_CreateArray(); - CHECK_NULL_RETURN(sampleArray, false); - cJSON_AddItemToObject(infoJson, "SampleRates", sampleArray); - for (const auto &value : micInfos_.sampleRates) { - cJSON_AddItemToArray(sampleArray, cJSON_CreateNumber(static_cast(value))); - } - - cJSON *channelArray = cJSON_CreateArray(); - CHECK_NULL_RETURN(channelArray, false); - cJSON_AddItemToObject(infoJson, "ChannelMasks", channelArray); - for (const auto &value : micInfos_.channels) { - cJSON_AddItemToArray(channelArray, cJSON_CreateNumber(static_cast(value))); - } - - cJSON *formatsArray = cJSON_CreateArray(); - CHECK_NULL_RETURN(formatsArray, false); - cJSON_AddItemToObject(infoJson, "Formats", formatsArray); - for (const auto &value : micInfos_.formats) { - cJSON_AddItemToArray(formatsArray, cJSON_CreateNumber(static_cast(value))); - } + return AddParamsToJson(dhItem, infoJson, MIC, micInfos_); } else if (deviceType == AUDIO_DEVICE_TYPE_SPEAKER) { - dhItem.subtype = "speaker"; - cJSON *sampleArray = cJSON_CreateArray(); - CHECK_NULL_RETURN(sampleArray, false); - cJSON_AddItemToObject(infoJson, "SampleRates", sampleArray); - for (const auto &value : spkInfos_.sampleRates) { - cJSON_AddItemToArray(sampleArray, cJSON_CreateNumber(static_cast(value))); - } - - cJSON *channelArray = cJSON_CreateArray(); - CHECK_NULL_RETURN(channelArray, false); - cJSON_AddItemToObject(infoJson, "ChannelMasks", channelArray); - for (const auto &value : spkInfos_.channels) { - cJSON_AddItemToArray(channelArray, cJSON_CreateNumber(static_cast(value))); - } + return AddParamsToJson(dhItem, infoJson, SPEAKER, spkInfos_); + } + return true; +} - cJSON *formatsArray = cJSON_CreateArray(); - CHECK_NULL_RETURN(formatsArray, false); - cJSON_AddItemToObject(infoJson, "Formats", formatsArray); - for (const auto &value : spkInfos_.formats) { - cJSON_AddItemToArray(formatsArray, cJSON_CreateNumber(static_cast(value))); - } +bool DAudioHandler::AddParamsToJson(DHItem &dhItem, cJSON* infoJson, const std::string &subtype, const AudioInfo &infos) +{ + dhItem.subtype = subtype; + cJSON *sampleArray = cJSON_CreateArray(); + CHECK_NULL_RETURN(sampleArray, false); + cJSON_AddItemToObject(infoJson, SAMPLERATES, sampleArray); + for (const auto &value : infos.sampleRates) { + cJSON_AddItemToArray(sampleArray, cJSON_CreateNumber(static_cast(value))); + } + cJSON *channelArray = cJSON_CreateArray(); + CHECK_NULL_RETURN(channelArray, false); + cJSON_AddItemToObject(infoJson, CHANNELMASKS, channelArray); + for (const auto &value : infos.channels) { + cJSON_AddItemToArray(channelArray, cJSON_CreateNumber(static_cast(value))); + } + cJSON *formatsArray = cJSON_CreateArray(); + CHECK_NULL_RETURN(formatsArray, false); + cJSON_AddItemToObject(infoJson, FORMATS, formatsArray); + for (const auto &value : infos.formats) { + cJSON_AddItemToArray(formatsArray, cJSON_CreateNumber(static_cast(value))); + } + cJSON *usageArray = cJSON_CreateArray(); + CHECK_NULL_RETURN(usageArray, false); + cJSON_AddItemToObject(infoJson, SUPPORTEDSTREAM, usageArray); + for (const auto &value : supportedStream_) { + cJSON_AddItemToArray(usageArray, cJSON_CreateString(value.c_str())); + } + cJSON *codecArray = cJSON_CreateArray(); + CHECK_NULL_RETURN(codecArray, false); + cJSON_AddItemToObject(infoJson, CODEC, codecArray); + for (const auto &value : codec_) { + cJSON_AddItemToArray(codecArray, cJSON_CreateString(value.c_str())); } + cJSON_AddStringToObject(infoJson, PROTOCOLVER, VERSION_TWO); return true; } @@ -184,6 +181,9 @@ int32_t DAudioHandler::QueryAudioInfo() spkInfos_.sampleRates = OHOS::AudioStandard::AudioRenderer::GetSupportedSamplingRates(); spkInfos_.formats = OHOS::AudioStandard::AudioRenderer::GetSupportedFormats(); spkInfos_.channels = OHOS::AudioStandard::AudioRenderer::GetSupportedChannels(); + supportedStream_.push_back(MUSIC); + codec_.push_back(AAC); + codec_.push_back(PCM); return DH_SUCCESS; } diff --git a/common/include/daudio_constants.h b/common/include/daudio_constants.h index 1405ddfa..4b198e66 100644 --- a/common/include/daudio_constants.h +++ b/common/include/daudio_constants.h @@ -148,7 +148,20 @@ constexpr const char *VOLUME_GROUP_ID = "VOLUME_GROUP_ID"; constexpr const char *VOLUME_EVENT_TYPE = "EVENT_TYPE"; constexpr const char *KEY_DATATYPE = "dataType"; constexpr const char *INTERRUPT_GROUP_ID = "INTERRUPT_GROUP_ID"; - +constexpr const char *KEY_CODEC_TYPE = "codecType"; +constexpr const char *CODEC = "Codec"; +constexpr const char *PROTOCOLVER = "ProtocolVer"; +constexpr const char *VERSION_TWO = "2.0"; +constexpr const char *SUPPORTEDSTREAM = "SupportedStream"; +constexpr const char *SAMPLERATES = "SampleRates"; +constexpr const char *CHANNELMASKS = "ChannelMasks"; +constexpr const char *FORMATS = "Formats"; +const std::string MUSIC = "Music"; +const std::string PCM = "PCM"; +const std::string AAC = "AAC"; +const std::string MIC = "mic"; +const std::string SPEAKER = "speaker"; +const std::string SUB_PROTOCOLVER = "ProtocolVer"; const std::string DUMP_FILE_PATH = "/data/data/daudio"; const std::string AUDIO_PERMISSION_NAME = "ohos.permission.ENABLE_DISTRIBUTED_HARDWARE"; const std::string SESSIONNAME_SPK_SINK = "ohos.dhardware.daudio.dspeaker_receiver.avtrans.control"; diff --git a/common/include/daudio_ringbuffer.h b/common/include/daudio_ringbuffer.h new file mode 100644 index 00000000..f9e0608c --- /dev/null +++ b/common/include/daudio_ringbuffer.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DAUDIO_RING_BUFFER_H +#define OHOS_DAUDIO_RING_BUFFER_H + +#include +#include + +#include "daudio_constants.h" +#include "daudio_errorcode.h" +#include "daudio_log.h" + +namespace OHOS { +namespace DistributedHardware { +class DaudioRingBuffer { +public: + DaudioRingBuffer() = default; + ~DaudioRingBuffer(); + int32_t RingBufferInit(uint8_t *&data); + int32_t RingBufferInsert(uint8_t *data, int32_t len); + int32_t RingBufferGetData(uint8_t *data, int32_t len); + bool CanBufferReadLen(int32_t readLen); + +private: + bool GetFullState(); + bool GetEmptyState(); + int32_t RingBufferInsertOnce(uint8_t *data, int32_t len); + int32_t RingBufferGetDataOnce(uint8_t *data, int32_t len); + +private: + const int32_t RINGBUFFERLEN = 40960; + const int32_t DAUDIO_DATA_SIZE = 4096; + uint8_t *array_ = nullptr; + int32_t writePos_ = 0; + int32_t readPos_ = 0; + int32_t tag_ = 0; +}; +} // namespace DistributedHardware +} // namespace OHOS +#endif // OHOS_DAUDIO_RING_BUFFER_H \ No newline at end of file diff --git a/common/src/daudio_ringbuffer.cpp b/common/src/daudio_ringbuffer.cpp new file mode 100644 index 00000000..8dba78bb --- /dev/null +++ b/common/src/daudio_ringbuffer.cpp @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "daudio_ringbuffer.h" + +#include +#include + +#undef DH_LOG_TAG +#define DH_LOG_TAG "DaudioRingBuffer" + +namespace OHOS { +namespace DistributedHardware { +DaudioRingBuffer::~DaudioRingBuffer() +{ + if (array_ != nullptr) { + delete[] array_; + array_ = nullptr; + } +} + +int32_t DaudioRingBuffer::RingBufferInit(uint8_t *&audioData) +{ + array_ = new (std::nothrow) uint8_t[RINGBUFFERLEN] {0}; + CHECK_AND_RETURN_RET_LOG(array_ == nullptr, ERR_DH_AUDIO_FAILED, "Buffer is malloced failed."); + writePos_ = 0; + readPos_ = 0; + tag_ = 0; + audioData = new (std::nothrow) uint8_t[DAUDIO_DATA_SIZE] {0}; + CHECK_AND_RETURN_RET_LOG(audioData == nullptr, ERR_DH_AUDIO_FAILED, "Audio data is malloced failed."); + return DH_SUCCESS; +} + +bool DaudioRingBuffer::GetFullState() +{ + if ((writePos_ == readPos_) && tag_ == 1) { + return true; + } + return false; +} + +bool DaudioRingBuffer::GetEmptyState() +{ + if ((writePos_ == readPos_) && tag_ == 0) { + return true; + } + return false; +} + +int32_t DaudioRingBuffer::RingBufferInsert(uint8_t *data, int32_t len) +{ + int32_t avaliable = RINGBUFFERLEN - writePos_; + if (avaliable < len) { + int32_t ret = RingBufferInsertOnce(data, avaliable); + CHECK_AND_RETURN_RET_LOG(ret != DH_SUCCESS, ERR_DH_AUDIO_FAILED, + "write first once error. errorcode: %{public}d", ret); + ret = RingBufferInsertOnce(data + avaliable, len - avaliable); + CHECK_AND_RETURN_RET_LOG(ret != DH_SUCCESS, ERR_DH_AUDIO_FAILED, + "write next once error. errorcode: %{public}d", ret); + } else { + int32_t ret = RingBufferInsertOnce(data, len); + CHECK_AND_RETURN_RET_LOG(ret != DH_SUCCESS, ERR_DH_AUDIO_FAILED, + "write only once error. errorcode: %{public}d", ret); + } + return DH_SUCCESS; +} + +int32_t DaudioRingBuffer::RingBufferInsertOnce(uint8_t *data, int32_t len) +{ + CHECK_AND_RETURN_RET_LOG(array_ == nullptr, ERR_DH_AUDIO_NULLPTR, "buffer is nullptr."); + CHECK_AND_RETURN_RET_LOG(data == nullptr, ERR_DH_AUDIO_NULLPTR, "data is nullptr."); + if (len < 0) { + DHLOGE("len < 0 error."); + return ERR_DH_AUDIO_NULLPTR; + } + if (GetFullState()) { + DHLOGE("buffer is full."); + return ERR_DH_AUDIO_FAILED; + } + int32_t avaliable = RINGBUFFERLEN - writePos_; + if (avaliable < len) { + DHLOGE("buffer is not avaliable. now avaliable: %{public}d.", avaliable); + return ERR_DH_AUDIO_FAILED; + } + if (writePos_ >= RINGBUFFERLEN || len >= RINGBUFFERLEN) { + DHLOGE("writePos_ or len is out of range."); + return ERR_DH_AUDIO_FAILED; + } + int32_t ret = memcpy_s(array_ + writePos_, len, data, len); + CHECK_AND_RETURN_RET_LOG(ret!= EOK, ERR_DH_AUDIO_FAILED, "memcpy_s error."); + writePos_ = (writePos_ + len) % RINGBUFFERLEN; + if (writePos_ == readPos_) { + tag_ = 1; + } + return DH_SUCCESS; +} + +int32_t DaudioRingBuffer::RingBufferGetData(uint8_t *data, int32_t len) +{ + CHECK_AND_RETURN_RET_LOG(array_ == nullptr, ERR_DH_AUDIO_NULLPTR, "buffer is nullptr."); + CHECK_AND_RETURN_RET_LOG(data == nullptr, ERR_DH_AUDIO_NULLPTR, "data is nullptr."); + int32_t avaliable = writePos_ - readPos_; + if (avaliable >= len) { + int32_t ret = RingBufferGetDataOnce(data, len); + CHECK_AND_RETURN_RET_LOG(ret!= DH_SUCCESS, ERR_DH_AUDIO_FAILED, "read only once error"); + } else if (avaliable > 0) { + DHLOGI("buffer is not enough. avaliable: %{public}d. len: %{public}d.", avaliable, len); + return ERR_DH_AUDIO_FAILED; + } else { + int32_t firstReadLen = RINGBUFFERLEN - readPos_; + if (firstReadLen >= len) { + int32_t ret = RingBufferGetDataOnce(data, len); + CHECK_AND_RETURN_RET_LOG(ret!= DH_SUCCESS, ERR_DH_AUDIO_FAILED, "read only once error"); + } else { + int32_t ret = RingBufferGetDataOnce(data, firstReadLen); + CHECK_AND_RETURN_RET_LOG(ret!= DH_SUCCESS, ERR_DH_AUDIO_FAILED, "read first once error"); + ret = RingBufferGetDataOnce(data + firstReadLen, len - firstReadLen); + CHECK_AND_RETURN_RET_LOG(ret!= DH_SUCCESS, ERR_DH_AUDIO_FAILED, "read next once error"); + } + } + return DH_SUCCESS; +} + +int32_t DaudioRingBuffer::RingBufferGetDataOnce(uint8_t *data, int32_t len) +{ + CHECK_AND_RETURN_RET_LOG(array_ == nullptr, ERR_DH_AUDIO_NULLPTR, "buffer is nullptr."); + CHECK_AND_RETURN_RET_LOG(data == nullptr, ERR_DH_AUDIO_NULLPTR, "data is nullptr."); + if (len < 0) { + DHLOGE("len < 0 error."); + return ERR_DH_AUDIO_NULLPTR; + } + int32_t avaliable = writePos_ - readPos_; + if (GetEmptyState()) { + DHLOGE("buffer is empty."); + return ERR_DH_AUDIO_FAILED; + } + if ((avaliable < len && avaliable > 0) || + (avaliable < 0 && RINGBUFFERLEN - readPos_ + writePos_ < len)) { + DHLOGE("buffer is not enough."); + return ERR_DH_AUDIO_FAILED; + } + if (readPos_ >= RINGBUFFERLEN || len >= RINGBUFFERLEN) { + DHLOGE("readPos_ or len is out of range."); + return ERR_DH_AUDIO_FAILED; + } + int32_t ret = memcpy_s(data, len, array_ + readPos_, len); + CHECK_AND_RETURN_RET_LOG(ret != EOK, ERR_DH_AUDIO_FAILED, "memcpy_s error."); + readPos_ = (readPos_ + len) % RINGBUFFERLEN; + if (readPos_ == writePos_) { + tag_ = 0; + } + return DH_SUCCESS; +} + +bool DaudioRingBuffer::CanBufferReadLen(int32_t readLen) +{ + if (GetEmptyState()) { + DHLOGD("buffer is empty."); + return false; + } + int32_t aval = writePos_ - readPos_; + if ((aval < readLen) && (aval > 0)) { + DHLOGD("remain : %{public}d, but not enough readLen: %{public}d", aval, readLen); + return false; + } else if (aval <= 0) { + int32_t avalRead = RINGBUFFERLEN - readPos_ + writePos_; + if (avalRead < readLen) { + DHLOGD("avalRead : %{public}d, but not enough readLen: %{public}d", avalRead, readLen); + return false; + } + } + return true; +} +} // namespace DistributedHardware +} // namespace OHOS \ No newline at end of file diff --git a/common/src/daudio_util.cpp b/common/src/daudio_util.cpp index 2ea362b2..0b2f2441 100644 --- a/common/src/daudio_util.cpp +++ b/common/src/daudio_util.cpp @@ -66,6 +66,7 @@ std::map typeCheckMap = { std::map::value_type(KEY_CONTENT_TYPE, &DistributedHardware::IsInt32), std::map::value_type(KEY_STREAM_USAGE, &DistributedHardware::IsInt32), std::map::value_type(KEY_DATATYPE, &DistributedHardware::IsString), + std::map::value_type(KEY_CODEC_TYPE, &DistributedHardware::IsInt32), }; std::map eventNameMap = { diff --git a/services/audioclient/micclient/src/dmic_client.cpp b/services/audioclient/micclient/src/dmic_client.cpp index 25630a79..cbed629c 100644 --- a/services/audioclient/micclient/src/dmic_client.cpp +++ b/services/audioclient/micclient/src/dmic_client.cpp @@ -294,7 +294,7 @@ void DMicClient::AudioFwkCaptureData() } int64_t endTime = GetNowTimeUs(); if (IsOutDurationRange(startTime, endTime, lastCaptureStartTime_)) { - DHLOGE("This time capture spend: %{public}" PRId64" us, The interval of capture this time and " + DHLOGD("This time capture spend: %{public}" PRId64" us, The interval of capture this time and " "the last time: %{public}" PRId64" us", endTime - startTime, startTime - lastCaptureStartTime_); } lastCaptureStartTime_ = startTime; @@ -315,7 +315,7 @@ void DMicClient::AudioFwkCaptureData() } int64_t endTransTime = GetNowTimeUs(); if (IsOutDurationRange(startTransTime, endTransTime, lastTransStartTime_)) { - DHLOGE("This time send data spend: %{public}" PRId64" us, The interval of send data this time and " + DHLOGD("This time send data spend: %{public}" PRId64" us, The interval of send data this time and " "the last time: %{public}" PRId64" us", endTransTime - startTransTime, startTransTime - lastTransStartTime_); } diff --git a/services/audioclient/spkclient/src/dspeaker_client.cpp b/services/audioclient/spkclient/src/dspeaker_client.cpp index b3685a70..f3ce13fb 100644 --- a/services/audioclient/spkclient/src/dspeaker_client.cpp +++ b/services/audioclient/spkclient/src/dspeaker_client.cpp @@ -54,7 +54,7 @@ void DSpeakerClient::OnEngineTransMessage(const std::shared_ptr void DSpeakerClient::OnEngineTransDataAvailable(const std::shared_ptr &audioData) { - DHLOGI("On Engine Data available"); + DHLOGD("On Engine Data available"); OnDecodeTransDataDone(audioData); } @@ -343,7 +343,7 @@ void DSpeakerClient::PlayThreadRunning() } int64_t endTime = GetNowTimeUs(); if (IsOutDurationRange(startTime, endTime, lastPlayStartTime_)) { - DHLOGE("This time play spend: %{public}" PRId64" us, The interval of play this time and " + DHLOGD("This time play spend: %{public}" PRId64" us, The interval of play this time and " "the last time: %{public}" PRId64" us", endTime - startTime, startTime - lastPlayStartTime_); } lastPlayStartTime_ = startTime; @@ -378,7 +378,7 @@ void DSpeakerClient::FlushJitterQueue() int32_t DSpeakerClient::OnDecodeTransDataDone(const std::shared_ptr &audioData) { - DHLOGI("Write stream buffer."); + DHLOGD("Write stream buffer."); int64_t startTime = GetNowTimeUs(); CHECK_NULL_RETURN(audioData, ERR_DH_AUDIO_NULLPTR); @@ -393,7 +393,7 @@ int32_t DSpeakerClient::OnDecodeTransDataDone(const std::shared_ptr & DHLOGD("Push new spk data, buf len: %{public}" PRIu64, queueSize); int64_t endTime = GetNowTimeUs(); if (IsOutDurationRange(startTime, endTime, lastReceiveStartTime_)) { - DHLOGE("This time receivce data spend: %{public}" PRId64" us, Receivce data this time and " + DHLOGD("This time receivce data spend: %{public}" PRId64" us, Receivce data this time and " "the last time: %{public}" PRId64" us", endTime - startTime, startTime - lastReceiveStartTime_); } lastReceiveStartTime_ = startTime; diff --git a/services/audiomanager/managersink/src/daudio_sink_dev.cpp b/services/audiomanager/managersink/src/daudio_sink_dev.cpp index 66e14df9..51c237bc 100644 --- a/services/audiomanager/managersink/src/daudio_sink_dev.cpp +++ b/services/audiomanager/managersink/src/daudio_sink_dev.cpp @@ -566,6 +566,12 @@ int32_t DAudioSinkDev::GetCJsonObjectItems(const cJSON *j, AudioParam &audioPara CHECK_AND_RETURN_RET_LOG(ret != DH_SUCCESS, ret, "%{public}s", "Get param value error."); ret = GetParamValue(j, KEY_CAPTURE_FLAGS, reinterpret_cast(audioParam.captureOpts.capturerFlags)); CHECK_AND_RETURN_RET_LOG(ret != DH_SUCCESS, ret, "%{public}s", "Get param value error."); + + if (CJsonParamCheck(j, { KEY_CODEC_TYPE })) { + ret = GetParamValue(j, KEY_CODEC_TYPE, reinterpret_cast(audioParam.comParam.codecType)); + CHECK_AND_RETURN_RET_LOG(ret != DH_SUCCESS, ret, "%{public}s", "Get param value error."); + } + DHLOGD("codecType: %{public}d", static_cast(audioParam.comParam.codecType)); return ret; } diff --git a/services/audiomanager/managersource/include/dmic_dev.h b/services/audiomanager/managersource/include/dmic_dev.h index 0f7f4dc8..42ec7161 100644 --- a/services/audiomanager/managersource/include/dmic_dev.h +++ b/services/audiomanager/managersource/include/dmic_dev.h @@ -32,6 +32,7 @@ #include "daudio_hdi_handler.h" #include "daudio_io_dev.h" #include "daudio_source_ctrl_trans.h" +#include "daudio_ringbuffer.h" #include "iaudio_data_transport.h" #include "iaudio_datatrans_callback.h" #include "iaudio_event_callback.h" @@ -93,9 +94,12 @@ public: private: void EnqueueThread(); void FillJitterQueue(); + void ReadFromRingbuffer(); + void SendToProcess(const std::shared_ptr &audioData); private: static constexpr uint8_t CHANNEL_WAIT_SECONDS = 5; + static constexpr uint8_t RINGBUFFER_WAIT_SECONDS = 5; static constexpr size_t DATA_QUEUE_MAX_SIZE = 10; static constexpr size_t DATA_QUEUE_HALF_SIZE = DATA_QUEUE_MAX_SIZE >> 1U; static constexpr uint32_t LOW_LATENCY_JITTER_MAX_TIME_MS = 150; @@ -127,8 +131,8 @@ private: AudioParamHDF paramHDF_; AudioParam param_; - uint32_t insertFrameCnt_ = 0; std::atomic isExistedEmpty_ = false; + std::atomic isNeedCodec_ = true; size_t dataQueSize_ = 0; sptr ashmem_ = nullptr; std::atomic isEnqueueRunning_ = false; @@ -150,6 +154,12 @@ private: FILE *dumpFileFast_ = nullptr; uint32_t lowLatencyHalfSize_ = 0; uint32_t lowLatencyMaxfSize_ = 0; + std::unique_ptr ringBuffer_ = nullptr; + uint8_t *frameData_ = nullptr; + int32_t frameSize_ = 0; + std::thread ringbufferThread_; + std::atomic isRingbufferOn_ = false; + std::mutex ringbufferMutex_; }; } // DistributedHardware } // OHOS diff --git a/services/audiomanager/managersource/include/dspeaker_dev.h b/services/audiomanager/managersource/include/dspeaker_dev.h index d2f53126..42c549e4 100644 --- a/services/audiomanager/managersource/include/dspeaker_dev.h +++ b/services/audiomanager/managersource/include/dspeaker_dev.h @@ -110,6 +110,7 @@ private: sptr ashmem_ = nullptr; std::atomic isEnqueueRunning_ = false; + std::atomic isNeedCodec_ = true; int32_t ashmemLength_ = -1; int32_t lengthPerTrans_ = -1; int32_t readIndex_ = -1; diff --git a/services/audiomanager/managersource/src/daudio_source_dev.cpp b/services/audiomanager/managersource/src/daudio_source_dev.cpp index ad9b04e6..166f43be 100644 --- a/services/audiomanager/managersource/src/daudio_source_dev.cpp +++ b/services/audiomanager/managersource/src/daudio_source_dev.cpp @@ -1114,7 +1114,6 @@ int32_t DAudioSourceDev::TaskOpenDMic(const std::string &args) NotifyHDF(NOTIFY_OPEN_MIC_RESULT, HDF_EVENT_INIT_ENGINE_FAILED, dhId); return ret; } - cJSON *jAudioParam = cJSON_CreateObject(); CHECK_NULL_RETURN(jAudioParam, ERR_DH_AUDIO_NULLPTR); to_json(jAudioParam, mic->GetAudioParam()); @@ -1471,6 +1470,7 @@ void DAudioSourceDev::to_json(cJSON *j, const AudioParam ¶m) cJSON_AddNumberToObject(j, KEY_FORMAT, param.comParam.bitFormat); cJSON_AddNumberToObject(j, KEY_CHANNELS, param.comParam.channelMask); cJSON_AddNumberToObject(j, KEY_FRAMESIZE, param.comParam.frameSize); + cJSON_AddNumberToObject(j, KEY_CODEC_TYPE, param.comParam.codecType); cJSON_AddNumberToObject(j, KEY_CONTENT_TYPE, param.renderOpts.contentType); cJSON_AddNumberToObject(j, KEY_STREAM_USAGE, param.renderOpts.streamUsage); cJSON_AddNumberToObject(j, KEY_RENDER_FLAGS, param.renderOpts.renderFlags); diff --git a/services/audiomanager/managersource/src/dmic_dev.cpp b/services/audiomanager/managersource/src/dmic_dev.cpp index dfa8250c..7c5d0548 100644 --- a/services/audiomanager/managersource/src/dmic_dev.cpp +++ b/services/audiomanager/managersource/src/dmic_dev.cpp @@ -55,6 +55,46 @@ void DMicDev::OnEngineTransMessage(const std::shared_ptr &messag } void DMicDev::OnEngineTransDataAvailable(const std::shared_ptr &audioData) +{ + std::lock_guard lock(ringbufferMutex_); + CHECK_NULL_VOID(ringBuffer_); + if (ringBuffer_->RingBufferInsert(audioData->Data(), static_cast(audioData->Capacity())) != DH_SUCCESS) { + DHLOGE("Insert ringbuffer failed."); + return; + } + DHLOGD("ringbuffer insert one"); +} + +void DMicDev::ReadFromRingbuffer() +{ + std::shared_ptr sendData = std::make_shared(frameSize_); + bool canRead = false; + while (isRingbufferOn_.load()) { + CHECK_NULL_VOID(ringBuffer_); + canRead = false; + { + std::lock_guard lock(ringbufferMutex_); + if (ringBuffer_->CanBufferReadLen(frameSize_)) { + canRead = true; + } + } + if (!canRead) { + DHLOGD("Can not read from ringbuffer."); + std::this_thread::sleep_for(std::chrono::milliseconds(RINGBUFFER_WAIT_SECONDS)); + continue; + } + { + std::lock_guard lock(ringbufferMutex_); + if (ringBuffer_->RingBufferGetData(sendData->Data(), sendData->Capacity()) != DH_SUCCESS) { + DHLOGE("Read ringbuffer failed."); + continue; + } + } + SendToProcess(sendData); + } +} + +void DMicDev::SendToProcess(const std::shared_ptr &audioData) { DHLOGD("On Engine Data available"); if (echoCannelOn_) { @@ -134,6 +174,13 @@ int32_t DMicDev::EnableDevice(const int32_t dhId, const std::string &capability) return ret; } dhId_ = dhId; + auto pos = capability.find(SUB_PROTOCOLVER); + if (pos != std::string::npos) { + DHLOGD("ProtocolVer : 2.0"); + } else { + isNeedCodec_.store(false); + DHLOGD("ProtocolVer : 1.0"); + } return DH_SUCCESS; } @@ -218,6 +265,10 @@ int32_t DMicDev::SetParameters(const int32_t streamId, const AudioParamHDF ¶ param_.comParam.channelMask = paramHDF_.channelMask; param_.comParam.bitFormat = paramHDF_.bitFormat; param_.comParam.codecType = AudioCodecType::AUDIO_CODEC_AAC; + if (isNeedCodec_.load()) { + param_.comParam.codecType = AudioCodecType::AUDIO_CODEC_AAC_EN; + } + DHLOGD("isNeedCodec_ : %{public}d.", isNeedCodec_.load()); param_.comParam.frameSize = paramHDF_.frameSize; if (paramHDF_.streamUsage == StreamUsage::STREAM_USAGE_VOICE_COMMUNICATION) { param_.captureOpts.sourceType = SOURCE_TYPE_VOICE_COMMUNICATION; @@ -263,6 +314,15 @@ int32_t DMicDev::SetUp() DHLOGE("Mic trans set up failed. ret: %{public}d.", ret); return ret; } + frameSize_ = static_cast(param_.comParam.frameSize); + { + std::lock_guard lock(ringbufferMutex_); + ringBuffer_ = std::make_unique(); + ringBuffer_->RingBufferInit(frameData_); + CHECK_NULL_RETURN(frameData_, ERR_DH_AUDIO_NULLPTR); + } + isRingbufferOn_.store(true); + ringbufferThread_ = std::thread([this]() { this->ReadFromRingbuffer(); }); echoCannelOn_ = true; #ifdef ECHO_CANNEL_ENABLE if (echoCannelOn_ && echoManager_ == nullptr) { @@ -355,6 +415,18 @@ int32_t DMicDev::Release() DHLOGE("Release mic trans failed, ret: %{public}d.", ret); return ret; } + isRingbufferOn_.store(false); + if (ringbufferThread_.joinable()) { + ringbufferThread_.join(); + } + { + std::lock_guard lock(ringbufferMutex_); + ringBuffer_ = nullptr; + if (frameData_ != nullptr) { + delete[] frameData_; + frameData_ = nullptr; + } + } #ifdef ECHO_CANNEL_ENABLE if (echoManager_ != nullptr) { echoManager_->Release(); @@ -387,17 +459,11 @@ int32_t DMicDev::ReadStreamData(const int32_t streamId, std::shared_ptr lock(dataQueueMtx_); uint32_t queSize = dataQueue_.size(); - if (insertFrameCnt_ >= queSize || queSize == 0) { - ++insertFrameCnt_; + if (queSize == 0) { isExistedEmpty_.store(true); - DHLOGD("Data queue is empty, count :%{public}u.", insertFrameCnt_); + DHLOGD("Data queue is empty"); data = std::make_shared(param_.comParam.frameSize); } else { - while (insertFrameCnt_ > 0) { - DHLOGD("Data discard, count: %{public}u", insertFrameCnt_); - dataQueue_.pop(); - --insertFrameCnt_; - } data = dataQueue_.front(); dataQueue_.pop(); } diff --git a/services/audiomanager/managersource/src/dspeaker_dev.cpp b/services/audiomanager/managersource/src/dspeaker_dev.cpp index edcbe8db..564dc2f4 100644 --- a/services/audiomanager/managersource/src/dspeaker_dev.cpp +++ b/services/audiomanager/managersource/src/dspeaker_dev.cpp @@ -47,6 +47,13 @@ int32_t DSpeakerDev::EnableDevice(const int32_t dhId, const std::string &capabil return ret; } dhId_ = dhId; + auto pos = capability.find(SUB_PROTOCOLVER); + if (pos != std::string::npos) { + DHLOGD("ProtocolVer : 2.0"); + } else { + isNeedCodec_.store(false); + DHLOGD("ProtocolVer : 1.0"); + } return DH_SUCCESS; } @@ -204,6 +211,10 @@ int32_t DSpeakerDev::SetParameters(const int32_t streamId, const AudioParamHDF & param_.renderOpts.contentType = CONTENT_TYPE_MUSIC; param_.renderOpts.renderFlags = paramHDF_.renderFlags; param_.renderOpts.streamUsage = paramHDF_.streamUsage; + if (isNeedCodec_.load()) { + param_.comParam.codecType = AudioCodecType::AUDIO_CODEC_AAC_EN; + } + DHLOGD("isNeedCodec_: %{public}d", isNeedCodec_.load()); return DH_SUCCESS; } diff --git a/services/audiomanager/test/unittest/sourcedevice/src/dmic_dev_test.cpp b/services/audiomanager/test/unittest/sourcedevice/src/dmic_dev_test.cpp index d3b8eb15..7f2c81f1 100644 --- a/services/audiomanager/test/unittest/sourcedevice/src/dmic_dev_test.cpp +++ b/services/audiomanager/test/unittest/sourcedevice/src/dmic_dev_test.cpp @@ -337,10 +337,8 @@ HWTEST_F(DMicDevTest, ReadStreamData_001, TestSize.Level1) EXPECT_EQ(ERR_DH_AUDIO_FAILED, mic_->ReadStreamData(streamId_, readData1)); mic_->curStatus_ = AudioStatus::STATUS_START; - mic_->insertFrameCnt_ = 1; EXPECT_EQ(DH_SUCCESS, mic_->ReadStreamData(streamId_, readData1)); - mic_->insertFrameCnt_ = 11; EXPECT_EQ(DH_SUCCESS, mic_->ReadStreamData(streamId_, readData1)); } diff --git a/services/audiotransport/receiverengine/src/av_receiver_engine_transport.cpp b/services/audiotransport/receiverengine/src/av_receiver_engine_transport.cpp index ce5482e7..036dd8f0 100644 --- a/services/audiotransport/receiverengine/src/av_receiver_engine_transport.cpp +++ b/services/audiotransport/receiverengine/src/av_receiver_engine_transport.cpp @@ -148,7 +148,7 @@ int32_t AVTransReceiverTransport::SetParameter(const AudioParam &audioParam) DHLOGI("SetParameter."); CHECK_NULL_RETURN(receiverAdapter_, ERR_DH_AUDIO_NULLPTR); receiverAdapter_->SetParameter(AVTransTag::AUDIO_SAMPLE_RATE, std::to_string(audioParam.comParam.sampleRate)); - receiverAdapter_->SetParameter(AVTransTag::AUDIO_SAMPLE_FORMAT, std::to_string(AudioSampleFormat::SAMPLE_F32LE)); + receiverAdapter_->SetParameter(AVTransTag::AUDIO_SAMPLE_FORMAT, std::to_string(AudioSampleFormat::SAMPLE_S16LE)); receiverAdapter_->SetParameter(AVTransTag::AUDIO_CHANNEL_MASK, std::to_string(audioParam.comParam.channelMask)); receiverAdapter_->SetParameter(AVTransTag::AUDIO_CHANNEL_LAYOUT, std::to_string(audioParam.comParam.channelMask)); receiverAdapter_->SetParameter(AVTransTag::AUDIO_BIT_RATE, std::to_string(AUDIO_SET_HISTREAMER_BIT_RATE)); diff --git a/services/common/BUILD.gn b/services/common/BUILD.gn index 083b753b..ec8cc07a 100644 --- a/services/common/BUILD.gn +++ b/services/common/BUILD.gn @@ -51,6 +51,7 @@ ohos_shared_library("distributed_audio_utils") { "${common_path}/dfx_utils/src/daudio_hisysevent.cpp", "${common_path}/dfx_utils/src/daudio_hitrace.cpp", "${common_path}/src/daudio_latency_test.cpp", + "${common_path}/src/daudio_ringbuffer.cpp", "${common_path}/src/daudio_util.cpp", "audiodata/src/audio_data.cpp", ] diff --git a/services/common/audioparam/audio_param.h b/services/common/audioparam/audio_param.h index 6efe4e09..95d36594 100644 --- a/services/common/audioparam/audio_param.h +++ b/services/common/audioparam/audio_param.h @@ -57,7 +57,8 @@ typedef enum { typedef enum { AUDIO_CODEC_AAC = 0, - AUDIO_CODEC_FLAC = 1 + AUDIO_CODEC_FLAC = 1, + AUDIO_CODEC_AAC_EN = 2 } AudioCodecType; typedef enum { diff --git a/services/test_example/distributedaudiotest.cpp b/services/test_example/distributedaudiotest.cpp index fb3c1d0e..0f930bc3 100644 --- a/services/test_example/distributedaudiotest.cpp +++ b/services/test_example/distributedaudiotest.cpp @@ -113,7 +113,7 @@ constexpr int32_t RENDER_CHANNEL_MASK = 2; constexpr int32_t CAPTURE_INTER_LEAVED = 1; constexpr int32_t CAPTURE_STREAM_ID = 2; constexpr int32_t CAPTURE_CHANNEL_MASK = 2; -constexpr int64_t AUDIO_FRAME_TIME_INTERFAL_DEFAULT = 21333; +constexpr int64_t AUDIO_FRAME_TIME_INTERFAL_DEFAULT = 20000; static OHOS::sptr g_manager = nullptr; static OHOS::sptr g_adapter = nullptr; -- Gitee