diff --git a/frameworks/native/pulseaudio/modules/hdi/hdi_sink.c b/frameworks/native/pulseaudio/modules/hdi/hdi_sink.c index 47aede2747a61d70625a8f844e1aea848d8a19bc..5180e598acbd6ab329c8c327b5a6c5ffedc6b673 100644 --- a/frameworks/native/pulseaudio/modules/hdi/hdi_sink.c +++ b/frameworks/native/pulseaudio/modules/hdi/hdi_sink.c @@ -1266,12 +1266,11 @@ static unsigned SinkRenderPrimaryCluster(pa_sink *si, size_t *length, pa_mix_inf if (mixlength == 0 || infoIn->chunk.length < mixlength) {mixlength = infoIn->chunk.length;} - if (pa_memblock_is_silence(infoIn->chunk.memblock)) { + if (pa_memblock_is_silence(infoIn->chunk.memblock) && sinkIn->thread_info.state == PA_SINK_INPUT_RUNNING) { AUTO_CTRACE("hdi_sink::PrimaryCluster::is_silence"); pa_sink_input_handle_ohos_underrun(sinkIn); } else { AUTO_CTRACE("hdi_sink::PrimaryCluster::is_not_silence"); - pa_atomic_store(&sinkIn->isFirstReaded, 1); } infoIn->userdata = pa_sink_input_ref(sinkIn); @@ -1369,10 +1368,12 @@ static unsigned SinkRenderMultiChannelCluster(pa_sink *si, size_t *length, pa_mi if (mixlength == 0 || infoIn->chunk.length < mixlength) {mixlength = infoIn->chunk.length;} - if (pa_memblock_is_silence(infoIn->chunk.memblock)) { + if (pa_memblock_is_silence(infoIn->chunk.memblock) && sinkIn->thread_info.state == PA_SINK_INPUT_RUNNING) { AUTO_CTRACE("hdi_sink::SinkRenderMultiChannelCluster::is_silence"); pa_sink_input_handle_ohos_underrun(sinkIn); } else if (pa_safe_streq(sinkSpatializationEnabled, "true")) { + AUTO_CTRACE("hdi_sink::SinkRenderMultiChannelCluster::is_not_silence"); + pa_atomic_store(&sinkIn->isFirstReaded, 1); PrepareMultiChannelFading(sinkIn, infoIn, si); CheckMultiChannelFadeinIsDone(si, sinkIn); } @@ -2346,6 +2347,8 @@ static int32_t ProcessRenderUseTimingOffload(struct Userdata *u, bool *wait, int size_t length = GetOffloadRenderLength(u, i, wait); if (*wait && length == 0) { InputsDropFromInputs2(infoInputs, nInputs); + AUTO_CTRACE("hdi_sink::ProcessRenderUseTimingOffload::underrun"); + pa_sink_input_handle_ohos_underrun(i); pa_sink_unref(s); return 0; } @@ -2758,14 +2761,12 @@ static void PaInputStateChangeCb(pa_sink_input *i, pa_sink_input_state_t state) return; } - { - pa_proplist *propList = pa_proplist_new(); - if (propList != NULL) { - 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); - pa_proplist_free(propList); - } + pa_proplist *propList = pa_proplist_new(); + if (propList != NULL) { + 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); + pa_proplist_free(propList); } const bool corking = i->thread_info.state == PA_SINK_INPUT_RUNNING && state == PA_SINK_INPUT_CORKED; @@ -2776,6 +2777,10 @@ static void PaInputStateChangeCb(pa_sink_input *i, pa_sink_input_state_t state) pa_atomic_store(&i->isFirstReaded, 0); } + if (starting) { + pa_atomic_store(&i->isFirstReaded, 1); + } + if (!corking && !starting && !stopping) { AUDIO_WARNING_LOG("PaInputStateChangeCb, input state change: invalid"); return; diff --git a/services/audio_service/server/include/renderer_in_server.h b/services/audio_service/server/include/renderer_in_server.h index 500d5335c7dbc8535ad0b6412a9505aca9adb8fa..2d31d0f6496b38029f3bae8fb0821938db5b62fa 100644 --- a/services/audio_service/server/include/renderer_in_server.h +++ b/services/audio_service/server/include/renderer_in_server.h @@ -142,6 +142,7 @@ private: bool isNeedFade_ = false; float oldAppliedVolume_ = MAX_FLOAT_VOLUME; std::mutex updateIndexLock_; + int64_t startedTime_ = 0; uint32_t underrunCount_ = 0; uint32_t standByCounter_ = 0; int64_t lastWriteTime_ = 0; diff --git a/services/audio_service/server/src/renderer_in_server.cpp b/services/audio_service/server/src/renderer_in_server.cpp index f60198242a1c0a47f72ea161f9a4ef20629a2f94..04edfffe967b050defd13f772fc509d369b30fb7 100644 --- a/services/audio_service/server/src/renderer_in_server.cpp +++ b/services/audio_service/server/src/renderer_in_server.cpp @@ -38,6 +38,7 @@ namespace AudioStandard { namespace { static constexpr int32_t VOLUME_SHIFT_NUMBER = 16; // 1 >> 16 = 65536, max volume static const int64_t MOCK_LATENCY = 45000000; // 45000000 -> 45ms + static const int64_t START_MIN_COST = 80000000; // 80000000 -> 80ms static const int32_t NO_FADING = 0; static const int32_t DO_FADINGOUT = 1; static const int32_t FADING_OUT_DONE = 2; @@ -193,6 +194,7 @@ void RendererInServer::OnStatusUpdate(IOperation operation) return; } status_ = I_STATUS_STARTED; + startedTime_ = ClockTime::GetCurNano(); stateListener->OnOperationHandled(START_STREAM, 0); break; case OPERATION_PAUSED: @@ -222,10 +224,6 @@ void RendererInServer::OnStatusUpdate(IOperation operation) } afterDrain = true; break; - case OPERATION_RELEASED: - stateListener->OnOperationHandled(RELEASE_STREAM, 0); - status_ = I_STATUS_RELEASED; - break; default: OnStatusUpdateSub(operation); } @@ -235,6 +233,10 @@ void RendererInServer::OnStatusUpdateSub(IOperation operation) { std::shared_ptr stateListener = streamListener_.lock(); switch (operation) { + case OPERATION_RELEASED: + stateListener->OnOperationHandled(RELEASE_STREAM, 0); + status_ = I_STATUS_RELEASED; + break; case OPERATION_UNDERRUN: AUDIO_INFO_LOG("Underrun: audioServerBuffer_->GetAvailableDataFrames(): %{public}d", audioServerBuffer_->GetAvailableDataFrames()); @@ -248,8 +250,10 @@ void RendererInServer::OnStatusUpdateSub(IOperation operation) } break; case OPERATION_UNDERFLOW: - underrunCount_++; - audioServerBuffer_->SetUnderrunCount(underrunCount_); + if (ClockTime::GetCurNano() - startedTime_ > START_MIN_COST) { + underrunCount_++; + audioServerBuffer_->SetUnderrunCount(underrunCount_); + } StandByCheck(); // if stand by is enbaled here, stream will be paused and not recv UNDERFLOW any more. break; case OPERATION_SET_OFFLOAD_ENABLE: @@ -279,7 +283,13 @@ void RendererInServer::StandByCheck() // call enable stand by std::unique_lock lock(statusLock_); standByEnable_ = true; - IStreamManager::GetPlaybackManager(managerType_).PauseRender(streamIndex_); + lock.unlock(); + // PaAdapterManager::PauseRender will hold mutex, may cause dead lock with pa_lock + if (managerType_ == PLAYBACK) { + stream_->Pause(); + } else if (managerType_ == DIRECT_PLAYBACK) { + IStreamManager::GetPlaybackManager(managerType_).PauseRender(streamIndex_); + } } bool RendererInServer::ShouldEnableStandBy() @@ -574,6 +584,7 @@ int32_t RendererInServer::Start() int ret = IStreamManager::GetPlaybackManager(managerType_).StartRender(streamIndex_); CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "Start stream failed, reason: %{public}d", ret); + startedTime_ = ClockTime::GetCurNano(); uint64_t currentReadFrame = audioServerBuffer_->GetCurReadFrame(); int64_t tempTime = ClockTime::GetCurNano() + MOCK_LATENCY; audioServerBuffer_->SetHandleInfo(currentReadFrame, tempTime);