From 6c56e991f5100766ff5cfc9dff3504e02fd21bbd Mon Sep 17 00:00:00 2001 From: zhanhang Date: Sat, 23 Dec 2023 22:23:25 +0800 Subject: [PATCH] Optimize latency interface Signed-off-by: zhanhang --- .../native/audiostream/include/audio_stream.h | 2 - .../bluetooth/bluetooth_renderer_sink.cpp | 7 ++ .../sink/common/i_audio_renderer_sink.h | 3 +- .../sink/fast/fast_audio_renderer_sink.cpp | 8 +++ .../sink/file/audio_renderer_file_sink.cpp | 5 ++ .../sink/file/audio_renderer_file_sink.h | 1 + .../multichannel_audio_renderer_sink.cpp | 7 ++ .../sink/primary/audio_renderer_sink.cpp | 30 ++++++++ .../remote/remote_audio_renderer_sink.cpp | 7 ++ .../remote_fast_audio_renderer_sink.cpp | 10 ++- .../source/common/i_audio_capturer_source.h | 1 + .../fast/fast_audio_capturer_source.cpp | 6 ++ .../file/audio_capturer_file_source.cpp | 5 ++ .../source/file/audio_capturer_file_source.h | 1 + .../source/primary/audio_capturer_source.cpp | 38 ++++++++++ .../remote/remote_audio_capturer_source.cpp | 7 ++ .../remote_fast_audio_capturer_source.cpp | 7 ++ frameworks/native/ohaudio/OHAudioCapturer.cpp | 13 ++-- frameworks/native/ohaudio/OHAudioCapturer.h | 2 +- frameworks/native/ohaudio/OHAudioRenderer.cpp | 13 ++-- frameworks/native/ohaudio/OHAudioRenderer.h | 2 +- .../test/example/oh_audio_capturer_test.cpp | 6 +- .../native/pulseaudio/modules/hdi/hdi_sink.c | 8 +++ .../include/audio_system_manager.h | 6 ++ .../client/include/audio_manager_base.h | 10 +++ .../client/include/audio_manager_proxy.h | 4 ++ .../client/include/audio_service_client.h | 30 ++++++++ .../include/pulseaudio_ipc_interface_code.h | 4 +- .../client/src/audio_manager_proxy.cpp | 60 ++++++++++++++++ .../client/src/audio_service_client.cpp | 69 ++++++++++++++++++- .../audio_service/client/src/audio_stream.cpp | 33 ++------- .../client/src/audio_system_manager.cpp | 22 ++++++ .../server/include/audio_server.h | 6 ++ .../server/src/audio_manager_stub.cpp | 28 ++++++++ .../audio_service/server/src/audio_server.cpp | 34 +++++++++ 35 files changed, 451 insertions(+), 44 deletions(-) diff --git a/frameworks/native/audiostream/include/audio_stream.h b/frameworks/native/audiostream/include/audio_stream.h index 5e16e5836d..afd64b20cf 100644 --- a/frameworks/native/audiostream/include/audio_stream.h +++ b/frameworks/native/audiostream/include/audio_stream.h @@ -133,8 +133,6 @@ private: AudioStreamType eStreamType_; AudioMode eMode_; State state_; - bool resetTime_; - uint64_t resetTimestamp_; struct timespec baseTimestamp_ = {0}; AudioRenderMode renderMode_; AudioCaptureMode captureMode_; diff --git a/frameworks/native/hdiadapter/sink/bluetooth/bluetooth_renderer_sink.cpp b/frameworks/native/hdiadapter/sink/bluetooth/bluetooth_renderer_sink.cpp index a84b7a4110..6c3924cf09 100644 --- a/frameworks/native/hdiadapter/sink/bluetooth/bluetooth_renderer_sink.cpp +++ b/frameworks/native/hdiadapter/sink/bluetooth/bluetooth_renderer_sink.cpp @@ -85,6 +85,7 @@ public: int32_t GetTransactionId(uint64_t *transactionId) override; void SetAudioMonoState(bool audioMono) override; void SetAudioBalanceValue(float audioBalance) override; + int32_t GetPresentationPosition(uint64_t& frames, int64_t& timeSec, int64_t& timeNanoSec) override; int32_t SetVoiceVolume(float volume) override; int32_t SetAudioScene(AudioScene audioScene, DeviceType activeDevice) override; @@ -745,6 +746,12 @@ void BluetoothRendererSinkInner::SetAudioBalanceValue(float audioBalance) } } +int32_t BluetoothRendererSinkInner::GetPresentationPosition(uint64_t& frames, int64_t& timeSec, int64_t& timeNanoSec) +{ + AUDIO_ERR_LOG("BluetoothRendererSink GetPresentationPosition not supported."); + return ERR_NOT_SUPPORTED; +} + void BluetoothRendererSinkInner::AdjustStereoToMono(char *data, uint64_t len) { if (attr_.channel != STEREO_CHANNEL_COUNT) { diff --git a/frameworks/native/hdiadapter/sink/common/i_audio_renderer_sink.h b/frameworks/native/hdiadapter/sink/common/i_audio_renderer_sink.h index 9fff3d23f5..fa2561c738 100644 --- a/frameworks/native/hdiadapter/sink/common/i_audio_renderer_sink.h +++ b/frameworks/native/hdiadapter/sink/common/i_audio_renderer_sink.h @@ -78,6 +78,8 @@ public: virtual void SetAudioMonoState(bool audioMono) = 0; virtual void SetAudioBalanceValue(float audioBalance) = 0; + virtual int32_t GetPresentationPosition(uint64_t &frames, int64_t &timeSec, int64_t &timeNanoSec) = 0; + virtual int32_t Preload(const std::string &usbInfoStr) { return 0; @@ -103,7 +105,6 @@ public: IOffloadAudioRendererSink() = default; virtual ~IOffloadAudioRendererSink() = default; virtual int32_t RegisterRenderCallback(OnRenderCallback (*callback), int8_t *userdata) = 0; - virtual int32_t GetPresentationPosition(uint64_t &frames, int64_t &timeSec, int64_t &timeNanoSec) = 0; virtual int32_t Drain(AudioDrainType type) = 0; virtual int32_t SetBufferSize(uint32_t sizeMs) = 0; diff --git a/frameworks/native/hdiadapter/sink/fast/fast_audio_renderer_sink.cpp b/frameworks/native/hdiadapter/sink/fast/fast_audio_renderer_sink.cpp index ce232ac1f5..7e7e309ab7 100644 --- a/frameworks/native/hdiadapter/sink/fast/fast_audio_renderer_sink.cpp +++ b/frameworks/native/hdiadapter/sink/fast/fast_audio_renderer_sink.cpp @@ -86,6 +86,8 @@ public: void SetAudioMonoState(bool audioMono) override; void SetAudioBalanceValue(float audioBalance) override; + int32_t GetPresentationPosition(uint64_t& frames, int64_t& timeSec, int64_t& timeNanoSec) override; + int32_t GetMmapBufferInfo(int &fd, uint32_t &totalSizeInframe, uint32_t &spanSizeInframe, uint32_t &byteSizePerFrame) override; int32_t GetMmapHandlePosition(uint64_t &frames, int64_t &timeSec, int64_t &timeNanoSec) override; @@ -759,6 +761,12 @@ void FastAudioRendererSinkInner::SetAudioBalanceValue(float audioBalance) return; } +int32_t FastAudioRendererSinkInner::GetPresentationPosition(uint64_t& frames, int64_t& timeSec, int64_t& timeNanoSec) +{ + AUDIO_ERR_LOG("FastAudioRendererSink GetPresentationPosition not supported."); + return ERR_NOT_SUPPORTED; +} + int32_t FastAudioRendererSinkInner::GetTransactionId(uint64_t *transactionId) { AUDIO_ERR_LOG("FastAudioRendererSink %{public}s", __func__); diff --git a/frameworks/native/hdiadapter/sink/file/audio_renderer_file_sink.cpp b/frameworks/native/hdiadapter/sink/file/audio_renderer_file_sink.cpp index 58ad511d49..2f8924b982 100644 --- a/frameworks/native/hdiadapter/sink/file/audio_renderer_file_sink.cpp +++ b/frameworks/native/hdiadapter/sink/file/audio_renderer_file_sink.cpp @@ -100,6 +100,11 @@ void AudioRendererFileSink::SetAudioBalanceValue(float audioBalance) return; } +int32_t AudioRendererFileSink::GetPresentationPosition(uint64_t& frames, int64_t& timeSec, int64_t& timeNanoSec) +{ + return ERR_NOT_SUPPORTED; +} + void AudioRendererFileSink::DeInit() { if (filePtr_ != nullptr) { diff --git a/frameworks/native/hdiadapter/sink/file/audio_renderer_file_sink.h b/frameworks/native/hdiadapter/sink/file/audio_renderer_file_sink.h index 05af455b64..936a5dcf05 100644 --- a/frameworks/native/hdiadapter/sink/file/audio_renderer_file_sink.h +++ b/frameworks/native/hdiadapter/sink/file/audio_renderer_file_sink.h @@ -57,6 +57,7 @@ public: void SetAudioMonoState(bool audioMono) override; void SetAudioBalanceValue(float audioBalance) override; + int32_t GetPresentationPosition(uint64_t& frames, int64_t& timeSec, int64_t& timeNanoSec) override; private: AudioRendererFileSink(); ~AudioRendererFileSink(); diff --git a/frameworks/native/hdiadapter/sink/multichannel/multichannel_audio_renderer_sink.cpp b/frameworks/native/hdiadapter/sink/multichannel/multichannel_audio_renderer_sink.cpp index b795c9051b..425405486c 100644 --- a/frameworks/native/hdiadapter/sink/multichannel/multichannel_audio_renderer_sink.cpp +++ b/frameworks/native/hdiadapter/sink/multichannel/multichannel_audio_renderer_sink.cpp @@ -97,6 +97,7 @@ public: void SetAudioParameter(const AudioParamKey key, const std::string &condition, const std::string &value) override; std::string GetAudioParameter(const AudioParamKey key, const std::string &condition) override; void RegisterParameterCallback(IAudioSinkCallback* callback) override; + int32_t GetPresentationPosition(uint64_t& frames, int64_t& timeSec, int64_t& timeNanoSec) override; void SetAudioMonoState(bool audioMono) override; void SetAudioBalanceValue(float audioBalance) override; @@ -350,6 +351,12 @@ void MultiChannelRendererSinkInner::RegisterParameterCallback(IAudioSinkCallback AUDIO_ERR_LOG("RegisterParameterCallback not supported."); } +int32_t MultiChannelRendererSinkInner::GetPresentationPosition(uint64_t& frames, int64_t& timeSec, int64_t& timeNanoSec) +{ + AUDIO_ERR_LOG("not supported."); + return ERR_INVALID_HANDLE; +} + void MultiChannelRendererSinkInner::DeInit() { AUDIO_INFO_LOG("Mch DeInit."); diff --git a/frameworks/native/hdiadapter/sink/primary/audio_renderer_sink.cpp b/frameworks/native/hdiadapter/sink/primary/audio_renderer_sink.cpp index b627b59ffa..c890ea9946 100644 --- a/frameworks/native/hdiadapter/sink/primary/audio_renderer_sink.cpp +++ b/frameworks/native/hdiadapter/sink/primary/audio_renderer_sink.cpp @@ -58,6 +58,8 @@ const unsigned int TIME_OUT_SECONDS = 5; constexpr int32_t RUNNINGLOCK_LOCK_TIMEOUTMS_LASTING = -1; #endif const int32_t SLEEP_TIME_FOR_RENDER_EMPTY = 120; + +const int64_t SECOND_TO_NANOSECOND = 1000000000; } class AudioRendererSinkInner : public AudioRendererSink { public: @@ -86,6 +88,7 @@ public: void SetAudioMonoState(bool audioMono) override; void SetAudioBalanceValue(float audioBalance) override; + int32_t GetPresentationPosition(uint64_t& frames, int64_t& timeSec, int64_t& timeNanoSec) override; int32_t SetOutputRoute(DeviceType outputDevice) override; int32_t SetOutputRoute(DeviceType outputDevice, AudioPortPin &outputPortPin); @@ -258,6 +261,33 @@ void AudioRendererSinkInner::SetAudioBalanceValue(float audioBalance) } } +int32_t AudioRendererSinkInner::GetPresentationPosition(uint64_t& frames, int64_t& timeSec, int64_t& timeNanoSec) +{ + int32_t ret; + if (audioRender_ == nullptr) { + AUDIO_ERR_LOG("failed audioRender_ is NULL"); + return ERR_INVALID_HANDLE; + } + struct AudioTimeStamp timestamp = {}; + ret = audioRender_->GetRenderPosition(audioRender_, &frames, ×tamp); + if (ret != 0) { + AUDIO_ERR_LOG("GetRenderPosition from hdi failed"); + return ERR_OPERATION_FAILED; + } + int64_t maxSec = 9223372036; // (9223372036 + 1) * 10^9 > INT64_MAX, seconds should not bigger than it; + if (timestamp.tvSec < 0 || timestamp.tvSec > maxSec || timestamp.tvNSec < 0 || + timestamp.tvNSec > SECOND_TO_NANOSECOND) { + AUDIO_ERR_LOG( + "Hdi GetRenderPosition get invaild second:%{public}" PRIu64 " or nanosecond:%{public}" PRIu64 " !", + timestamp.tvSec, timestamp.tvNSec); + return ERR_OPERATION_FAILED; + } + + timeSec = timestamp.tvSec; + timeNanoSec = timestamp.tvNSec; + return ret; +} + void AudioRendererSinkInner::AdjustStereoToMono(char *data, uint64_t len) { if (attr_.channel != STEREO_CHANNEL_COUNT) { diff --git a/frameworks/native/hdiadapter/sink/remote/remote_audio_renderer_sink.cpp b/frameworks/native/hdiadapter/sink/remote/remote_audio_renderer_sink.cpp index 89846b596a..3cca31a147 100644 --- a/frameworks/native/hdiadapter/sink/remote/remote_audio_renderer_sink.cpp +++ b/frameworks/native/hdiadapter/sink/remote/remote_audio_renderer_sink.cpp @@ -78,6 +78,7 @@ public: std::string GetAudioParameter(const AudioParamKey key, const std::string &condition) override; void SetAudioMonoState(bool audioMono) override; void SetAudioBalanceValue(float audioBalance) override; + int32_t GetPresentationPosition(uint64_t& frames, int64_t& timeSec, int64_t& timeNanoSec) override; void RegisterParameterCallback(IAudioSinkCallback* callback) override; void OnAudioParamChange(const std::string &adapterName, const AudioParamKey key, const std::string &condition, @@ -643,6 +644,12 @@ void RemoteAudioRendererSinkInner::SetAudioBalanceValue(float audioBalance) return; } +int32_t RemoteAudioRendererSinkInner::GetPresentationPosition(uint64_t& frames, int64_t& timeSec, int64_t& timeNanoSec) +{ + AUDIO_ERR_LOG("GetPresentationPosition not supported"); + return ERR_NOT_SUPPORTED; +} + std::string RemoteAudioRendererSinkInner::GetNetworkId() { return deviceNetworkId_; diff --git a/frameworks/native/hdiadapter/sink/remote_fast/remote_fast_audio_renderer_sink.cpp b/frameworks/native/hdiadapter/sink/remote_fast/remote_fast_audio_renderer_sink.cpp index a9ba0d60f5..8b2ddf6ab7 100644 --- a/frameworks/native/hdiadapter/sink/remote_fast/remote_fast_audio_renderer_sink.cpp +++ b/frameworks/native/hdiadapter/sink/remote_fast/remote_fast_audio_renderer_sink.cpp @@ -75,6 +75,7 @@ public: std::string GetAudioParameter(const AudioParamKey key, const std::string &condition) override; void SetAudioMonoState(bool audioMono) override; void SetAudioBalanceValue(float audioBalance) override; + int32_t GetPresentationPosition(uint64_t& frames, int64_t& timeSec, int64_t& timeNanoSec) override; void RegisterParameterCallback(IAudioSinkCallback* callback) override; int32_t GetMmapBufferInfo(int &fd, uint32_t &totalSizeInframe, uint32_t &spanSizeInframe, @@ -667,6 +668,13 @@ void RemoteFastAudioRendererSinkInner::SetAudioBalanceValue(float audioBalance) return; } +int32_t RemoteFastAudioRendererSinkInner::GetPresentationPosition(uint64_t& frames, int64_t& timeSec, + int64_t& timeNanoSec) +{ + AUDIO_ERR_LOG("GetPresentationPosition not supported"); + return ERR_NOT_SUPPORTED; +} + int32_t RemoteFastAudioRendererSinkInner::SetAudioScene(AudioScene audioScene, DeviceType activeDevice) { AUDIO_INFO_LOG("SetAudioScene not supported"); @@ -695,4 +703,4 @@ OHOS::AudioStandard::IAudioSinkCallback* RemoteFastAudioRendererSinkInner::GetPa return callback_; } } // namespace AudioStandard -} // namespace OHOS \ No newline at end of file +} // namespace OHOS diff --git a/frameworks/native/hdiadapter/source/common/i_audio_capturer_source.h b/frameworks/native/hdiadapter/source/common/i_audio_capturer_source.h index d4467062b2..37006c7e77 100644 --- a/frameworks/native/hdiadapter/source/common/i_audio_capturer_source.h +++ b/frameworks/native/hdiadapter/source/common/i_audio_capturer_source.h @@ -73,6 +73,7 @@ public: virtual int32_t SetAudioScene(AudioScene audioScene, DeviceType activeDevice) = 0; virtual int32_t SetInputRoute(DeviceType deviceType) = 0; virtual uint64_t GetTransactionId() = 0; + virtual int32_t GetPresentationPosition(uint64_t& frames, int64_t& timeSec, int64_t& timeNanoSec) = 0; virtual void RegisterWakeupCloseCallback(IAudioSourceCallback *callback) = 0; virtual void RegisterAudioCapturerSourceCallback(IAudioSourceCallback *callback) = 0; diff --git a/frameworks/native/hdiadapter/source/fast/fast_audio_capturer_source.cpp b/frameworks/native/hdiadapter/source/fast/fast_audio_capturer_source.cpp index 0d85d8e05b..78981b20d9 100644 --- a/frameworks/native/hdiadapter/source/fast/fast_audio_capturer_source.cpp +++ b/frameworks/native/hdiadapter/source/fast/fast_audio_capturer_source.cpp @@ -56,6 +56,7 @@ public: int32_t SetInputRoute(DeviceType inputDevice) override; uint64_t GetTransactionId() override; + int32_t GetPresentationPosition(uint64_t& frames, int64_t& timeSec, int64_t& timeNanoSec) override; void RegisterWakeupCloseCallback(IAudioSourceCallback *callback) override; void RegisterAudioCapturerSourceCallback(IAudioSourceCallback *callback) override; void RegisterParameterCallback(IAudioSourceCallback *callback) override; @@ -533,6 +534,11 @@ uint64_t FastAudioCapturerSourceInner::GetTransactionId() return reinterpret_cast(audioCapture_); } +int32_t FastAudioCapturerSourceInner::GetPresentationPosition(uint64_t& frames, int64_t& timeSec, int64_t& timeNanoSec) +{ + return ERR_DEVICE_NOT_SUPPORTED; +} + void FastAudioCapturerSourceInner::RegisterWakeupCloseCallback(IAudioSourceCallback *callback) { AUDIO_ERR_LOG("RegisterWakeupCloseCallback FAILED"); diff --git a/frameworks/native/hdiadapter/source/file/audio_capturer_file_source.cpp b/frameworks/native/hdiadapter/source/file/audio_capturer_file_source.cpp index 414a701974..04fce593eb 100644 --- a/frameworks/native/hdiadapter/source/file/audio_capturer_file_source.cpp +++ b/frameworks/native/hdiadapter/source/file/audio_capturer_file_source.cpp @@ -87,6 +87,11 @@ uint64_t AudioCapturerFileSource::GetTransactionId(void) return res; } +int32_t AudioCapturerFileSource::GetPresentationPosition(uint64_t& frames, int64_t& timeSec, int64_t& timeNanoSec) +{ + return SUCCESS; +} + int32_t AudioCapturerFileSource::Pause(void) { return SUCCESS; diff --git a/frameworks/native/hdiadapter/source/file/audio_capturer_file_source.h b/frameworks/native/hdiadapter/source/file/audio_capturer_file_source.h index 775842b88b..93a40b3caf 100644 --- a/frameworks/native/hdiadapter/source/file/audio_capturer_file_source.h +++ b/frameworks/native/hdiadapter/source/file/audio_capturer_file_source.h @@ -45,6 +45,7 @@ public: int32_t SetAudioScene(AudioScene audioScene, DeviceType activeDevice) override; int32_t SetInputRoute(DeviceType deviceType) override; uint64_t GetTransactionId() override; + int32_t GetPresentationPosition(uint64_t& frames, int64_t& timeSec, int64_t& timeNanoSec) override; void RegisterWakeupCloseCallback(IAudioSourceCallback *callback) override; void RegisterAudioCapturerSourceCallback(IAudioSourceCallback *callback) override; void RegisterParameterCallback(IAudioSourceCallback *callback) override; diff --git a/frameworks/native/hdiadapter/source/primary/audio_capturer_source.cpp b/frameworks/native/hdiadapter/source/primary/audio_capturer_source.cpp index 65f77d8673..0d9f7f569b 100644 --- a/frameworks/native/hdiadapter/source/primary/audio_capturer_source.cpp +++ b/frameworks/native/hdiadapter/source/primary/audio_capturer_source.cpp @@ -35,6 +35,9 @@ using namespace std; namespace OHOS { namespace AudioStandard { +namespace { + const int64_t SECOND_TO_NANOSECOND = 1000000000; +} class AudioCapturerSourceInner : public AudioCapturerSource { public: int32_t Init(const IAudioSourceAttr &attr) override; @@ -60,6 +63,8 @@ public: int32_t SetInputRoute(DeviceType inputDevice) override; uint64_t GetTransactionId() override; + int32_t GetPresentationPosition(uint64_t& frames, int64_t& timeSec, int64_t& timeNanoSec) override; + void RegisterWakeupCloseCallback(IAudioSourceCallback *callback) override; void RegisterAudioCapturerSourceCallback(IAudioSourceCallback *callback) override; void RegisterParameterCallback(IAudioSourceCallback *callback) override; @@ -140,6 +145,7 @@ public: int32_t SetInputRoute(DeviceType inputDevice) override; uint64_t GetTransactionId() override; + int32_t GetPresentationPosition(uint64_t& frames, int64_t& timeSec, int64_t& timeNanoSec) override; void RegisterWakeupCloseCallback(IAudioSourceCallback *callback) override; void RegisterAudioCapturerSourceCallback(IAudioSourceCallback *callback) override; @@ -839,6 +845,33 @@ uint64_t AudioCapturerSourceInner::GetTransactionId() return reinterpret_cast(audioCapture_); } +int32_t AudioCapturerSourceInner::GetPresentationPosition(uint64_t& frames, int64_t& timeSec, int64_t& timeNanoSec) +{ + int32_t ret; + if (audioCapture_ == nullptr) { + AUDIO_ERR_LOG("failed audioCapture_ is NULL"); + return ERR_INVALID_HANDLE; + } + struct AudioTimeStamp timestamp = {}; + ret = audioCapture_->GetCapturePosition(audioCapture_, &frames, ×tamp); + if (ret != 0) { + AUDIO_ERR_LOG("get position failed"); + return ERR_OPERATION_FAILED; + } + int64_t maxSec = 9223372036; // (9223372036 + 1) * 10^9 > INT64_MAX, seconds should not bigger than it; + if (timestamp.tvSec < 0 || timestamp.tvSec > maxSec || timestamp.tvNSec < 0 || + timestamp.tvNSec > SECOND_TO_NANOSECOND) { + AUDIO_ERR_LOG( + "Hdi GetRenderPosition get invaild second:%{public}" PRIu64 " or nanosecond:%{public}" PRIu64 " !", + timestamp.tvSec, timestamp.tvNSec); + return ERR_OPERATION_FAILED; + } + + timeSec = timestamp.tvSec; + timeNanoSec = timestamp.tvNSec; + return ret; +} + int32_t AudioCapturerSourceInner::Stop(void) { AUDIO_INFO_LOG("Stop."); @@ -1190,6 +1223,11 @@ uint64_t AudioCapturerSourceWakeup::GetTransactionId() return audioCapturerSource_.GetTransactionId(); } +int32_t AudioCapturerSourceWakeup::GetPresentationPosition(uint64_t& frames, int64_t& timeSec, int64_t& timeNanoSec) +{ + return audioCapturerSource_.GetPresentationPosition(frames, timeSec, timeNanoSec); +} + void AudioCapturerSourceWakeup::RegisterWakeupCloseCallback(IAudioSourceCallback *callback) { audioCapturerSource_.RegisterWakeupCloseCallback(callback); diff --git a/frameworks/native/hdiadapter/source/remote/remote_audio_capturer_source.cpp b/frameworks/native/hdiadapter/source/remote/remote_audio_capturer_source.cpp index fffca1f1e6..8447f5ef72 100644 --- a/frameworks/native/hdiadapter/source/remote/remote_audio_capturer_source.cpp +++ b/frameworks/native/hdiadapter/source/remote/remote_audio_capturer_source.cpp @@ -53,6 +53,7 @@ public: int32_t SetAudioScene(AudioScene audioScene, DeviceType activeDevice) override; int32_t SetInputRoute(DeviceType inputDevice) override; uint64_t GetTransactionId() override; + int32_t GetPresentationPosition(uint64_t& frames, int64_t& timeSec, int64_t& timeNanoSec) override; void RegisterWakeupCloseCallback(IAudioSourceCallback *callback) override; void RegisterAudioCapturerSourceCallback(IAudioSourceCallback *callback) override; void RegisterParameterCallback(IAudioSourceCallback *callback) override; @@ -544,6 +545,12 @@ uint64_t RemoteAudioCapturerSourceInner::GetTransactionId() return reinterpret_cast(audioCapture_); } +int32_t RemoteAudioCapturerSourceInner::GetPresentationPosition(uint64_t& frames, int64_t& timeSec, + int64_t& timeNanoSec) +{ + return ERR_OPERATION_FAILED; +} + void RemoteAudioCapturerSourceInner::RegisterWakeupCloseCallback(IAudioSourceCallback *callback) { AUDIO_ERR_LOG("RegisterWakeupCloseCallback FAILED"); diff --git a/frameworks/native/hdiadapter/source/remote_fast/remote_fast_audio_capturer_source.cpp b/frameworks/native/hdiadapter/source/remote_fast/remote_fast_audio_capturer_source.cpp index 2fd7822bbd..06d1896e21 100644 --- a/frameworks/native/hdiadapter/source/remote_fast/remote_fast_audio_capturer_source.cpp +++ b/frameworks/native/hdiadapter/source/remote_fast/remote_fast_audio_capturer_source.cpp @@ -51,6 +51,7 @@ public: int32_t SetAudioScene(AudioScene audioScene, DeviceType activeDevice) override; int32_t SetInputRoute(DeviceType inputDevice) override; uint64_t GetTransactionId() override; + int32_t GetPresentationPosition(uint64_t& frames, int64_t& timeSec, int64_t& timeNanoSec) override; void RegisterWakeupCloseCallback(IAudioSourceCallback *callback) override; void RegisterAudioCapturerSourceCallback(IAudioSourceCallback *callback) override; void RegisterParameterCallback(IAudioSourceCallback *callback) override; @@ -612,6 +613,12 @@ uint64_t RemoteFastAudioCapturerSourceInner::GetTransactionId() return reinterpret_cast(audioCapture_); } +int32_t RemoteFastAudioCapturerSourceInner::GetPresentationPosition(uint64_t& frames, int64_t& timeSec, + int64_t& timeNanoSec) +{ + return ERR_OPERATION_FAILED; +} + int32_t RemoteFastAudioCapturerSourceInner::SetInputPortPin(DeviceType inputDevice, AudioRouteNode &source) { int32_t ret = SUCCESS; diff --git a/frameworks/native/ohaudio/OHAudioCapturer.cpp b/frameworks/native/ohaudio/OHAudioCapturer.cpp index 3a97bd24ab..01635715db 100644 --- a/frameworks/native/ohaudio/OHAudioCapturer.cpp +++ b/frameworks/native/ohaudio/OHAudioCapturer.cpp @@ -173,10 +173,15 @@ OH_AudioStream_Result OH_AudioCapturer_GetTimestamp(OH_AudioCapturer* capturer, { OHOS::AudioStandard::OHAudioCapturer *audioCapturer = convertCapturer(capturer); CHECK_AND_RETURN_RET_LOG(audioCapturer != nullptr, AUDIOSTREAM_ERROR_INVALID_PARAM, "convert capturer failed"); + CHECK_AND_RETURN_RET_LOG(clockId == CLOCK_MONOTONIC, AUDIOSTREAM_ERROR_INVALID_PARAM, "error clockId value"); Timestamp stamp; Timestamp::Timestampbase base = Timestamp::Timestampbase::MONOTONIC; - audioCapturer->GetAudioTime(stamp, base); + bool ret = audioCapturer->GetAudioTime(stamp, base); + if (!ret) { + AUDIO_ERR_LOG("GetAudioTime error!"); + return AUDIOSTREAM_ERROR_ILLEGAL_STATE; + } *framePosition = stamp.framePosition; *timestamp = stamp.time.tv_sec * SECOND_TO_NANOSECOND + stamp.time.tv_nsec; return AUDIOSTREAM_SUCCESS; @@ -338,10 +343,10 @@ int64_t OHAudioCapturer::GetFramesRead() return audioCapturer_->GetFramesRead(); } -void OHAudioCapturer::GetAudioTime(Timestamp ×tamp, Timestamp::Timestampbase base) +bool OHAudioCapturer::GetAudioTime(Timestamp ×tamp, Timestamp::Timestampbase base) { - CHECK_AND_RETURN_LOG(audioCapturer_ != nullptr, "capturer client is nullptr"); - audioCapturer_->GetAudioTime(timestamp, base); + CHECK_AND_RETURN_RET_LOG(audioCapturer_ != nullptr, false, "capturer client is nullptr"); + return audioCapturer_->GetAudioTime(timestamp, base); } int32_t OHAudioCapturer::GetFrameSizeInCallback() diff --git a/frameworks/native/ohaudio/OHAudioCapturer.h b/frameworks/native/ohaudio/OHAudioCapturer.h index bbf59181ee..2e42d5d85c 100644 --- a/frameworks/native/ohaudio/OHAudioCapturer.h +++ b/frameworks/native/ohaudio/OHAudioCapturer.h @@ -75,7 +75,7 @@ class OHAudioCapturer { AudioSampleFormat GetSampleFormat(); void GetCapturerInfo(AudioCapturerInfo& capturerInfo); int64_t GetFramesRead(); - void GetAudioTime(Timestamp ×tamp, Timestamp::Timestampbase base); + bool GetAudioTime(Timestamp ×tamp, Timestamp::Timestampbase base); int32_t GetFrameSizeInCallback(); int32_t GetBufferDesc(BufferDesc &bufDesc) const; int32_t Enqueue(const BufferDesc &bufDesc) const; diff --git a/frameworks/native/ohaudio/OHAudioRenderer.cpp b/frameworks/native/ohaudio/OHAudioRenderer.cpp index de4a922e56..e27c73342d 100644 --- a/frameworks/native/ohaudio/OHAudioRenderer.cpp +++ b/frameworks/native/ohaudio/OHAudioRenderer.cpp @@ -173,9 +173,14 @@ OH_AudioStream_Result OH_AudioRenderer_GetTimestamp(OH_AudioRenderer* renderer, { OHOS::AudioStandard::OHAudioRenderer *audioRenderer = convertRenderer(renderer); CHECK_AND_RETURN_RET_LOG(audioRenderer != nullptr, AUDIOSTREAM_ERROR_INVALID_PARAM, "convert renderer failed"); + CHECK_AND_RETURN_RET_LOG(clockId == CLOCK_MONOTONIC, AUDIOSTREAM_ERROR_INVALID_PARAM, "error clockId value"); Timestamp stamp; Timestamp::Timestampbase base = Timestamp::Timestampbase::MONOTONIC; - audioRenderer->GetAudioTime(stamp, base); + bool ret = audioRenderer->GetAudioTime(stamp, base); + if (!ret) { + AUDIO_ERR_LOG("GetAudioTime error!"); + return AUDIOSTREAM_ERROR_ILLEGAL_STATE; + } *framePosition = stamp.framePosition; *timestamp = stamp.time.tv_sec * SECOND_TO_NANOSECOND + stamp.time.tv_nsec; return AUDIOSTREAM_SUCCESS; @@ -333,10 +338,10 @@ int64_t OHAudioRenderer::GetFramesWritten() return audioRenderer_->GetFramesWritten(); } -void OHAudioRenderer::GetAudioTime(Timestamp ×tamp, Timestamp::Timestampbase base) +bool OHAudioRenderer::GetAudioTime(Timestamp ×tamp, Timestamp::Timestampbase base) { - CHECK_AND_RETURN_LOG(audioRenderer_ != nullptr, "renderer client is nullptr"); - audioRenderer_->GetAudioTime(timestamp, base); + CHECK_AND_RETURN_RET_LOG(audioRenderer_ != nullptr, false, "renderer client is nullptr"); + return audioRenderer_->GetAudioTime(timestamp, base); } int32_t OHAudioRenderer::GetFrameSizeInCallback() diff --git a/frameworks/native/ohaudio/OHAudioRenderer.h b/frameworks/native/ohaudio/OHAudioRenderer.h index 73f8163bc5..7e21f9a27f 100644 --- a/frameworks/native/ohaudio/OHAudioRenderer.h +++ b/frameworks/native/ohaudio/OHAudioRenderer.h @@ -119,7 +119,7 @@ class OHAudioRenderer { AudioEncodingType GetEncodingType(); int64_t GetFramesWritten(); void GetRendererInfo(AudioRendererInfo& rendererInfo); - void GetAudioTime(Timestamp ×tamp, Timestamp::Timestampbase base); + bool GetAudioTime(Timestamp ×tamp, Timestamp::Timestampbase base); int32_t GetFrameSizeInCallback(); int32_t GetBufferDesc(BufferDesc &bufDesc) const; int32_t Enqueue(const BufferDesc &bufDesc) const; diff --git a/frameworks/native/ohaudio/test/example/oh_audio_capturer_test.cpp b/frameworks/native/ohaudio/test/example/oh_audio_capturer_test.cpp index f97e7fedc1..14a1508095 100644 --- a/frameworks/native/ohaudio/test/example/oh_audio_capturer_test.cpp +++ b/frameworks/native/ohaudio/test/example/oh_audio_capturer_test.cpp @@ -92,8 +92,12 @@ void RecorderTest(char *argv[]) stopthread.detach(); int timeLeft = AudioTestConstants::RECODER_TIME; + int64_t framePosition = 0; + int64_t timestamp = 0; while (!stop) { - printf("Recording audio is in the countdown ... %d s \n", timeLeft / AudioTestConstants::CONVERT_RATE); + OH_AudioCapturer_GetTimestamp(audioCapturer, CLOCK_MONOTONIC, &framePosition, ×tamp); + printf("Recording audio is in the countdown ... %d s (framePosition: %lu)((timestamp: %lu))\n", + timeLeft / AudioTestConstants::CONVERT_RATE, framePosition, timestamp); std::this_thread::sleep_for(std::chrono::milliseconds(AudioTestConstants::COUNTDOWN_INTERVAL)); timeLeft = timeLeft - AudioTestConstants::COUNTDOWN_INTERVAL; } diff --git a/frameworks/native/pulseaudio/modules/hdi/hdi_sink.c b/frameworks/native/pulseaudio/modules/hdi/hdi_sink.c index bb255fa81b..cf60b6039a 100644 --- a/frameworks/native/pulseaudio/modules/hdi/hdi_sink.c +++ b/frameworks/native/pulseaudio/modules/hdi/hdi_sink.c @@ -2120,6 +2120,14 @@ static void PaInputStateChangeCb(pa_sink_input *i, pa_sink_input_state_t state) return; } + { + // const char *render_in_idle_state = u->render_in_idle_state + pa_proplist *propList = pa_proplist_new(); + pa_proplist_sets(propList, "old_state", GetInputStateInfo(i->thread_info.state)); + pa_proplist_sets(propList, "new_state", GetInputStateInfo(state)); + pa_sink_input_send_event(i, "state_changed", propList); + } + const bool corking = i->thread_info.state == PA_SINK_INPUT_RUNNING && state == PA_SINK_INPUT_CORKED; const bool starting = i->thread_info.state == PA_SINK_INPUT_CORKED && state == PA_SINK_INPUT_RUNNING; const bool stopping = state == PA_SINK_INPUT_UNLINKED; diff --git a/interfaces/inner_api/native/audiomanager/include/audio_system_manager.h b/interfaces/inner_api/native/audiomanager/include/audio_system_manager.h index 5d28758f27..38fb53112e 100644 --- a/interfaces/inner_api/native/audiomanager/include/audio_system_manager.h +++ b/interfaces/inner_api/native/audiomanager/include/audio_system_manager.h @@ -1024,6 +1024,12 @@ public: int32_t OffloadDrain(); + int32_t GetCapturePresentationPosition(const std::string& deviceClass, uint64_t& frames, int64_t& timeSec, + int64_t& timeNanoSec); + + int32_t GetRenderPresentationPosition(const std::string& deviceClass, uint64_t& frames, int64_t& timeSec, + int64_t& timeNanoSec); + int32_t OffloadGetPresentationPosition(uint64_t& frames, int64_t& timeSec, int64_t& timeNanoSec); int32_t OffloadSetBufferSize(uint32_t sizeMs); diff --git a/services/audio_service/client/include/audio_manager_base.h b/services/audio_service/client/include/audio_manager_base.h index f051962568..c18f31fa09 100644 --- a/services/audio_service/client/include/audio_manager_base.h +++ b/services/audio_service/client/include/audio_manager_base.h @@ -44,6 +44,12 @@ public: */ virtual int32_t SetVoiceVolume(float volume) = 0; + virtual int32_t GetCapturePresentationPosition(const std::string& deviceClass, uint64_t& frames, int64_t& timeSec, + int64_t& timeNanoSec) = 0; + + virtual int32_t GetRenderPresentationPosition(const std::string& deviceClass, uint64_t& frames, int64_t& timeSec, + int64_t& timeNanoSec) = 0; + virtual int32_t OffloadSetVolume(float volume) = 0; virtual int32_t OffloadDrain() = 0; virtual int32_t OffloadGetPresentationPosition(uint64_t& frames, int64_t& timeSec, int64_t& timeNanoSec) = 0; @@ -284,6 +290,8 @@ private: int HandleSetWakeupSourceCallback(MessageParcel &data, MessageParcel &reply); int HandleSetCaptureSilentState(MessageParcel &data, MessageParcel &reply); int HandleUpdateSpatializationState(MessageParcel &data, MessageParcel &reply); + int HandleGetCapturePresentationPosition(MessageParcel &data, MessageParcel &reply); + int HandleGetRenderPresentationPosition(MessageParcel &data, MessageParcel &reply); int HandleOffloadSetVolume(MessageParcel &data, MessageParcel &reply); int HandleOffloadDrain(MessageParcel &data, MessageParcel &reply); int HandleOffloadGetPresentationPosition(MessageParcel &data, MessageParcel &reply); @@ -322,6 +330,8 @@ private: &AudioManagerStub::HandleOffloadGetPresentationPosition, &AudioManagerStub::HandleOffloadSetBufferSize, &AudioManagerStub::HandleNotifyStreamVolumeChanged, + &AudioManagerStub::HandleGetCapturePresentationPosition, + &AudioManagerStub::HandleGetRenderPresentationPosition, }; static constexpr size_t handlersNums = sizeof(handlers) / sizeof(HandlerFunc); static_assert(handlersNums == (static_cast (AudioServerInterfaceCode::AUDIO_SERVER_CODE_MAX) + 1), diff --git a/services/audio_service/client/include/audio_manager_proxy.h b/services/audio_service/client/include/audio_manager_proxy.h index fff1c76c6b..1d46f937ce 100644 --- a/services/audio_service/client/include/audio_manager_proxy.h +++ b/services/audio_service/client/include/audio_manager_proxy.h @@ -29,6 +29,10 @@ public: int32_t SetMicrophoneMute(bool isMute) override; int32_t SetVoiceVolume(float volume) override; + int32_t GetCapturePresentationPosition(const std::string& deviceClass, uint64_t& frames, int64_t& timeSec, + int64_t& timeNanoSec) override; + int32_t GetRenderPresentationPosition(const std::string& deviceClass, uint64_t& frames, int64_t& timeSec, + int64_t& timeNanoSec) override; int32_t OffloadSetVolume(float volume) override; int32_t OffloadDrain() override; int32_t OffloadGetPresentationPosition(uint64_t& frames, int64_t& timeSec, int64_t& timeNanoSec) override; diff --git a/services/audio_service/client/include/audio_service_client.h b/services/audio_service/client/include/audio_service_client.h index 948c58cd35..9f88936066 100644 --- a/services/audio_service/client/include/audio_service_client.h +++ b/services/audio_service/client/include/audio_service_client.h @@ -128,6 +128,13 @@ public: virtual void OnEventCb(AudioServiceEventTypes error) const = 0; }; +enum UpdatePositionTimeNode { + START_NODE = 1, + CORKED_NODE = 2, + RUNNING_NODE = 3, + USER_NODE = 4, +}; + class AudioServiceClient : public IAudioStream, public AudioTimer, public AppExecFwk::EventHandler { public: static constexpr char PA_RUNTIME_DIR[] = "/data/data/.pulse_dir/runtime"; @@ -259,6 +266,23 @@ public: */ int32_t GetCurrentTimeStamp(uint64_t &timeStamp); + /** + * Provides the current timestamp for playback/record stream created using CreateStream + * + * @param framePosition will be filled up with current frame position + * @param timeStamp will be filled up with current timestamp + * @return Returns {@code 0} if success; returns {@code -1} otherwise. + */ + int32_t GetCurrentPosition(uint64_t &framePosition, uint64_t &timeStamp); + + /** + * Update the stream positon and timestamp + * + * @param node The time node for updating the stream position and its timestamp + * @return Returns {@code 0} if success; returns {@code -1} otherwise. + */ + int32_t UpdateStreamPosition(UpdatePositionTimeNode node); + void GetOffloadCurrentTimeStamp(uint64_t& timeStamp, bool beforeLocked); /** @@ -609,6 +633,7 @@ private: std::mutex runnerMutex_; std::mutex writeCallbackMutex_; std::mutex stoppingMutex_; + std::mutex streamPositionMutex_; bool runnerReleased_ = false; AudioCache acache_; const void *internalReadBuffer_; @@ -714,6 +739,11 @@ private: AudioOffloadType offloadNextStateTargetPolicy_ = OFFLOAD_DEFAULT; time_t lastOffloadUpdateFinishTime_ = 0; float speed_ = 1.0; + + uint64_t lastStreamPosition_ = 0; + uint64_t lastPositionTimestamp_ = 0; + uint64_t lastHdiPosition_ = 0; + int32_t ConnectStreamToPA(); std::pair GetDeviceNameForConnect(); int32_t UpdatePAProbListOffload(AudioOffloadType statePolicy); diff --git a/services/audio_service/client/include/pulseaudio_ipc_interface_code.h b/services/audio_service/client/include/pulseaudio_ipc_interface_code.h index 0dc90ae9d5..b7f867a8b3 100644 --- a/services/audio_service/client/include/pulseaudio_ipc_interface_code.h +++ b/services/audio_service/client/include/pulseaudio_ipc_interface_code.h @@ -52,7 +52,9 @@ namespace AudioStandard { OFFLOAD_GET_PRESENTATION_POSITION, OFFLOAD_SET_BUFFER_SIZE, NOTIFY_STREAM_VOLUME_CHANGED, - AUDIO_SERVER_CODE_MAX = NOTIFY_STREAM_VOLUME_CHANGED, + GET_CAPTURE_PRESENTATION_POSITION, + GET_RENDER_PRESENTATION_POSITION, + AUDIO_SERVER_CODE_MAX = GET_RENDER_PRESENTATION_POSITION, }; } // namespace AudioStandard } // namespace OHOS diff --git a/services/audio_service/client/src/audio_manager_proxy.cpp b/services/audio_service/client/src/audio_manager_proxy.cpp index e4e99323d4..b9995d62d6 100644 --- a/services/audio_service/client/src/audio_manager_proxy.cpp +++ b/services/audio_service/client/src/audio_manager_proxy.cpp @@ -122,6 +122,66 @@ int32_t AudioManagerProxy::OffloadDrain() return result; } +int32_t AudioManagerProxy::GetCapturePresentationPosition(const std::string& deviceClass, uint64_t& frames, + int64_t& timeSec, int64_t& timeNanoSec) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteInterfaceToken(GetDescriptor())) { + AUDIO_ERR_LOG("AudioManagerProxy: WriteInterfaceToken failed"); + return -1; + } + + data.WriteString(deviceClass); + + int32_t error = Remote()->SendRequest( + static_cast(AudioServerInterfaceCode::GET_CAPTURE_PRESENTATION_POSITION), data, reply, option); + if (error != ERR_NONE) { + AUDIO_ERR_LOG("GetCapturePresentationPosition failed, error: %d", error); + return false; + } + + int32_t result = reply.ReadInt32(); + frames = reply.ReadUint64(); + timeSec = reply.ReadInt64(); + timeNanoSec = reply.ReadInt64(); + AUDIO_DEBUG_LOG("ret %{public}d, frames %{public}" PRIu64 ", sec %{public}" PRId64 ", Nasec %{public}" PRId64, + result, frames, timeSec, timeNanoSec); + return result; +} + +int32_t AudioManagerProxy::GetRenderPresentationPosition(const std::string& deviceClass, uint64_t& frames, + int64_t& timeSec, int64_t& timeNanoSec) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option; + + if (!data.WriteInterfaceToken(GetDescriptor())) { + AUDIO_ERR_LOG("AudioManagerProxy: WriteInterfaceToken failed"); + return -1; + } + + data.WriteString(deviceClass); + + int32_t error = Remote()->SendRequest( + static_cast(AudioServerInterfaceCode::GET_RENDER_PRESENTATION_POSITION), data, reply, option); + if (error != ERR_NONE) { + AUDIO_ERR_LOG("GetRenderPresentationPosition failed, error: %d", error); + return false; + } + + int32_t result = reply.ReadInt32(); + frames = reply.ReadUint64(); + timeSec = reply.ReadInt64(); + timeNanoSec = reply.ReadInt64(); + AUDIO_DEBUG_LOG("ret %{public}d, frames %{public}" PRIu64 ", sec %{public}" PRId64 ", Nasec %{public}" PRId64, + result, frames, timeSec, timeNanoSec); + return result; +} + int32_t AudioManagerProxy::OffloadGetPresentationPosition(uint64_t& frames, int64_t& timeSec, int64_t& timeNanoSec) { MessageParcel data; diff --git a/services/audio_service/client/src/audio_service_client.cpp b/services/audio_service/client/src/audio_service_client.cpp index 611a0714d8..78c7acf6a0 100644 --- a/services/audio_service/client/src/audio_service_client.cpp +++ b/services/audio_service/client/src/audio_service_client.cpp @@ -53,6 +53,9 @@ const int32_t OFFLOAD_HDI_CACHE1 = 200; // ms, should equal with val in hdi_sink const int32_t OFFLOAD_HDI_CACHE2 = 7000; // ms, should equal with val in hdi_sink.c const uint32_t OFFLOAD_BUFFER = 50; const uint64_t AUDIO_US_PER_MS = 1000; +const uint64_t AUDIO_S_TO_NS = 1000000000; +const uint64_t HDI_OFFLOAD_SAMPLE_RATE = 48000; +const int64_t SECOND_TO_MICROSECOND = 1000000; static const string INNER_CAPTURER_SOURCE = "Speaker.monitor"; @@ -184,10 +187,10 @@ void AudioServiceClient::PAStreamStartSuccessCb(pa_stream *stream, int32_t succe AUDIO_ERR_LOG("PAStreamStartSuccessCb: userdata is null"); return; } - AudioServiceClient *asClient = static_cast(userdata); pa_threaded_mainloop *mainLoop = static_cast(asClient->mainLoop); + asClient->UpdateStreamPosition(UpdatePositionTimeNode::START_NODE); asClient->state_ = RUNNING; asClient->breakingWritePa_ = false; asClient->offloadTsLast_ = 0; @@ -450,6 +453,21 @@ void AudioServiceClient::PAStreamEventCb(pa_stream *stream, const char *event, p pa_threaded_mainloop_signal(asClient->mainLoop, 0); AUDIO_DEBUG_LOG("AudioServiceClient::PAEventCb receive event signal_mainloop"); } + + if (!strcmp(event, "state_changed")) { + const char *old_state = pa_proplist_gets(pl, "old_state"); + const char *new_state = pa_proplist_gets(pl, "new_state"); + AUDIO_INFO_LOG("AudioServiceClient::PAEventCb old state : %{public}s, new state : %{public}s", + old_state, new_state); + if (asClient != nullptr) { + if (!strcmp(old_state, "RUNNING") && !strcmp(new_state, "CORKED")) { + asClient->UpdateStreamPosition(UpdatePositionTimeNode::CORKED_NODE); + } + if (!strcmp(old_state, "CORKED") && !strcmp(new_state, "RUNNING")) { + asClient->UpdateStreamPosition(UpdatePositionTimeNode::RUNNING_NODE); + } + } + } } void AudioServiceClient::PAStreamLatencyUpdateCb(pa_stream *stream, void *userdata) @@ -2241,6 +2259,54 @@ int32_t AudioServiceClient::GetAudioLatencyOffload(uint64_t &latency) return AUDIO_CLIENT_SUCCESS; } +int32_t AudioServiceClient::UpdateStreamPosition(UpdatePositionTimeNode node) +{ + uint64_t frames; + int64_t timeSec, timeNanoSec; + + unique_lock positionLock(streamPositionMutex_); + std::string deviceClass = offloadEnable_ ? "offload" : "primary"; + if (eAudioClientType == AUDIO_SERVICE_CLIENT_PLAYBACK && + audioSystemManager_->GetRenderPresentationPosition(deviceClass, frames, timeSec, timeNanoSec) == 0) { + if (offloadEnable_) { + frames = frames * HDI_OFFLOAD_SAMPLE_RATE / SECOND_TO_MICROSECOND; + lastStreamPosition_ = frames; + lastPositionTimestamp_ = timeSec * AUDIO_S_TO_NS + timeNanoSec; + return AUDIO_CLIENT_SUCCESS; + } + if (node == UpdatePositionTimeNode::USER_NODE && state_ == RUNNING) { + lastStreamPosition_ = lastStreamPosition_ + frames - lastHdiPosition_; + lastPositionTimestamp_ = timeSec * AUDIO_S_TO_NS + timeNanoSec; + lastHdiPosition_ = frames; + } else if (node == UpdatePositionTimeNode::CORKED_NODE) { + lastStreamPosition_ = lastStreamPosition_ + frames - lastHdiPosition_; + lastHdiPosition_ = frames; + } else if (node == UpdatePositionTimeNode::RUNNING_NODE) { + lastHdiPosition_ = frames; + } + return AUDIO_CLIENT_SUCCESS; + } else if (eAudioClientType == AUDIO_SERVICE_CLIENT_RECORD && + audioSystemManager_->GetCapturePresentationPosition("primary", frames, timeSec, timeNanoSec) == 0) { + lastStreamPosition_ = frames; + lastPositionTimestamp_ = timeSec * AUDIO_S_TO_NS + timeNanoSec; + return AUDIO_CLIENT_SUCCESS; + } else { + AUDIO_ERR_LOG("UpdateStreamPosition failed!"); + return AUDIO_CLIENT_ERR; + } +} + +int32_t AudioServiceClient::GetCurrentPosition(uint64_t &framePosition, uint64_t &timeStamp) +{ + int32_t ret = UpdateStreamPosition(UpdatePositionTimeNode::USER_NODE); + if (ret != AUDIO_CLIENT_SUCCESS) { + return ret; + } + framePosition = lastStreamPosition_; + timeStamp = lastPositionTimestamp_; + return AUDIO_CLIENT_SUCCESS; +} + int32_t AudioServiceClient::GetAudioLatency(uint64_t &latency) { lock_guard lock(dataMutex_); @@ -3622,3 +3688,4 @@ void AudioSpatializationStateChangeCallbackImpl::OnSpatializationStateChange( } } // namespace AudioStandard } // namespace OHOS + diff --git a/services/audio_service/client/src/audio_stream.cpp b/services/audio_service/client/src/audio_stream.cpp index d7b8d097c6..3397175515 100644 --- a/services/audio_service/client/src/audio_stream.cpp +++ b/services/audio_service/client/src/audio_stream.cpp @@ -36,8 +36,6 @@ using namespace OHOS::AppExecFwk; namespace OHOS { namespace AudioStandard { -const unsigned long long TIME_CONVERSION_US_S = 1000000ULL; /* us to s */ -const unsigned long long TIME_CONVERSION_NS_US = 1000ULL; /* ns to us */ const unsigned long long TIME_CONVERSION_NS_S = 1000000000ULL; /* ns to s */ constexpr int32_t WRITE_RETRY_DELAY_IN_US = 500; constexpr int32_t CB_WRITE_BUFFERS_WAIT_IN_MS = 80; @@ -81,8 +79,6 @@ AudioStream::AudioStream(AudioStreamType eStreamType, AudioMode eMode, int32_t a : eStreamType_(eStreamType), eMode_(eMode), state_(NEW), - resetTime_(false), - resetTimestamp_(0), renderMode_(RENDER_MODE_NORMAL), captureMode_(CAPTURE_MODE_NORMAL), isReadyToWrite_(false), @@ -165,29 +161,13 @@ bool AudioStream::GetAudioTime(Timestamp ×tamp, Timestamp::Timestampbase ba if (state_ == STOPPED) { return false; } - uint64_t paTimeStamp = 0; - if (GetCurrentTimeStamp(paTimeStamp) == SUCCESS) { - if (resetTime_) { - AUDIO_INFO_LOG("AudioStream::GetAudioTime resetTime_ %{public}d", resetTime_); - resetTime_ = false; - resetTimestamp_ = paTimeStamp; - } - if (eMode_ == AUDIO_MODE_PLAYBACK) { - timestamp.framePosition = GetStreamFramesWritten() * speed_; - } else { - timestamp.framePosition = GetStreamFramesRead(); - } - - uint64_t delta = paTimeStamp > resetTimestamp_ ? paTimeStamp - resetTimestamp_ : 0; - timestamp.time.tv_sec = static_cast(delta / TIME_CONVERSION_US_S); + uint64_t framePosition = 0; + uint64_t timeStamp = 0; + if (GetCurrentPosition(framePosition, timeStamp) == SUCCESS) { + timestamp.framePosition = framePosition; + timestamp.time.tv_sec = static_cast(timeStamp / TIME_CONVERSION_NS_S); timestamp.time.tv_nsec - = static_cast((delta - (timestamp.time.tv_sec * TIME_CONVERSION_US_S)) - * TIME_CONVERSION_NS_US); - timestamp.time.tv_sec += baseTimestamp_.tv_sec; - timestamp.time.tv_nsec += baseTimestamp_.tv_nsec; - timestamp.time.tv_sec += (timestamp.time.tv_nsec / TIME_CONVERSION_NS_S); - timestamp.time.tv_nsec = (timestamp.time.tv_nsec % TIME_CONVERSION_NS_S); - + = static_cast(timeStamp - (timestamp.time.tv_sec * TIME_CONVERSION_NS_S)); return true; } return false; @@ -401,7 +381,6 @@ bool AudioStream::StartAudioStream(StateChangeCmdType cmdType) return false; } - resetTime_ = true; int32_t retCode = clock_gettime(CLOCK_MONOTONIC, &baseTimestamp_); if (retCode != 0) { AUDIO_ERR_LOG("AudioStream::StartAudioStream get system elapsed time failed: %d", retCode); diff --git a/services/audio_service/client/src/audio_system_manager.cpp b/services/audio_service/client/src/audio_system_manager.cpp index afa2a6d9ed..4c715d8182 100644 --- a/services/audio_service/client/src/audio_system_manager.cpp +++ b/services/audio_service/client/src/audio_system_manager.cpp @@ -1143,6 +1143,28 @@ int32_t AudioSystemManager::OffloadDrain() return gasp->OffloadDrain(); } +int32_t AudioSystemManager::GetCapturePresentationPosition(const std::string& deviceClass, uint64_t& frames, + int64_t& timeSec, int64_t& timeNanoSec) +{ + const sptr gasp = GetAudioSystemManagerProxy(); + if (gasp == nullptr) { + AUDIO_ERR_LOG("GetCapturePresentationPosition Audio service unavailable."); + return ERR_INVALID_PARAM; + } + return gasp->GetCapturePresentationPosition(deviceClass, frames, timeSec, timeNanoSec); +} + +int32_t AudioSystemManager::GetRenderPresentationPosition(const std::string& deviceClass, uint64_t& frames, + int64_t& timeSec, int64_t& timeNanoSec) +{ + const sptr gasp = GetAudioSystemManagerProxy(); + if (gasp == nullptr) { + AUDIO_ERR_LOG("GetRenderPresentationPosition Audio service unavailable."); + return ERR_INVALID_PARAM; + } + return gasp->GetRenderPresentationPosition(deviceClass, frames, timeSec, timeNanoSec); +} + int32_t AudioSystemManager::OffloadGetPresentationPosition(uint64_t& frames, int64_t& timeSec, int64_t& timeNanoSec) { const sptr gasp = GetAudioSystemManagerProxy(); diff --git a/services/audio_service/server/include/audio_server.h b/services/audio_service/server/include/audio_server.h index a91349e847..cffbcd4681 100644 --- a/services/audio_service/server/include/audio_server.h +++ b/services/audio_service/server/include/audio_server.h @@ -97,6 +97,12 @@ public: int32_t SetCaptureSilentState(bool state) override; + int32_t GetCapturePresentationPosition(const std::string& deviceClass, uint64_t& frames, int64_t& timeSec, + int64_t& timeNanoSec) override; + + int32_t GetRenderPresentationPosition(const std::string& deviceClass, uint64_t& frames, int64_t& timeSec, + int64_t& timeNanoSec) override; + int32_t OffloadGetPresentationPosition(uint64_t& frames, int64_t& timeSec, int64_t& timeNanoSec) override; int32_t OffloadSetBufferSize(uint32_t sizeMs) override; diff --git a/services/audio_service/server/src/audio_manager_stub.cpp b/services/audio_service/server/src/audio_manager_stub.cpp index 9abd872e1b..c605dfd67c 100644 --- a/services/audio_service/server/src/audio_manager_stub.cpp +++ b/services/audio_service/server/src/audio_manager_stub.cpp @@ -368,6 +368,34 @@ int AudioManagerStub::HandleUpdateSpatializationState(MessageParcel &data, Messa return AUDIO_OK; } +int AudioManagerStub::HandleGetCapturePresentationPosition(MessageParcel &data, MessageParcel &reply) +{ + const std::string deviceClass = data.ReadString(); + uint64_t frames; + int64_t timeSec, timeNanoSec; + int32_t result = GetCapturePresentationPosition(deviceClass, frames, timeSec, timeNanoSec); + reply.WriteInt32(result); + reply.WriteUint64(frames); + reply.WriteInt64(timeSec); + reply.WriteInt64(timeNanoSec); + + return AUDIO_OK; +} + +int AudioManagerStub::HandleGetRenderPresentationPosition(MessageParcel &data, MessageParcel &reply) +{ + const std::string deviceClass = data.ReadString(); + uint64_t frames; + int64_t timeSec, timeNanoSec; + int32_t result = GetRenderPresentationPosition(deviceClass, frames, timeSec, timeNanoSec); + reply.WriteInt32(result); + reply.WriteUint64(frames); + reply.WriteInt64(timeSec); + reply.WriteInt64(timeNanoSec); + + return AUDIO_OK; +} + int AudioManagerStub::HandleOffloadSetVolume(MessageParcel &data, MessageParcel &reply) { const float volume = data.ReadFloat(); diff --git a/services/audio_service/server/src/audio_server.cpp b/services/audio_service/server/src/audio_server.cpp index 06625defa5..8854900e03 100644 --- a/services/audio_service/server/src/audio_server.cpp +++ b/services/audio_service/server/src/audio_server.cpp @@ -822,6 +822,40 @@ int32_t AudioServer::OffloadDrain() return audioRendererSinkInstance->Drain(AUDIO_DRAIN_EARLY_NOTIFY); } +int32_t AudioServer::GetCapturePresentationPosition(const std::string& deviceClass, uint64_t& frames, int64_t& timeSec, + int64_t& timeNanoSec) +{ + int32_t callingUid = IPCSkeleton::GetCallingUid(); + if (callingUid != audioUid_ && callingUid != ROOT_UID) { + AUDIO_ERR_LOG("GetCapturePresentationPosition refused for %{public}d", callingUid); + return ERROR; + } + + AudioCapturerSource *audioCapturerSourceInstance = AudioCapturerSource::GetInstance("primary"); + if (audioCapturerSourceInstance == nullptr) { + AUDIO_ERR_LOG("Capturer is null."); + return ERROR; + } + return audioCapturerSourceInstance->GetPresentationPosition(frames, timeSec, timeNanoSec); +} + +int32_t AudioServer::GetRenderPresentationPosition(const std::string& deviceClass, uint64_t& frames, int64_t& timeSec, + int64_t& timeNanoSec) +{ + int32_t callingUid = IPCSkeleton::GetCallingUid(); + if (callingUid != audioUid_ && callingUid != ROOT_UID) { + AUDIO_ERR_LOG("GetCapturePresentationPosition refused for %{public}d", callingUid); + return ERROR; + } + + IAudioRendererSink *audioRendererSinkInstance = IAudioRendererSink::GetInstance(deviceClass.c_str(), ""); + if (audioRendererSinkInstance == nullptr) { + AUDIO_ERR_LOG("Renderer is null."); + return ERROR; + } + return audioRendererSinkInstance->GetPresentationPosition(frames, timeSec, timeNanoSec); +} + int32_t AudioServer::OffloadGetPresentationPosition(uint64_t& frames, int64_t& timeSec, int64_t& timeNanoSec) { auto *audioRendererSinkInstance = static_cast (IAudioRendererSink::GetInstance( -- Gitee