From 377c24611f45a73c0164ba873040e3a22414207a Mon Sep 17 00:00:00 2001 From: cailei Date: Mon, 11 Nov 2024 11:31:23 +0800 Subject: [PATCH] fix latency Signed-off-by: cailei --- .../offload/offload_audio_renderer_sink.cpp | 14 ++++++++ .../native/pulseaudio/modules/hdi/hdi_sink.c | 3 ++ .../server/src/pa_renderer_stream_impl.cpp | 36 ++++++------------- 3 files changed, 28 insertions(+), 25 deletions(-) diff --git a/frameworks/native/hdiadapter/sink/offload/offload_audio_renderer_sink.cpp b/frameworks/native/hdiadapter/sink/offload/offload_audio_renderer_sink.cpp index 9526b470cb..cb47afa45c 100644 --- a/frameworks/native/hdiadapter/sink/offload/offload_audio_renderer_sink.cpp +++ b/frameworks/native/hdiadapter/sink/offload/offload_audio_renderer_sink.cpp @@ -435,6 +435,20 @@ int32_t OffloadAudioRendererSinkInner::GetPresentationPosition(uint64_t& frames, frames = frames_ * SECOND_TO_MICROSECOND / attr_.sampleRate; timeSec = timestamp.tvSec; timeNanoSec = timestamp.tvNSec; + // check hdi timestamp out of range 40 * 1000 * 1000 ns + struct timespec time; + clockid_t clockId = CLOCK_MONOTONIC; + if (clock_gettime(clockId, &time) >= 0) { + int64_t curNs = time.tv_sec * AUDIO_NS_PER_SECOND + time.tv_nsec; + int64_t hdiNs = timestamp.tvSec * AUDIO_NS_PER_SECOND + timestamp.tvNSec; + int64_t outNs = 40 * 1000 * 1000; // 40 * 1000 * 1000 ns + if (curNs <= hdiNs || curNs > hdiNs + outNs) { + AUDIO_PRERELEASE_LOGW("HDI time is not in the range, timestamp: %{public}" PRId64 + ", now: %{public}" PRId64, hdiNs, curNs); + timeSec = time.tv_sec; + timeNanoSec = time.tv_nsec; + } + } return ret; } diff --git a/frameworks/native/pulseaudio/modules/hdi/hdi_sink.c b/frameworks/native/pulseaudio/modules/hdi/hdi_sink.c index 50320002a1..28b5b7382d 100644 --- a/frameworks/native/pulseaudio/modules/hdi/hdi_sink.c +++ b/frameworks/native/pulseaudio/modules/hdi/hdi_sink.c @@ -3658,6 +3658,9 @@ static int32_t SinkProcessMsg(pa_msgobject *o, int32_t code, void *data, int64_t uint64_t time = now > u->offload.hdiPosTs ? (now - u->offload.hdiPosTs) / PA_USEC_PER_MSEC : 0; uint64_t hdiPos = u->offload.hdiPos + time * PA_USEC_PER_MSEC; *((uint64_t *)data) = pos > hdiPos ? (pos - hdiPos) : 0; + AUDIO_DEBUG_LOG("offload latency: %{public}" PRIu64 " write pos: %{public}" PRIu64 + " hdi pos: %{public}" PRIu64 " time: %{public}" PRIu64, + *((uint64_t *)data), pos, u->offload.hdiPos, time * PA_USEC_PER_MSEC); } else if (u->sink_latency) { *((uint64_t *)data) = u->sink_latency * PA_USEC_PER_MSEC; } else { 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 7dc0d20ae2..2960ef5316 100644 --- a/services/audio_service/server/src/pa_renderer_stream_impl.cpp +++ b/services/audio_service/server/src/pa_renderer_stream_impl.cpp @@ -438,21 +438,10 @@ int32_t PaRendererStreamImpl::GetCurrentPosition(uint64_t &framePosition, uint64 preTimeGetPaLatency_ = curTimeGetLatency; } - pa_usec_t paLatency {0}; - int32_t negative {0}; - if (pa_stream_get_latency(paStream_, &paLatency, &negative) >= 0 && negative) { - return ERR_OPERATION_FAILED; - } - const pa_timing_info *info = pa_stream_get_timing_info(paStream_); CHECK_AND_RETURN_RET_LOG(info != nullptr, ERR_OPERATION_FAILED, "pa_stream_get_timing_info failed"); const pa_sample_spec *sampleSpec = pa_stream_get_sample_spec(paStream_); uint64_t readIndex = pa_bytes_to_usec(info->read_index, sampleSpec); - uint64_t writeIndex = pa_bytes_to_usec(info->write_index, sampleSpec); - if (writeIndex <= paLatency || sampleSpec == nullptr) { - AUDIO_ERR_LOG("error data!"); - return ERR_OPERATION_FAILED; - } framePosition = readIndex * sampleSpec->rate / AUDIO_US_PER_S; latency = info->sink_usec * sampleSpec->rate / AUDIO_US_PER_S; lock.Unlock(); @@ -500,28 +489,25 @@ int32_t PaRendererStreamImpl::GetLatency(uint64_t &latency) return ERR_ILLEGAL_STATE; } pa_usec_t paLatency {0}; - pa_usec_t cacheLatency {0}; - int32_t negative {0}; UpdatePaTimingInfo(); - - if (pa_stream_get_latency(paStream_, &paLatency, &negative) >= 0) { - if (negative) { - AUDIO_WARNING_LOG("pa_stream_get_latency failed"); - return ERR_OPERATION_FAILED; - } - } - + const pa_timing_info *info = pa_stream_get_timing_info(paStream_); + CHECK_AND_RETURN_RET_LOG(info != nullptr, ERR_OPERATION_FAILED, "pa_stream_get_timing_info failed"); + const pa_sample_spec *sampleSpec = pa_stream_get_sample_spec(paStream_); + uint64_t readIndex = pa_bytes_to_usec(info->read_index < 0 ? 0 : info->read_index, sampleSpec); + uint64_t writeIndex = pa_bytes_to_usec(info->write_index < 0 ? 0 : info->write_index, sampleSpec); + pa_usec_t usec = readIndex >= info->sink_usec ? readIndex - info->sink_usec : 0; + paLatency = writeIndex >= usec ? writeIndex - usec : 0; lock.Unlock(); - latency = paLatency + cacheLatency; + latency = paLatency; uint32_t algorithmLatency = GetEffectChainLatency(); latency += offloadEnable_ ? 0 : algorithmLatency * AUDIO_US_PER_MS; uint32_t a2dpOffloadLatency = GetA2dpOffloadLatency(); latency += a2dpOffloadLatency * AUDIO_US_PER_MS; - AUDIO_DEBUG_LOG("total latency: %{public}" PRIu64 ", pa latency: %{public}" PRIu64 ", cache latency: %{public}" - PRIu64 ", algo latency: %{public}u ms, a2dp offload latency: %{public}u ms", - latency, paLatency, cacheLatency, algorithmLatency, a2dpOffloadLatency); + AUDIO_DEBUG_LOG("total latency: %{public}" PRIu64 ", pa latency: %{public}" PRIu64 ", algo latency: %{public}u ms" + ", a2dp offload latency: %{public}u ms, write: %{public}" PRIu64 ", read: %{public}" PRIu64 ", sink:%{public}" + PRIu64, latency, paLatency, algorithmLatency, a2dpOffloadLatency, writeIndex, readIndex, info->sink_usec); preLatency_ = latency; preTimeGetLatency_ = curTimeGetLatency; -- Gitee