mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-07-12 20:55:56 +00:00
avplayer: implemented pause/resume
This commit is contained in:
parent
f48fa9f447
commit
c39179a5f4
8 changed files with 77 additions and 12 deletions
|
@ -159,11 +159,11 @@ s32 PS4_SYSV_ABI sceAvPlayerJumpToTime(AvPlayerHandle handle, uint64_t time) {
|
|||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAvPlayerPause(AvPlayerHandle handle) {
|
||||
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->Pause();
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAvPlayerPostInit(AvPlayerHandle handle, AvPlayerPostInitData* data) {
|
||||
|
@ -180,11 +180,11 @@ s32 PS4_SYSV_ABI sceAvPlayerPrintf(const char* format, ...) {
|
|||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAvPlayerResume(AvPlayerHandle handle) {
|
||||
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->Resume();
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAvPlayerSetAvSyncMode(AvPlayerHandle handle, AvPlayerAvSyncMode sync_mode) {
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
namespace Libraries::AvPlayer {
|
||||
|
||||
enum class AvState {
|
||||
Unknown,
|
||||
Initial,
|
||||
AddingSource,
|
||||
Ready,
|
||||
|
|
|
@ -148,7 +148,21 @@ s32 AvPlayer::EnableStream(u32 stream_index) {
|
|||
}
|
||||
|
||||
s32 AvPlayer::Start() {
|
||||
if (!m_state->Start()) {
|
||||
if (m_state == nullptr || !m_state->Start()) {
|
||||
return ORBIS_AVPLAYER_ERROR_OPERATION_FAILED;
|
||||
}
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 AvPlayer::Pause() {
|
||||
if (m_state == nullptr || !m_state->Pause()) {
|
||||
return ORBIS_AVPLAYER_ERROR_OPERATION_FAILED;
|
||||
}
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 AvPlayer::Resume() {
|
||||
if (m_state == nullptr || !m_state->Resume()) {
|
||||
return ORBIS_AVPLAYER_ERROR_OPERATION_FAILED;
|
||||
}
|
||||
return ORBIS_OK;
|
||||
|
|
|
@ -28,6 +28,8 @@ public:
|
|||
s32 GetStreamInfo(u32 stream_index, AvPlayerStreamInfo& info);
|
||||
s32 EnableStream(u32 stream_index);
|
||||
s32 Start();
|
||||
s32 Pause();
|
||||
s32 Resume();
|
||||
bool GetAudioData(AvPlayerFrameInfo& audio_info);
|
||||
bool GetVideoData(AvPlayerFrameInfo& video_info);
|
||||
bool GetVideoData(AvPlayerFrameInfoEx& video_info);
|
||||
|
|
|
@ -280,6 +280,16 @@ bool AvPlayerSource::Stop() {
|
|||
return true;
|
||||
}
|
||||
|
||||
void AvPlayerSource::Pause() {
|
||||
m_last_paused_time = std::chrono::high_resolution_clock::now();
|
||||
m_is_paused = true;
|
||||
}
|
||||
|
||||
void AvPlayerSource::Resume() {
|
||||
m_stalled_time += std::chrono::high_resolution_clock::now() - m_last_paused_time;
|
||||
m_is_paused = false;
|
||||
}
|
||||
|
||||
bool AvPlayerSource::GetVideoData(AvPlayerFrameInfo& video_info) {
|
||||
if (!IsActive()) {
|
||||
return false;
|
||||
|
@ -299,7 +309,7 @@ bool AvPlayerSource::GetVideoData(AvPlayerFrameInfo& video_info) {
|
|||
}
|
||||
|
||||
bool AvPlayerSource::GetVideoData(AvPlayerFrameInfoEx& video_info) {
|
||||
if (!IsActive()) {
|
||||
if (!IsActive() || m_is_paused) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -313,8 +323,7 @@ bool AvPlayerSource::GetVideoData(AvPlayerFrameInfoEx& video_info) {
|
|||
|
||||
{
|
||||
using namespace std::chrono;
|
||||
auto elapsed_time =
|
||||
duration_cast<milliseconds>(high_resolution_clock::now() - m_start_time).count();
|
||||
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; })) {
|
||||
|
@ -334,7 +343,7 @@ bool AvPlayerSource::GetVideoData(AvPlayerFrameInfoEx& video_info) {
|
|||
}
|
||||
|
||||
bool AvPlayerSource::GetAudioData(AvPlayerFrameInfo& audio_info) {
|
||||
if (!IsActive()) {
|
||||
if (!IsActive() || m_is_paused) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -348,8 +357,7 @@ bool AvPlayerSource::GetAudioData(AvPlayerFrameInfo& audio_info) {
|
|||
|
||||
{
|
||||
using namespace std::chrono;
|
||||
auto elapsed_time =
|
||||
duration_cast<milliseconds>(high_resolution_clock::now() - m_start_time).count();
|
||||
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; })) {
|
||||
|
@ -379,7 +387,8 @@ u64 AvPlayerSource::CurrentTime() {
|
|||
return 0;
|
||||
}
|
||||
using namespace std::chrono;
|
||||
return duration_cast<milliseconds>(high_resolution_clock::now() - m_start_time).count();
|
||||
return duration_cast<milliseconds>(high_resolution_clock::now() - m_start_time - m_stalled_time)
|
||||
.count();
|
||||
}
|
||||
|
||||
bool AvPlayerSource::IsActive() {
|
||||
|
|
|
@ -130,6 +130,8 @@ public:
|
|||
std::optional<bool> HasFrames(u32 num_frames);
|
||||
bool Start();
|
||||
bool Stop();
|
||||
void Pause();
|
||||
void Resume();
|
||||
bool GetAudioData(AvPlayerFrameInfo& audio_info);
|
||||
bool GetVideoData(AvPlayerFrameInfo& video_info);
|
||||
bool GetVideoData(AvPlayerFrameInfoEx& video_info);
|
||||
|
@ -170,6 +172,7 @@ private:
|
|||
u32 m_num_output_video_framebuffers{};
|
||||
|
||||
std::atomic_bool m_is_looping = false;
|
||||
std::atomic_bool m_is_paused = false;
|
||||
std::atomic_bool m_is_eof = false;
|
||||
|
||||
std::unique_ptr<IDataStreamer> m_up_data_streamer;
|
||||
|
@ -211,6 +214,8 @@ private:
|
|||
SWSContextPtr m_sws_context{nullptr, &ReleaseSWSContext};
|
||||
|
||||
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{};
|
||||
};
|
||||
|
||||
} // namespace Libraries::AvPlayer
|
||||
|
|
|
@ -185,6 +185,38 @@ bool AvPlayerState::Start() {
|
|||
return true;
|
||||
}
|
||||
|
||||
// Called inside GAME thread
|
||||
bool AvPlayerState::Pause() {
|
||||
std::shared_lock lock(m_source_mutex);
|
||||
if (m_current_state == AvState::EndOfFile) {
|
||||
return true;
|
||||
}
|
||||
if (m_up_source == nullptr || m_current_state == AvState::Pause ||
|
||||
m_current_state == AvState::Ready || m_current_state == AvState::Initial ||
|
||||
m_current_state == AvState::Unknown || m_current_state == AvState::AddingSource) {
|
||||
LOG_ERROR(Lib_AvPlayer, "Could not pause playback.");
|
||||
return false;
|
||||
}
|
||||
m_up_source->Pause();
|
||||
SetState(AvState::Pause);
|
||||
OnPlaybackStateChanged(AvState::Pause);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Called inside GAME thread
|
||||
bool AvPlayerState::Resume() {
|
||||
std::shared_lock lock(m_source_mutex);
|
||||
if (m_up_source == nullptr || m_current_state != AvState::Pause) {
|
||||
LOG_ERROR(Lib_AvPlayer, "Could not resume playback.");
|
||||
return false;
|
||||
}
|
||||
m_up_source->Resume();
|
||||
const auto state = m_previous_state.load();
|
||||
SetState(state);
|
||||
OnPlaybackStateChanged(state);
|
||||
return true;
|
||||
}
|
||||
|
||||
void AvPlayerState::AvControllerThread(std::stop_token stop) {
|
||||
using std::chrono::milliseconds;
|
||||
Common::SetCurrentThreadName("shadPS4:AvController");
|
||||
|
|
|
@ -28,6 +28,8 @@ public:
|
|||
bool EnableStream(u32 stream_index);
|
||||
bool Start();
|
||||
bool Stop();
|
||||
bool Pause();
|
||||
bool Resume();
|
||||
bool GetAudioData(AvPlayerFrameInfo& audio_info);
|
||||
bool GetVideoData(AvPlayerFrameInfo& video_info);
|
||||
bool GetVideoData(AvPlayerFrameInfoEx& video_info);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue