avplayer: implemented sync modes

This commit is contained in:
Vladislav Mikhalin 2025-02-16 16:52:20 +03:00
parent c39179a5f4
commit 8162bc2af1
7 changed files with 36 additions and 19 deletions

View file

@ -188,11 +188,11 @@ s32 PS4_SYSV_ABI sceAvPlayerResume(AvPlayerHandle handle) {
} }
s32 PS4_SYSV_ABI sceAvPlayerSetAvSyncMode(AvPlayerHandle handle, AvPlayerAvSyncMode sync_mode) { 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) { if (handle == nullptr) {
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS; 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) { s32 PS4_SYSV_ABI sceAvPlayerSetLogCallback(AvPlayerLogCallback log_cb, void* user_data) {

View file

@ -168,6 +168,14 @@ s32 AvPlayer::Resume() {
return ORBIS_OK; 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) { bool AvPlayer::GetVideoData(AvPlayerFrameInfo& video_info) {
if (m_state == nullptr) { if (m_state == nullptr) {
return false; return false;

View file

@ -30,6 +30,7 @@ public:
s32 Start(); s32 Start();
s32 Pause(); s32 Pause();
s32 Resume(); s32 Resume();
s32 SetAvSyncMode(AvPlayerAvSyncMode sync_mode);
bool GetAudioData(AvPlayerFrameInfo& audio_info); bool GetAudioData(AvPlayerFrameInfo& audio_info);
bool GetVideoData(AvPlayerFrameInfo& video_info); bool GetVideoData(AvPlayerFrameInfo& video_info);
bool GetVideoData(AvPlayerFrameInfoEx& video_info); bool GetVideoData(AvPlayerFrameInfoEx& video_info);

View file

@ -321,12 +321,16 @@ bool AvPlayerSource::GetVideoData(AvPlayerFrameInfoEx& video_info) {
return false; return false;
} }
{ if (m_state.GetSyncMode() == AvPlayerAvSyncMode::Default && m_audio_stream_index.has_value()) {
using namespace std::chrono; const auto audio_ts = m_last_audio_packet_time;
auto elapsed_time = CurrentTime(); if (audio_ts < frame->info.timestamp) {
if (elapsed_time < frame->info.timestamp) { using namespace std::chrono;
if (m_stop_cv.WaitFor(milliseconds(frame->info.timestamp - elapsed_time), const auto start = high_resolution_clock::now();
[&] { return elapsed_time >= frame->info.timestamp; })) { if (!m_stop_cv.WaitFor(milliseconds(frame->info.timestamp - audio_ts), [&] {
const auto passed =
duration_cast<milliseconds>(high_resolution_clock::now() - start).count();
return (audio_ts + passed) >= frame->info.timestamp;
})) {
return false; return false;
} }
} }
@ -355,23 +359,13 @@ bool AvPlayerSource::GetAudioData(AvPlayerFrameInfo& audio_info) {
return false; 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 // return the buffer to the queue
if (m_current_audio_frame.has_value()) { if (m_current_audio_frame.has_value()) {
m_audio_buffers.Push(std::move(m_current_audio_frame.value())); m_audio_buffers.Push(std::move(m_current_audio_frame.value()));
m_audio_buffers_cv.Notify(); m_audio_buffers_cv.Notify();
} }
m_current_audio_frame = std::move(frame->buffer); m_current_audio_frame = std::move(frame->buffer);
m_last_audio_packet_time = frame->info.timestamp;
audio_info = {}; audio_info = {};
audio_info.timestamp = frame->info.timestamp; audio_info.timestamp = frame->info.timestamp;

View file

@ -30,6 +30,8 @@ class AvPlayerStateCallback {
public: public:
virtual ~AvPlayerStateCallback() = default; virtual ~AvPlayerStateCallback() = default;
virtual AvPlayerAvSyncMode GetSyncMode() = 0;
virtual void OnWarning(u32 id) = 0; virtual void OnWarning(u32 id) = 0;
virtual void OnError() = 0; virtual void OnError() = 0;
virtual void OnEOF() = 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_start_time{};
std::chrono::high_resolution_clock::time_point m_last_paused_time{}; std::chrono::high_resolution_clock::time_point m_last_paused_time{};
std::chrono::high_resolution_clock::duration m_stalled_time{}; std::chrono::high_resolution_clock::duration m_stalled_time{};
u64 m_last_audio_packet_time{};
}; };
} // namespace Libraries::AvPlayer } // namespace Libraries::AvPlayer

View file

@ -217,6 +217,10 @@ bool AvPlayerState::Resume() {
return true; return true;
} }
void AvPlayerState::SetAvSyncMode(AvPlayerAvSyncMode sync_mode) {
m_sync_mode = sync_mode;
}
void AvPlayerState::AvControllerThread(std::stop_token stop) { void AvPlayerState::AvControllerThread(std::stop_token stop) {
using std::chrono::milliseconds; using std::chrono::milliseconds;
Common::SetCurrentThreadName("shadPS4:AvController"); Common::SetCurrentThreadName("shadPS4:AvController");
@ -337,6 +341,10 @@ void AvPlayerState::OnWarning(u32 id) {
WarningEvent(id); WarningEvent(id);
} }
AvPlayerAvSyncMode AvPlayerState::GetSyncMode() {
return m_sync_mode;
}
void AvPlayerState::OnError() { void AvPlayerState::OnError() {
SetState(AvState::Error); SetState(AvState::Error);
OnPlaybackStateChanged(AvState::Error); OnPlaybackStateChanged(AvState::Error);

View file

@ -30,6 +30,7 @@ public:
bool Stop(); bool Stop();
bool Pause(); bool Pause();
bool Resume(); bool Resume();
void SetAvSyncMode(AvPlayerAvSyncMode sync_mode);
bool GetAudioData(AvPlayerFrameInfo& audio_info); bool GetAudioData(AvPlayerFrameInfo& audio_info);
bool GetVideoData(AvPlayerFrameInfo& video_info); bool GetVideoData(AvPlayerFrameInfo& video_info);
bool GetVideoData(AvPlayerFrameInfoEx& video_info); bool GetVideoData(AvPlayerFrameInfoEx& video_info);
@ -45,6 +46,7 @@ private:
static void PS4_SYSV_ABI DefaultEventCallback(void* handle, AvPlayerEvents event_id, static void PS4_SYSV_ABI DefaultEventCallback(void* handle, AvPlayerEvents event_id,
s32 source_id, void* event_data); s32 source_id, void* event_data);
AvPlayerAvSyncMode GetSyncMode() override;
void OnWarning(u32 id) override; void OnWarning(u32 id) override;
void OnError() override; void OnError() override;
void OnEOF() override; void OnEOF() override;
@ -72,6 +74,7 @@ private:
AvPlayerEventReplacement m_event_replacement{}; AvPlayerEventReplacement m_event_replacement{};
bool m_auto_start{}; bool m_auto_start{};
char m_default_language[4]{}; char m_default_language[4]{};
AvPlayerAvSyncMode m_sync_mode = AvPlayerAvSyncMode::Default;
std::atomic<AvState> m_current_state; std::atomic<AvState> m_current_state;
std::atomic<AvState> m_previous_state; std::atomic<AvState> m_previous_state;