ajm mp3: fix resampling (#1500)
Some checks failed
Build and Release / reuse (push) Has been cancelled
Build and Release / clang-format (push) Has been cancelled
Build and Release / get-info (push) Has been cancelled
Build and Release / windows-sdl (push) Has been cancelled
Build and Release / windows-qt (push) Has been cancelled
Build and Release / macos-sdl (push) Has been cancelled
Build and Release / macos-qt (push) Has been cancelled
Build and Release / linux-sdl (push) Has been cancelled
Build and Release / linux-qt (push) Has been cancelled
Build and Release / pre-release (push) Has been cancelled

This commit is contained in:
Vladislav Mikhalin 2024-11-08 08:45:03 +03:00 committed by GitHub
parent 176d222519
commit 75d2181489
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 24 additions and 18 deletions

View File

@ -28,8 +28,6 @@ static constexpr std::array<std::array<s32, 15>, 2> BitrateTable = {{
static constexpr std::array<s32, 2> UnkTable = {0x48, 0x90};
SwrContext* swr_context{};
static AVSampleFormat AjmToAVSampleFormat(AjmFormatEncoding format) {
switch (format) {
case AjmFormatEncoding::S16:
@ -49,26 +47,28 @@ AVFrame* AjmMp3Decoder::ConvertAudioFrame(AVFrame* frame) {
return frame;
}
auto pcm16_frame = av_frame_clone(frame);
pcm16_frame->format = format;
AVFrame* new_frame = av_frame_alloc();
new_frame->pts = frame->pts;
new_frame->pkt_dts = frame->pkt_dts < 0 ? 0 : frame->pkt_dts;
new_frame->format = format;
new_frame->ch_layout = frame->ch_layout;
new_frame->sample_rate = frame->sample_rate;
if (swr_context) {
swr_free(&swr_context);
swr_context = nullptr;
}
AVChannelLayout in_ch_layout = frame->ch_layout;
AVChannelLayout out_ch_layout = pcm16_frame->ch_layout;
swr_alloc_set_opts2(&swr_context, &out_ch_layout, AVSampleFormat(pcm16_frame->format),
AVChannelLayout out_ch_layout = new_frame->ch_layout;
swr_alloc_set_opts2(&m_swr_context, &out_ch_layout, AVSampleFormat(new_frame->format),
frame->sample_rate, &in_ch_layout, AVSampleFormat(frame->format),
frame->sample_rate, 0, nullptr);
swr_init(swr_context);
const auto res = swr_convert_frame(swr_context, pcm16_frame, frame);
swr_init(m_swr_context);
const auto res = swr_convert_frame(m_swr_context, new_frame, frame);
if (res < 0) {
LOG_ERROR(Lib_AvPlayer, "Could not convert to S16: {}", av_err2str(res));
av_frame_free(&new_frame);
av_frame_free(&frame);
return nullptr;
}
av_frame_free(&frame);
return pcm16_frame;
return new_frame;
}
AjmMp3Decoder::AjmMp3Decoder(AjmFormatEncoding format)
@ -78,6 +78,7 @@ AjmMp3Decoder::AjmMp3Decoder(AjmFormatEncoding format)
}
AjmMp3Decoder::~AjmMp3Decoder() {
swr_free(&m_swr_context);
avcodec_free_context(&m_codec_context);
}
@ -108,6 +109,11 @@ std::tuple<u32, u32> AjmMp3Decoder::ProcessData(std::span<u8>& in_buf, SparseOut
u32 frames_decoded = 0;
u32 samples_decoded = 0;
auto max_samples =
max_samples_per_channel.has_value()
? max_samples_per_channel.value() * m_codec_context->ch_layout.nb_channels
: std::numeric_limits<u32>::max();
if (pkt->size) {
// Send the packet with the compressed data to the decoder
pkt->pts = m_parser->pts;
@ -121,6 +127,7 @@ std::tuple<u32, u32> AjmMp3Decoder::ProcessData(std::span<u8>& in_buf, SparseOut
AVFrame* frame = av_frame_alloc();
ret = avcodec_receive_frame(m_codec_context, frame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
av_frame_free(&frame);
break;
} else if (ret < 0) {
UNREACHABLE_MSG("Error during decoding");
@ -135,11 +142,6 @@ std::tuple<u32, u32> AjmMp3Decoder::ProcessData(std::span<u8>& in_buf, SparseOut
gapless.skipped_samples += skipped_samples;
}
const auto max_samples =
max_samples_per_channel.has_value()
? max_samples_per_channel.value() * frame->ch_layout.nb_channels
: std::numeric_limits<u32>::max();
switch (m_format) {
case AjmFormatEncoding::S16:
samples_decoded +=
@ -157,6 +159,8 @@ std::tuple<u32, u32> AjmMp3Decoder::ProcessData(std::span<u8>& in_buf, SparseOut
UNREACHABLE();
}
max_samples -= samples_decoded;
av_frame_free(&frame);
}
}

View File

@ -8,6 +8,7 @@
extern "C" {
#include <libavcodec/avcodec.h>
struct SwrContext;
}
namespace Libraries::Ajm {
@ -82,6 +83,7 @@ private:
const AVCodec* m_codec = nullptr;
AVCodecContext* m_codec_context = nullptr;
AVCodecParserContext* m_parser = nullptr;
SwrContext* m_swr_context = nullptr;
};
} // namespace Libraries::Ajm