diff --git a/common/include/daudio_ipc_interface_code.h b/common/include/daudio_ipc_interface_code.h index a18c0683f1ed76a4d4ec572c97dbc6f6363a1d84..b37acfac40db329946c154765c90e0f89db81f6c 100644 --- a/common/include/daudio_ipc_interface_code.h +++ b/common/include/daudio_ipc_interface_code.h @@ -28,6 +28,7 @@ enum class IDAudioSourceInterfaceCode : uint32_t { UNREGISTER_DISTRIBUTED_HARDWARE = 3, CONFIG_DISTRIBUTED_HARDWARE = 4, DAUDIO_NOTIFY = 5, + UPDATE_WORKMODE = 6, }; /* SAID: 4806 */ diff --git a/interfaces/inner_kits/native_cpp/audio_source/include/daudio_source_handler.h b/interfaces/inner_kits/native_cpp/audio_source/include/daudio_source_handler.h index ca187db3eb0aa1cac7066a8d0bc2d14556b814a7..b1d9986d6c28b08e717b3d6685053cac02c7faea 100644 --- a/interfaces/inner_kits/native_cpp/audio_source/include/daudio_source_handler.h +++ b/interfaces/inner_kits/native_cpp/audio_source/include/daudio_source_handler.h @@ -43,6 +43,8 @@ public: int32_t UnLoadDistributedHDF() override; void OnRemoteSourceSvrDied(const wptr &remote); void FinishStartSA(const std::string ¶m, const sptr &remoteObject); + // int32_t UpdateDistributedHardwareWorkMode(const std::string &devId, const std::string &dhId, + // const WorkModeParam param) override; private: class DAudioSourceSvrRecipient : public IRemoteObject::DeathRecipient { diff --git a/interfaces/inner_kits/native_cpp/audio_source/include/daudio_source_proxy.h b/interfaces/inner_kits/native_cpp/audio_source/include/daudio_source_proxy.h index 4cb89acb0abe3c1976ad35ec7e367b0a01f8c95c..42f8bcbf4177a644cb85e1e87ac753f3a79733b7 100644 --- a/interfaces/inner_kits/native_cpp/audio_source/include/daudio_source_proxy.h +++ b/interfaces/inner_kits/native_cpp/audio_source/include/daudio_source_proxy.h @@ -37,6 +37,9 @@ public: const std::string &value) override; void DAudioNotify(const std::string &devId, const std::string &dhId, const int32_t eventType, const std::string &eventContent) override; + int32_t UpdateDistributedHardwareWorkMode(const std::string &devId, const std::string &dhId, + const WorkModeParam ¶ms) override; + private: static inline BrokerDelegator delegator_; diff --git a/interfaces/inner_kits/native_cpp/audio_source/include/idaudio_source.h b/interfaces/inner_kits/native_cpp/audio_source/include/idaudio_source.h index 33f658448032829b47cbc3dd51b22a267d4fe9ee..b8d978c9753b84f6584c6d0f92ffd5defc0c2565 100644 --- a/interfaces/inner_kits/native_cpp/audio_source/include/idaudio_source.h +++ b/interfaces/inner_kits/native_cpp/audio_source/include/idaudio_source.h @@ -37,6 +37,8 @@ public: const std::string &value) = 0; virtual void DAudioNotify(const std::string &devId, const std::string &dhId, const int32_t eventType, const std::string &eventContent) = 0; + virtual int32_t UpdateDistributedHardwareWorkMode(const std::string &devId, const std::string &dhId, + const WorkModeParam ¶ms) = 0; }; } // DistributedHardware } // OHOS diff --git a/interfaces/inner_kits/native_cpp/audio_source/src/daudio_source_handler.cpp b/interfaces/inner_kits/native_cpp/audio_source/src/daudio_source_handler.cpp index f5a1b94f897cd661d30ff2dcdce14f17f9c07601..3c76edb2b236d9b7a20ecd8772501d63f5b6b2bf 100644 --- a/interfaces/inner_kits/native_cpp/audio_source/src/daudio_source_handler.cpp +++ b/interfaces/inner_kits/native_cpp/audio_source/src/daudio_source_handler.cpp @@ -219,6 +219,20 @@ void DAudioSourceHandler::FinishStartSA(const std::string ¶m, const sptr lock(sourceProxyMutex_); +// CHECK_NULL_RETURN(dAudioSourceProxy_, ERR_DH_AUDIO_SA_PROXY_NOT_INIT); +// if (devId.length() > DAUDIO_MAX_DEVICE_ID_LEN || dhId.length() > DAUDIO_MAX_DEVICE_ID_LEN) { +// return ERR_DH_AUDIO_SA_DEVID_ILLEGAL; +// } +// std::string reduceDhId = dhId; +// return dAudioSourceProxy_->UpdateDistributedHardwareWorkMode(devId, reduceDhId, param); +// } + void DAudioSourceHandler::DAudioSourceSvrRecipient::OnRemoteDied(const wptr &remote) { DAudioSourceHandler::GetInstance().OnRemoteSourceSvrDied(remote); diff --git a/interfaces/inner_kits/native_cpp/audio_source/src/daudio_source_proxy.cpp b/interfaces/inner_kits/native_cpp/audio_source/src/daudio_source_proxy.cpp index 77fb57c8ec009862d97dbfa96cd43b69bc23a630..cc37d38b4cf7132ff625140de94ef19db3da9cb8 100644 --- a/interfaces/inner_kits/native_cpp/audio_source/src/daudio_source_proxy.cpp +++ b/interfaces/inner_kits/native_cpp/audio_source/src/daudio_source_proxy.cpp @@ -171,5 +171,34 @@ void DAudioSourceProxy::DAudioNotify(const std::string &devId, const std::string Remote()->SendRequest(static_cast(IDAudioSourceInterfaceCode::DAUDIO_NOTIFY), data, reply, option); } + +int32_t DAudioSourceProxy::UpdateDistributedHardwareWorkMode(const std::string &devId, const std::string &dhId, + + const WorkModeParam ¶ms) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + if (!data.WriteInterfaceToken(GetDescriptor())) { + return ERR_DH_AUDIO_SA_WRITE_INTERFACE_TOKEN_FAILED; + } + if (devId.length() > DAUDIO_MAX_DEVICE_ID_LEN || dhId.length() > DAUDIO_MAX_DEVICE_ID_LEN) { + return ERR_DH_AUDIO_SA_DEVID_ILLEGAL; + } + if (!data.WriteString(devId) || !data.WriteString(dhId) || !data.WriteInt32(params.fd) || + !data.WriteInt32(params.sharedMemLen) || !data.WriteInt32(params.scene) || !data.WriteBool(params.isAVsync)) { + DHLOGE("Write params failed."); + return ERR_DH_AUDIO_SA_WRITE_PARAM_FAIED; + } + + if (Remote() == nullptr) { + DHLOGE("remote service is null."); + return ERR_DH_AUDIO_NULLPTR; + } + Remote()->SendRequest(static_cast(IDAudioSourceInterfaceCode::UPDATE_WORKMODE), + data, reply, option); + int32_t ret = reply.ReadInt32(); + return ret; +} } // namespace DistributedHardware } // namespace OHOS \ No newline at end of file diff --git a/services/audioclient/micclient/include/dmic_client.h b/services/audioclient/micclient/include/dmic_client.h index 5488621e11f079bf016f5ff43d32b952dc3f07c1..87af7e35fc5cc292d35333129266ee1bd88068a5 100644 --- a/services/audioclient/micclient/include/dmic_client.h +++ b/services/audioclient/micclient/include/dmic_client.h @@ -99,6 +99,12 @@ private: int64_t lastTransStartTime_ = 0; std::atomic isPauseStatus_ = false; FILE *dumpFile_ = nullptr; + std::atomic micDataPts_ = 0; + constexpr static int64_t AUDIO_FRAME_INTERVAL_US = 20000; + constexpr static int64_t TIME_CONVERSION_NTOU = 1000; + constexpr static int64_t TIME_CONVERSION_STOU = 1000000; + std::atomic getAudioTimeCounter_ = 0; + int64_t frameIndex_ = 0; }; } // DistributedHardware } // OHOS diff --git a/services/audioclient/micclient/src/dmic_client.cpp b/services/audioclient/micclient/src/dmic_client.cpp index 7ad9589d2b6a1c05178e2fefded88c6111500620..31fc14631f56074cffeaaeed0a9bd00496dc6276 100644 --- a/services/audioclient/micclient/src/dmic_client.cpp +++ b/services/audioclient/micclient/src/dmic_client.cpp @@ -302,6 +302,21 @@ void DMicClient::AudioFwkCaptureData() DHLOGE("Bytes read failed."); return; } + micDataPts_.fetch_add(AUDIO_FRAME_INTERVAL_US); + if (getAudioTimeCounter_ % 50 == 0) { + AudioStandard::Timestamp timestamp; + audioCapturer_->GetTimeStampInfo(timestamp, AudioStandard::Timestamp::Timestampbase::MONOTONIC); + int64_t ptsOrigin = timestamp.time.tv_sec * TIME_CONVERSION_STOU + + timestamp.time.tv_nsec / TIME_CONVERSION_NTOU; + int64_t frameNumOfPts = static_cast(timestamp.framePosition) / 960; + int64_t ptsFinal = ptsOrigin - (frameNumOfPts - frameIndex_) * 20; + micDataPts_.store(ptsFinal); + getAudioTimeCounter_ = 0; + } + getAudioTimeCounter_++; + frameIndex_++; + DHLOGI("micDataPts_: %{public}" PRId64, micDataPts_.load()); + audioData->SetPts(micDataPts_.load()); if (isPauseStatus_.load()) { memset_s(audioData->Data(), audioData->Size(), 0, audioData->Size()); } diff --git a/services/audiomanager/managersource/include/daudio_io_dev.h b/services/audiomanager/managersource/include/daudio_io_dev.h index 74a4b63a704c1a3bd43b8189f6f373e05dedc47b..c89c04856f4253012180f161c1e9bfdf3d6e1c91 100644 --- a/services/audiomanager/managersource/include/daudio_io_dev.h +++ b/services/audiomanager/managersource/include/daudio_io_dev.h @@ -32,6 +32,19 @@ namespace OHOS { namespace DistributedHardware { +struct AudioAsyncParam +{ + int32_t fd; + int32_t sharedMemLen; + uint32_t scene; + bool isAVsync; +}; + +enum class AudioAVScene : uint32_t { + BROADCAST, + VIDEOCALL +}; + class DAudioIoDev : public IDAudioHdiCallback { public: explicit DAudioIoDev(const std::string &devId) @@ -58,6 +71,8 @@ public: virtual AudioParam GetAudioParam() const = 0; virtual int32_t NotifyHdfAudioEvent(const AudioEvent &event, const int32_t portId) = 0; + virtual int32_t UpdateWorkModeParam(const std::string &devId, const std::string &dhId, + const AudioAsyncParam ¶m) = 0; protected: const std::string devId_; diff --git a/services/audiomanager/managersource/include/daudio_source_dev.h b/services/audiomanager/managersource/include/daudio_source_dev.h index 19a083719d7044d27c1b4c047f936a7acf5d06ec..a5d4ed206b71ff334f7c96744f9338619f90d610 100644 --- a/services/audiomanager/managersource/include/daudio_source_dev.h +++ b/services/audiomanager/managersource/include/daudio_source_dev.h @@ -58,6 +58,7 @@ public: bool GetThreadStatusFlag(); void NotifyEvent(const AudioEvent &event) override; void SetTokenId(uint64_t value); + int32_t UpdateWorkModeParam(const std::string &devId, const std::string &dhId, const AudioAsyncParam ¶m); private: int32_t EnableDSpeaker(const int32_t dhId, const std::string &attrs); diff --git a/services/audiomanager/managersource/include/daudio_source_manager.h b/services/audiomanager/managersource/include/daudio_source_manager.h index d4dbda941af9e7505e0c1b27e448f25b4fa8215f..e4846030c3a19a8ffa0021ca6ded93d484ada500 100644 --- a/services/audiomanager/managersource/include/daudio_source_manager.h +++ b/services/audiomanager/managersource/include/daudio_source_manager.h @@ -54,6 +54,7 @@ public: IAVEngineProvider *getSenderProvider(); IAVEngineProvider *getReceiverProvider(); void SetCallerTokenId(uint64_t tokenId); + int32_t UpdateWorkModeParam(const std::string &devId, const std::string &dhId, const AudioAsyncParam ¶m); private: DAudioSourceManager(); diff --git a/services/audiomanager/managersource/include/dmic_dev.h b/services/audiomanager/managersource/include/dmic_dev.h index 46a422613309376ff69f594d7e6d05568404eefd..f39da64c5cd8d7ad2c8cedd822026e7cba7fccbc 100644 --- a/services/audiomanager/managersource/include/dmic_dev.h +++ b/services/audiomanager/managersource/include/dmic_dev.h @@ -16,7 +16,7 @@ #ifndef OHOS_DMIC_DEV_H #define OHOS_DMIC_DEV_H -#include +#include #include #include #include "cJSON.h" @@ -90,6 +90,10 @@ public: int32_t OnStateChange(const AudioEventType type) override; int32_t OnDecodeTransDataDone(const std::shared_ptr &audioData) override; + int32_t UpdateWorkModeParam(const std::string &devId, const std::string &dhId, + const AudioAsyncParam ¶m) override; + int32_t AVsyncRefreshAshmem(int32_t fd, int32_t ashmemLength); + void AVsyncDeintAshmem(); private: void EnqueueThread(); @@ -99,17 +103,28 @@ private: void GetCodecCaps(const std::string &capability); void AddToVec(std::vector &container, const AudioCodecType value); bool IsMimeSupported(const AudioCodecType coder); + int32_t GetAudioDataFromQueue(std::shared_ptr &data); + int32_t WriteTimeStampToAVsync(const int64_t timePts); + int32_t ReadTimeStampFromAVsync(int64_t &timePts); + uint32_t GetQueSize(); + bool IsAVsync(); + int32_t AVsyncMacthScene(std::shared_ptr &data); private: static constexpr uint8_t CHANNEL_WAIT_SECONDS = 5; static constexpr uint8_t RINGBUFFER_WAIT_SECONDS = 5; + static constexpr uint8_t SCENE_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 size_t DATA_QUEUE_BROADCAST_SIZE = 20; + static constexpr size_t DATA_QUEUE_VIDEOCALL_SIZE = 20; + static constexpr int64_t TIMESTAMP_COMPENSATION = 0; static constexpr uint32_t LOW_LATENCY_JITTER_MAX_TIME_MS = 150; static constexpr uint32_t LOW_LATENCY_JITTER_TIME_MS = 50; static constexpr uint8_t MMAP_NORMAL_PERIOD = 5; static constexpr uint8_t MMAP_VOIP_PERIOD = 20; static constexpr uint32_t MMAP_WAIT_FRAME_US = 5000; + constexpr static int64_t ONE_FRAME_COMPENSATION = 20000; static constexpr const char* ENQUEUE_THREAD = "micEnqueueTh"; const std::string DUMP_DAUDIO_MIC_READ_FROM_BUF_NAME = "dump_source_mic_read_from_trans.pcm"; const std::string DUMP_DAUDIO_LOWLATENCY_MIC_FROM_BUF_NAME = "dump_source_mic_write_to_ashmem.pcm"; @@ -128,7 +143,7 @@ private: #ifdef ECHO_CANNEL_ENABLE std::shared_ptr echoManager_ = nullptr; #endif - std::queue> dataQueue_; + std::deque> dataQueue_; AudioStatus curStatus_ = AudioStatus::STATUS_IDLE; // Mic capture parameters AudioParamHDF paramHDF_; @@ -163,6 +178,31 @@ private: std::atomic isRingbufferOn_ = false; std::mutex ringbufferMutex_; std::vector codec_; + + uint64_t frameInIndex_ = 0; + uint64_t frameOutIndex_ = 0; + uint64_t framnum_ = 0; + std::map ptsMap_; + std::mutex ptsMutex_; + AudioAsyncParam avSyncParam_ {}; + std::mutex avSyncMutex_; + uint32_t scene_ = DATA_QUEUE_HALF_SIZE; + std::atomic isStartStatus_ = true; + sptr avsyncAshmem_ = nullptr; + constexpr static int64_t TIME_CONVERSION_NTOU = 1000; + constexpr static int64_t TIME_CONVERSION_STOU = 1000000; + struct AVsyncShareData { + volatile int lock = 1; + uint64_t audio_current_pts = 0; + uint64_t audio_update_clock = 0; + float audio_speed = 1.0f; + uint64_t video_current_pts = 0; + uint64_t video_update_clock = 0; + float video_speed = 1.0f; + uint64_t sync_strategy = 1; + bool reset = false; + }; + std::shared_ptr avsyncShareData_ = nullptr; }; } // DistributedHardware } // OHOS diff --git a/services/audiomanager/managersource/include/dspeaker_dev.h b/services/audiomanager/managersource/include/dspeaker_dev.h index 68d2eaeaa008aaa3523d61b32713e48d6c8f96cf..cf4ba8498430a8af62f8e46ac740a990ae14948b 100644 --- a/services/audiomanager/managersource/include/dspeaker_dev.h +++ b/services/audiomanager/managersource/include/dspeaker_dev.h @@ -84,6 +84,8 @@ public: AudioParam GetAudioParam() const override; int32_t NotifyHdfAudioEvent(const AudioEvent &event, const int32_t portId) override; + int32_t UpdateWorkModeParam(const std::string &devId, const std::string &dhId, + const AudioAsyncParam ¶m) override; private: void EnqueueThread(); diff --git a/services/audiomanager/managersource/src/daudio_source_dev.cpp b/services/audiomanager/managersource/src/daudio_source_dev.cpp index f97dac19016c8a11c3bbbbce7e6ef1b72cfa8a16..de3f832b9f2f086799dd1721f166c641e52b0580 100644 --- a/services/audiomanager/managersource/src/daudio_source_dev.cpp +++ b/services/audiomanager/managersource/src/daudio_source_dev.cpp @@ -1582,6 +1582,20 @@ int32_t DAudioSourceDev::CheckOsType(std::string &networkId, bool &isInvalid) return DH_SUCCESS; } +int32_t DAudioSourceDev::UpdateWorkModeParam(const std::string &devId, const std::string &dhId, + const AudioAsyncParam ¶m) +{ + int32_t dhIdNum = ConvertString2Int(dhId); + CHECK_AND_RETURN_RET_LOG(dhIdNum == ERR_DH_AUDIO_FAILED, ERR_DH_AUDIO_FAILED, "dhId is invalid."); + std::lock_guard devLck(ioDevMtx_); + CHECK_AND_RETURN_RET_LOG(deviceMap_.find(dhIdNum) == deviceMap_.end(), ERR_DH_AUDIO_FAILED, "map not found."); + auto ioDev = deviceMap_[dhIdNum]; + CHECK_NULL_RETURN(ioDev, ERR_DH_AUDIO_FAILED); + int32_t ret = ioDev->UpdateWorkModeParam(devId, dhId, param); + CHECK_AND_RETURN_RET_LOG(ret != DH_SUCCESS, ERR_DH_AUDIO_FAILED, "UpdateWorkModeParam failed."); + return DH_SUCCESS; +} + DAudioSourceDev::SourceEventHandler::SourceEventHandler(const std::shared_ptr &runner, const std::shared_ptr &dev) : AppExecFwk::EventHandler(runner), sourceDev_(dev) { diff --git a/services/audiomanager/managersource/src/daudio_source_manager.cpp b/services/audiomanager/managersource/src/daudio_source_manager.cpp index 69629309ced314842b198171e772c44d44dd7efc..72f1d1ffb86d7f34115e773f1b460fb0aa1767da 100644 --- a/services/audiomanager/managersource/src/daudio_source_manager.cpp +++ b/services/audiomanager/managersource/src/daudio_source_manager.cpp @@ -573,6 +573,26 @@ void DAudioSourceManager::SetCallerTokenId(uint64_t tokenId) callerTokenId_ = tokenId; } +int32_t DAudioSourceManager::UpdateWorkModeParam(const std::string &devId, const std::string &dhId, + const AudioAsyncParam ¶m) +{ + std::shared_ptr sourceDev = nullptr; + { + std::lock_guard lock(devMapMtx_); + auto device = audioDevMap_.find(devId); + if (device == audioDevMap_.end()) { + if (CreateAudioDevice(devId) != DH_SUCCESS) { + return ERR_DH_AUDIO_FAILED; + } + } + sourceDev = audioDevMap_[devId].dev; + } + CHECK_NULL_RETURN(sourceDev, ERR_DH_AUDIO_FAILED); + int32_t ret = sourceDev->UpdateWorkModeParam(devId, dhId, param); + CHECK_AND_RETURN_RET_LOG(ret != DH_SUCCESS, ret, "UpdateWorkModeParam failed, ret: %{public}d", ret); + return DH_SUCCESS; +} + IAVEngineProvider *DAudioSourceManager::getSenderProvider() { return sendProviderPtr_; diff --git a/services/audiomanager/managersource/src/dmic_dev.cpp b/services/audiomanager/managersource/src/dmic_dev.cpp index daac1b46213716f3bbf4fa82b90b0aa6c3eb03d0..11feebc94385e99368970db57e2fe040b0d3c4af 100644 --- a/services/audiomanager/managersource/src/dmic_dev.cpp +++ b/services/audiomanager/managersource/src/dmic_dev.cpp @@ -16,6 +16,7 @@ #include "dmic_dev.h" #include +#include #include #include #include @@ -59,11 +60,21 @@ void DMicDev::OnEngineTransDataAvailable(const std::shared_ptr &audio { 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; - } + CHECK_NULL_VOID(audioData); + CHECK_AND_RETURN_LOG(ringBuffer_->RingBufferInsert(audioData->Data(), + static_cast(audioData->Capacity())) != DH_SUCCESS, "RingBufferInsert failed."); DHLOGD("ringbuffer insert one"); + int64_t timestamp = audioData->GetPts(); + std::lock_guard timeLock(ptsMutex_); + ptsMap_[frameInIndex_] = timestamp; + DHLOGD("audioData->GetPts(): %{public}" PRId64", index: %{public}" PRIu64, timestamp, frameInIndex_); + frameInIndex_++; + if (frameInIndex_ == 15) { + timestamp = audioData->GetPtsSpecial(); + ptsMap_[frameInIndex_] = timestamp; + DHLOGD("audioData->GetPtsSpecial(): %{public}" PRId64", index: %{public}" PRIu64, timestamp, frameInIndex_); + frameInIndex_ = 0; + } } void DMicDev::ReadFromRingbuffer() @@ -98,6 +109,26 @@ void DMicDev::ReadFromRingbuffer() void DMicDev::SendToProcess(const std::shared_ptr &audioData) { DHLOGD("On Engine Data available"); + CHECK_NULL_VOID(audioData); + int64_t pts = 0; + { + std::lock_guard lock(ptsMutex_); + auto iter = ptsMap_.find(frameOutIndex_); + if (iter != ptsMap_.end()) { + pts = iter->second; + audioData->SetPts(pts); + ptsMap_.erase(iter); + } else { + DHLOGI("iter == ptsMap_.end()"); + } + frameOutIndex_++; + if (frameOutIndex_ == 16) { + frameOutIndex_ = 0; + } + } + DHLOGD("Set timestamp %{public}" PRId64 " for frame index %{public}" PRIu64, audioData->GetPts(), frameOutIndex_); + framnum_++; + DHLOGD("current frame index: %{public}" PRIu64, framnum_); if (echoCannelOn_) { #ifdef ECHO_CANNEL_ENABLE if (echoManager_ == nullptr) { @@ -326,6 +357,7 @@ int32_t DMicDev::NotifyEvent(const int32_t streamId, const AudioEvent &event) case AudioEventType::AUDIO_START: curStatus_ = AudioStatus::STATUS_START; isExistedEmpty_.store(false); + isStartStatus_.store(true); break; case AudioEventType::AUDIO_STOP: curStatus_ = AudioStatus::STATUS_STOP; @@ -362,7 +394,8 @@ int32_t DMicDev::SetUp() } ptr->ReadFromRingbuffer(); }); - echoCannelOn_ = true; + echoCannelOn_ = false; + DHLOGI("echoCannelOn_: %{public}d", echoCannelOn_); #ifdef ECHO_CANNEL_ENABLE if (echoCannelOn_ && echoManager_ == nullptr) { echoManager_ = std::make_shared(); @@ -451,6 +484,11 @@ int32_t DMicDev::Release() } CHECK_NULL_RETURN(micTrans_, DH_SUCCESS); + AVsyncDeintAshmem(); + avSyncParam_.fd = -1; + avSyncParam_.sharedMemLen = 0; + DHLOGI("AVsync mode closed"); + int32_t ret = micTrans_->Release(); DaudioRadar::GetInstance().ReportMicCloseProgress("Release", MicClose::RELEASE_TRANS, ret); if (ret != DH_SUCCESS) { @@ -492,24 +530,140 @@ int32_t DMicDev::WriteStreamData(const int32_t streamId, std::shared_ptr &data) +int32_t DMicDev::ReadTimeStampFromAVsync(int64_t &timePts) { - int64_t startTime = GetNowTimeUs(); - if (curStatus_ != AudioStatus::STATUS_START) { - DHLOGE("Distributed audio is not starting status."); - return ERR_DH_AUDIO_FAILED; + if (IsAVsync() && avsyncAshmem_ != nullptr) { + auto sycData = avsyncAshmem_->ReadFromAshmem(avSyncParam_.sharedMemLen, 0); + AVSyncShareData *readSyncShareData = reinterpret_cast(const_cast(syncData)); + while (!readSyncShareData->lock) { + DHLOGE("AVsync lock is false"); + syncData = avsyncAshmem_->ReadFromAshmem(avSyncParam_.sharedMemLen, 0); + readSyncShareData = reinterpret_cast(const_cast(syncData)); + } + DHLOGE("AVsync lock is true"); + avsyncShareData_ = std::make_shared(); + avsyncShareData_->lock = 0; + ret = avsyncAshmem_->WriteToAshmem(static_cast(avsyncShareData_.get()), sizeof(AVsyncShareData), 0); + CHECK_AND_RETURN_RET_LOG(!ret, ERR_DH_AUDIO_FAILED, "Write avsync data failed."); + timePts = avsyncShareData_->video_current_pts; + avsyncShareData_->lock = 1; + bool ret = avsyncAshmem_->WriteToAshmem(static_cast(avsyncShareData_.get()), sizeof(AVsyncShareData), 0); + CHECK_AND_RETURN_RET_LOG(!ret, ERR_DH_AUDIO_FAILED, "Write avsync data failed."); + DHLOGI("avsyncShareData_->audio_current_pts: %{public}" PRId64", avsyncShareData_->audio_update_clock: " + "%{public}" PRId64, avsyncShareData_->audio_current_pts, avsyncShareData_->audio_update_clock); } + return DH_SUCCESS; +} + +int32_t DMicDev::WriteTimeStampToAVsync(const int64_t timePts) +{ + if (IsAVsync() && avsyncAshmem_ != nullptr) { + auto sycData = avsyncAshmem_->ReadFromAshmem(avSyncParam_.sharedMemLen, 0); + AVSyncShareData *readSyncShareData = reinterpret_cast(const_cast(syncData)); + while (!readSyncShareData->lock) { + DHLOGE("AVsync lock is false"); + syncData = avsyncAshmem_->ReadFromAshmem(avSyncParam_.sharedMemLen, 0); + readSyncShareData = reinterpret_cast(const_cast(syncData)); + } + DHLOGE("AVsync lock is true"); + avsyncShareData_ = std::make_shared(); + avsyncShareData_->lock = 0; + ret = avsyncAshmem_->WriteToAshmem(static_cast(avsyncShareData_.get()), sizeof(AVsyncShareData), 0); + CHECK_AND_RETURN_RET_LOG(!ret, ERR_DH_AUDIO_FAILED, "Write avsync data failed."); + struct timespec time = {0, 0}; + clock_gettime(CLOCK_REALTIME, &time); + int64_t updatePts = static_cast(time.tv_sec) * TIME_CONVERSION_STOU + + static_cast(time.tv_nsec) / TIME_CONVERSION_NTOU; + avsyncShareData_->lock = 1; + avsyncShareData_->audio_current_pts = timePts; + avsyncShareData_->audio_update_clock = updatePts; + bool ret = avsyncAshmem_->WriteToAshmem(static_cast(avsyncShareData_.get()), sizeof(AVsyncShareData), 0); + CHECK_AND_RETURN_RET_LOG(!ret, ERR_DH_AUDIO_FAILED, "Write avsync data failed."); + DHLOGI("avsyncShareData_->audio_current_pts: %{public}" PRId64", avsyncShareData_->audio_update_clock: " + "%{public}" PRId64, avsyncShareData_->audio_current_pts, avsyncShareData_->audio_update_clock); + } + return DH_SUCCESS; +} + +uint32_t DMicDev::GetQueSize() +{ std::lock_guard lock(dataQueueMtx_); - uint32_t queSize = dataQueue_.size(); - if (queSize == 0) { + return dataQueue_.size(); +} + +bool DMicDev::IsAVsync() +{ + bool isAVsync = false; + std::lock_guard lock(avSyncMutex_); + isAVsync = avSyncParam_.isAVsync; + return isAVsync; +} + +int32_t DMicDev::AVsyncMacthScene(std::shared_ptr &data) +{ + if (GetQueSize() < scene_ && isStartStatus_.load()) { + int64_t videoPts = 0; + int64_t audioPts = 0; + int32_t ret = ReadTimeStampFromAVsync(videoPts); + CHECK_AND_RETURN_RET_LOG(ret != DH_SUCCESS, ERR_DH_AUDIO_FAILED, "ReadTimeStampFromAVsync failed."); + if (GetQueSize() != 0) { + CHECK_NULL_RETURN(dataQueue_.back()); + audioPts = dataQueue_.back()->GetPts(); + } + int64_t diff = audioPts - videoPts + TIMESTAMP_COMPENSATION; + DHLOGD("diff: %{public}" PRId64", videoPts: %{public}" PRId64 + ", audioPts: %{public}" PRId64, diff, videoPts, audioPts); + if (diff > 5 || diff < -80) { + data = std::make_shared(param_.comParam.frameSize); + } else { + isStartStatus_.store(false); + data = dataQueue_.front(); + dataQueue_.pop_front(); + } + return DH_SUCCESS; + } + isStartStatus_.store(false); + if (GetQueSize() == 0) { isExistedEmpty_.store(true); DHLOGD("Data queue is empty"); data = std::make_shared(param_.comParam.frameSize); } else { data = dataQueue_.front(); - dataQueue_.pop(); + dataQueue_.pop_front(); } - CHECK_NULL_RETURN(data, ERR_DH_AUDIO_NULLPTR); + return DH_SUCCESS; +} + +int32_t DMicDev::GetAudioDataFromQueue(std::shared_ptr &data) +{ + if (IsAVsync()) { + int32_t ret = AVsyncMacthScene(data); + CHECK_AND_RETURN_RET_LOG(ret != DH_SUCCESS, ERR_DH_AUDIO_FAILED, "AVsyncMacthScene failed."); + } else { + if (GetQueSize() == 0) { + isExistedEmpty_.store(true); + DHLOGD("Data queue is empty"); + data = std::make_shared(param_.comParam.frameSize); + } else { + data = dataQueue_.front(); + dataQueue_.pop_front(); + } + } + return DH_SUCCESS; +} + +int32_t DMicDev::ReadStreamData(const int32_t streamId, std::shared_ptr &data) +{ + int64_t startTime = GetNowTimeUs(); + if (curStatus_ != AudioStatus::STATUS_START) { + DHLOGE("Distributed audio is not starting status."); + return ERR_DH_AUDIO_FAILED; + } + int32_t ret = GetAudioDataFromQueue(data); + CHECK_AND_RETURN_RET_LOG(ret != DH_SUCCESS && data == nullptr, ERR_DH_AUDIO_NULLPTR, "GetAudioData failed"); + ret = WriteTimeStampToAVsync(data->GetPts()); + CHECK_AND_RETURN_RET_LOG(ret != DH_SUCCESS, ERR_DH_AUDIO_FAILED, "WriteTimeStampToAVsync failed"); + DumpFileUtil::WriteDumpFile(dumpFileCommn_, static_cast(data->Data()), data->Size()); int64_t endTime = GetNowTimeUs(); if (IsOutDurationRange(startTime, endTime, lastReadStartTime_)) { @@ -594,7 +748,7 @@ void DMicDev::EnqueueThread() audioData = std::make_shared(param_.comParam.frameSize); } else { audioData = dataQueue_.front(); - dataQueue_.pop(); + dataQueue_.pop_front(); } if (audioData == nullptr) { DHLOGD("The audioData is nullptr."); @@ -705,8 +859,8 @@ int32_t DMicDev::OnDecodeTransDataDone(const std::shared_ptr &audioDa CHECK_NULL_RETURN(audioData, ERR_DH_AUDIO_NULLPTR); std::lock_guard lock(dataQueueMtx_); dataQueSize_ = curStatus_ != AudioStatus::STATUS_START ? - (param_.captureOpts.capturerFlags == MMAP_MODE ? lowLatencyHalfSize_ : DATA_QUEUE_HALF_SIZE) : - (param_.captureOpts.capturerFlags == MMAP_MODE ? lowLatencyMaxfSize_ : DATA_QUEUE_MAX_SIZE); + (param_.captureOpts.capturerFlags == MMAP_MODE ? lowLatencyHalfSize_ : scene_) : + (param_.captureOpts.capturerFlags == MMAP_MODE ? lowLatencyMaxfSize_ : scene_ + scene_); if (isExistedEmpty_.load()) { dataQueSize_ = param_.captureOpts.capturerFlags == MMAP_MODE ? dataQueSize_ : DATA_QUEUE_EXT_SIZE; } @@ -714,12 +868,64 @@ int32_t DMicDev::OnDecodeTransDataDone(const std::shared_ptr &audioDa while (dataQueue_.size() > dataQueSize_) { queueSize = static_cast(dataQueue_.size()); DHLOGD("Data queue overflow. buf current size: %{public}" PRIu64, queueSize); - dataQueue_.pop(); + dataQueue_.pop_front(); + + } + auto dataEnque = std::make_shared(param_.comParam.frameSize); + if (memcpy_s(dataEnque->Data(), dataEnque->Capacity(), audioData->Data(), audioData->Capacity()) != EOK) { + DHLOGE("memcpy_s failed, empty frame."); } - dataQueue_.push(audioData); + dataEnque->SetPts(audioData->GetPts()); + dataQueue_.push_back(dataEnque); queueSize = static_cast(dataQueue_.size()); DHLOGD("Push new mic data, buf len: %{public}" PRIu64, queueSize); return DH_SUCCESS; } + +int32_t DMicDev::AVsyncRefreshAshmem(int32_t fd, int32_t ashmemLength) +{ + DHLOGD("AVsync mode: fd:%{public}d, ashmemLength: %{public}d", fd, ashmemLength); + if (avsyncAshmem_ != nullptr) { + return DH_SUCCESS; + } + if (ashmemLength < ASHMEM_MAX_LEN && fd > 0) { + avsyncAshmem_ = sptr(new Ashmem(fd, ashmemLength)); + ashmemLength_ = ashmemLength; + DHLOGD("Create ashmem success. fd:%{public}d, ashmem length: %{public}d", fd, ashmemLength_); + bool mapRet = avsyncAshmem_->MapReadAndWriteAshmem(); + if (!mapRet) { + DHLOGE("Mmap ashmem failed."); + return ERR_DH_AUDIO_NULLPTR; + } + } + return DH_SUCCESS; +} + +void DMicDev::AVsyncDeintAshmem() +{ + if (avsyncAshmem_ != nullptr) { + avsyncAshmem_->UnmapAshmem(); + avsyncAshmem_->CloseAshmem(); + avsyncAshmem_ = nullptr; + } +} + +int32_t DMicDev::UpdateWorkModeParam(const std::string &devId, const std::string &dhId, const AudioAsyncParam ¶m) +{ + std::lock_guard lock(avSyncMutex_); + avSyncParam_ = param; + if (avSyncParam_.isAVsync) { + auto ret = AVsyncRefreshAshmem(avSyncParam_.fd, avSyncParam_.sharedMemLen); + CHECK_AND_RETURN_RET_LOG(ret != DH_SUCCESS, ret, "AVsyncRefreshAshmemInfo failed"); + scene_ = avSyncParam_.scene == AudioAVScene::BROADCAST ? DATA_QUEUE_BROADCAST_SIZE : DATA_QUEUE_VIDEOCALL_SIZE; + DHLOGI("AVsync mode opened"); + } else { + AVsyncDeintAshmem(); + avSyncParam_.fd = -1; + avSyncParam_.sharedMemLen = 0; + DHLOGI("AVsync mode closed"); + } + return DH_SUCCESS; +} } // DistributedHardware } // OHOS diff --git a/services/audiomanager/managersource/src/dspeaker_dev.cpp b/services/audiomanager/managersource/src/dspeaker_dev.cpp index 18ee517273e9ff07888bfdbe26f2ec7c31205319..7457e0cfdc3e68e9ef292f59936d74a339a8af7d 100644 --- a/services/audiomanager/managersource/src/dspeaker_dev.cpp +++ b/services/audiomanager/managersource/src/dspeaker_dev.cpp @@ -552,5 +552,14 @@ int32_t DSpeakerDev::OnDecodeTransDataDone(const std::shared_ptr &aud (void) audioData; return DH_SUCCESS; } + +int32_t DSpeakerDev::UpdateWorkModeParam(const std::string &devId, const std::string &dhId, + const AudioAsyncParam ¶m) +{ + (void)devId; + (void)dhId; + (void)param; + return DH_SUCCESS; +} } // DistributedHardware } // OHOS diff --git a/services/audiomanager/servicesource/include/daudio_source_service.h b/services/audiomanager/servicesource/include/daudio_source_service.h index 6bf5a4ef90efb5740e57eb2cb1cbde824b07c23f..1e214917e6b88332d42c9edaafc0a72314c89dc2 100644 --- a/services/audiomanager/servicesource/include/daudio_source_service.h +++ b/services/audiomanager/servicesource/include/daudio_source_service.h @@ -45,6 +45,8 @@ public: void DAudioNotify(const std::string &devId, const std::string &dhId, const int32_t eventType, const std::string &eventContent) override; int Dump(int32_t fd, const std::vector& args) override; + int32_t DAudioSourceService::UpdateDistributedWorkMode(const std::string &devId, const std::string &dhId, + const WorkModeParam ¶ms) override; protected: void OnStart() override; diff --git a/services/audiomanager/servicesource/include/daudio_source_stub.h b/services/audiomanager/servicesource/include/daudio_source_stub.h index 7cef6bb263e81825444ec46e44ec9ed28d157514..e7125a448e59a24e13f1293fa8b334d1e2469d48 100644 --- a/services/audiomanager/servicesource/include/daudio_source_stub.h +++ b/services/audiomanager/servicesource/include/daudio_source_stub.h @@ -38,6 +38,7 @@ private: int32_t ConfigDistributedHardwareInner(MessageParcel &data, MessageParcel &reply, MessageOption &option); int32_t DAudioNotifyInner(MessageParcel &data, MessageParcel &reply, MessageOption &option); bool VerifyPermission(); + int32_t UpdateDAudioWorkModeInner(MessageParcel &data, MessageParcel &reply, MessageOption &option) using DAudioSourceServiceFunc = int32_t (DAudioSourceStub::*)(MessageParcel &data, MessageParcel &reply, MessageOption &option); diff --git a/services/audiomanager/servicesource/src/daudio_source_service.cpp b/services/audiomanager/servicesource/src/daudio_source_service.cpp index e77ff184ff9383015603f32ed45269ce42d8e33c..5078c8bf761b743ff19cae07fb55e05f06e0bad0 100644 --- a/services/audiomanager/servicesource/src/daudio_source_service.cpp +++ b/services/audiomanager/servicesource/src/daudio_source_service.cpp @@ -157,5 +157,19 @@ int DAudioSourceService::Dump(int32_t fd, const std::vector& arg return DH_SUCCESS; } + +int32_t DAudioSourceService::UpdateDistributedWorkMode(const std::string &devId, const std::string &dhId, + const WorkModeParam ¶ms) +{ + DHLOGI("Update workmode, devId: %{public}s, dhId: %{public}s.", GetAnonyString(devId).c_str(), + dhId.c_str()); + AudioAsyncParam asyncParam; + asyncParam.fd = params.fd; + asyncParam.sharedMemLen = params.sharedMemLen; + asyncParam.scene = params.scene; + asyncParam.isAVsync = params.isAVsync; + DAudioSourceManager::GetInstance().UpdateDistributedWorkMode(devId, dhId, asyncParam); + return DH_SUCCESS; +} } // namespace DistributedHardware } // namespace OHOS \ No newline at end of file diff --git a/services/audiomanager/servicesource/src/daudio_source_stub.cpp b/services/audiomanager/servicesource/src/daudio_source_stub.cpp index 93491e4d1f8deaf2267684e520128d6413950fdc..82ecfc16a9952b3f729d3c51bb0caec9aee5a556 100644 --- a/services/audiomanager/servicesource/src/daudio_source_stub.cpp +++ b/services/audiomanager/servicesource/src/daudio_source_stub.cpp @@ -44,6 +44,8 @@ DAudioSourceStub::DAudioSourceStub() : IRemoteStub(true) &DAudioSourceStub::ConfigDistributedHardwareInner; memberFuncMap_[static_cast(IDAudioSourceInterfaceCode::DAUDIO_NOTIFY)] = &DAudioSourceStub::DAudioNotifyInner; + memberFuncMap_[static_cast(IDAudioSourceInterfaceCode::UPDATE_WORKMODE)] = + &DAudioSourceStub::UpdateDAudioWorkModeInner; } int32_t DAudioSourceStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, @@ -70,6 +72,8 @@ int32_t DAudioSourceStub::OnRemoteRequest(uint32_t code, MessageParcel &data, Me return ConfigDistributedHardwareInner(data, reply, option); case static_cast(IDAudioSourceInterfaceCode::DAUDIO_NOTIFY): return DAudioNotifyInner(data, reply, option); + case static_cast(IDAudioSourceInterfaceCode::UPDATE_WORKMODE): + return UpdateDAudioWorkModeInner(data, reply, option); default: DHLOGE("Invalid request code."); return IPCObjectStub::OnRemoteRequest(code, data, reply, option); @@ -177,5 +181,25 @@ int32_t DAudioSourceStub::DAudioNotifyInner(MessageParcel &data, MessageParcel & DAudioNotify(networkId, dhId, eventType, eventContent); return DH_SUCCESS; } + +int32_t DAudioSourceStub::UpdateDAudioWorkModeInner(MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + // if (!VerifyPermission()) { + // DHLOGE("Permission verification fail."); + // return ERR_DH_AUDIO_SA_PERMISSION_FAIED; + // } + std::string devId = data.ReadString(); + std::string dhId = data.ReadString(); + WorkModeParam params(-1, 0, 0, 0); + params.fd = data.ReadFileDescriptor(); // fd need to close + + params.sharedMemLen = data.ReadInt32(); + params.scene = data.ReadUint32(); + params.isAVsync = data.ReadInt32(); + + int32_t ret = UpdateDistributedWorkMode(devId, dhId, params); + reply.WriteInt32(ret); + return DH_SUCCESS; +} } // namespace DistributedHardware } // namespace OHOS diff --git a/services/audiotransport/receiverengine/src/av_receiver_engine_transport.cpp b/services/audiotransport/receiverengine/src/av_receiver_engine_transport.cpp index 036dd8f0e89f6a110807dec403af7f4df5dda376..5e98c712e1632e65f05bf8050b0ef1e89e735659 100644 --- a/services/audiotransport/receiverengine/src/av_receiver_engine_transport.cpp +++ b/services/audiotransport/receiverengine/src/av_receiver_engine_transport.cpp @@ -138,6 +138,8 @@ void AVTransReceiverTransport::OnEngineDataAvailable(const std::shared_ptrSetPts(buffer->GetPts()); + audioData->SetPtsSpecial(buffer->GetPtsSpecial()); auto sourceDevObj = transCallback_.lock(); CHECK_NULL_VOID(sourceDevObj); sourceDevObj->OnEngineTransDataAvailable(audioData); diff --git a/services/audiotransport/senderengine/src/av_sender_engine_adapter.cpp b/services/audiotransport/senderengine/src/av_sender_engine_adapter.cpp index fd0205f296465eabbffcdfca7d5feea58883c425..0f7aee30f64684bea5582e6739e0a8032401fb53 100644 --- a/services/audiotransport/senderengine/src/av_sender_engine_adapter.cpp +++ b/services/audiotransport/senderengine/src/av_sender_engine_adapter.cpp @@ -112,6 +112,7 @@ int32_t AVTransSenderAdapter::PushData(std::shared_ptr &audioData) CHECK_NULL_RETURN(bufferData, ERR_DH_AUDIO_NULLPTR); bufferData->Write(audioData->Data(), audioData->Size()); + transBuffer->SetPts(audioData->GetPts()); return senderEngine_->PushData(transBuffer); } diff --git a/services/common/audiodata/include/audio_data.h b/services/common/audiodata/include/audio_data.h index 333616075261dd2c879d621ace0f0da564a5bd6c..0dd6594e14194b87197fb6d2b4387ad8e7ba448b 100644 --- a/services/common/audiodata/include/audio_data.h +++ b/services/common/audiodata/include/audio_data.h @@ -33,6 +33,10 @@ public: size_t Capacity() const; uint8_t *Data() const; int32_t SetRange(size_t offset, size_t size); + void SetPts(int64_t pts); + int64_t GetPts(); + void SetPtsSpecial(int64_t pts); + int64_t GetPtsSpecial(); void SetInt64(const string name, int64_t value); bool FindInt32(const string &name, int32_t &value); @@ -45,6 +49,8 @@ private: size_t rangeOffset_ = 0; size_t rangeLength_ = 0; uint8_t *data_ = nullptr; + int64_t pts_ = 0; + int64_t ptsSpecial_ = 0; map int32Map_; map int64Map_; diff --git a/services/common/audiodata/src/audio_data.cpp b/services/common/audiodata/src/audio_data.cpp index 8f5b2a1ab668243030d84e783e763154b95f122b..5698561d544dd0c81e704e615a0dc8e7b816e7eb 100644 --- a/services/common/audiodata/src/audio_data.cpp +++ b/services/common/audiodata/src/audio_data.cpp @@ -55,6 +55,26 @@ int32_t AudioData::SetRange(size_t offset, size_t size) return DH_SUCCESS; } +void AudioData::SetPts(int64_t pts) +{ + pts_ = pts; +} + +int64_t AudioData::GetPts() +{ + return pts_; +} + +void AudioData::SetPtsSpecial(int64_t pts) +{ + ptsSpecial_ = pts; +} + +int64_t AudioData::GetPtsSpecial() +{ + return ptsSpecial_; +} + void AudioData::SetInt64(const string name, int64_t value) { int64Map_[name] = value;