diff --git a/src/core/libraries/avplayer/avplayer.cpp b/src/core/libraries/avplayer/avplayer.cpp index 73d0b13c0..2495db9e6 100644 --- a/src/core/libraries/avplayer/avplayer.cpp +++ b/src/core/libraries/avplayer/avplayer.cpp @@ -188,11 +188,11 @@ s32 PS4_SYSV_ABI sceAvPlayerResume(AvPlayerHandle handle) { } s32 PS4_SYSV_ABI sceAvPlayerSetAvSyncMode(AvPlayerHandle handle, AvPlayerAvSyncMode sync_mode) { - LOG_ERROR(Lib_AvPlayer, "(STUBBED) called"); + LOG_TRACE(Lib_AvPlayer, "(STUBBED) called"); if (handle == nullptr) { return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS; } - return ORBIS_OK; + return handle->SetAvSyncMode(sync_mode); } s32 PS4_SYSV_ABI sceAvPlayerSetLogCallback(AvPlayerLogCallback log_cb, void* user_data) { diff --git a/src/core/libraries/avplayer/avplayer_impl.cpp b/src/core/libraries/avplayer/avplayer_impl.cpp index 6d7c8cc3e..138747da4 100644 --- a/src/core/libraries/avplayer/avplayer_impl.cpp +++ b/src/core/libraries/avplayer/avplayer_impl.cpp @@ -168,6 +168,14 @@ s32 AvPlayer::Resume() { return ORBIS_OK; } +s32 AvPlayer::SetAvSyncMode(AvPlayerAvSyncMode sync_mode) { + if (m_state == nullptr) { + return ORBIS_AVPLAYER_ERROR_OPERATION_FAILED; + } + m_state->SetAvSyncMode(sync_mode); + return ORBIS_OK; +} + bool AvPlayer::GetVideoData(AvPlayerFrameInfo& video_info) { if (m_state == nullptr) { return false; diff --git a/src/core/libraries/avplayer/avplayer_impl.h b/src/core/libraries/avplayer/avplayer_impl.h index a2812ee0b..7e4aec43c 100644 --- a/src/core/libraries/avplayer/avplayer_impl.h +++ b/src/core/libraries/avplayer/avplayer_impl.h @@ -30,6 +30,7 @@ public: s32 Start(); s32 Pause(); s32 Resume(); + s32 SetAvSyncMode(AvPlayerAvSyncMode sync_mode); bool GetAudioData(AvPlayerFrameInfo& audio_info); bool GetVideoData(AvPlayerFrameInfo& video_info); bool GetVideoData(AvPlayerFrameInfoEx& video_info); diff --git a/src/core/libraries/avplayer/avplayer_source.cpp b/src/core/libraries/avplayer/avplayer_source.cpp index 651353a11..480df3011 100644 --- a/src/core/libraries/avplayer/avplayer_source.cpp +++ b/src/core/libraries/avplayer/avplayer_source.cpp @@ -321,12 +321,16 @@ bool AvPlayerSource::GetVideoData(AvPlayerFrameInfoEx& video_info) { return false; } - { - using namespace std::chrono; - auto elapsed_time = CurrentTime(); - if (elapsed_time < frame->info.timestamp) { - if (m_stop_cv.WaitFor(milliseconds(frame->info.timestamp - elapsed_time), - [&] { return elapsed_time >= frame->info.timestamp; })) { + if (m_state.GetSyncMode() == AvPlayerAvSyncMode::Default && m_audio_stream_index.has_value()) { + const auto audio_ts = m_last_audio_packet_time; + if (audio_ts < frame->info.timestamp) { + using namespace std::chrono; + const auto start = high_resolution_clock::now(); + if (!m_stop_cv.WaitFor(milliseconds(frame->info.timestamp - audio_ts), [&] { + const auto passed = + duration_cast(high_resolution_clock::now() - start).count(); + return (audio_ts + passed) >= frame->info.timestamp; + })) { return false; } } @@ -355,23 +359,13 @@ bool AvPlayerSource::GetAudioData(AvPlayerFrameInfo& audio_info) { return false; } - { - using namespace std::chrono; - auto elapsed_time = CurrentTime(); - if (elapsed_time < frame->info.timestamp) { - if (m_stop_cv.WaitFor(milliseconds(frame->info.timestamp - elapsed_time), - [&] { return elapsed_time >= frame->info.timestamp; })) { - return false; - } - } - } - // return the buffer to the queue if (m_current_audio_frame.has_value()) { m_audio_buffers.Push(std::move(m_current_audio_frame.value())); m_audio_buffers_cv.Notify(); } m_current_audio_frame = std::move(frame->buffer); + m_last_audio_packet_time = frame->info.timestamp; audio_info = {}; audio_info.timestamp = frame->info.timestamp; diff --git a/src/core/libraries/avplayer/avplayer_source.h b/src/core/libraries/avplayer/avplayer_source.h index 67e7a639a..5518b87d1 100644 --- a/src/core/libraries/avplayer/avplayer_source.h +++ b/src/core/libraries/avplayer/avplayer_source.h @@ -30,6 +30,8 @@ class AvPlayerStateCallback { public: virtual ~AvPlayerStateCallback() = default; + virtual AvPlayerAvSyncMode GetSyncMode() = 0; + virtual void OnWarning(u32 id) = 0; virtual void OnError() = 0; virtual void OnEOF() = 0; @@ -216,6 +218,7 @@ private: std::chrono::high_resolution_clock::time_point m_start_time{}; std::chrono::high_resolution_clock::time_point m_last_paused_time{}; std::chrono::high_resolution_clock::duration m_stalled_time{}; + u64 m_last_audio_packet_time{}; }; } // namespace Libraries::AvPlayer diff --git a/src/core/libraries/avplayer/avplayer_state.cpp b/src/core/libraries/avplayer/avplayer_state.cpp index aa66d690e..889884945 100644 --- a/src/core/libraries/avplayer/avplayer_state.cpp +++ b/src/core/libraries/avplayer/avplayer_state.cpp @@ -217,6 +217,10 @@ bool AvPlayerState::Resume() { return true; } +void AvPlayerState::SetAvSyncMode(AvPlayerAvSyncMode sync_mode) { + m_sync_mode = sync_mode; +} + void AvPlayerState::AvControllerThread(std::stop_token stop) { using std::chrono::milliseconds; Common::SetCurrentThreadName("shadPS4:AvController"); @@ -337,6 +341,10 @@ void AvPlayerState::OnWarning(u32 id) { WarningEvent(id); } +AvPlayerAvSyncMode AvPlayerState::GetSyncMode() { + return m_sync_mode; +} + void AvPlayerState::OnError() { SetState(AvState::Error); OnPlaybackStateChanged(AvState::Error); diff --git a/src/core/libraries/avplayer/avplayer_state.h b/src/core/libraries/avplayer/avplayer_state.h index 93f0e0a89..c67855c89 100644 --- a/src/core/libraries/avplayer/avplayer_state.h +++ b/src/core/libraries/avplayer/avplayer_state.h @@ -30,6 +30,7 @@ public: bool Stop(); bool Pause(); bool Resume(); + void SetAvSyncMode(AvPlayerAvSyncMode sync_mode); bool GetAudioData(AvPlayerFrameInfo& audio_info); bool GetVideoData(AvPlayerFrameInfo& video_info); bool GetVideoData(AvPlayerFrameInfoEx& video_info); @@ -45,6 +46,7 @@ private: static void PS4_SYSV_ABI DefaultEventCallback(void* handle, AvPlayerEvents event_id, s32 source_id, void* event_data); + AvPlayerAvSyncMode GetSyncMode() override; void OnWarning(u32 id) override; void OnError() override; void OnEOF() override; @@ -72,6 +74,7 @@ private: AvPlayerEventReplacement m_event_replacement{}; bool m_auto_start{}; char m_default_language[4]{}; + AvPlayerAvSyncMode m_sync_mode = AvPlayerAvSyncMode::Default; std::atomic m_current_state; std::atomic m_previous_state;