From 3f0f11a5458642f4cc2a4380c5796dab6da521ca Mon Sep 17 00:00:00 2001 From: "hezhiqiang19@huawei.com" Date: Fri, 19 Jan 2024 16:03:58 +0800 Subject: [PATCH] add tools for auto call unlock | modify log Signed-off-by: hezhiqiang19@huawei.com Change-Id: I7115315de3aed8af8256b2782928a87b9198d235 --- .../server/include/pa_adapter_tools.h | 50 +++++++++++++ .../server/include/pa_capturer_stream_impl.h | 2 - .../server/include/pa_renderer_stream_impl.h | 2 - .../server/src/capturer_in_server.cpp | 2 +- .../server/src/pa_adapter_manager.cpp | 28 ++++---- .../server/src/pa_capturer_stream_impl.cpp | 45 ++++++------ .../server/src/pa_renderer_stream_impl.cpp | 70 +++++++++---------- .../server/src/renderer_in_server.cpp | 2 +- 8 files changed, 124 insertions(+), 77 deletions(-) create mode 100644 services/audio_service/server/include/pa_adapter_tools.h diff --git a/services/audio_service/server/include/pa_adapter_tools.h b/services/audio_service/server/include/pa_adapter_tools.h new file mode 100644 index 0000000000..cc2b97bc0e --- /dev/null +++ b/services/audio_service/server/include/pa_adapter_tools.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PA_ADAPTER_TOOLS_H +#define PA_ADAPTER_TOOLS_H + +#include +#include + +namespace OHOS { +namespace AudioStandard { +// PaLockGuard is used to auto-call unlock. +class PaLockGuard { +public: + PaLockGuard(pa_threaded_mainloop *mainloop) : mainloop_(mainloop) + { + pa_threaded_mainloop_lock(mainloop_); + } + + ~PaLockGuard() + { + Unlock(); + } + + void Unlock() + { + if (!isUnlocked_) { + pa_threaded_mainloop_unlock(mainloop_); + isUnlocked_ = true; + } + } +private: + bool isUnlocked_ = false; + pa_threaded_mainloop *mainloop_ = nullptr; +}; +} // namespace AudioStandard +} // namespace OHOS +#endif // PA_ADAPTER_TOOLS_H diff --git a/services/audio_service/server/include/pa_capturer_stream_impl.h b/services/audio_service/server/include/pa_capturer_stream_impl.h index 2863b463cf..6f315cdf4f 100644 --- a/services/audio_service/server/include/pa_capturer_stream_impl.h +++ b/services/audio_service/server/include/pa_capturer_stream_impl.h @@ -32,7 +32,6 @@ public: int32_t Drain() override { return 0; }; int32_t Stop() override; int32_t Release() override; - int32_t CorkStream(); int32_t GetStreamFramesRead(uint64_t &framesRead) override; int32_t GetCurrentTimeStamp(uint64_t &timeStamp) override; int32_t GetLatency(uint64_t &latency) override; @@ -58,7 +57,6 @@ private: static void PAStreamPauseSuccessCb(pa_stream *stream, int32_t success, void *userdata); static void PAStreamFlushSuccessCb(pa_stream *stream, int32_t success, void *userdata); static void PAStreamStopSuccessCb(pa_stream *stream, int32_t success, void *userdata); - pa_stream_success_cb_t PAStreamCorkSuccessCb; uint32_t streamIndex_ = static_cast(-1); // invalid index diff --git a/services/audio_service/server/include/pa_renderer_stream_impl.h b/services/audio_service/server/include/pa_renderer_stream_impl.h index 5b202d4039..9957c1bd6f 100644 --- a/services/audio_service/server/include/pa_renderer_stream_impl.h +++ b/services/audio_service/server/include/pa_renderer_stream_impl.h @@ -31,7 +31,6 @@ public: int32_t Drain() override; int32_t Stop() override; int32_t Release() override; - int32_t CorkStream(); int32_t GetStreamFramesWritten(uint64_t &framesWritten) override; int32_t GetCurrentTimeStamp(uint64_t &timeStamp) override; int32_t GetLatency(uint64_t &latency) override; @@ -71,7 +70,6 @@ private: uint32_t streamIndex_ = static_cast(-1); // invalid index - pa_stream_success_cb_t PAStreamCorkSuccessCb; pa_stream *paStream_ = nullptr; AudioProcessConfig processConfig_; std::weak_ptr statusCallback_; diff --git a/services/audio_service/server/src/capturer_in_server.cpp b/services/audio_service/server/src/capturer_in_server.cpp index dba5c332ce..77565aee03 100644 --- a/services/audio_service/server/src/capturer_in_server.cpp +++ b/services/audio_service/server/src/capturer_in_server.cpp @@ -220,7 +220,7 @@ int32_t CapturerInServer::OnReadData(size_t length) int32_t CapturerInServer::UpdateReadIndex() { - AUDIO_INFO_LOG("UpdateReadIndex: audioServerBuffer_->GetAvailableDataFrames(): %{public}d, needStart: %{public}d", + AUDIO_DEBUG_LOG("audioServerBuffer_->GetAvailableDataFrames(): %{public}d, needStart: %{public}d", audioServerBuffer_->GetAvailableDataFrames(), needStart); return SUCCESS; } diff --git a/services/audio_service/server/src/pa_adapter_manager.cpp b/services/audio_service/server/src/pa_adapter_manager.cpp index 4b8c06c3fe..f881cb6d33 100644 --- a/services/audio_service/server/src/pa_adapter_manager.cpp +++ b/services/audio_service/server/src/pa_adapter_manager.cpp @@ -19,6 +19,7 @@ #include "audio_log.h" #include "audio_errors.h" #include "audio_schedule.h" +#include "pa_adapter_tools.h" #include "pa_renderer_stream_impl.h" #include "pa_capturer_stream_impl.h" #include "audio_utils.h" @@ -166,10 +167,9 @@ int32_t PaAdapterManager::ResetPaContext() if (context_) { pa_context_set_state_callback(context_, nullptr, nullptr); if (isContextConnected_ == true) { - pa_threaded_mainloop_lock(mainLoop_); + PaLockGuard lock(mainLoop_); pa_context_disconnect(context_); pa_context_unref(context_); - pa_threaded_mainloop_unlock(mainLoop_); isContextConnected_ = false; context_ = nullptr; } @@ -197,7 +197,11 @@ int32_t PaAdapterManager::InitPaContext() mainLoop_ = pa_threaded_mainloop_new(); CHECK_AND_RETURN_RET_LOG(mainLoop_ != nullptr, ERR_DEVICE_INIT, "Failed to init pa mainLoop"); api_ = pa_threaded_mainloop_get_api(mainLoop_); - pa_threaded_mainloop_set_name(mainLoop_, "OS_ClientsML"); + if (managerType_ == PLAYBACK) { + pa_threaded_mainloop_set_name(mainLoop_, "OS_RendererML"); + } else { + pa_threaded_mainloop_set_name(mainLoop_, "OS_CapturerML"); + } if (api_ == nullptr) { pa_threaded_mainloop_free(mainLoop_); AUDIO_ERR_LOG("Get api from mainLoop failed"); @@ -225,16 +229,14 @@ int32_t PaAdapterManager::InitPaContext() isContextConnected_ = true; HandleMainLoopStart(); - pa_threaded_mainloop_unlock(mainLoop_); return SUCCESS; } int32_t PaAdapterManager::HandleMainLoopStart() { int error = ERROR; - pa_threaded_mainloop_lock(mainLoop_); + PaLockGuard lock(mainLoop_); if (pa_threaded_mainloop_start(mainLoop_) < 0) { - pa_threaded_mainloop_unlock(mainLoop_); return ERR_DEVICE_INIT; } isMainLoopStarted_ = true; @@ -249,7 +251,7 @@ int32_t PaAdapterManager::HandleMainLoopStart() if (!PA_CONTEXT_IS_GOOD(state)) { error = pa_context_errno(context_); AUDIO_ERR_LOG("Context bad state error: %{public}s", pa_strerror(error)); - pa_threaded_mainloop_unlock(mainLoop_); + lock.Unlock(); ResetPaContext(); return ERR_DEVICE_INIT; } @@ -286,18 +288,17 @@ pa_stream *PaAdapterManager::InitPaStream(AudioProcessConfig processConfig, uint AUDIO_DEBUG_LOG("Enter InitPaStream"); std::lock_guard lock(paElementsMutex_); int32_t error = ERROR; + PaLockGuard palock(mainLoop_); if (CheckReturnIfinvalid(mainLoop_ && context_, ERR_ILLEGAL_STATE) < 0) { AUDIO_ERR_LOG("CheckReturnIfinvalid failed"); return nullptr; } - pa_threaded_mainloop_lock(mainLoop_); // Use struct to save spec size pa_sample_spec sampleSpec = ConvertToPAAudioParams(processConfig); pa_proplist *propList = pa_proplist_new(); if (propList == nullptr) { AUDIO_ERR_LOG("pa_proplist_new failed"); - pa_threaded_mainloop_unlock(mainLoop_); return nullptr; } const std::string streamName = GetStreamName(processConfig.streamType); @@ -309,14 +310,13 @@ pa_stream *PaAdapterManager::InitPaStream(AudioProcessConfig processConfig, uint if (!paStream) { error = pa_context_errno(context_); pa_proplist_free(propList); - pa_threaded_mainloop_unlock(mainLoop_); AUDIO_ERR_LOG("pa_stream_new_with_proplist failed, error: %{public}d", error); return nullptr; } pa_proplist_free(propList); pa_stream_set_state_callback(paStream, PAStreamStateCb, (void *)this); - pa_threaded_mainloop_unlock(mainLoop_); + palock.Unlock(); std::string deviceName; int32_t errorCode = GetDeviceNameForConnect(processConfig, deviceName); @@ -420,7 +420,7 @@ int32_t PaAdapterManager::ConnectStreamToPA(pa_stream *paStream, pa_sample_spec return ERR_ILLEGAL_STATE; } - pa_threaded_mainloop_lock(mainLoop_); + PaLockGuard lock(mainLoop_); if (managerType_ == PLAYBACK) { int32_t rendererRet = ConnectRendererStreamToPA(paStream, sampleSpec); CHECK_AND_RETURN_RET_LOG(rendererRet == SUCCESS, rendererRet, "ConnectRendererStreamToPA failed"); @@ -436,13 +436,11 @@ int32_t PaAdapterManager::ConnectStreamToPA(pa_stream *paStream, pa_sample_spec } if (!PA_STREAM_IS_GOOD(state)) { int32_t error = pa_context_errno(context_); - pa_threaded_mainloop_unlock(mainLoop_); AUDIO_ERR_LOG("connection to stream error: %{public}d", error); return ERR_INVALID_OPERATION; } pa_threaded_mainloop_wait(mainLoop_); } - pa_threaded_mainloop_unlock(mainLoop_); return SUCCESS; } @@ -468,7 +466,6 @@ int32_t PaAdapterManager::ConnectRendererStreamToPA(pa_stream *paStream, pa_samp if (result < 0) { int32_t error = pa_context_errno(context_); AUDIO_ERR_LOG("connection to stream error: %{public}d", error); - pa_threaded_mainloop_unlock(mainLoop_); return ERR_INVALID_OPERATION; } return SUCCESS; @@ -493,7 +490,6 @@ int32_t PaAdapterManager::ConnectCapturerStreamToPA(pa_stream *paStream, pa_samp if (result < 0) { int32_t error = pa_context_errno(context_); AUDIO_ERR_LOG("connection to stream error: %{public}d", error); - pa_threaded_mainloop_unlock(mainLoop_); return ERR_INVALID_OPERATION; } return SUCCESS; diff --git a/services/audio_service/server/src/pa_capturer_stream_impl.cpp b/services/audio_service/server/src/pa_capturer_stream_impl.cpp index 9193d1fdcc..9013c29f2e 100644 --- a/services/audio_service/server/src/pa_capturer_stream_impl.cpp +++ b/services/audio_service/server/src/pa_capturer_stream_impl.cpp @@ -14,6 +14,7 @@ */ #include "pa_capturer_stream_impl.h" +#include "pa_adapter_tools.h" #include "audio_errors.h" #include "audio_log.h" @@ -66,6 +67,7 @@ inline uint32_t PcmFormatToBits(uint8_t format) int32_t PaCapturerStreamImpl::InitParams() { + PaLockGuard lock(mainloop_); pa_stream_set_moved_callback(paStream_, PAStreamMovedCb, (void *)this); // used to notify sink/source moved pa_stream_set_read_callback(paStream_, PAStreamReadCb, (void *)this); pa_stream_set_underflow_callback(paStream_, PAStreamUnderFlowCb, (void *)this); @@ -110,7 +112,8 @@ int32_t PaCapturerStreamImpl::InitParams() int32_t PaCapturerStreamImpl::Start() { - AUDIO_DEBUG_LOG("Enter PaCapturerStreamImpl::Start"); + AUDIO_INFO_LOG("Enter PaCapturerStreamImpl::Start"); + PaLockGuard lock(mainloop_); if (CheckReturnIfStreamInvalid(paStream_, ERROR) < 0) { return ERR_ILLEGAL_STATE; } @@ -129,23 +132,17 @@ int32_t PaCapturerStreamImpl::Start() int32_t PaCapturerStreamImpl::Pause() { AUDIO_INFO_LOG("Enter PaCapturerStreamImpl::Pause"); - PAStreamCorkSuccessCb = PAStreamPauseSuccessCb; - return CorkStream(); -} - -int32_t PaCapturerStreamImpl::CorkStream() -{ + PaLockGuard lock(mainloop_); if (CheckReturnIfStreamInvalid(paStream_, ERROR) < 0) { return ERR_ILLEGAL_STATE; } - pa_operation *operation = nullptr; pa_stream_state_t state = pa_stream_get_state(paStream_); if (state != PA_STREAM_READY) { AUDIO_ERR_LOG("Stream Stop Failed"); return ERR_ILLEGAL_STATE; } - operation = pa_stream_cork(paStream_, 1, PAStreamCorkSuccessCb, (void *)this); + pa_operation *operation = pa_stream_cork(paStream_, 1, PAStreamPauseSuccessCb, (void *)this); pa_operation_unref(operation); return SUCCESS; } @@ -162,10 +159,10 @@ int32_t PaCapturerStreamImpl::GetStreamFramesRead(uint64_t &framesRead) int32_t PaCapturerStreamImpl::GetCurrentTimeStamp(uint64_t &timeStamp) { + PaLockGuard lock(mainloop_); if (CheckReturnIfStreamInvalid(paStream_, ERROR) < 0) { return ERR_ILLEGAL_STATE; } - pa_threaded_mainloop_lock(mainloop_); pa_operation *operation = pa_stream_update_timing_info(paStream_, NULL, NULL); if (operation != nullptr) { @@ -180,13 +177,11 @@ int32_t PaCapturerStreamImpl::GetCurrentTimeStamp(uint64_t &timeStamp) const pa_timing_info *info = pa_stream_get_timing_info(paStream_); if (info == nullptr) { AUDIO_ERR_LOG("pa_stream_get_timing_info failed"); - pa_threaded_mainloop_unlock(mainloop_); return ERR_OPERATION_FAILED; } if (pa_stream_get_time(paStream_, &timeStamp)) { AUDIO_ERR_LOG("GetCurrentTimeStamp failed for AUDIO_SERVICE_CLIENT_RECORD"); - pa_threaded_mainloop_unlock(mainloop_); return ERR_OPERATION_FAILED; } int32_t uid = static_cast(getuid()); @@ -197,12 +192,12 @@ int32_t PaCapturerStreamImpl::GetCurrentTimeStamp(uint64_t &timeStamp) if (uid == media_service) { timeStamp = pa_bytes_to_usec(totalBytesRead_, sampleSpec); } - pa_threaded_mainloop_unlock(mainloop_); return SUCCESS; } int32_t PaCapturerStreamImpl::GetLatency(uint64_t &latency) { + PaLockGuard lock(mainloop_); if (CheckReturnIfStreamInvalid(paStream_, ERROR) < 0) { return ERR_ILLEGAL_STATE; } @@ -211,7 +206,6 @@ int32_t PaCapturerStreamImpl::GetLatency(uint64_t &latency) int32_t negative {0}; // Get PA latency - pa_threaded_mainloop_lock(mainloop_); while (true) { pa_operation *operation = pa_stream_update_timing_info(paStream_, NULL, NULL); if (operation != nullptr) { @@ -222,7 +216,6 @@ int32_t PaCapturerStreamImpl::GetLatency(uint64_t &latency) if (pa_stream_get_latency(paStream_, &paLatency, &negative) >= 0) { if (negative) { latency = 0; - pa_threaded_mainloop_unlock(mainloop_); return ERR_OPERATION_FAILED; } break; @@ -230,7 +223,6 @@ int32_t PaCapturerStreamImpl::GetLatency(uint64_t &latency) AUDIO_INFO_LOG("waiting for audio latency information"); pa_threaded_mainloop_wait(mainloop_); } - pa_threaded_mainloop_unlock(mainloop_); // In plan, 怎么计算cacheLatency // Get audio read cache latency @@ -246,6 +238,7 @@ int32_t PaCapturerStreamImpl::GetLatency(uint64_t &latency) int32_t PaCapturerStreamImpl::Flush() { AUDIO_INFO_LOG("Enter PaCapturerStreamImpl::Flush"); + PaLockGuard lock(mainloop_); if (CheckReturnIfStreamInvalid(paStream_, ERROR) < 0) { return ERR_ILLEGAL_STATE; } @@ -269,8 +262,19 @@ int32_t PaCapturerStreamImpl::Flush() int32_t PaCapturerStreamImpl::Stop() { AUDIO_INFO_LOG("Enter PaCapturerStreamImpl::Stop"); - PAStreamCorkSuccessCb = PAStreamStopSuccessCb; - return CorkStream(); + PaLockGuard lock(mainloop_); + if (CheckReturnIfStreamInvalid(paStream_, ERROR) < 0) { + return ERR_ILLEGAL_STATE; + } + + pa_stream_state_t state = pa_stream_get_state(paStream_); + if (state != PA_STREAM_READY) { + AUDIO_ERR_LOG("Stream Stop Failed"); + return ERR_ILLEGAL_STATE; + } + pa_operation *operation = pa_stream_cork(paStream_, 1, PAStreamStopSuccessCb, (void *)this); + pa_operation_unref(operation); + return SUCCESS; } int32_t PaCapturerStreamImpl::Release() @@ -281,12 +285,13 @@ int32_t PaCapturerStreamImpl::Release() } state_ = RELEASED; if (paStream_) { + PaLockGuard lock(mainloop_); pa_stream_set_state_callback(paStream_, nullptr, nullptr); pa_stream_set_read_callback(paStream_, nullptr, nullptr); - pa_stream_set_read_callback(paStream_, nullptr, nullptr); pa_stream_set_latency_update_callback(paStream_, nullptr, nullptr); pa_stream_set_underflow_callback(paStream_, nullptr, nullptr); - + pa_stream_set_moved_callback(paStream_, nullptr, nullptr); + pa_stream_set_started_callback(paStream_, nullptr, nullptr); pa_stream_disconnect(paStream_); pa_stream_unref(paStream_); paStream_ = nullptr; diff --git a/services/audio_service/server/src/pa_renderer_stream_impl.cpp b/services/audio_service/server/src/pa_renderer_stream_impl.cpp index 9c990f9e92..142e9bba95 100644 --- a/services/audio_service/server/src/pa_renderer_stream_impl.cpp +++ b/services/audio_service/server/src/pa_renderer_stream_impl.cpp @@ -14,6 +14,7 @@ */ #include "pa_renderer_stream_impl.h" +#include "pa_adapter_tools.h" #include "audio_errors.h" #include "audio_log.h" #include "audio_utils.h" @@ -39,13 +40,6 @@ PaRendererStreamImpl::PaRendererStreamImpl(pa_stream *paStream, AudioProcessConf mainloop_ = mainloop; paStream_ = paStream; processConfig_ = processConfig; - - pa_stream_set_moved_callback(paStream, PAStreamMovedCb, (void *)this); // used to notify sink/source moved - pa_stream_set_write_callback(paStream, PAStreamWriteCb, (void *)this); - pa_stream_set_underflow_callback(paStream, PAStreamUnderFlowCb, (void *)this); - pa_stream_set_started_callback(paStream, PAStreamSetStartedCb, (void *)this); - - InitParams(); } inline uint32_t PcmFormatToBits(uint8_t format) @@ -68,10 +62,16 @@ inline uint32_t PcmFormatToBits(uint8_t format) int32_t PaRendererStreamImpl::InitParams() { + PaLockGuard lock(mainloop_); if (CheckReturnIfStreamInvalid(paStream_, ERR_ILLEGAL_STATE) < 0) { return ERR_ILLEGAL_STATE; } + pa_stream_set_moved_callback(paStream_, PAStreamMovedCb, (void *)this); // used to notify sink/source moved + pa_stream_set_write_callback(paStream_, PAStreamWriteCb, (void *)this); + pa_stream_set_underflow_callback(paStream_, PAStreamUnderFlowCb, (void *)this); + pa_stream_set_started_callback(paStream_, PAStreamSetStartedCb, (void *)this); + // Get byte size per frame const pa_sample_spec *sampleSpec = pa_stream_get_sample_spec(paStream_); AUDIO_INFO_LOG("sampleSpec: channels: %{public}u, formats: %{public}d, rate: %{public}d", sampleSpec->channels, @@ -100,6 +100,7 @@ int32_t PaRendererStreamImpl::InitParams() } spanSizeInFrame_ = minBufferSize_ / byteSizePerFrame_; + lock.Unlock(); // In plan: Get data from xml effectSceneName_ = GetEffectSceneName(processConfig_.streamType); return SUCCESS; @@ -107,7 +108,8 @@ int32_t PaRendererStreamImpl::InitParams() int32_t PaRendererStreamImpl::Start() { - AUDIO_DEBUG_LOG("Enter PaRendererStreamImpl::Start"); + AUDIO_INFO_LOG("Enter PaRendererStreamImpl::Start"); + PaLockGuard lock(mainloop_); if (CheckReturnIfStreamInvalid(paStream_, ERR_ILLEGAL_STATE) < 0) { return ERR_ILLEGAL_STATE; } @@ -127,12 +129,7 @@ int32_t PaRendererStreamImpl::Start() int32_t PaRendererStreamImpl::Pause() { AUDIO_INFO_LOG("Enter PaRendererStreamImpl::Pause"); - PAStreamCorkSuccessCb = PAStreamPauseSuccessCb; - return CorkStream(); -} - -int32_t PaRendererStreamImpl::CorkStream() -{ + PaLockGuard lock(mainloop_); if (CheckReturnIfStreamInvalid(paStream_, ERR_ILLEGAL_STATE) < 0) { return ERR_ILLEGAL_STATE; } @@ -143,7 +140,7 @@ int32_t PaRendererStreamImpl::CorkStream() AUDIO_ERR_LOG("Stream Stop Failed"); return ERR_OPERATION_FAILED; } - operation = pa_stream_cork(paStream_, 1, PAStreamCorkSuccessCb, (void *)this); + operation = pa_stream_cork(paStream_, 1, PAStreamPauseSuccessCb, (void *)this); pa_operation_unref(operation); return SUCCESS; } @@ -151,6 +148,7 @@ int32_t PaRendererStreamImpl::CorkStream() int32_t PaRendererStreamImpl::Flush() { AUDIO_INFO_LOG("Enter PaRendererStreamImpl::Flush"); + PaLockGuard lock(mainloop_); if (CheckReturnIfStreamInvalid(paStream_, ERR_ILLEGAL_STATE) < 0) { return ERR_ILLEGAL_STATE; } @@ -175,6 +173,7 @@ int32_t PaRendererStreamImpl::Flush() int32_t PaRendererStreamImpl::Drain() { AUDIO_INFO_LOG("Enter PaRendererStreamImpl::Drain"); + PaLockGuard lock(mainloop_); if (CheckReturnIfStreamInvalid(paStream_, ERR_ILLEGAL_STATE) < 0) { return ERR_ILLEGAL_STATE; } @@ -196,6 +195,7 @@ int32_t PaRendererStreamImpl::Stop() { AUDIO_INFO_LOG("Enter PaRendererStreamImpl::Stop"); state_ = STOPPING; + PaLockGuard lock(mainloop_); if (CheckReturnIfStreamInvalid(paStream_, ERR_ILLEGAL_STATE) < 0) { return ERR_ILLEGAL_STATE; @@ -215,12 +215,14 @@ int32_t PaRendererStreamImpl::Release() statusCallback->OnStatusUpdate(OPERATION_RELEASED); } state_ = RELEASED; + PaLockGuard lock(mainloop_); if (paStream_) { pa_stream_set_state_callback(paStream_, nullptr, nullptr); pa_stream_set_write_callback(paStream_, nullptr, nullptr); - pa_stream_set_read_callback(paStream_, nullptr, nullptr); pa_stream_set_latency_update_callback(paStream_, nullptr, nullptr); pa_stream_set_underflow_callback(paStream_, nullptr, nullptr); + pa_stream_set_moved_callback(paStream_, nullptr, nullptr); + pa_stream_set_started_callback(paStream_, nullptr, nullptr); pa_stream_disconnect(paStream_); pa_stream_unref(paStream_); @@ -238,10 +240,10 @@ int32_t PaRendererStreamImpl::GetStreamFramesWritten(uint64_t &framesWritten) int32_t PaRendererStreamImpl::GetCurrentTimeStamp(uint64_t &timeStamp) { + PaLockGuard lock(mainloop_); if (CheckReturnIfStreamInvalid(paStream_, ERR_ILLEGAL_STATE) < 0) { return ERR_ILLEGAL_STATE; } - pa_threaded_mainloop_lock(mainloop_); pa_operation *operation = pa_stream_update_timing_info(paStream_, NULL, NULL); if (operation != nullptr) { @@ -256,18 +258,17 @@ int32_t PaRendererStreamImpl::GetCurrentTimeStamp(uint64_t &timeStamp) const pa_timing_info *info = pa_stream_get_timing_info(paStream_); if (info == nullptr) { AUDIO_ERR_LOG("pa_stream_get_timing_info failed"); - pa_threaded_mainloop_unlock(mainloop_); return ERR_OPERATION_FAILED; } const pa_sample_spec *sampleSpec = pa_stream_get_sample_spec(paStream_); timeStamp = pa_bytes_to_usec(info->write_index, sampleSpec); - pa_threaded_mainloop_unlock(mainloop_); return SUCCESS; } int32_t PaRendererStreamImpl::GetLatency(uint64_t &latency) { + PaLockGuard lock(mainloop_); if (CheckReturnIfStreamInvalid(paStream_, ERR_ILLEGAL_STATE) < 0) { return ERR_ILLEGAL_STATE; } @@ -276,7 +277,6 @@ int32_t PaRendererStreamImpl::GetLatency(uint64_t &latency) int32_t negative {0}; // Get PA latency - pa_threaded_mainloop_lock(mainloop_); while (true) { pa_operation *operation = pa_stream_update_timing_info(paStream_, NULL, NULL); if (operation != nullptr) { @@ -287,7 +287,6 @@ int32_t PaRendererStreamImpl::GetLatency(uint64_t &latency) if (pa_stream_get_latency(paStream_, &paLatency, &negative) >= 0) { if (negative) { latency = 0; - pa_threaded_mainloop_unlock(mainloop_); return ERR_OPERATION_FAILED; } break; @@ -295,7 +294,7 @@ int32_t PaRendererStreamImpl::GetLatency(uint64_t &latency) AUDIO_INFO_LOG("waiting for audio latency information"); pa_threaded_mainloop_wait(mainloop_); } - pa_threaded_mainloop_unlock(mainloop_); + lock.Unlock(); cacheLatency = 0; // In plan: Total latency will be sum of audio write cache latency plus PA latency uint64_t fwLatency = paLatency + cacheLatency; @@ -314,6 +313,7 @@ int32_t PaRendererStreamImpl::GetLatency(uint64_t &latency) int32_t PaRendererStreamImpl::SetRate(int32_t rate) { AUDIO_INFO_LOG("SetRate in"); + PaLockGuard lock(mainloop_); if (CheckReturnIfStreamInvalid(paStream_, ERR_ILLEGAL_STATE) < 0) { return ERR_ILLEGAL_STATE; } @@ -332,21 +332,19 @@ int32_t PaRendererStreamImpl::SetRate(int32_t rate) } renderRate_ = rate; - pa_threaded_mainloop_lock(mainloop_); pa_operation *operation = pa_stream_update_sample_rate(paStream_, currentRate, nullptr, nullptr); if (operation != nullptr) { pa_operation_unref(operation); } else { AUDIO_ERR_LOG("SetRate: operation is nullptr"); } - pa_threaded_mainloop_unlock(mainloop_); return SUCCESS; } int32_t PaRendererStreamImpl::SetLowPowerVolume(float powerVolume) { AUDIO_INFO_LOG("SetLowPowerVolume: %{public}f", powerVolume); - + PaLockGuard lock(mainloop_); if (CheckReturnIfStreamInvalid(paStream_, ERR_ILLEGAL_STATE) < 0) { return ERR_ILLEGAL_STATE; } @@ -357,13 +355,10 @@ int32_t PaRendererStreamImpl::SetLowPowerVolume(float powerVolume) return -1; } - pa_threaded_mainloop_lock(mainloop_); - powerVolumeFactor_ = powerVolume; pa_proplist *propList = pa_proplist_new(); if (propList == nullptr) { AUDIO_ERR_LOG("pa_proplist_new failed"); - pa_threaded_mainloop_unlock(mainloop_); return ERR_OPERATION_FAILED; } @@ -374,7 +369,6 @@ int32_t PaRendererStreamImpl::SetLowPowerVolume(float powerVolume) pa_operation_unref(updatePropOperation); // In plan: Call reset volume - pa_threaded_mainloop_unlock(mainloop_); return SUCCESS; } @@ -388,10 +382,10 @@ int32_t PaRendererStreamImpl::GetLowPowerVolume(float &powerVolume) int32_t PaRendererStreamImpl::SetAudioEffectMode(int32_t effectMode) { AUDIO_INFO_LOG("SetAudioEffectMode: %{public}d", effectMode); + PaLockGuard lock(mainloop_); if (CheckReturnIfStreamInvalid(paStream_, ERR_ILLEGAL_STATE) < 0) { return ERR_ILLEGAL_STATE; } - pa_threaded_mainloop_lock(mainloop_); effectMode_ = effectMode; const std::string effectModeName = GetEffectModeName(effectMode_); @@ -399,7 +393,6 @@ int32_t PaRendererStreamImpl::SetAudioEffectMode(int32_t effectMode) pa_proplist *propList = pa_proplist_new(); if (propList == nullptr) { AUDIO_ERR_LOG("pa_proplist_new failed"); - pa_threaded_mainloop_unlock(mainloop_); return ERR_OPERATION_FAILED; } @@ -409,8 +402,6 @@ int32_t PaRendererStreamImpl::SetAudioEffectMode(int32_t effectMode) pa_proplist_free(propList); pa_operation_unref(updatePropOperation); - pa_threaded_mainloop_unlock(mainloop_); - return SUCCESS; } @@ -465,6 +456,7 @@ BufferDesc PaRendererStreamImpl::DequeueBuffer(size_t length) { BufferDesc bufferDesc; bufferDesc.bufLength = length; + // DequeueBuffer is called in PAStreamWriteCb which is running in mainloop, so don't need lock mainloop. pa_stream_begin_write(paStream_, reinterpret_cast(&bufferDesc.buffer), &bufferDesc.bufLength); return bufferDesc; } @@ -473,16 +465,24 @@ int32_t PaRendererStreamImpl::EnqueueBuffer(const BufferDesc &bufferDesc) { Trace trace("PaRendererStreamImpl::EnqueueBuffer " + std::to_string(bufferDesc.bufLength) + " totalBytesWritten" + std::to_string(totalBytesWritten_)); - pa_threaded_mainloop_lock(mainloop_); int32_t error = 0; + // EnqueueBuffer is called in mainloop in most cases and don't need lock. + bool isInMainloop = pa_threaded_mainloop_in_thread(mainloop_) ? true : false; + if (!isInMainloop) { + pa_threaded_mainloop_lock(mainloop_); + } + error = pa_stream_write(paStream_, static_cast(bufferDesc.buffer), bufferDesc.bufLength, nullptr, 0LL, PA_SEEK_RELATIVE); if (error < 0) { AUDIO_ERR_LOG("Write stream failed"); pa_stream_cancel_write(paStream_); } + + if (!isInMainloop) { + pa_threaded_mainloop_unlock(mainloop_); + } totalBytesWritten_ += bufferDesc.bufLength; - pa_threaded_mainloop_unlock(mainloop_); return SUCCESS; } diff --git a/services/audio_service/server/src/renderer_in_server.cpp b/services/audio_service/server/src/renderer_in_server.cpp index 1d63e47f73..0b9d3b0e94 100644 --- a/services/audio_service/server/src/renderer_in_server.cpp +++ b/services/audio_service/server/src/renderer_in_server.cpp @@ -197,7 +197,7 @@ void RendererInServer::WriteData() Trace::Count("RendererInServer::WriteData", (currentWriteFrame - currentReadFrame) / spanSizeInFrame_); Trace trace1("RendererInServer::WriteData"); if (currentReadFrame + spanSizeInFrame_ > currentWriteFrame) { - AUDIO_INFO_LOG("Underrun!!!"); + AUDIO_INFO_LOG("near underrun"); Trace trace2("RendererInServer::Underrun"); std::shared_ptr stateListener = streamListener_.lock(); CHECK_AND_RETURN_LOG(stateListener != nullptr, "IStreamListener is nullptr"); -- Gitee