1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-22 02:32:36 +01:00

cellVdec: send AUDONE even when the queue is being flushed/restarted

Fixes GT6 regression
This commit is contained in:
Megamouse 2022-04-24 13:52:51 +02:00
parent 7924784215
commit c175cdf3d8

View File

@ -393,7 +393,7 @@ struct vdec_context final
std::deque<vdec_frame> decoded_frames;
if (!abort_decode)
if (!abort_decode && seq_id == cmd->seq_id)
{
cellVdec.trace("AU decoding: handle=0x%x, seq_id=%d, cmd_id=%d, size=0x%x, pts=0x%llx, dts=0x%llx, userdata=0x%llx", handle, cmd->seq_id, cmd->id, au_size, au_pts, au_dts, au_usrd);
@ -402,11 +402,11 @@ struct vdec_context final
fmt::throw_exception("AU queuing error (handle=0x%x, seq_id=%d, cmd_id=%d, error=0x%x): %s", handle, cmd->seq_id, cmd->id, ret, utils::av_error_to_string(ret));
}
while (!abort_decode)
while (!abort_decode && seq_id == cmd->seq_id)
{
// Keep receiving frames
vdec_frame frame;
frame.cmd_id = cmd->seq_id;
frame.seq_id = cmd->seq_id;
frame.cmd_id = cmd->id;
frame.avf.reset(av_frame_alloc());
@ -534,8 +534,9 @@ struct vdec_context final
}
}
if (thread_ctrl::state() != thread_state::aborting && !abort_decode)
if (thread_ctrl::state() != thread_state::aborting)
{
// Send AUDONE even if the current sequence was reset and a new sequence was started.
cellVdec.trace("Sending CELL_VDEC_MSG_TYPE_AUDONE (handle=0x%x, seq_id=%d, cmd_id=%d)", handle, cmd->seq_id, cmd->id);
cb_func(ppu, vid, CELL_VDEC_MSG_TYPE_AUDONE, CELL_OK, cb_arg);
lv2_obj::sleep(ppu);
@ -545,12 +546,12 @@ struct vdec_context final
--au_count;
}
while (!decoded_frames.empty())
while (!decoded_frames.empty() && seq_id == cmd->seq_id)
{
// Wait until there is free space in the image queue.
// Do this after pushing the frame to the queue. That way the game can consume the frame and we can move on.
u32 elapsed = 0;
while (thread_ctrl::state() != thread_state::aborting && !abort_decode)
while (thread_ctrl::state() != thread_state::aborting && !abort_decode && seq_id == cmd->seq_id)
{
{
std::lock_guard lock{mutex};
@ -569,7 +570,7 @@ struct vdec_context final
}
}
if (thread_ctrl::state() == thread_state::aborting || abort_decode)
if (thread_ctrl::state() == thread_state::aborting || abort_decode || seq_id != cmd->seq_id)
{
break;
}
@ -586,7 +587,7 @@ struct vdec_context final
}
}
if (abort_decode)
if (abort_decode || seq_id != cmd->seq_id)
{
cellVdec.warning("AU decoding: aborted (handle=0x%x, seq_id=%d, cmd_id=%d, abort_decode=%d)", handle, cmd->seq_id, cmd->id, abort_decode.load());
}
@ -979,27 +980,10 @@ error_code cellVdecStartSeq(u32 handle)
const u64 cmd_id = vdec->next_cmd_id++;
cellVdec.trace("Adding start cmd (handle=0x%x, seq_id=%d, cmd_id=%d)", handle, seq_id, cmd_id);
vdec->abort_decode = true;
vdec->abort_decode = false;
vdec->is_running = false;
vdec->in_cmd.push(vdec_cmd(vdec_cmd_type::start_sequence, seq_id, cmd_id));
// Wait until the thread is ready
u32 elapsed = 0;
while (thread_ctrl::state() != thread_state::aborting)
{
if (vdec->is_running)
{
break;
}
thread_ctrl::wait_for(1000);
if (elapsed++ >= 5000) // 5 seconds
{
cellVdec.error("Timeout in cellVdecStartSeq.");
elapsed = 0;
}
}
std::lock_guard lock{vdec->mutex};
if (false) // TODO: set to old state in case of error
@ -1038,7 +1022,7 @@ error_code cellVdecEndSeq(u32 handle)
const u64 seq_id = vdec->seq_id;
const u64 cmd_id = vdec->next_cmd_id++;
cellVdec.trace("Adding end cmd (handle=0x%x, seq_id=d, cmd_id=%d)", handle, seq_id, cmd_id);
cellVdec.trace("Adding end cmd (handle=0x%x, seq_id=%d, cmd_id=%d)", handle, seq_id, cmd_id);
vdec->in_cmd.push(vdec_cmd(vdec_cmd_type::end_sequence, seq_id, cmd_id));
@ -1182,6 +1166,8 @@ error_code cellVdecGetPictureExt(u32 handle, vm::cptr<CellVdecPicFormat2> format
vdec_frame frame;
bool notify = false;
u64 sequence_id{};
{
std::lock_guard lock(vdec->mutex);
@ -1191,6 +1177,7 @@ error_code cellVdecGetPictureExt(u32 handle, vm::cptr<CellVdecPicFormat2> format
}
frame = std::move(vdec->out_queue.front());
sequence_id = vdec->seq_id;
vdec->out_queue.pop_front();
if (vdec->out_queue.size() + 1 == vdec->out_max)
@ -1203,6 +1190,11 @@ error_code cellVdecGetPictureExt(u32 handle, vm::cptr<CellVdecPicFormat2> format
if (vdec_ppu) thread_ctrl::notify(*vdec_ppu);
}
if (sequence_id != frame.seq_id)
{
return { CELL_VDEC_ERROR_EMPTY, "sequence_id=%d, seq_id=%d", sequence_id, frame.seq_id };
}
if (outBuff)
{
const int w = frame->width;
@ -1245,7 +1237,7 @@ error_code cellVdecGetPictureExt(u32 handle, vm::cptr<CellVdecPicFormat2> format
fmt::throw_exception("cellVdecGetPictureExt: Unknown frame format (%d)", frame->format);
}
cellVdec.trace("cellVdecGetPictureExt: handle=0x%x, seq_id=d, cmd_id=%d, w=%d, h=%d, frameFormat=%d, formatType=%d, in_f=%d, out_f=%d, alpha_plane=%d, alpha=%d, colorMatrixType=%d", handle, frame.seq_id, frame.cmd_id, w, h, frame->format, format->formatType, +in_f, +out_f, !!alpha_plane, format->alpha, format->colorMatrixType);
cellVdec.trace("cellVdecGetPictureExt: handle=0x%x, seq_id=%d, cmd_id=%d, w=%d, h=%d, frameFormat=%d, formatType=%d, in_f=%d, out_f=%d, alpha_plane=%d, alpha=%d, colorMatrixType=%d", handle, frame.seq_id, frame.cmd_id, w, h, frame->format, format->formatType, +in_f, +out_f, !!alpha_plane, format->alpha, format->colorMatrixType);
vdec->sws = sws_getCachedContext(vdec->sws, w, h, in_f, w, h, out_f, SWS_POINT, nullptr, nullptr, nullptr);
@ -1312,6 +1304,8 @@ error_code cellVdecGetPicItem(u32 handle, vm::pptr<CellVdecPicItem> picItem)
return CELL_VDEC_ERROR_ARG;
}
u64 sequence_id{};
{
std::lock_guard lock{vdec->mutex};
@ -1319,6 +1313,8 @@ error_code cellVdecGetPicItem(u32 handle, vm::pptr<CellVdecPicItem> picItem)
{
return { CELL_VDEC_ERROR_SEQ, vdec->seq_state.load() };
}
sequence_id = vdec->seq_id;
}
struct all_info_t
@ -1368,10 +1364,10 @@ error_code cellVdecGetPicItem(u32 handle, vm::pptr<CellVdecPicItem> picItem)
}
}
if (!frame)
if (!frame || seq_id != sequence_id)
{
// If frame is empty info was not found
return CELL_VDEC_ERROR_EMPTY;
return { CELL_VDEC_ERROR_EMPTY, " frame=%d, sequence_id=%d, seq_id=%d", !!frame, sequence_id, seq_id };
}
info->codecType = vdec->type;