[3PP] Switch FFmpeg to latest release with port of xmaframes codec

And pull out all the xenia specific build junk into
third_party/ffmpeg-xenia rather than keeping it checked in the
submodule
This commit is contained in:
Herman S.
2026-02-12 01:36:21 +09:00
parent d6ed83f1ea
commit cd5df622a9
25 changed files with 998 additions and 41 deletions

View File

@@ -130,7 +130,7 @@ ProcessAudioResult ProcessAudioLoop(AudioMediaPlayer* player,
break;
}
ConvertAudioFrame(frame, avctx->channels, &frameBuffer);
ConvertAudioFrame(frame, avctx->ch_layout.nb_channels, &frameBuffer);
player->ProcessAudioBuffer(&frameBuffer);
}
}
@@ -230,7 +230,8 @@ void AudioMediaPlayer::Play() {
AVCodecContext* codecContext = nullptr;
InitializeAndOpenAvCodec(song_buffer, formatContext, codecContext);
if (!SetupDriver(codecContext->sample_rate, codecContext->channels)) {
if (!SetupDriver(codecContext->sample_rate,
codecContext->ch_layout.nb_channels)) {
XELOGE("Driver initialization failed!");
avcodec_free_context(&codecContext);
av_freep(&formatContext->pb->buffer);

View File

@@ -14,5 +14,6 @@ project("xenia-apu")
})
includedirs({
project_root.."/third_party/FFmpeg",
project_root.."/third_party/ffmpeg-xenia",
})
local_platform_files()

View File

@@ -49,7 +49,7 @@ void XmaContext::DumpRaw(AVFrame* frame, int id) {
}
size_t data_size = sizeof(float);
for (int i = 0; i < frame->nb_samples; i++) {
for (int ch = 0; ch < frame->channels; ch++) {
for (int ch = 0; ch < frame->ch_layout.nb_channels; ch++) {
fwrite(frame->data[ch] + data_size * i, 1, data_size, outfile);
}
}

View File

@@ -252,7 +252,7 @@ class XmaContext {
// ffmpeg structures
AVPacket* av_packet_ = nullptr;
AVCodec* av_codec_ = nullptr;
const AVCodec* av_codec_ = nullptr;
AVCodecContext* av_context_ = nullptr;
AVFrame* av_frame_ = nullptr;
};

View File

@@ -25,6 +25,7 @@ extern "C" {
#pragma warning(disable : 4101 4244 5033)
#endif
#include "third_party/FFmpeg/libavcodec/avcodec.h"
#include "third_party/FFmpeg/libavutil/channel_layout.h"
#if XE_COMPILER_MSVC
#pragma warning(pop)
#endif
@@ -40,10 +41,7 @@ XmaContextMaster::XmaContextMaster() = default;
XmaContextMaster::~XmaContextMaster() {
if (av_context_) {
if (avcodec_is_open(av_context_)) {
avcodec_close(av_context_);
}
av_free(av_context_);
avcodec_free_context(&av_context_);
}
if (av_frame_) {
av_frame_free(&av_frame_);
@@ -78,7 +76,7 @@ int XmaContextMaster::Setup(uint32_t id, Memory* memory, uint32_t guest_ptr) {
}
// Initialize these to 0. They'll actually be set later.
av_context_->channels = 0;
av_context_->ch_layout = AVChannelLayout{};
av_context_->sample_rate = 0;
av_frame_ = av_frame_alloc();
@@ -825,13 +823,14 @@ int XmaContextMaster::PrepareDecoder(uint8_t* packet, int sample_rate,
// Re-initialize the context with new sample rate and channels.
uint32_t channels = is_two_channel ? 2 : 1;
if (av_context_->sample_rate != sample_rate ||
av_context_->channels != channels) {
// We have to reopen the codec so it'll realloc whatever data it needs.
// TODO(DrChat): Find a better way.
avcodec_close(av_context_);
av_context_->ch_layout.nb_channels != (int)channels) {
// We have to recreate the codec context so it'll realloc whatever data it
// needs.
avcodec_free_context(&av_context_);
av_context_ = avcodec_alloc_context3(av_codec_);
av_context_->sample_rate = sample_rate;
av_context_->channels = channels;
av_channel_layout_default(&av_context_->ch_layout, channels);
if (avcodec_open2(av_context_, av_codec_, NULL) < 0) {
XELOGE("XmaContext: Failed to reopen FFmpeg context");

View File

@@ -20,6 +20,7 @@ extern "C" {
#pragma warning(disable : 4101 4244 5033)
#endif
#include "third_party/FFmpeg/libavcodec/avcodec.h"
#include "third_party/FFmpeg/libavutil/channel_layout.h"
#if XE_COMPILER_MSVC
#pragma warning(pop)
#endif
@@ -35,10 +36,7 @@ XmaContextNew::XmaContextNew() = default;
XmaContextNew::~XmaContextNew() {
if (av_context_) {
if (avcodec_is_open(av_context_)) {
avcodec_close(av_context_);
}
av_free(av_context_);
avcodec_free_context(&av_context_);
}
if (av_frame_) {
av_frame_free(&av_frame_);
@@ -69,7 +67,7 @@ int XmaContextNew::Setup(uint32_t id, Memory* memory, uint32_t guest_ptr) {
}
// Initialize these to 0. They'll actually be set later.
av_context_->channels = 0;
av_context_->ch_layout = AVChannelLayout{};
av_context_->sample_rate = 0;
av_frame_ = av_frame_alloc();
@@ -818,16 +816,17 @@ int XmaContextNew::PrepareDecoder(int sample_rate, bool is_two_channel) {
// Re-initialize the context with new sample rate and channels.
uint32_t channels = is_two_channel ? 2 : 1;
if (av_context_->sample_rate != sample_rate ||
av_context_->channels != channels) {
av_context_->ch_layout.nb_channels != (int)channels) {
XELOGAPU("XmaContext {}: Codec reinit: rate {} -> {}, channels {} -> {}",
id(), av_context_->sample_rate, sample_rate, av_context_->channels,
channels);
// We have to reopen the codec so it'll realloc whatever data it needs.
// TODO(DrChat): Find a better way.
avcodec_close(av_context_);
id(), av_context_->sample_rate, sample_rate,
av_context_->ch_layout.nb_channels, channels);
// We have to recreate the codec context so it'll realloc whatever data it
// needs.
avcodec_free_context(&av_context_);
av_context_ = avcodec_alloc_context3(av_codec_);
av_context_->sample_rate = sample_rate;
av_context_->channels = channels;
av_channel_layout_default(&av_context_->ch_layout, channels);
if (avcodec_open2(av_context_, av_codec_, NULL) < 0) {
XELOGE("XmaContext: Failed to reopen FFmpeg context");

View File

@@ -25,6 +25,7 @@ extern "C" {
#pragma warning(disable : 4101 4244 5033)
#endif
#include "third_party/FFmpeg/libavcodec/avcodec.h"
#include "third_party/FFmpeg/libavutil/channel_layout.h"
#if XE_COMPILER_MSVC
#pragma warning(pop)
#endif
@@ -40,10 +41,7 @@ XmaContextOld::XmaContextOld() = default;
XmaContextOld::~XmaContextOld() {
if (av_context_) {
if (avcodec_is_open(av_context_)) {
avcodec_close(av_context_);
}
av_free(av_context_);
avcodec_free_context(&av_context_);
}
if (av_frame_) {
av_frame_free(&av_frame_);
@@ -78,7 +76,7 @@ int XmaContextOld::Setup(uint32_t id, Memory* memory, uint32_t guest_ptr) {
}
// Initialize these to 0. They'll actually be set later.
av_context_->channels = 0;
av_context_->ch_layout = AVChannelLayout{};
av_context_->sample_rate = 0;
av_frame_ = av_frame_alloc();
@@ -664,7 +662,8 @@ void XmaContextOld::Decode(XMA_CONTEXT_DATA* data) {
// dump_raw(av_frame_, id());
ConvertFrame(reinterpret_cast<const uint8_t**>(&av_frame_->data),
bool(av_frame_->channels > 1), raw_frame_.data());
bool(av_frame_->ch_layout.nb_channels > 1),
raw_frame_.data());
// decoded_consumed_samples_ += kSamplesPerFrame;
auto byte_count = kBytesPerFrameChannel << data->is_stereo;
@@ -928,13 +927,14 @@ int XmaContextOld::PrepareDecoder(uint8_t* packet, int sample_rate,
// Re-initialize the context with new sample rate and channels.
uint32_t channels = is_two_channel ? 2 : 1;
if (av_context_->sample_rate != sample_rate ||
av_context_->channels != channels) {
// We have to reopen the codec so it'll realloc whatever data it needs.
// TODO(DrChat): Find a better way.
avcodec_close(av_context_);
av_context_->ch_layout.nb_channels != (int)channels) {
// We have to recreate the codec context so it'll realloc whatever data it
// needs.
avcodec_free_context(&av_context_);
av_context_ = avcodec_alloc_context3(av_codec_);
av_context_->sample_rate = sample_rate;
av_context_->channels = channels;
av_channel_layout_default(&av_context_->ch_layout, channels);
if (avcodec_open2(av_context_, av_codec_, NULL) < 0) {
XELOGE("XmaContext: Failed to reopen FFmpeg context");