From f497d6319eaf335e3925e03a3b6767bb3de0e4fe Mon Sep 17 00:00:00 2001
From: Albion Drakon <albinio.drakon@yandex.ru>
Date: Thu, 28 Aug 2025 01:13:48 +0300
Subject: [PATCH] Fix new ffmpeg & gcc build

---
 CMakeLists.txt                                |  1 +
 apps/openmw-mp/Script/Types.hpp               |  5 --
 apps/openmw/mwsound/ffmpeg_decoder.cpp        | 66 +++++++++----------
 apps/openmw/mwsound/ffmpeg_decoder.hpp        |  2 +-
 apps/openmw/mwsound/movieaudiofactory.cpp     |  2 +-
 build.sh                                      |  6 ++
 components/myguiplatform/myguidatamanager.cpp |  1 +
 components/vfs/filesystemarchive.cpp          |  2 +
 .../osg-ffmpeg-videoplayer/audiodecoder.cpp   | 48 +++++++-------
 .../osg-ffmpeg-videoplayer/audiodecoder.hpp   |  2 +-
 10 files changed, 70 insertions(+), 65 deletions(-)
 create mode 100755 build.sh

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 59d81eb9b..84c2336b5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,6 +2,7 @@ project(OpenMW)
 cmake_minimum_required(VERSION 3.1.0)
 set(CMAKE_CXX_STANDARD 17)
 set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_CXX_EXTENSIONS OFF)
 
 # for link time optimization, remove if cmake version is >= 3.9
 if(POLICY CMP0069) # LTO
diff --git a/apps/openmw-mp/Script/Types.hpp b/apps/openmw-mp/Script/Types.hpp
index 88590d61d..1b591ff9e 100644
--- a/apps/openmw-mp/Script/Types.hpp
+++ b/apps/openmw-mp/Script/Types.hpp
@@ -99,13 +99,8 @@ struct CallbackIdentity
 struct ScriptFunctionPointer : public ScriptIdentity
 {
     void *addr;
-#if (!defined(__clang__) && defined(__GNUC__))
-    template<typename R, typename... Types>
-    constexpr ScriptFunctionPointer(Function<R, Types...> addr) : ScriptIdentity(addr), addr((void*)(addr)) {}
-#else
     template<typename R, typename... Types>
     constexpr ScriptFunctionPointer(Function<R, Types...> addr) : ScriptIdentity(addr), addr(addr) {}
-#endif
 };
 
 struct ScriptFunctionData
diff --git a/apps/openmw/mwsound/ffmpeg_decoder.cpp b/apps/openmw/mwsound/ffmpeg_decoder.cpp
index 0a9641635..e78e3aa8e 100644
--- a/apps/openmw/mwsound/ffmpeg_decoder.cpp
+++ b/apps/openmw/mwsound/ffmpeg_decoder.cpp
@@ -121,7 +121,7 @@ bool FFmpeg_Decoder::getAVAudioData()
             if(!mDataBuf || mDataBufLen < mFrame->nb_samples)
             {
                 av_freep(&mDataBuf);
-                if(av_samples_alloc(&mDataBuf, nullptr, av_get_channel_layout_nb_channels(mOutputChannelLayout),
+                  if (av_samples_alloc(&mDataBuf, nullptr, mOutputChannelLayout.nb_channels,
                                     mFrame->nb_samples, mOutputSampleFormat, 0) < 0)
                     return false;
                 else
@@ -156,7 +156,7 @@ size_t FFmpeg_Decoder::readAVAudioData(void *data, size_t length)
             if(!getAVAudioData())
                 break;
             mFramePos = 0;
-            mFrameSize = mFrame->nb_samples * av_get_channel_layout_nb_channels(mOutputChannelLayout) *
+              mFrameSize = mFrame->nb_samples * mOutputChannelLayout.nb_channels*
                          av_get_bytes_per_sample(mOutputSampleFormat);
         }
 
@@ -253,11 +253,11 @@ void FFmpeg_Decoder::open(const std::string &fname)
         else
             mOutputSampleFormat = AV_SAMPLE_FMT_S16;
 
-        mOutputChannelLayout = (*mStream)->codecpar->channel_layout;
-        if(mOutputChannelLayout == 0)
-            mOutputChannelLayout = av_get_default_channel_layout(mCodecCtx->channels);
+        mOutputChannelLayout = (*mStream)->codecpar->ch_layout; // sefault
+        if (mOutputChannelLayout.u.mask == 0)
+            av_channel_layout_default(&mOutputChannelLayout, mCodecCtx->ch_layout.nb_channels);
 
-        mCodecCtx->channel_layout = mOutputChannelLayout;
+        mCodecCtx->ch_layout = mOutputChannelLayout;
     }
     catch(...)
     {
@@ -343,51 +343,51 @@ void FFmpeg_Decoder::getInfo(int *samplerate, ChannelConfig *chans, SampleType *
         *type = SampleType_Int16;
     }
 
-    if(mOutputChannelLayout == AV_CH_LAYOUT_MONO)
+    if(mOutputChannelLayout.u.mask ==AV_CH_LAYOUT_MONO)
         *chans = ChannelConfig_Mono;
-    else if(mOutputChannelLayout == AV_CH_LAYOUT_STEREO)
+    else if(mOutputChannelLayout.u.mask ==AV_CH_LAYOUT_STEREO)
         *chans = ChannelConfig_Stereo;
-    else if(mOutputChannelLayout == AV_CH_LAYOUT_QUAD)
+    else if(mOutputChannelLayout.u.mask ==AV_CH_LAYOUT_QUAD)
         *chans = ChannelConfig_Quad;
-    else if(mOutputChannelLayout == AV_CH_LAYOUT_5POINT1)
+    else if(mOutputChannelLayout.u.mask ==AV_CH_LAYOUT_5POINT1)
         *chans = ChannelConfig_5point1;
-    else if(mOutputChannelLayout == AV_CH_LAYOUT_7POINT1)
+    else if(mOutputChannelLayout.u.mask ==AV_CH_LAYOUT_7POINT1)
         *chans = ChannelConfig_7point1;
     else
     {
         char str[1024];
-        av_get_channel_layout_string(str, sizeof(str), mCodecCtx->channels, mCodecCtx->channel_layout);
-        Log(Debug::Error) << "Unsupported channel layout: "<< str;
+        av_channel_layout_describe(&mCodecCtx->ch_layout, str, sizeof(str));
+        Log(Debug::Error) << "Unsupported channel layout: " << str;
 
-        if(mCodecCtx->channels == 1)
+        if (mCodecCtx->ch_layout.nb_channels == 1)
         {
-            mOutputChannelLayout = AV_CH_LAYOUT_MONO;
+            mOutputChannelLayout = AV_CHANNEL_LAYOUT_MONO;
             *chans = ChannelConfig_Mono;
         }
         else
         {
-            mOutputChannelLayout = AV_CH_LAYOUT_STEREO;
+            mOutputChannelLayout = AV_CHANNEL_LAYOUT_STEREO;
             *chans = ChannelConfig_Stereo;
         }
     }
 
     *samplerate = mCodecCtx->sample_rate;
-    int64_t ch_layout = mCodecCtx->channel_layout;
-    if(ch_layout == 0)
-        ch_layout = av_get_default_channel_layout(mCodecCtx->channels);
+    AVChannelLayout chLayout = mCodecCtx->ch_layout;
+    if (chLayout.u.mask == 0)
+        av_channel_layout_default(&chLayout, mCodecCtx->ch_layout.nb_channels);
 
-    if(mOutputSampleFormat != mCodecCtx->sample_fmt ||
-       mOutputChannelLayout != ch_layout)
+    if (mOutputSampleFormat != mCodecCtx->sample_fmt ||
+       mOutputChannelLayout.u.mask != chLayout.u.mask)
     {
-        mSwr = swr_alloc_set_opts(mSwr,                   // SwrContext
-                          mOutputChannelLayout,           // output ch layout
-                          mOutputSampleFormat,            // output sample format
-                          mCodecCtx->sample_rate, // output sample rate
-                          ch_layout,                      // input ch layout
-                          mCodecCtx->sample_fmt,         // input sample format
-                          mCodecCtx->sample_rate, // input sample rate
-                          0,                              // logging level offset
-                          nullptr);                          // log context
+          swr_alloc_set_opts2(&mSwr, // SwrContext
+                      &mOutputChannelLayout, // output ch layout
+                      mOutputSampleFormat, // output sample format
+                      mCodecCtx->sample_rate, // output sample rate
+                      &chLayout, // input ch layout
+                      mCodecCtx->sample_fmt, // input sample format
+                      mCodecCtx->sample_rate, // input sample rate
+                      0, // logging level offset
+                      nullptr); // log context
         if(!mSwr)
             throw std::runtime_error("Couldn't allocate SwrContext");
         int init=swr_init(mSwr);
@@ -416,7 +416,7 @@ void FFmpeg_Decoder::readAll(std::vector<char> &output)
 
     while(getAVAudioData())
     {
-        size_t got = mFrame->nb_samples * av_get_channel_layout_nb_channels(mOutputChannelLayout) *
+        size_t got = mFrame->nb_samples * mOutputChannelLayout.nb_channels *
                      av_get_bytes_per_sample(mOutputSampleFormat);
         const char *inbuf = reinterpret_cast<char*>(mFrameData[0]);
         output.insert(output.end(), inbuf, inbuf+got);
@@ -425,7 +425,7 @@ void FFmpeg_Decoder::readAll(std::vector<char> &output)
 
 size_t FFmpeg_Decoder::getSampleOffset()
 {
-    int delay = (mFrameSize-mFramePos) / av_get_channel_layout_nb_channels(mOutputChannelLayout) /
+    int delay = (mFrameSize-mFramePos) / mOutputChannelLayout.nb_channels /
                 av_get_bytes_per_sample(mOutputSampleFormat);
     return (int)(mNextPts*mCodecCtx->sample_rate) - delay;
 }
@@ -441,7 +441,7 @@ FFmpeg_Decoder::FFmpeg_Decoder(const VFS::Manager* vfs)
   , mNextPts(0.0)
   , mSwr(nullptr)
   , mOutputSampleFormat(AV_SAMPLE_FMT_NONE)
-  , mOutputChannelLayout(0)
+  , mOutputChannelLayout({})
   , mDataBuf(nullptr)
   , mFrameData(nullptr)
   , mDataBufLen(0)
diff --git a/apps/openmw/mwsound/ffmpeg_decoder.hpp b/apps/openmw/mwsound/ffmpeg_decoder.hpp
index 0a67a4758..8cf3fc854 100644
--- a/apps/openmw/mwsound/ffmpeg_decoder.hpp
+++ b/apps/openmw/mwsound/ffmpeg_decoder.hpp
@@ -50,7 +50,7 @@ namespace MWSound
 
         SwrContext *mSwr;
         enum AVSampleFormat mOutputSampleFormat;
-        int64_t mOutputChannelLayout;
+         AVChannelLayout mOutputChannelLayout;
         uint8_t *mDataBuf;
         uint8_t **mFrameData;
         int mDataBufLen;
diff --git a/apps/openmw/mwsound/movieaudiofactory.cpp b/apps/openmw/mwsound/movieaudiofactory.cpp
index d8c1c928e..e178d70fe 100644
--- a/apps/openmw/mwsound/movieaudiofactory.cpp
+++ b/apps/openmw/mwsound/movieaudiofactory.cpp
@@ -44,7 +44,7 @@ namespace MWSound
 
         size_t getSampleOffset()
         {
-            ssize_t clock_delay = (mFrameSize-mFramePos) / av_get_channel_layout_nb_channels(mOutputChannelLayout) /
+              ssize_t clock_delay = (mFrameSize-mFramePos) / mOutputChannelLayout.nb_channels /
                                   av_get_bytes_per_sample(mOutputSampleFormat);
             return (size_t)(mAudioClock*mAudioContext->sample_rate) - clock_delay;
         }
diff --git a/build.sh b/build.sh
new file mode 100755
index 000000000..73372cd45
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+cd ../
+rm -rf build
+mkdir build && cd build
+CXXFLAGS="-fpermissive" cmake ..
+make -j4
\ No newline at end of file
diff --git a/components/myguiplatform/myguidatamanager.cpp b/components/myguiplatform/myguidatamanager.cpp
index 0310e996b..829b9d095 100644
--- a/components/myguiplatform/myguidatamanager.cpp
+++ b/components/myguiplatform/myguidatamanager.cpp
@@ -1,3 +1,4 @@
+#include <memory>
 #include "myguidatamanager.hpp"
 
 #include <MyGUI_DataFileStream.h>
diff --git a/components/vfs/filesystemarchive.cpp b/components/vfs/filesystemarchive.cpp
index 6eef4b93a..f0d172aa6 100644
--- a/components/vfs/filesystemarchive.cpp
+++ b/components/vfs/filesystemarchive.cpp
@@ -4,6 +4,8 @@
 
 #include <components/debug/debuglog.hpp>
 
+#include <algorithm>
+
 namespace VFS
 {
 
diff --git a/extern/osg-ffmpeg-videoplayer/audiodecoder.cpp b/extern/osg-ffmpeg-videoplayer/audiodecoder.cpp
index decf57e4d..e6050a8b8 100644
--- a/extern/osg-ffmpeg-videoplayer/audiodecoder.cpp
+++ b/extern/osg-ffmpeg-videoplayer/audiodecoder.cpp
@@ -53,7 +53,7 @@ MovieAudioDecoder::MovieAudioDecoder(VideoState* videoState)
     : mVideoState(videoState)
     , mAVStream(*videoState->audio_st)
     , mOutputSampleFormat(AV_SAMPLE_FMT_NONE)
-    , mOutputChannelLayout(0)
+    , mOutputChannelLayout({})
     , mOutputSampleRate(0)
     , mFramePos(0)
     , mFrameSize(0)
@@ -109,31 +109,32 @@ void MovieAudioDecoder::setupFormat()
 
     AVSampleFormat inputSampleFormat = mAudioContext->sample_fmt;
 
-    uint64_t inputChannelLayout = mAudioContext->channel_layout;
-    if (inputChannelLayout == 0)
-        inputChannelLayout = av_get_default_channel_layout(mAudioContext->channels);
+    AVChannelLayout inputChannelLayout = mAudioContext->ch_layout;
+    if (inputChannelLayout.u.mask != 0)
+        mOutputChannelLayout = inputChannelLayout;
+    else
+        av_channel_layout_default(&mOutputChannelLayout, mAudioContext->ch_layout.nb_channels);
 
     int inputSampleRate = mAudioContext->sample_rate;
 
     mOutputSampleRate = inputSampleRate;
     mOutputSampleFormat = inputSampleFormat;
-    mOutputChannelLayout = inputChannelLayout;
-    adjustAudioSettings(mOutputSampleFormat, mOutputChannelLayout, mOutputSampleRate);
+    adjustAudioSettings(mOutputSampleFormat, mOutputChannelLayout.u.mask, mOutputSampleRate);
 
-    if (inputSampleFormat != mOutputSampleFormat
-            || inputChannelLayout != mOutputChannelLayout
+     if (inputSampleFormat != mOutputSampleFormat
+            || inputChannelLayout.u.mask != mOutputChannelLayout.u.mask
             || inputSampleRate != mOutputSampleRate)
     {
-        mAudioResampler->mSwr = swr_alloc_set_opts(mAudioResampler->mSwr,
-                          mOutputChannelLayout,
-                          mOutputSampleFormat,
-                          mOutputSampleRate,
-                          inputChannelLayout,
-                          inputSampleFormat,
-                          inputSampleRate,
-                          0,                             // logging level offset
-                          nullptr);                      // log context
-        if(!mAudioResampler->mSwr)
+        swr_alloc_set_opts2(&mAudioResampler->mSwr,
+          &mOutputChannelLayout,
+          mOutputSampleFormat,
+          mOutputSampleRate,
+          &inputChannelLayout,
+          inputSampleFormat,
+          inputSampleRate,
+          0,                             // logging level offset
+          nullptr);                      // log context
+		     if(!mAudioResampler->mSwr)
             fail(std::string("Couldn't allocate SwrContext"));
         if(swr_init(mAudioResampler->mSwr) < 0)
             fail(std::string("Couldn't initialize SwrContext"));
@@ -158,7 +159,7 @@ int MovieAudioDecoder::synchronize_audio()
         if(fabs(avg_diff) >= mAudioDiffThreshold)
         {
             int n = av_get_bytes_per_sample(mOutputSampleFormat) *
-                    av_get_channel_layout_nb_channels(mOutputChannelLayout);
+                    mOutputChannelLayout.nb_channels;
             sample_skip = ((int)(diff * mAudioContext->sample_rate) * n);
         }
     }
@@ -204,7 +205,7 @@ int MovieAudioDecoder::audio_decode_frame(AVFrame *frame, int &sample_skip)
                 if(!mDataBuf || mDataBufLen < frame->nb_samples)
                 {
                     av_freep(&mDataBuf);
-                    if(av_samples_alloc(&mDataBuf, nullptr, av_get_channel_layout_nb_channels(mOutputChannelLayout),
+                    if(av_samples_alloc(&mDataBuf, nullptr, mOutputChannelLayout.nb_channels,
                                         frame->nb_samples, mOutputSampleFormat, 0) < 0)
                         break;
                     else
@@ -221,7 +222,7 @@ int MovieAudioDecoder::audio_decode_frame(AVFrame *frame, int &sample_skip)
             else
                 mFrameData = &frame->data[0];
 
-            int result = frame->nb_samples * av_get_channel_layout_nb_channels(mOutputChannelLayout) *
+             int result = frame->nb_samples * mOutputChannelLayout.nb_channels *
                     av_get_bytes_per_sample(mOutputSampleFormat);
 
             /* We have data, return it and come back for more later */
@@ -298,7 +299,7 @@ size_t MovieAudioDecoder::read(char *stream, size_t len)
             len1 = std::min<size_t>(len1, -mFramePos);
 
             int n = av_get_bytes_per_sample(mOutputSampleFormat)
-                    * av_get_channel_layout_nb_channels(mOutputChannelLayout);
+                    * mOutputChannelLayout.nb_channels;
 
             /* add samples by copying the first sample*/
             if(n == 1)
@@ -348,9 +349,8 @@ int MovieAudioDecoder::getOutputSampleRate() const
 
 uint64_t MovieAudioDecoder::getOutputChannelLayout() const
 {
-    return mOutputChannelLayout;
+     return mOutputChannelLayout.u.mask;
 }
-
 AVSampleFormat MovieAudioDecoder::getOutputSampleFormat() const
 {
     return mOutputSampleFormat;
diff --git a/extern/osg-ffmpeg-videoplayer/audiodecoder.hpp b/extern/osg-ffmpeg-videoplayer/audiodecoder.hpp
index bbb5a2783..c65d91756 100644
--- a/extern/osg-ffmpeg-videoplayer/audiodecoder.hpp
+++ b/extern/osg-ffmpeg-videoplayer/audiodecoder.hpp
@@ -43,7 +43,7 @@ protected:
     AVCodecContext* mAudioContext;
     AVStream *mAVStream;
     enum AVSampleFormat mOutputSampleFormat;
-    uint64_t mOutputChannelLayout;
+    AVChannelLayout mOutputChannelLayout;
     int mOutputSampleRate;
     ssize_t mFramePos;
     ssize_t mFrameSize;
-- 
2.47.2

