Skip to content

Commit 5376439

Browse files
committed
[XMA] Swap input buffer on unresolvable split frames
1 parent 8512a65 commit 5376439

File tree

1 file changed

+30
-6
lines changed

1 file changed

+30
-6
lines changed

src/xenia/apu/xma_context_new.cc

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,8 @@ bool XmaContextNew::Work() {
174174
data.output_buffer_valid, data.subframe_decode_count,
175175
data.output_buffer_padding);
176176

177+
const uint32_t pre_decode_offset = data.input_buffer_read_offset;
178+
177179
Decode(&data);
178180
Consume(&output_rb, &data);
179181

@@ -183,6 +185,18 @@ bool XmaContextNew::Work() {
183185
id(), data.IsAnyInputBufferValid(), data.error_status);
184186
break;
185187
}
188+
189+
// If Decode didn't advance the read offset and produced no frame, we can't
190+
// make progress (e.g. split frame waiting for next buffer).
191+
// Break to avoid spinning.
192+
if (data.input_buffer_read_offset == pre_decode_offset &&
193+
current_frame_remaining_subframes_ == 0) {
194+
XELOGAPU(
195+
"XmaContext {}: Decode stalled at offset {} (no progress), "
196+
"waiting for next buffer",
197+
id(), pre_decode_offset);
198+
break;
199+
}
186200
}
187201

188202
data.output_buffer_write_offset =
@@ -461,8 +475,15 @@ void XmaContextNew::Decode(XMA_CONTEXT_DATA* data) {
461475
const uint8_t* next_packet =
462476
GetNextPacket(data, next_packet_index, current_input_packet_count);
463477
if (!next_packet) {
464-
// Matching split-body error handling below; correct error code unknown.
465-
data->error_status = 4;
478+
// Next buffer not available yet. We can't resolve the split header
479+
// without it, so consume (swap) the current buffer and move on.
480+
// This loses one frame but avoids a deadlock where the game waits
481+
// for us to finish this buffer before providing the next one.
482+
XELOGAPU(
483+
"XmaContext {}: Split frame header at packet {}, next buffer "
484+
"unavailable — swapping input buffer",
485+
id(), packet_index);
486+
SwapInputBuffer(data);
466487
return;
467488
}
468489
std::memcpy(input_buffer_.data(), packet + kBytesPerPacketHeader,
@@ -507,10 +528,13 @@ void XmaContextNew::Decode(XMA_CONTEXT_DATA* data) {
507528
GetNextPacket(data, next_packet_index, current_input_packet_count);
508529

509530
if (!next_packet) {
510-
// Error path
511-
// Decoder probably should return error here
512-
// Not sure what error code should be returned
513-
data->error_status = 4;
531+
// Next buffer not available yet. We can't decode the split frame
532+
// without it, so consume (swap) the current buffer and move on.
533+
XELOGAPU(
534+
"XmaContext {}: Split frame body at packet {}, next buffer "
535+
"unavailable — swapping input buffer (need packet {}/{})",
536+
id(), packet_index, next_packet_index, current_input_packet_count);
537+
SwapInputBuffer(data);
514538
return;
515539
}
516540
// Copy next packet to buffer

0 commit comments

Comments
 (0)