mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-08-05 00:42:48 +00:00
disable breaking the loop in multi-frame if storage is insufficient
This commit is contained in:
parent
5f63f46204
commit
4d4d9d5e2c
@ -123,14 +123,16 @@ AjmSidebandFormat AjmAt9Decoder::GetFormat() const {
|
|||||||
.channel_mask = GetChannelMask(u32(m_codec_info.channels)),
|
.channel_mask = GetChannelMask(u32(m_codec_info.channels)),
|
||||||
.sampl_freq = u32(m_codec_info.samplingRate),
|
.sampl_freq = u32(m_codec_info.samplingRate),
|
||||||
.sample_encoding = m_format,
|
.sample_encoding = m_format,
|
||||||
.bitrate = u32(m_codec_info.samplingRate * GetPCMSize(m_format) * 8),
|
.bitrate = u32((m_codec_info.samplingRate * m_codec_info.superframeSize * 8) /
|
||||||
|
(m_codec_info.framesInSuperframe * m_codec_info.frameSamples)),
|
||||||
.reserved = 0,
|
.reserved = 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 AjmAt9Decoder::GetNextFrameSize(u32 max_samples) const {
|
u32 AjmAt9Decoder::GetNextFrameSize(u32 skip_samples, u32 max_samples) const {
|
||||||
return std::min(u32(m_codec_info.frameSamples), max_samples) * m_codec_info.channels *
|
skip_samples = std::min({skip_samples, u32(m_codec_info.frameSamples), max_samples});
|
||||||
GetPCMSize(m_format);
|
return (std::min(u32(m_codec_info.frameSamples), max_samples) - skip_samples) *
|
||||||
|
m_codec_info.channels * GetPCMSize(m_format);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Libraries::Ajm
|
} // namespace Libraries::Ajm
|
||||||
|
@ -35,7 +35,7 @@ struct AjmAt9Decoder final : AjmCodec {
|
|||||||
void Initialize(const void* buffer, u32 buffer_size) override;
|
void Initialize(const void* buffer, u32 buffer_size) override;
|
||||||
void GetInfo(void* out_info) const override;
|
void GetInfo(void* out_info) const override;
|
||||||
AjmSidebandFormat GetFormat() const override;
|
AjmSidebandFormat GetFormat() const override;
|
||||||
u32 GetNextFrameSize(u32 max_samples) const override;
|
u32 GetNextFrameSize(u32 skip_samples, u32 max_samples) const override;
|
||||||
std::tuple<u32, u32> ProcessData(std::span<u8>& input, SparseOutputBuffer& output,
|
std::tuple<u32, u32> ProcessData(std::span<u8>& input, SparseOutputBuffer& output,
|
||||||
AjmSidebandGaplessDecode& gapless,
|
AjmSidebandGaplessDecode& gapless,
|
||||||
std::optional<u32> max_samples) override;
|
std::optional<u32> max_samples) override;
|
||||||
|
@ -135,7 +135,10 @@ AjmJob AjmJobFromBatchBuffer(u32 instance_id, AjmBatchBuffer batch_buffer) {
|
|||||||
case Identifier::AjmIdentInputControlBuf: {
|
case Identifier::AjmIdentInputControlBuf: {
|
||||||
ASSERT_MSG(!input_control_buffer.has_value(),
|
ASSERT_MSG(!input_control_buffer.has_value(),
|
||||||
"Only one instance of input control buffer is allowed per job");
|
"Only one instance of input control buffer is allowed per job");
|
||||||
input_control_buffer = batch_buffer.Consume<AjmChunkBuffer>();
|
const auto& buffer = batch_buffer.Consume<AjmChunkBuffer>();
|
||||||
|
if (buffer.p_address != nullptr && buffer.size != 0) {
|
||||||
|
input_control_buffer = buffer;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Identifier::AjmIdentControlFlags:
|
case Identifier::AjmIdentControlFlags:
|
||||||
@ -155,19 +158,27 @@ AjmJob AjmJobFromBatchBuffer(u32 instance_id, AjmBatchBuffer batch_buffer) {
|
|||||||
case Identifier::AjmIdentInlineBuf: {
|
case Identifier::AjmIdentInlineBuf: {
|
||||||
ASSERT_MSG(!output_control_buffer.has_value(),
|
ASSERT_MSG(!output_control_buffer.has_value(),
|
||||||
"Only one instance of inline buffer is allowed per job");
|
"Only one instance of inline buffer is allowed per job");
|
||||||
inline_buffer = batch_buffer.Consume<AjmChunkBuffer>();
|
const auto& buffer = batch_buffer.Consume<AjmChunkBuffer>();
|
||||||
|
if (buffer.p_address != nullptr && buffer.size != 0) {
|
||||||
|
inline_buffer = buffer;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Identifier::AjmIdentOutputRunBuf: {
|
case Identifier::AjmIdentOutputRunBuf: {
|
||||||
auto& buffer = batch_buffer.Consume<AjmChunkBuffer>();
|
auto& buffer = batch_buffer.Consume<AjmChunkBuffer>();
|
||||||
u8* p_begin = reinterpret_cast<u8*>(buffer.p_address);
|
u8* p_begin = reinterpret_cast<u8*>(buffer.p_address);
|
||||||
job.output.buffers.emplace_back(std::span<u8>(p_begin, p_begin + buffer.size));
|
if (p_begin != nullptr && buffer.size != 0) {
|
||||||
|
job.output.buffers.emplace_back(std::span<u8>(p_begin, p_begin + buffer.size));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Identifier::AjmIdentOutputControlBuf: {
|
case Identifier::AjmIdentOutputControlBuf: {
|
||||||
ASSERT_MSG(!output_control_buffer.has_value(),
|
ASSERT_MSG(!output_control_buffer.has_value(),
|
||||||
"Only one instance of output control buffer is allowed per job");
|
"Only one instance of output control buffer is allowed per job");
|
||||||
output_control_buffer = batch_buffer.Consume<AjmChunkBuffer>();
|
const auto& buffer = batch_buffer.Consume<AjmChunkBuffer>();
|
||||||
|
if (buffer.p_address != nullptr && buffer.size != 0) {
|
||||||
|
output_control_buffer = buffer;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -78,8 +78,12 @@ void AjmInstance::ExecuteJob(AjmJob& job) {
|
|||||||
}
|
}
|
||||||
if (job.input.gapless_decode.has_value()) {
|
if (job.input.gapless_decode.has_value()) {
|
||||||
auto& params = job.input.gapless_decode.value();
|
auto& params = job.input.gapless_decode.value();
|
||||||
m_gapless.total_samples = params.total_samples;
|
if (params.total_samples != 0) {
|
||||||
m_gapless.skip_samples = params.skip_samples;
|
m_gapless.total_samples = std::max(params.total_samples, m_gapless.total_samples);
|
||||||
|
}
|
||||||
|
if (params.skip_samples != 0) {
|
||||||
|
m_gapless.skip_samples = std::max(params.skip_samples, m_gapless.skip_samples);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!job.input.buffer.empty() && !job.output.buffers.empty()) {
|
if (!job.input.buffer.empty() && !job.output.buffers.empty()) {
|
||||||
@ -90,16 +94,14 @@ void AjmInstance::ExecuteJob(AjmJob& job) {
|
|||||||
auto in_size = in_buf.size();
|
auto in_size = in_buf.size();
|
||||||
auto out_size = out_buf.Size();
|
auto out_size = out_buf.Size();
|
||||||
while (!in_buf.empty() && !out_buf.IsEmpty() && !IsGaplessEnd()) {
|
while (!in_buf.empty() && !out_buf.IsEmpty() && !IsGaplessEnd()) {
|
||||||
const auto samples_remain = GetNumRemainingSamples();
|
if (!HasEnoughSpace(out_buf)) {
|
||||||
if (!HasEnoughSpace(out_buf, samples_remain)) {
|
if (job.output.p_mframe == nullptr || frames_decoded == 0) {
|
||||||
if (job.output.p_mframe == nullptr) {
|
|
||||||
LOG_ERROR(Lib_Ajm, "Single-frame job buffer too small.");
|
|
||||||
job.output.p_result->result = ORBIS_AJM_RESULT_NOT_ENOUGH_ROOM;
|
job.output.p_result->result = ORBIS_AJM_RESULT_NOT_ENOUGH_ROOM;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
const auto [nframes, nsamples] =
|
const auto [nframes, nsamples] =
|
||||||
m_codec->ProcessData(in_buf, out_buf, m_gapless, samples_remain);
|
m_codec->ProcessData(in_buf, out_buf, m_gapless, GetNumRemainingSamples());
|
||||||
frames_decoded += nframes;
|
frames_decoded += nframes;
|
||||||
m_total_samples += nsamples;
|
m_total_samples += nsamples;
|
||||||
m_gapless_samples += nsamples;
|
m_gapless_samples += nsamples;
|
||||||
@ -138,10 +140,11 @@ bool AjmInstance::IsGaplessEnd() const {
|
|||||||
return m_gapless.total_samples != 0 && m_gapless_samples >= m_gapless.total_samples;
|
return m_gapless.total_samples != 0 && m_gapless_samples >= m_gapless.total_samples;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AjmInstance::HasEnoughSpace(const SparseOutputBuffer& output,
|
bool AjmInstance::HasEnoughSpace(const SparseOutputBuffer& output) const {
|
||||||
std::optional<u32> opt_samples_remain) const {
|
const auto skip =
|
||||||
const auto remain = opt_samples_remain.value_or(std::numeric_limits<u32>::max());
|
m_gapless.skip_samples - std::min(m_gapless.skip_samples, m_gapless.skipped_samples);
|
||||||
return output.Size() >= m_codec->GetNextFrameSize(remain);
|
const auto remain = GetNumRemainingSamples().value_or(std::numeric_limits<u32>::max());
|
||||||
|
return output.Size() >= m_codec->GetNextFrameSize(skip, remain);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<u32> AjmInstance::GetNumRemainingSamples() const {
|
std::optional<u32> AjmInstance::GetNumRemainingSamples() const {
|
||||||
|
@ -66,7 +66,7 @@ public:
|
|||||||
virtual void Reset() = 0;
|
virtual void Reset() = 0;
|
||||||
virtual void GetInfo(void* out_info) const = 0;
|
virtual void GetInfo(void* out_info) const = 0;
|
||||||
virtual AjmSidebandFormat GetFormat() const = 0;
|
virtual AjmSidebandFormat GetFormat() const = 0;
|
||||||
virtual u32 GetNextFrameSize(u32 max_samples) const = 0;
|
virtual u32 GetNextFrameSize(u32 skip_samples, u32 max_samples) const = 0;
|
||||||
virtual std::tuple<u32, u32> ProcessData(std::span<u8>& input, SparseOutputBuffer& output,
|
virtual std::tuple<u32, u32> ProcessData(std::span<u8>& input, SparseOutputBuffer& output,
|
||||||
AjmSidebandGaplessDecode& gapless,
|
AjmSidebandGaplessDecode& gapless,
|
||||||
std::optional<u32> max_samples_per_channel) = 0;
|
std::optional<u32> max_samples_per_channel) = 0;
|
||||||
@ -80,7 +80,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
bool IsGaplessEnd() const;
|
bool IsGaplessEnd() const;
|
||||||
bool HasEnoughSpace(const SparseOutputBuffer& output, std::optional<u32> samples_remain) const;
|
bool HasEnoughSpace(const SparseOutputBuffer& output) const;
|
||||||
std::optional<u32> GetNumRemainingSamples() const;
|
std::optional<u32> GetNumRemainingSamples() const;
|
||||||
|
|
||||||
AjmInstanceFlags m_flags{};
|
AjmInstanceFlags m_flags{};
|
||||||
|
@ -219,9 +219,10 @@ std::tuple<u32, u32> AjmMp3Decoder::ProcessData(std::span<u8>& in_buf, SparseOut
|
|||||||
return {frames_decoded, samples_decoded / m_codec_context->ch_layout.nb_channels};
|
return {frames_decoded, samples_decoded / m_codec_context->ch_layout.nb_channels};
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 AjmMp3Decoder::GetNextFrameSize(u32 max_samples) const {
|
u32 AjmMp3Decoder::GetNextFrameSize(u32 skip_samples, u32 max_samples) const {
|
||||||
return std::min(m_frame_samples, max_samples) * m_codec_context->ch_layout.nb_channels *
|
skip_samples = std::min({skip_samples, m_frame_samples, max_samples});
|
||||||
GetPCMSize(m_format);
|
return (std::min(m_frame_samples, max_samples) - skip_samples) *
|
||||||
|
m_codec_context->ch_layout.nb_channels * GetPCMSize(m_format);
|
||||||
}
|
}
|
||||||
|
|
||||||
class BitReader {
|
class BitReader {
|
||||||
|
@ -70,7 +70,7 @@ public:
|
|||||||
void Initialize(const void* buffer, u32 buffer_size) override {}
|
void Initialize(const void* buffer, u32 buffer_size) override {}
|
||||||
void GetInfo(void* out_info) const override;
|
void GetInfo(void* out_info) const override;
|
||||||
AjmSidebandFormat GetFormat() const override;
|
AjmSidebandFormat GetFormat() const override;
|
||||||
u32 GetNextFrameSize(u32 max_samples) const override;
|
u32 GetNextFrameSize(u32 skip_samples, u32 max_samples) const override;
|
||||||
std::tuple<u32, u32> ProcessData(std::span<u8>& input, SparseOutputBuffer& output,
|
std::tuple<u32, u32> ProcessData(std::span<u8>& input, SparseOutputBuffer& output,
|
||||||
AjmSidebandGaplessDecode& gapless,
|
AjmSidebandGaplessDecode& gapless,
|
||||||
std::optional<u32> max_samples_per_channel) override;
|
std::optional<u32> max_samples_per_channel) override;
|
||||||
|
Loading…
Reference in New Issue
Block a user