diff --git a/src/audio_core/audio_core.cpp b/src/audio_core/audio_core.cpp index cf7e763e63..9feec18296 100644 --- a/src/audio_core/audio_core.cpp +++ b/src/audio_core/audio_core.cpp @@ -57,4 +57,12 @@ void AudioCore::PauseSinks(const bool pausing) const { } } +void AudioCore::SetNVDECActive(bool active) { + nvdec_active = active; +} + +bool AudioCore::IsNVDECActive() const { + return nvdec_active; +} + } // namespace AudioCore diff --git a/src/audio_core/audio_core.h b/src/audio_core/audio_core.h index fd1e43356a..ac9afefaa4 100644 --- a/src/audio_core/audio_core.h +++ b/src/audio_core/audio_core.h @@ -65,6 +65,18 @@ public: */ void PauseSinks(bool pausing) const; + /** + * Toggle NVDEC state, used to avoid stall in playback. + * + * @param active - Set true if nvdec is active, otherwise false. + */ + void SetNVDECActive(bool active); + + /** + * Get NVDEC state. + */ + bool IsNVDECActive() const; + private: /** * Create the sinks on startup. @@ -79,6 +91,8 @@ private: std::unique_ptr input_sink; /// The ADSP in the sysmodule std::unique_ptr adsp; + /// Is NVDec currently active? + bool nvdec_active{false}; }; } // namespace AudioCore diff --git a/src/audio_core/sink/sink_stream.cpp b/src/audio_core/sink/sink_stream.cpp index 3770c515d9..24636e512b 100644 --- a/src/audio_core/sink/sink_stream.cpp +++ b/src/audio_core/sink/sink_stream.cpp @@ -9,6 +9,7 @@ #include #include +#include "audio_core/audio_core.h" #include "audio_core/common/common.h" #include "audio_core/sink/sink_stream.h" #include "common/common_types.h" @@ -194,7 +195,12 @@ void SinkStream::ProcessAudioOutAndRender(std::span output_buffer, std::siz const std::size_t frame_size_bytes = frame_size * sizeof(s16); size_t frames_written{0}; - if (queued_buffers > max_queue_size) { + // Due to many frames being queued up with nvdec (5 frames or so?), a lot of buffers also get + // queued up (30+) but not all at once, which causes constant stalling here, so just let the + // video play out without attempting to stall. + // Can hopefully remove this later with a more complete NVDEC implementation. + const auto nvdec_active{system.AudioCore().IsNVDECActive()}; + if (!nvdec_active && queued_buffers > max_queue_size) { Stall(); } diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp index 2a5128c602..a7385fce81 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "audio_core/audio_core.h" #include "common/assert.h" #include "common/logging/log.h" #include "core/core.h" @@ -65,7 +66,10 @@ NvResult nvhost_nvdec::Ioctl3(DeviceFD fd, Ioctl command, const std::vector& return NvResult::NotImplemented; } -void nvhost_nvdec::OnOpen(DeviceFD fd) {} +void nvhost_nvdec::OnOpen(DeviceFD fd) { + LOG_INFO(Service_NVDRV, "NVDEC video stream started"); + system.AudioCore().SetNVDECActive(true); +} void nvhost_nvdec::OnClose(DeviceFD fd) { LOG_INFO(Service_NVDRV, "NVDEC video stream ended"); @@ -73,6 +77,7 @@ void nvhost_nvdec::OnClose(DeviceFD fd) { if (iter != fd_to_id.end()) { system.GPU().ClearCdmaInstance(iter->second); } + system.AudioCore().SetNVDECActive(false); } } // namespace Service::Nvidia::Devices