XMAContext abort instantly if libav failed mid-packet.
This commit is contained in:
parent
e37479c7b0
commit
766788be7b
|
@ -246,35 +246,41 @@ void XmaContext::DecodePackets(XMA_CONTEXT_DATA& data) {
|
||||||
// This'll copy audio samples into the output buffer.
|
// This'll copy audio samples into the output buffer.
|
||||||
// The samples need to be 2 bytes long!
|
// The samples need to be 2 bytes long!
|
||||||
// Copies one frame at a time, so keep calling this until size == 0
|
// Copies one frame at a time, so keep calling this until size == 0
|
||||||
int read_bytes = 0;
|
int written_bytes = 0;
|
||||||
int decode_attempts_remaining = 3;
|
int decode_attempts_remaining = 3;
|
||||||
|
|
||||||
uint8_t work_buffer[kOutputMaxSizeBytes];
|
uint8_t work_buffer[kOutputMaxSizeBytes];
|
||||||
while (decode_attempts_remaining) {
|
while (decode_attempts_remaining) {
|
||||||
read_bytes = DecodePacket(work_buffer, 0, output_remaining_bytes);
|
size_t read_bytes = 0;
|
||||||
if (read_bytes >= 0) {
|
written_bytes =
|
||||||
// assert_true((read_bytes % 256) == 0);
|
DecodePacket(work_buffer, 0, output_remaining_bytes, &read_bytes);
|
||||||
auto written_bytes = output_rb.Write(work_buffer, read_bytes);
|
if (written_bytes >= 0) {
|
||||||
assert_true(read_bytes == written_bytes);
|
// assert_true((written_bytes % 256) == 0);
|
||||||
|
auto written_bytes_rb = output_rb.Write(work_buffer, written_bytes);
|
||||||
|
assert_true(written_bytes == written_bytes_rb);
|
||||||
|
|
||||||
// Ok.
|
// Ok.
|
||||||
break;
|
break;
|
||||||
} else {
|
} else if (read_bytes % 2048 == 0) {
|
||||||
// Sometimes the decoder will fail on a packet. I think it's
|
// Sometimes the decoder will fail on a packet. I think it's
|
||||||
// looking for cross-packet frames and failing. If you run it again
|
// looking for cross-packet frames and failing. If you run it again
|
||||||
// on the same packet it'll work though.
|
// on the same packet it'll work though.
|
||||||
--decode_attempts_remaining;
|
--decode_attempts_remaining;
|
||||||
|
} else {
|
||||||
|
// Failed in the middle of a packet, do not retry!
|
||||||
|
decode_attempts_remaining = 0;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!decode_attempts_remaining) {
|
if (!decode_attempts_remaining) {
|
||||||
XELOGAPU("XmaContext: libav failed to decode packet (returned %.8X)",
|
XELOGAPU("XmaContext: libav failed to decode packet (returned %.8X)",
|
||||||
-read_bytes);
|
-written_bytes);
|
||||||
|
|
||||||
// Failed out.
|
// Failed out.
|
||||||
if (data.input_buffer_0_valid || data.input_buffer_1_valid) {
|
if (data.input_buffer_0_valid || data.input_buffer_1_valid) {
|
||||||
// There's new data available - maybe we'll be ok if we decode it?
|
// There's new data available - maybe we'll be ok if we decode it?
|
||||||
read_bytes = 0;
|
written_bytes = 0;
|
||||||
DiscardPacket();
|
DiscardPacket();
|
||||||
} else {
|
} else {
|
||||||
// No data and hosed - bail.
|
// No data and hosed - bail.
|
||||||
|
@ -283,10 +289,10 @@ void XmaContext::DecodePackets(XMA_CONTEXT_DATA& data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
data.output_buffer_write_offset = output_rb.write_offset() / 256;
|
data.output_buffer_write_offset = output_rb.write_offset() / 256;
|
||||||
output_remaining_bytes -= read_bytes;
|
output_remaining_bytes -= written_bytes;
|
||||||
|
|
||||||
// If we need more data and the input buffers have it, grab it.
|
// If we need more data and the input buffers have it, grab it.
|
||||||
if (read_bytes) {
|
if (written_bytes) {
|
||||||
// Haven't finished with current packet.
|
// Haven't finished with current packet.
|
||||||
continue;
|
continue;
|
||||||
} else if (data.input_buffer_0_valid || data.input_buffer_1_valid) {
|
} else if (data.input_buffer_0_valid || data.input_buffer_1_valid) {
|
||||||
|
@ -417,9 +423,12 @@ void XmaContext::DiscardPacket() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int XmaContext::DecodePacket(uint8_t* output, size_t output_offset,
|
int XmaContext::DecodePacket(uint8_t* output, size_t output_offset,
|
||||||
size_t output_size) {
|
size_t output_size, size_t* read_bytes) {
|
||||||
size_t to_copy = 0;
|
size_t to_copy = 0;
|
||||||
size_t original_offset = output_offset;
|
size_t original_offset = output_offset;
|
||||||
|
if (read_bytes) {
|
||||||
|
*read_bytes = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// We're holding onto an already-decoded frame. Copy it out.
|
// We're holding onto an already-decoded frame. Copy it out.
|
||||||
if (current_frame_pos_ != frame_samples_size_) {
|
if (current_frame_pos_ != frame_samples_size_) {
|
||||||
|
@ -443,6 +452,10 @@ int XmaContext::DecodePacket(uint8_t* output, size_t output_offset,
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (read_bytes) {
|
||||||
|
*read_bytes += len;
|
||||||
|
}
|
||||||
|
|
||||||
// Offset by decoded length
|
// Offset by decoded length
|
||||||
packet_->size -= len;
|
packet_->size -= len;
|
||||||
packet_->data += len;
|
packet_->data += len;
|
||||||
|
|
|
@ -171,7 +171,8 @@ class XmaContext {
|
||||||
int sample_rate, int channels);
|
int sample_rate, int channels);
|
||||||
void DiscardPacket();
|
void DiscardPacket();
|
||||||
|
|
||||||
int DecodePacket(uint8_t* output, size_t offset, size_t size);
|
int DecodePacket(uint8_t* output, size_t offset, size_t size,
|
||||||
|
size_t* read_bytes);
|
||||||
|
|
||||||
Memory* memory_;
|
Memory* memory_;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue