mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-04-20 11:35:45 +00:00
refactored ajm
This commit is contained in:
parent
d1ba4c91b2
commit
c98315d486
6 changed files with 91 additions and 138 deletions
|
@ -51,8 +51,9 @@ void AjmAt9Decoder::GetInfo(void* out_info) {
|
|||
info->next_frame_size = static_cast<Atrac9Handle*>(m_handle)->Config.FrameBytes;
|
||||
}
|
||||
|
||||
u32 AjmAt9Decoder::ProcessFrame(std::span<u8>& in_buf, SparseOutputBuffer& output,
|
||||
AjmSidebandGaplessDecode& gapless, u32 max_samples_per_channel) {
|
||||
std::tuple<u32, u32> AjmAt9Decoder::ProcessData(std::span<u8>& in_buf, SparseOutputBuffer& output,
|
||||
AjmSidebandGaplessDecode& gapless,
|
||||
u32 max_samples_per_channel) {
|
||||
int bytes_used = 0;
|
||||
u32 ret = Atrac9Decode(m_handle, in_buf.data(), m_pcm_buffer.data(), &bytes_used);
|
||||
ASSERT_MSG(ret == At9Status::ERR_SUCCESS, "Atrac9Decode failed ret = {:#x}", ret);
|
||||
|
@ -84,7 +85,7 @@ u32 AjmAt9Decoder::ProcessFrame(std::span<u8>& in_buf, SparseOutputBuffer& outpu
|
|||
m_num_frames = 0;
|
||||
}
|
||||
|
||||
return (written / m_codec_info.channels) / sizeof(s16);
|
||||
return {1, (written / m_codec_info.channels) / sizeof(s16)};
|
||||
}
|
||||
|
||||
} // namespace Libraries::Ajm
|
||||
|
|
|
@ -26,8 +26,8 @@ struct AjmAt9Decoder final : AjmCodec {
|
|||
void Reset() override;
|
||||
void Initialize(const void* buffer, u32 buffer_size) override;
|
||||
void GetInfo(void* out_info) override;
|
||||
u32 ProcessFrame(std::span<u8>& input, SparseOutputBuffer& output,
|
||||
AjmSidebandGaplessDecode& gapless, u32 max_samples) override;
|
||||
std::tuple<u32, u32> ProcessData(std::span<u8>& input, SparseOutputBuffer& output,
|
||||
AjmSidebandGaplessDecode& gapless, u32 max_samples) override;
|
||||
|
||||
private:
|
||||
void* m_handle{};
|
||||
|
|
|
@ -65,8 +65,9 @@ void AjmInstance::ExecuteJob(AjmJob& job) {
|
|||
const u32 samples_remain = m_gapless.total_samples != 0
|
||||
? m_gapless.total_samples - m_gapless_samples
|
||||
: std::numeric_limits<u32>::max();
|
||||
const auto nsamples = m_codec->ProcessFrame(in_buf, out_buf, m_gapless, samples_remain);
|
||||
++frames_decoded;
|
||||
const auto [nframes, nsamples] =
|
||||
m_codec->ProcessData(in_buf, out_buf, m_gapless, samples_remain);
|
||||
frames_decoded += nframes;
|
||||
m_total_samples += nsamples;
|
||||
m_gapless_samples += nsamples;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <tuple>
|
||||
|
||||
namespace Libraries::Ajm {
|
||||
|
||||
|
@ -76,8 +77,9 @@ public:
|
|||
virtual void Initialize(const void* buffer, u32 buffer_size) = 0;
|
||||
virtual void Reset() = 0;
|
||||
virtual void GetInfo(void* out_info) = 0;
|
||||
virtual u32 ProcessFrame(std::span<u8>& input, SparseOutputBuffer& output,
|
||||
AjmSidebandGaplessDecode& gapless, u32 max_samples) = 0;
|
||||
virtual std::tuple<u32, u32> ProcessData(std::span<u8>& input, SparseOutputBuffer& output,
|
||||
AjmSidebandGaplessDecode& gapless,
|
||||
u32 max_samples) = 0;
|
||||
};
|
||||
|
||||
class AjmInstance {
|
||||
|
|
|
@ -54,136 +54,87 @@ AVFrame* ConvertAudioFrame(AVFrame* frame) {
|
|||
}
|
||||
|
||||
AjmMp3Decoder::AjmMp3Decoder() {
|
||||
codec = avcodec_find_decoder(AV_CODEC_ID_MP3);
|
||||
ASSERT_MSG(codec, "MP3 codec not found");
|
||||
parser = av_parser_init(codec->id);
|
||||
ASSERT_MSG(parser, "Parser not found");
|
||||
m_codec = avcodec_find_decoder(AV_CODEC_ID_MP3);
|
||||
ASSERT_MSG(m_codec, "MP3 m_codec not found");
|
||||
m_parser = av_parser_init(m_codec->id);
|
||||
ASSERT_MSG(m_parser, "Parser not found");
|
||||
AjmMp3Decoder::Reset();
|
||||
}
|
||||
|
||||
AjmMp3Decoder::~AjmMp3Decoder() {
|
||||
avcodec_free_context(&codec_context);
|
||||
av_free(codec_context);
|
||||
avcodec_free_context(&m_codec_context);
|
||||
}
|
||||
|
||||
void AjmMp3Decoder::Reset() {
|
||||
if (codec_context) {
|
||||
avcodec_free_context(&codec_context);
|
||||
av_free(codec_context);
|
||||
if (m_codec_context) {
|
||||
avcodec_free_context(&m_codec_context);
|
||||
}
|
||||
codec_context = avcodec_alloc_context3(codec);
|
||||
ASSERT_MSG(codec_context, "Could not allocate audio codec context");
|
||||
int ret = avcodec_open2(codec_context, codec, nullptr);
|
||||
ASSERT_MSG(ret >= 0, "Could not open codec");
|
||||
// total_decoded_samples = 0;
|
||||
// gapless_decoded_samples = 0;
|
||||
m_codec_context = avcodec_alloc_context3(m_codec);
|
||||
ASSERT_MSG(m_codec_context, "Could not allocate audio m_codec context");
|
||||
int ret = avcodec_open2(m_codec_context, m_codec, nullptr);
|
||||
ASSERT_MSG(ret >= 0, "Could not open m_codec");
|
||||
}
|
||||
|
||||
u32 AjmMp3Decoder::ProcessFrame(std::span<u8>& input, SparseOutputBuffer& output,
|
||||
AjmSidebandGaplessDecode& gapless, u32 max_samples) {
|
||||
// AVPacket* pkt = av_packet_alloc();
|
||||
void AjmMp3Decoder::GetInfo(void* out_info) {
|
||||
auto* info = reinterpret_cast<AjmSidebandDecMp3CodecInfo*>(out_info);
|
||||
}
|
||||
|
||||
// size_t out_buffer_index = 0;
|
||||
// std::span<const u8> in_buf(input->buffer);
|
||||
// std::span<u8> out_buf = output->buffers[out_buffer_index];
|
||||
// const auto should_decode = [&] {
|
||||
// if (in_buf.empty() || out_buf.empty()) {
|
||||
// return false;
|
||||
// }
|
||||
// if (gapless.total_samples != 0 && gapless.total_samples < gapless_decoded_samples) {
|
||||
// return false;
|
||||
// }
|
||||
// return true;
|
||||
// };
|
||||
std::tuple<u32, u32> AjmMp3Decoder::ProcessData(std::span<u8>& in_buf, SparseOutputBuffer& output,
|
||||
AjmSidebandGaplessDecode& gapless,
|
||||
u32 max_samples) {
|
||||
AVPacket* pkt = av_packet_alloc();
|
||||
|
||||
// const auto write_output = [&](std::span<s16> pcm) {
|
||||
// while (!pcm.empty()) {
|
||||
// auto size = std::min(pcm.size() * sizeof(u16), out_buf.size());
|
||||
// std::memcpy(out_buf.data(), pcm.data(), size);
|
||||
// pcm = pcm.subspan(size >> 1);
|
||||
// out_buf = out_buf.subspan(size);
|
||||
// if (out_buf.empty()) {
|
||||
// out_buffer_index += 1;
|
||||
// if (out_buffer_index >= output->buffers.size()) {
|
||||
// return pcm.empty();
|
||||
// }
|
||||
// out_buf = output->buffers[out_buffer_index];
|
||||
// }
|
||||
// }
|
||||
// return true;
|
||||
// };
|
||||
int ret = av_parser_parse2(m_parser, m_codec_context, &pkt->data, &pkt->size, in_buf.data(),
|
||||
in_buf.size(), AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);
|
||||
ASSERT_MSG(ret >= 0, "Error while parsing {}", ret);
|
||||
in_buf = in_buf.subspan(ret);
|
||||
|
||||
// while (should_decode()) {
|
||||
// int ret = av_parser_parse2(parser, codec_context, &pkt->data, &pkt->size, in_buf.data(),
|
||||
// in_buf.size(), AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);
|
||||
// ASSERT_MSG(ret >= 0, "Error while parsing {}", ret);
|
||||
// in_buf = in_buf.subspan(ret);
|
||||
u32 frames_decoded = 0;
|
||||
u32 samples_decoded = 0;
|
||||
|
||||
// if (output->p_stream) {
|
||||
// output->p_stream->input_consumed += ret;
|
||||
// }
|
||||
// if (pkt->size) {
|
||||
// // Send the packet with the compressed data to the decoder
|
||||
// pkt->pts = parser->pts;
|
||||
// pkt->dts = parser->dts;
|
||||
// pkt->flags = (parser->key_frame == 1) ? AV_PKT_FLAG_KEY : 0;
|
||||
// ret = avcodec_send_packet(codec_context, pkt);
|
||||
// ASSERT_MSG(ret >= 0, "Error submitting the packet to the decoder {}", ret);
|
||||
if (pkt->size) {
|
||||
// Send the packet with the compressed data to the decoder
|
||||
pkt->pts = m_parser->pts;
|
||||
pkt->dts = m_parser->dts;
|
||||
pkt->flags = (m_parser->key_frame == 1) ? AV_PKT_FLAG_KEY : 0;
|
||||
ret = avcodec_send_packet(m_codec_context, pkt);
|
||||
ASSERT_MSG(ret >= 0, "Error submitting the packet to the decoder {}", ret);
|
||||
|
||||
// // Read all the output frames (in general there may be any number of them
|
||||
// while (ret >= 0) {
|
||||
// AVFrame* frame = av_frame_alloc();
|
||||
// ret = avcodec_receive_frame(codec_context, frame);
|
||||
// if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
|
||||
// break;
|
||||
// } else if (ret < 0) {
|
||||
// UNREACHABLE_MSG("Error during decoding");
|
||||
// }
|
||||
// if (frame->format != AV_SAMPLE_FMT_S16) {
|
||||
// frame = ConvertAudioFrame(frame);
|
||||
// }
|
||||
// const auto size = frame->ch_layout.nb_channels * frame->nb_samples * sizeof(u16);
|
||||
// if (gapless.skipped_samples < gapless.skip_samples) {
|
||||
// gapless.skipped_samples += frame->nb_samples;
|
||||
// if (gapless.skipped_samples > gapless.skip_samples) {
|
||||
// const u32 nsamples = gapless.skipped_samples - gapless.skip_samples;
|
||||
// const auto start = frame->nb_samples - nsamples;
|
||||
// write_output({reinterpret_cast<s16*>(frame->data[0]),
|
||||
// nsamples * frame->ch_layout.nb_channels});
|
||||
// gapless.skipped_samples = gapless.skip_samples;
|
||||
// total_decoded_samples += nsamples;
|
||||
// if (gapless.total_samples != 0) {
|
||||
// gapless_decoded_samples += nsamples;
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// write_output({reinterpret_cast<s16*>(frame->data[0]), size >> 1});
|
||||
// total_decoded_samples += frame->nb_samples;
|
||||
// if (gapless.total_samples != 0) {
|
||||
// gapless_decoded_samples += frame->nb_samples;
|
||||
// }
|
||||
// }
|
||||
// av_frame_free(&frame);
|
||||
// if (output->p_stream) {
|
||||
// output->p_stream->output_written += size;
|
||||
// }
|
||||
// if (output->p_mframe) {
|
||||
// output->p_mframe->num_frames += 1;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// av_packet_free(&pkt);
|
||||
// if (gapless.total_samples != 0 && gapless_decoded_samples >= gapless.total_samples) {
|
||||
// if (flags.gapless_loop) {
|
||||
// gapless.skipped_samples = 0;
|
||||
// gapless_decoded_samples = 0;
|
||||
// }
|
||||
// }
|
||||
// if (output->p_stream) {
|
||||
// output->p_stream->total_decoded_samples = total_decoded_samples;
|
||||
// }
|
||||
return 0;
|
||||
// Read all the output frames (in general there may be any number of them
|
||||
while (ret >= 0) {
|
||||
AVFrame* frame = av_frame_alloc();
|
||||
ret = avcodec_receive_frame(m_codec_context, frame);
|
||||
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
|
||||
break;
|
||||
} else if (ret < 0) {
|
||||
UNREACHABLE_MSG("Error during decoding");
|
||||
}
|
||||
if (frame->format != AV_SAMPLE_FMT_S16) {
|
||||
frame = ConvertAudioFrame(frame);
|
||||
}
|
||||
|
||||
frames_decoded += 1;
|
||||
samples_decoded += frame->nb_samples;
|
||||
const auto size = frame->ch_layout.nb_channels * frame->nb_samples * sizeof(u16);
|
||||
std::span<s16> pcm_data(reinterpret_cast<s16*>(frame->data[0]), size >> 1);
|
||||
if (gapless.skipped_samples < gapless.skip_samples) {
|
||||
const auto skipped_samples = std::min(
|
||||
u32(frame->nb_samples), u32(gapless.skip_samples - gapless.skipped_samples));
|
||||
gapless.skipped_samples += skipped_samples;
|
||||
pcm_data = pcm_data.subspan(skipped_samples * frame->ch_layout.nb_channels);
|
||||
samples_decoded -= skipped_samples;
|
||||
}
|
||||
|
||||
const auto pcm_size = std::min(u32(pcm_data.size()), max_samples);
|
||||
output.Write(pcm_data.subspan(0, pcm_size));
|
||||
|
||||
av_frame_free(&frame);
|
||||
}
|
||||
}
|
||||
|
||||
av_packet_free(&pkt);
|
||||
|
||||
return {frames_decoded, samples_decoded};
|
||||
}
|
||||
|
||||
int AjmMp3Decoder::ParseMp3Header(const u8* buf, u32 stream_size, int parse_ofl,
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <fstream>
|
||||
#include "common/types.h"
|
||||
#include "core/libraries/ajm/ajm_instance.h"
|
||||
|
||||
|
@ -11,6 +10,8 @@ extern "C" {
|
|||
struct AVCodec;
|
||||
struct AVCodecContext;
|
||||
struct AVCodecParserContext;
|
||||
struct AVFrame;
|
||||
struct AVPacket;
|
||||
}
|
||||
|
||||
namespace Libraries::Ajm {
|
||||
|
@ -51,27 +52,24 @@ struct AjmSidebandDecMp3CodecInfo {
|
|||
u16 reserved[3];
|
||||
};
|
||||
|
||||
struct AjmDecMp3GetCodecInfoResult {
|
||||
AjmSidebandResult result;
|
||||
AjmSidebandDecMp3CodecInfo codec_info;
|
||||
};
|
||||
|
||||
struct AjmMp3Decoder : public AjmCodec {
|
||||
const AVCodec* codec = nullptr;
|
||||
AVCodecContext* codec_context = nullptr;
|
||||
AVCodecParserContext* parser = nullptr;
|
||||
|
||||
class AjmMp3Decoder : public AjmCodec {
|
||||
public:
|
||||
explicit AjmMp3Decoder();
|
||||
~AjmMp3Decoder() override;
|
||||
|
||||
void Reset() override;
|
||||
void Initialize(const void* buffer, u32 buffer_size) override {}
|
||||
void GetInfo(void* out_info) override {}
|
||||
u32 ProcessFrame(std::span<u8>& input, SparseOutputBuffer& output,
|
||||
AjmSidebandGaplessDecode& gapless, u32 max_samples) override;
|
||||
void GetInfo(void* out_info) override;
|
||||
std::tuple<u32, u32> ProcessData(std::span<u8>& input, SparseOutputBuffer& output,
|
||||
AjmSidebandGaplessDecode& gapless, u32 max_samples) override;
|
||||
|
||||
static int ParseMp3Header(const u8* buf, u32 stream_size, int parse_ofl,
|
||||
AjmDecMp3ParseFrame* frame);
|
||||
|
||||
private:
|
||||
const AVCodec* m_codec = nullptr;
|
||||
AVCodecContext* m_codec_context = nullptr;
|
||||
AVCodecParserContext* m_parser = nullptr;
|
||||
};
|
||||
|
||||
} // namespace Libraries::Ajm
|
||||
|
|
Loading…
Add table
Reference in a new issue