diff --git a/services/audio_service/server/include/audio_playback_engine.h b/services/audio_service/server/include/audio_playback_engine.h index 3e0745fbca57be2f436ebd0b55d2145724fcb1cd..0f4b8caf4161e01974590a9b273c30c402e4d190 100644 --- a/services/audio_service/server/include/audio_playback_engine.h +++ b/services/audio_service/server/include/audio_playback_engine.h @@ -34,6 +34,7 @@ public: virtual int32_t Stop() override; virtual int32_t Pause() override; virtual int32_t Flush() override; + virtual uint64_t GetLatency() noexcept override; virtual bool IsPlaybackEngineRunning() const noexcept override; diff --git a/services/audio_service/server/include/i_audio_engine.h b/services/audio_service/server/include/i_audio_engine.h index 575a6a4633e8b8b52eba59dac9a1c8fbe7baebe7..8f32c381a9c89d2c06e77f3b328a01672e18f392 100644 --- a/services/audio_service/server/include/i_audio_engine.h +++ b/services/audio_service/server/include/i_audio_engine.h @@ -29,6 +29,7 @@ public: virtual int32_t Pause() = 0; virtual int32_t Flush() = 0; virtual bool IsPlaybackEngineRunning() const noexcept = 0; + virtual uint64_t GetLatency() noexcept = 0; }; } // namespace AudioStandard } // namespace OHOS diff --git a/services/audio_service/server/include/i_stream_manager.h b/services/audio_service/server/include/i_stream_manager.h index 56d13d3942b6834dc6215c1ef126c0a2076e8235..810e75f2edb989c833c6a2c9bcf64c254a9f3a45 100644 --- a/services/audio_service/server/include/i_stream_manager.h +++ b/services/audio_service/server/include/i_stream_manager.h @@ -49,6 +49,7 @@ public: virtual int32_t CreateCapturer(AudioProcessConfig processConfig, std::shared_ptr &stream) = 0; virtual int32_t ReleaseCapturer(uint32_t streamIndex_) = 0; virtual int32_t AddUnprocessStream(int32_t appUid) = 0; + virtual uint64_t GetLatency() noexcept = 0; }; } // namespace AudioStandard } // namespace OHOS diff --git a/services/audio_service/server/include/none_mix_engine.h b/services/audio_service/server/include/none_mix_engine.h index 5d2fe39591336941590461b24e47a74d2dd1aae9..9a1d6fbcd5f6239a3651f24518c3679aa748d48f 100644 --- a/services/audio_service/server/include/none_mix_engine.h +++ b/services/audio_service/server/include/none_mix_engine.h @@ -35,6 +35,8 @@ public: void RemoveRenderer(const std::shared_ptr &stream) override; bool IsPlaybackEngineRunning() const noexcept override; + uint64_t GetLatency() noexcept override; + protected: void MixStreams() override; @@ -60,6 +62,7 @@ private: std::atomic failedCount_; uint64_t writeCount_; uint64_t fwkSyncTime_; + uint64_t latency_; std::shared_ptr stream_; std::mutex startMutex; diff --git a/services/audio_service/server/include/pa_adapter_manager.h b/services/audio_service/server/include/pa_adapter_manager.h index cc2405cf362896421392e34187baa9748e9bd793..87bf9b14408b5a8764d49b54416e87ade842311c 100644 --- a/services/audio_service/server/include/pa_adapter_manager.h +++ b/services/audio_service/server/include/pa_adapter_manager.h @@ -72,6 +72,7 @@ public: int32_t ReleaseCapturer(uint32_t streamIndex_) override; int32_t AddUnprocessStream(int32_t appUid) override; uint32_t ConvertChLayoutToPaChMap(const uint64_t &channelLayout, pa_channel_map &paMap); + uint64_t GetLatency() noexcept override; private: // audio channel index diff --git a/services/audio_service/server/include/pro_audio_stream_manager.h b/services/audio_service/server/include/pro_audio_stream_manager.h index db7cb5048bbf1fd9290aa40dfeb694a975e2e617..5b1d1bb6a114e9163af046320fecff75005dbc9d 100644 --- a/services/audio_service/server/include/pro_audio_stream_manager.h +++ b/services/audio_service/server/include/pro_audio_stream_manager.h @@ -38,6 +38,9 @@ public: int32_t ReleaseCapturer(uint32_t streamIndex) override; int32_t AddUnprocessStream(int32_t appUid) override; + + uint64_t GetLatency() noexcept override; + private: std::shared_ptr CreateRendererStream(AudioProcessConfig processConfig); int32_t CreatePlayBackEngine(const std::shared_ptr &stream); diff --git a/services/audio_service/server/src/audio_playback_engine.cpp b/services/audio_service/server/src/audio_playback_engine.cpp index ef42d37804094422ba2fb35eca955b262cca8d2b..f559d5ca49aad1b667644edb9bdadbbe50a8808a 100644 --- a/services/audio_service/server/src/audio_playback_engine.cpp +++ b/services/audio_service/server/src/audio_playback_engine.cpp @@ -68,5 +68,10 @@ bool AudioPlaybackEngine::IsPlaybackEngineRunning() const noexcept { return false; } + +uint64_t AudioPlaybackEngine::GetLatency() noexcept +{ + return 0; +} } // namespace AudioStandard } // namespace OHOS diff --git a/services/audio_service/server/src/none_mix_engine.cpp b/services/audio_service/server/src/none_mix_engine.cpp index bff85ec0d58e4116abd2c11e0579292d352ecc68..1b6de6e88393335105bb9effbee55aba1221f22a 100644 --- a/services/audio_service/server/src/none_mix_engine.cpp +++ b/services/audio_service/server/src/none_mix_engine.cpp @@ -27,6 +27,9 @@ namespace OHOS { namespace AudioStandard { constexpr int32_t DELTA_TIME = 4000000; // 4ms constexpr int32_t PERIOD_NS = 20000000; // 20ms +constexpr int32_t AUDIO_US_PER_MS = 1000; +constexpr int32_t AUDIO_DEFAULT_LATENCY_US = 160000; +constexpr int32_t AUDIO_FRAME_WORK_LATENCY_US = 40000; constexpr int32_t FADING_MS = 20; // 20ms constexpr int32_t MAX_ERROR_COUNT = 50; constexpr int16_t STEREO_CHANNEL_COUNT = 2; @@ -46,6 +49,7 @@ NoneMixEngine::NoneMixEngine() failedCount_(0), writeCount_(0), fwkSyncTime_(0), + latency_(0), stream_(nullptr), startFadein_(false), startFadeout_(false), @@ -106,6 +110,7 @@ int32_t NoneMixEngine::Start() playbackThread_ = std::make_unique(THREAD_NAME); playbackThread_->RegisterJob([this] { this->MixStreams(); }); } + latency_ = 0; if (!isStart_) { startFadeout_ = false; startFadein_ = true; @@ -453,5 +458,24 @@ int32_t NoneMixEngine::SwitchSink(const AudioStreamInfo &streamInfo, bool isVoip isVoip_ = isVoip; return InitSink(streamInfo); } + +uint64_t NoneMixEngine::GetLatency() noexcept +{ + if (!isStart_) { + return 0; + } + if (latency_ > 0) { + return latency_; + } + uint32_t latency = 0; + if (renderSink_->GetLatency(&latency) == 0) { + latency_ = latency * AUDIO_US_PER_MS + AUDIO_FRAME_WORK_LATENCY_US; + } else { + AUDIO_INFO_LOG("get latency failed,use default"); + latency_ = AUDIO_DEFAULT_LATENCY_US; + } + AUDIO_INFO_LOG("latency value:%{public}" PRId64 " ns", latency_); + return latency_; +} } // namespace AudioStandard } // namespace OHOS diff --git a/services/audio_service/server/src/pa_adapter_manager.cpp b/services/audio_service/server/src/pa_adapter_manager.cpp index 2ba6cd4d5274de26f6e7fefa030f201d3b03e046..893e41c2be6333ed64fbf128513a61999b535aa9 100644 --- a/services/audio_service/server/src/pa_adapter_manager.cpp +++ b/services/audio_service/server/src/pa_adapter_manager.cpp @@ -884,5 +884,10 @@ const std::string PaAdapterManager::GetEnhanceSceneName(SourceType sourceType) return sceneName; } +uint64_t PaAdapterManager::GetLatency() noexcept +{ + return 0; +} + } // namespace AudioStandard } // namespace OHOS diff --git a/services/audio_service/server/src/pro_audio_stream_manager.cpp b/services/audio_service/server/src/pro_audio_stream_manager.cpp index c3fc8e89a48386f5ee8b186c571551cb24b31b28..54b9c0764ed822aecb12c57e2f3fb97735d0ddc9 100644 --- a/services/audio_service/server/src/pro_audio_stream_manager.cpp +++ b/services/audio_service/server/src/pro_audio_stream_manager.cpp @@ -214,5 +214,11 @@ int32_t ProAudioStreamManager::AddUnprocessStream(int32_t appUid) return SUCCESS; } +uint64_t ProAudioStreamManager::GetLatency() noexcept +{ + CHECK_AND_RETURN_RET_LOG(playbackEngine_ != nullptr, 0, "engine not init"); + return playbackEngine_->GetLatency(); +} + } // namespace AudioStandard } // namespace OHOS \ No newline at end of file diff --git a/services/audio_service/server/src/renderer_in_server.cpp b/services/audio_service/server/src/renderer_in_server.cpp index 454b10f70aca494f2cc5c9505f1f707d55296a39..b9064b877b925d17154963d1f546f87ff2260d8c 100644 --- a/services/audio_service/server/src/renderer_in_server.cpp +++ b/services/audio_service/server/src/renderer_in_server.cpp @@ -986,6 +986,10 @@ int32_t RendererInServer::GetAudioPosition(uint64_t &framePos, uint64_t ×ta int32_t RendererInServer::GetLatency(uint64_t &latency) { std::unique_lock lock(statusLock_); + if (managerType_ == DIRECT_PLAYBACK) { + latency = IStreamManager::GetPlaybackManager(managerType_).GetLatency(); + return SUCCESS; + } return stream_->GetLatency(latency); } diff --git a/services/audio_service/test/unittest/none_mix_engine_unit_test.cpp b/services/audio_service/test/unittest/none_mix_engine_unit_test.cpp index 299ef0b6add32e98f19ec5a27f8653b76252a704..8bf397fcb5913adb417f124c7b23928243a398ed 100644 --- a/services/audio_service/test/unittest/none_mix_engine_unit_test.cpp +++ b/services/audio_service/test/unittest/none_mix_engine_unit_test.cpp @@ -1321,5 +1321,39 @@ HWTEST_F(NoneMixEngineUnitTest, NoneMixEngine_035, TestSize.Level1) ret = noneMixEngineRet.GetDirectFormatByteSize(formatRet); EXPECT_EQ(ret, sizeof(int32_t)); } + +/** + * @tc.name : Test NoneMixEngine API + * @tc.type : FUNC + * @tc.number: NoneMixEngine_036 + * @tc.desc : Test NoneMixEngine::GetLatency + */ +HWTEST_F(NoneMixEngineUnitTest, NoneMixEngine_036, TestSize.Level1) +{ + auto ptrNoneMixEngine = std::make_shared(); + EXPECT_NE(ptrNoneMixEngine, nullptr); + uint64_t latency = ptrNoneMixEngine->GetLatency(); + EXPECT_EQ(latency, 0); + + AudioStreamInfo streamInfo; + ptrNoneMixEngine->isInit_ = false; + ptrNoneMixEngine->renderSink_ = IAudioRendererSink::GetInstance("primary", ""); + EXPECT_NE(ptrNoneMixEngine->renderSink_, nullptr); + + streamInfo.channels = AudioChannel::CHANNEL_15; + streamInfo.format = AudioSampleFormat::SAMPLE_U8; + ptrNoneMixEngine->uChannel_ = 2; + ptrNoneMixEngine->uFormat_ = HdiAdapterFormat::SAMPLE_S16; + ptrNoneMixEngine->isVoip_ = true; + streamInfo.samplingRate = AudioSamplingRate::SAMPLE_RATE_8000; + ptrNoneMixEngine->uSampleRate_ = AudioSamplingRate::SAMPLE_RATE_16000; + bool isVoip = true; + ptrNoneMixEngine->SwitchSink(streamInfo, isVoip); + int32_t ret = ptrNoneMixEngine->Start(); + EXPECT_EQ(ret, SUCCESS); + + latency = ptrNoneMixEngine->GetLatency(); + EXPECT_NE(latency, 0); +} } // namespace AudioStandard } // namespace OHOS diff --git a/services/audio_service/test/unittest/pro_audio_stream_manager_unit_test/src/pro_audio_stream_manager_unit_test.cpp b/services/audio_service/test/unittest/pro_audio_stream_manager_unit_test/src/pro_audio_stream_manager_unit_test.cpp index 232841a5f3435afb99031a19f55a9e308596b59f..da5923d40a0b06c832a41de61166a3cc4777d472 100644 --- a/services/audio_service/test/unittest/pro_audio_stream_manager_unit_test/src/pro_audio_stream_manager_unit_test.cpp +++ b/services/audio_service/test/unittest/pro_audio_stream_manager_unit_test/src/pro_audio_stream_manager_unit_test.cpp @@ -361,6 +361,9 @@ HWTEST(ProAudioStreamManagerUnitTest, ProAudioStreamManager_012, TestSize.Level1 shared_ptr audioStreamManager = make_shared(DIRECT_PLAYBACK); ASSERT_TRUE(audioStreamManager != nullptr); + uint64_t latency = audioStreamManager->GetLatency(); + EXPECT_EQ(latency, 0); + AudioProcessConfig config; config.appInfo.appUid = CAPTURER_FLAG; config.appInfo.appPid = CAPTURER_FLAG;