cellAtracXdec: review fixes

This commit is contained in:
capriots 2024-06-11 19:23:48 +02:00 committed by Megamouse
parent 624f34ae13
commit 965dbf2c12

View File

@ -153,7 +153,10 @@ void AtracXdecDecoder::free_avcodec()
void AtracXdecDecoder::init_avcodec() void AtracXdecDecoder::init_avcodec()
{ {
avcodec_close(ctx); if (int err = avcodec_close(ctx); err)
{
fmt::throw_exception("avcodec_close() failed (err=0x%x='%s')", err, utils::av_error_to_string(err));
}
ctx->block_align = nbytes; ctx->block_align = nbytes;
ctx->ch_layout.nb_channels = nch_in; ctx->ch_layout.nb_channels = nch_in;
@ -298,6 +301,7 @@ void AtracXdecContext::exec(ppu_thread& ppu)
switch (cmd.type) switch (cmd.type)
{ {
case AtracXdecCmdType::start_seq: case AtracXdecCmdType::start_seq:
{
first_decode = true; first_decode = true;
skip_next_frame = true; skip_next_frame = true;
@ -317,7 +321,7 @@ void AtracXdecContext::exec(ppu_thread& ppu)
atracx_param = cmd.atracx_param; atracx_param = cmd.atracx_param;
break; break;
}
case AtracXdecCmdType::end_seq: case AtracXdecCmdType::end_seq:
{ {
skip_getting_command = true; skip_getting_command = true;
@ -411,11 +415,9 @@ void AtracXdecContext::exec(ppu_thread& ppu)
error = CELL_ADEC_ERROR_ATX_NON_FATAL; // Not accurate, FFmpeg doesn't provide detailed errors like LLE error = CELL_ADEC_ERROR_ATX_NON_FATAL; // Not accurate, FFmpeg doesn't provide detailed errors like LLE
} }
// Always call avcodec_receive_frame() to clear the AVFrame, even if avcodec_send_packet() returned an error if (int err = avcodec_receive_frame(decoder.ctx, decoder.frame); err != 0 && err != AVERROR(EAGAIN))
if (int err = avcodec_receive_frame(decoder.ctx, decoder.frame); err)
{ {
cellAtracXdec.error("avcodec_receive_frame() failed (err=0x%x='%s')", err, utils::av_error_to_string(err)); fmt::throw_exception("avcodec_receive_frame() failed (err=0x%x='%s')", err, utils::av_error_to_string(err));
error = CELL_ADEC_ERROR_ATX_NON_FATAL; // Not accurate, FFmpeg doesn't provide detailed errors like LLE
} }
decoded_samples_num = decoder.frame->nb_samples; decoded_samples_num = decoder.frame->nb_samples;
@ -430,99 +432,109 @@ void AtracXdecContext::exec(ppu_thread& ppu)
} }
// Convert FFmpeg output to LLE output // Convert FFmpeg output to LLE output
const auto output_f32 = vm::static_ptr_cast<f32>(output); const auto output_f32 = vm::static_ptr_cast<f32>(output).get_ptr();
const auto output_s16 = vm::static_ptr_cast<s16>(output); const auto output_s16 = vm::static_ptr_cast<s16>(output).get_ptr();
const auto output_s32 = vm::static_ptr_cast<s32>(output); const auto output_s32 = vm::static_ptr_cast<s32>(output).get_ptr();
const u8* const ch_map = ATXDEC_AVCODEC_CH_MAP[decoder.ch_config_idx - 1];
const u32 nch_in = decoder.nch_in;
switch (decoder.bw_pcm) switch (decoder.bw_pcm)
{ {
case CELL_ADEC_ATRACX_WORD_SZ_FLOAT: case CELL_ADEC_ATRACX_WORD_SZ_FLOAT:
for (u32 channel_idx = 0; channel_idx < decoder.nch_in; channel_idx++) for (u32 channel_idx = 0; channel_idx < nch_in; channel_idx++)
{ {
for (u32 sample_idx = 0; sample_idx < decoded_samples_num; sample_idx++) const f32* samples = reinterpret_cast<f32*>(decoder.frame->data[channel_idx]);
for (u32 in_sample_idx = 0, out_sample_idx = ch_map[channel_idx]; in_sample_idx < decoded_samples_num; in_sample_idx++, out_sample_idx += nch_in)
{ {
const f32 sample = reinterpret_cast<f32*>(decoder.frame->data[channel_idx])[sample_idx]; const f32 sample = samples[in_sample_idx];
if (sample >= std::bit_cast<f32>(std::bit_cast<u32>(1.f) - 1)) if (sample >= std::bit_cast<f32>(std::bit_cast<u32>(1.f) - 1))
{ {
output_f32[sample_idx * decoder.nch_in + ATXDEC_AVCODEC_CH_MAP[decoder.ch_config_idx - 1][channel_idx]] = std::bit_cast<be_t<f32>>("\x3f\x7f\xff\xff"_u32); // Prevents an unnecessary endian swap output_f32[out_sample_idx] = std::bit_cast<be_t<f32>>("\x3f\x7f\xff\xff"_u32); // Prevents an unnecessary endian swap
} }
else if (sample <= -1.f) else if (sample <= -1.f)
{ {
output_f32[sample_idx * decoder.nch_in + ATXDEC_AVCODEC_CH_MAP[decoder.ch_config_idx - 1][channel_idx]] = -1.f; output_f32[out_sample_idx] = -1.f;
} }
else else
{ {
output_f32[sample_idx * decoder.nch_in + ATXDEC_AVCODEC_CH_MAP[decoder.ch_config_idx - 1][channel_idx]] = sample; output_f32[out_sample_idx] = sample;
} }
} }
} }
break; break;
case CELL_ADEC_ATRACX_WORD_SZ_16BIT: case CELL_ADEC_ATRACX_WORD_SZ_16BIT:
for (u32 channel_idx = 0; channel_idx < decoder.nch_in; channel_idx++) for (u32 channel_idx = 0; channel_idx < nch_in; channel_idx++)
{ {
for (u32 sample_idx = 0; sample_idx < decoded_samples_num; sample_idx++) const f32* samples = reinterpret_cast<f32*>(decoder.frame->data[channel_idx]);
for (u32 in_sample_idx = 0, out_sample_idx = ch_map[channel_idx]; in_sample_idx < decoded_samples_num; in_sample_idx++, out_sample_idx += nch_in)
{ {
const f32 sample = reinterpret_cast<f32*>(decoder.frame->data[channel_idx])[sample_idx]; const f32 sample = samples[in_sample_idx];
if (sample >= 1.f) if (sample >= 1.f)
{ {
output_s16[sample_idx * decoder.nch_in + ATXDEC_AVCODEC_CH_MAP[decoder.ch_config_idx - 1][channel_idx]] = INT16_MAX; output_s16[out_sample_idx] = INT16_MAX;
} }
else if (sample <= -1.f) else if (sample <= -1.f)
{ {
output_s16[sample_idx * decoder.nch_in + ATXDEC_AVCODEC_CH_MAP[decoder.ch_config_idx - 1][channel_idx]] = INT16_MIN; output_s16[out_sample_idx] = INT16_MIN;
} }
else else
{ {
output_s16[sample_idx * decoder.nch_in + ATXDEC_AVCODEC_CH_MAP[decoder.ch_config_idx - 1][channel_idx]] = static_cast<s16>(std::floor(sample * 0x8000u)); output_s16[out_sample_idx] = static_cast<s16>(std::floor(sample * 0x8000u));
} }
} }
} }
break; break;
case CELL_ADEC_ATRACX_WORD_SZ_24BIT: case CELL_ADEC_ATRACX_WORD_SZ_24BIT:
for (u32 channel_idx = 0; channel_idx < decoder.nch_in; channel_idx++) for (u32 channel_idx = 0; channel_idx < nch_in; channel_idx++)
{ {
for (u32 sample_idx = 0; sample_idx < decoded_samples_num; sample_idx++) const f32* samples = reinterpret_cast<f32*>(decoder.frame->data[channel_idx]);
for (u32 in_sample_idx = 0, out_sample_idx = ch_map[channel_idx]; in_sample_idx < decoded_samples_num; in_sample_idx++, out_sample_idx += nch_in)
{ {
const f32 sample = reinterpret_cast<f32*>(decoder.frame->data[channel_idx])[sample_idx]; const f32 sample = samples[in_sample_idx];
if (sample >= 1.f) if (sample >= 1.f)
{ {
output_s32[sample_idx * decoder.nch_in + ATXDEC_AVCODEC_CH_MAP[decoder.ch_config_idx - 1][channel_idx]] = 0x007fffff; output_s32[out_sample_idx] = 0x007fffff;
} }
else if (sample <= -1.f) else if (sample <= -1.f)
{ {
output_s32[sample_idx * decoder.nch_in + ATXDEC_AVCODEC_CH_MAP[decoder.ch_config_idx - 1][channel_idx]] = 0x00800000; output_s32[out_sample_idx] = 0x00800000;
} }
else else
{ {
output_s32[sample_idx * decoder.nch_in + ATXDEC_AVCODEC_CH_MAP[decoder.ch_config_idx - 1][channel_idx]] = static_cast<s32>(std::floor(sample * 0x00800000u)) & 0x00ffffff; output_s32[out_sample_idx] = static_cast<s32>(std::floor(sample * 0x00800000u)) & 0x00ffffff;
} }
} }
} }
break; break;
case CELL_ADEC_ATRACX_WORD_SZ_32BIT: case CELL_ADEC_ATRACX_WORD_SZ_32BIT:
for (u32 channel_idx = 0; channel_idx < decoder.nch_in; channel_idx++) for (u32 channel_idx = 0; channel_idx < nch_in; channel_idx++)
{ {
for (u32 sample_idx = 0; sample_idx < decoded_samples_num; sample_idx++) const f32* samples = reinterpret_cast<f32*>(decoder.frame->data[channel_idx]);
for (u32 in_sample_idx = 0, out_sample_idx = ch_map[channel_idx]; in_sample_idx < decoded_samples_num; in_sample_idx++, out_sample_idx += nch_in)
{ {
const f32 sample = reinterpret_cast<f32*>(decoder.frame->data[channel_idx])[sample_idx]; const f32 sample = samples[in_sample_idx];
if (sample >= 1.f) if (sample >= 1.f)
{ {
output_s32[sample_idx * decoder.nch_in + ATXDEC_AVCODEC_CH_MAP[decoder.ch_config_idx - 1][channel_idx]] = INT32_MAX; output_s32[out_sample_idx] = INT32_MAX;
} }
else if (sample <= -1.f) else if (sample <= -1.f)
{ {
output_s32[sample_idx * decoder.nch_in + ATXDEC_AVCODEC_CH_MAP[decoder.ch_config_idx - 1][channel_idx]] = INT32_MIN; output_s32[out_sample_idx] = INT32_MIN;
} }
else else
{ {
output_s32[sample_idx * decoder.nch_in + ATXDEC_AVCODEC_CH_MAP[decoder.ch_config_idx - 1][channel_idx]] = static_cast<s32>(std::floor(sample * 0x80000000u)); output_s32[out_sample_idx] = static_cast<s32>(std::floor(sample * 0x80000000u));
} }
} }
} }
@ -568,13 +580,16 @@ void AtracXdecContext::exec(ppu_thread& ppu)
const vm::var<CellAdecAtracXInfo> bsi_info{{ decoder.sampling_freq, decoder.ch_config_idx, decoder.nbytes }}; const vm::var<CellAdecAtracXInfo> bsi_info{{ decoder.sampling_freq, decoder.ch_config_idx, decoder.nbytes }};
AdecCorrectPtsValueType correct_pts_type = ADEC_CORRECT_PTS_VALUE_TYPE_UNSPECIFIED; const AdecCorrectPtsValueType correct_pts_type = [&]
switch (decoder.sampling_freq)
{ {
case 32000u: correct_pts_type = ADEC_CORRECT_PTS_VALUE_TYPE_ATRACX_32000Hz; break; switch (decoder.sampling_freq)
case 44100u: correct_pts_type = ADEC_CORRECT_PTS_VALUE_TYPE_ATRACX_44100Hz; break; {
case 48000u: correct_pts_type = ADEC_CORRECT_PTS_VALUE_TYPE_ATRACX_48000Hz; break; case 32000u: return ADEC_CORRECT_PTS_VALUE_TYPE_ATRACX_32000Hz;
} case 44100u: return ADEC_CORRECT_PTS_VALUE_TYPE_ATRACX_44100Hz;
case 48000u: return ADEC_CORRECT_PTS_VALUE_TYPE_ATRACX_48000Hz;
default: return ADEC_CORRECT_PTS_VALUE_TYPE_UNSPECIFIED;
}
}();
notify_pcm_out.cbFunc(ppu, cmd.pcm_handle, output, output_size, notify_pcm_out.cbArg, vm::make_var<vm::bcptr<void>>(bsi_info), correct_pts_type, error); notify_pcm_out.cbFunc(ppu, cmd.pcm_handle, output, output_size, notify_pcm_out.cbArg, vm::make_var<vm::bcptr<void>>(bsi_info), correct_pts_type, error);
break; break;