Skip to content

Commit

Permalink
Merge pull request #750 from okias/ffmpeg-new
Browse files Browse the repository at this point in the history
ffmpeg 7.1 support
  • Loading branch information
Lihis authored Jan 8, 2025
2 parents e20356b + 2e79b75 commit d758675
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 37 deletions.
81 changes: 45 additions & 36 deletions rwengine/src/audio/SoundSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,12 @@ extern "C" {
#include <libswresample/swresample.h>
}

// Rename some functions for older libavcodec/ffmpeg versions (e.g. Ubuntu
// Trusty)
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55, 28, 1)
#define av_frame_alloc avcodec_alloc_frame
#define av_frame_free avcodec_free_frame
#endif

#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(57, 80, 100)
#define avio_context_free av_freep
#endif

#define HAVE_CH_LAYOUT (LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100))

constexpr int kNumOutputChannels = 2;
constexpr AVSampleFormat kOutputFMT = AV_SAMPLE_FMT_S16;
constexpr size_t kNrFramesToPreload = 50;
Expand Down Expand Up @@ -207,7 +202,6 @@ bool SoundSource::prepareCodecContext() {
// Fill the codecCtx with the parameters of the codec used in the read file.
if (avcodec_parameters_to_context(codecContext, audioStream->codecpar) !=
0) {
avcodec_close(codecContext);
avcodec_free_context(&codecContext);
avformat_close_input(&formatContext);
RW_ERROR("Couldn't find parametrs for context");
Expand All @@ -216,7 +210,6 @@ bool SoundSource::prepareCodecContext() {

// Initialize the decoder.
if (avcodec_open2(codecContext, codec, nullptr) != 0) {
avcodec_close(codecContext);
avcodec_free_context(&codecContext);
avformat_close_input(&formatContext);
RW_ERROR("Couldn't open the audio codec context");
Expand Down Expand Up @@ -250,7 +243,6 @@ bool SoundSource::prepareCodecContextSfx() {
0) {
av_free(formatContext->pb->buffer);
avio_context_free(&formatContext->pb);
avcodec_close(codecContext);
avcodec_free_context(&codecContext);
avformat_close_input(&formatContext);
RW_ERROR("Couldn't find parametrs for context");
Expand All @@ -261,7 +253,6 @@ bool SoundSource::prepareCodecContextSfx() {
if (avcodec_open2(codecContext, codec, nullptr) != 0) {
av_free(formatContext->pb->buffer);
avio_context_free(&formatContext->pb);
avcodec_close(codecContext);
avcodec_free_context(&codecContext);
avformat_close_input(&formatContext);
RW_ERROR("Couldn't open the audio codec context");
Expand All @@ -274,9 +265,9 @@ bool SoundSource::prepareCodecContextSfx() {
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 37, 100)
void SoundSource::decodeFramesLegacy(size_t framesToDecode) {
while ((framesToDecode == 0 || decodedFrames < framesToDecode) &&
av_read_frame(formatContext, &readingPacket) == 0) {
if (readingPacket.stream_index == audioStream->index) {
AVPacket decodingPacket = readingPacket;
av_read_frame(formatContext, readingPacket) == 0) {
if (readingPacket->stream_index == audioStream->index) {
AVPacket decodingPacket = *readingPacket;

while (decodingPacket.size > 0) {
// Decode audio packet
Expand Down Expand Up @@ -306,7 +297,7 @@ void SoundSource::decodeFramesLegacy(size_t framesToDecode) {
}
}
}
av_free_packet(&readingPacket);
av_free_packet(readingPacket);
++decodedFrames;
}
}
Expand All @@ -322,9 +313,9 @@ void SoundSource::decodeFramesSfxWrap() {

void SoundSource::decodeFrames(size_t framesToDecode) {
while ((framesToDecode == 0 || decodedFrames < framesToDecode) &&
av_read_frame(formatContext, &readingPacket) == 0) {
if (readingPacket.stream_index == audioStream->index) {
AVPacket decodingPacket = readingPacket;
av_read_frame(formatContext, readingPacket) == 0) {
if (readingPacket->stream_index == audioStream->index) {
AVPacket decodingPacket = *readingPacket;

int sendPacket = avcodec_send_packet(codecContext, &decodingPacket);
int receiveFrame = 0;
Expand All @@ -349,7 +340,7 @@ void SoundSource::decodeFrames(size_t framesToDecode) {
}
}
}
av_packet_unref(&readingPacket);
av_packet_unref(readingPacket);
++decodedFrames;
}
}
Expand All @@ -366,21 +357,38 @@ void SoundSource::decodeAndResampleFrames(const std::filesystem::path& filePath,
size_t framesToDecode) {
RW_UNUSED(filePath); // it's used by macro
AVFrame* resampled = av_frame_alloc();
int err = 0;

while ((framesToDecode == 0 || decodedFrames < framesToDecode) &&
av_read_frame(formatContext, &readingPacket) == 0) {
if (readingPacket.stream_index == audioStream->index) {
int sendPacket = avcodec_send_packet(codecContext, &readingPacket);
av_packet_unref(&readingPacket);
av_read_frame(formatContext, readingPacket) == 0) {
if (readingPacket->stream_index == audioStream->index) {
int sendPacket = avcodec_send_packet(codecContext, readingPacket);
av_packet_unref(readingPacket);
int receiveFrame = 0;

while ((receiveFrame =
avcodec_receive_frame(codecContext, frame)) == 0) {
if (!swr) {
if (frame->channels == 1 || frame->channel_layout == 0) {
#if HAVE_CH_LAYOUT
AVChannelLayout out_chlayout = AV_CHANNEL_LAYOUT_STEREO;
err = swr_alloc_set_opts2(
&swr, &out_chlayout, kOutputFMT, frame->sample_rate,
&frame->ch_layout, // input channel layout
static_cast<AVSampleFormat>(
frame->format), // input format
frame->sample_rate, // input sample rate
0, nullptr);

if (err < 0) {
RW_ERROR(
"Resampler has not been successfully allocated.");
return;
}
#else
if (frame->channels == 1 || frame->channel_layout == 0)
frame->channel_layout =
av_get_default_channel_layout(1);
}

swr = swr_alloc_set_opts(
nullptr,
AV_CH_LAYOUT_STEREO, // output channel layout
Expand All @@ -391,6 +399,7 @@ void SoundSource::decodeAndResampleFrames(const std::filesystem::path& filePath,
frame->format), // input format
frame->sample_rate, // input sample rate
0, nullptr);
#endif
if (!swr) {
RW_ERROR(
"Resampler has not been successfully allocated.");
Expand All @@ -407,10 +416,14 @@ void SoundSource::decodeAndResampleFrames(const std::filesystem::path& filePath,
// Decode audio packet
if (receiveFrame == 0 && sendPacket == 0) {
// Write samples to audio buffer
#if HAVE_CH_LAYOUT
resampled->ch_layout = AV_CHANNEL_LAYOUT_STEREO;
#else
resampled->channel_layout = AV_CH_LAYOUT_STEREO;
resampled->channels = kNumOutputChannels;
#endif
resampled->sample_rate = frame->sample_rate;
resampled->format = kOutputFMT;
resampled->channels = kNumOutputChannels;

swr_config_frame(swr, resampled, frame);

Expand Down Expand Up @@ -445,10 +458,6 @@ void SoundSource::cleanupAfterSoundLoading() {
/// Free all data used by the frame.
av_frame_free(&frame);

/// Close the context and free all data associated to it, but not the
/// context itself.
avcodec_close(codecContext);

/// Free the context itself.
avcodec_free_context(&codecContext);

Expand All @@ -460,10 +469,6 @@ void SoundSource::cleanupAfterSfxLoading() {
/// Free all data used by the frame.
av_frame_free(&frame);

/// Close the context and free all data associated to it, but not the
/// context itself.
avcodec_close(codecContext);

/// Free the context itself.
avcodec_free_context(&codecContext);

Expand All @@ -481,7 +486,11 @@ void SoundSource::exposeSoundMetadata() {
}

void SoundSource::exposeSfxMetadata(LoaderSDT& sdt) {
#if HAVE_CH_LAYOUT
channels = static_cast<size_t>(codecContext->ch_layout.nb_channels);
#else
channels = static_cast<size_t>(codecContext->channels);
#endif
sampleRate = sdt.assetInfo.sampleRate;
}

Expand Down Expand Up @@ -509,7 +518,7 @@ void SoundSource::loadFromFile(const std::filesystem::path& filePath, bool strea
if (allocateAudioFrame() && allocateFormatContext(filePath) &&
findAudioStream(filePath) && prepareCodecContextWrap()) {
exposeSoundMetadata();
av_init_packet(&readingPacket);
readingPacket = av_packet_alloc();

decodeFramesWrap(filePath);

Expand All @@ -528,7 +537,7 @@ void SoundSource::loadSfx(LoaderSDT& sdt, size_t index, bool asWave,
if (allocateAudioFrame() && prepareFormatContextSfx(sdt, index, asWave) &&
findAudioStreamSfx() && prepareCodecContextSfxWrap()) {
exposeSfxMetadata(sdt);
av_init_packet(&readingPacket);
readingPacket = av_packet_alloc();

decodeFramesSfxWrap();

Expand Down
2 changes: 1 addition & 1 deletion rwengine/src/audio/SoundSource.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ class SoundSource {
const AVCodec* codec = nullptr;
SwrContext* swr = nullptr;
AVCodecContext* codecContext = nullptr;
AVPacket readingPacket;
AVPacket* readingPacket;

// For sfx
AVIOContext* avioContext;
Expand Down

0 comments on commit d758675

Please sign in to comment.