Package: performous
Version: 1.3.0+ds-1
Followup-For: Bug #1072444
User: ubuntu-de...@lists.ubuntu.com
Usertags: origin-ubuntu oracular ubuntu-patch
Control: tags -1 patch ftbfs

Dear Maintainer,

In Ubuntu, the attached patch was applied to achieve the following:

  * d/p/ffmpeg-5.1.patch: add a patch to fix FTBFS with FFmpeg 7
    (LP: #2080271, #2080302).


Thanks for considering the patch.


-- System Information:
Debian Release: trixie/sid
  APT prefers noble-updates
  APT policy: (500, 'noble-updates'), (500, 'noble-security'), (500, 'noble'), 
(100, 'noble-backports')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 6.8.0-45-generic (SMP w/10 CPU threads; PREEMPT)
Kernel taint flags: TAINT_PROPRIETARY_MODULE, TAINT_OOT_MODULE
Locale: LANG=en_CA.UTF-8, LC_CTYPE=en_CA.UTF-8 (charmap=UTF-8), 
LANGUAGE=en_CA:en
Shell: /bin/sh linked to /usr/bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled
diff -Nru performous-1.3.0+ds/debian/patches/ffmpeg-5.1.patch 
performous-1.3.0+ds/debian/patches/ffmpeg-5.1.patch
--- performous-1.3.0+ds/debian/patches/ffmpeg-5.1.patch 1969-12-31 
17:00:00.000000000 -0700
+++ performous-1.3.0+ds/debian/patches/ffmpeg-5.1.patch 2024-09-18 
15:47:56.000000000 -0600
@@ -0,0 +1,184 @@
+Description: ffmpeg: Use AVChannelLayout API when available
+ This adds support for ffmpeg@5.1+
+Author: Gregorio Litenstein <g.litenst...@gmail.com>
+Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/performous/+bug/2080302
+Origin: upstream, 
https://github.com/performous/performous/commit/f26c27bf74b85fa3e3b150682ab9ecf9aecb3c50
+Last-Update: 2024-09-18
+---
+diff --git a/game/ffmpeg.cc b/game/ffmpeg.cc
+index db204fb885..f2bc349c4f 100644
+--- a/game/ffmpeg.cc
++++ b/game/ffmpeg.cc
+@@ -6,8 +6,8 @@
+ #include "util.hh"
+ 
+ #include "aubio/aubio.h"
+-#include <memory>
+ #include <iostream>
++#include <memory>
+ #include <sstream>
+ #include <stdexcept>
+ #include <system_error>
+@@ -31,6 +31,11 @@ extern "C" {
+ 
+ #define AUDIO_CHANNELS 2
+ 
++#if !defined(__PRETTY_FUNCTION__) && defined(_MSC_VER)
++#define __PRETTY_FUNCTION__ __FUNCSIG__
++#endif
++
++#define FFMPEG_CHECKED(func, args, caller) FFmpeg::check(func args, caller)
+ 
+ namespace {
+       std::string ffversion(unsigned ver) {
+@@ -229,18 +234,13 @@ static void printFFmpegInfo() {
+ #endif
+ }
+ 
+-class FFmpeg::Error: public std::runtime_error {
+-  public:
+-      Error(const FFmpeg &self, int errorValue): 
std::runtime_error(msgFmt(self, errorValue)) {}
+-  private:
+-      static std::string msgFmt(const FFmpeg &self, int errorValue) {
++std::string FFmpeg::Error::msgFmt(const FFmpeg &self, int errorValue, const 
char *func) {
+               char message[AV_ERROR_MAX_STRING_SIZE];
+               av_strerror(errorValue, message, AV_ERROR_MAX_STRING_SIZE);
+               std::ostringstream oss;
+-              oss << "FFmpeg Error: Processing file " << self.m_filename << " 
code=" << errorValue << ", error=" << message;
++              oss << "FFmpeg Error: Processing file " << self.m_filename << " 
code=" << errorValue << ", error=" << message << ", in function=" << func;
+               return oss.str();
+-      }
+-};
++}
+ 
+ FFmpeg::FFmpeg(fs::path const& _filename, int mediaType) : 
m_filename(_filename) {
+       static std::once_flag static_infos;
+@@ -249,12 +249,10 @@ FFmpeg::FFmpeg(fs::path const& _filename, int mediaType) 
: m_filename(_filename)
+       av_log_set_level(AV_LOG_ERROR);
+       {
+               AVFormatContext *avfctx = nullptr;
+-              auto err = avformat_open_input(&avfctx, 
m_filename.string().c_str(), nullptr, nullptr);
+-              if (err) throw Error(*this, err);
++              FFMPEG_CHECKED(avformat_open_input, (&avfctx, 
m_filename.string().c_str(), nullptr, nullptr), __PRETTY_FUNCTION__);
+               m_formatContext.reset(avfctx);
+       }
+-      auto err = avformat_find_stream_info(m_formatContext.get(), nullptr);
+-      if (err < 0) throw Error(*this, err);
++      FFMPEG_CHECKED(avformat_find_stream_info, (m_formatContext.get(), 
nullptr), __PRETTY_FUNCTION__);
+       m_formatContext->flags |= AVFMT_FLAG_GENPTS;
+       // Find a track and open the codec
+ #if (LIBAVFORMAT_VERSION_INT) >= (AV_VERSION_INT(59, 0, 100))
+@@ -262,7 +260,7 @@ FFmpeg::FFmpeg(fs::path const& _filename, int mediaType) : 
m_filename(_filename)
+ #endif
+       AVCodec* codec = nullptr;
+       m_streamId = av_find_best_stream(m_formatContext.get(), 
static_cast<AVMediaType>(mediaType), -1, -1, &codec, 0);
+-      if (m_streamId < 0) throw Error(*this, m_streamId);
++      if (m_streamId < 0) throw Error(*this, m_streamId, __PRETTY_FUNCTION__);
+ 
+       decltype(m_codecContext) pCodecCtx{avcodec_alloc_context3(codec), 
avcodec_free_context};
+       avcodec_parameters_to_context(pCodecCtx.get(), 
m_formatContext->streams[m_streamId]->codecpar);
+@@ -270,8 +268,7 @@ FFmpeg::FFmpeg(fs::path const& _filename, int mediaType) : 
m_filename(_filename)
+               static std::mutex s_avcodec_mutex;
+               // ffmpeg documentation is clear on the fact that avcodec_open2 
is not thread safe.
+               std::lock_guard<std::mutex> l(s_avcodec_mutex);
+-              err = avcodec_open2(pCodecCtx.get(), codec, nullptr);
+-              if (err < 0) throw Error(*this, err);
++              FFMPEG_CHECKED(avcodec_open2, (pCodecCtx.get(), codec, 
nullptr), __PRETTY_FUNCTION__);
+       }
+       pCodecCtx->workaround_bugs = FF_BUG_AUTODETECT;
+       m_codecContext = std::move(pCodecCtx);
+@@ -290,13 +287,29 @@ AudioFFmpeg::AudioFFmpeg(fs::path const& filename, int 
rate, AudioCb audioCb) :
+               // setup resampler
+               m_resampleContext.reset(swr_alloc());
+               if (!m_resampleContext) throw std::runtime_error("Cannot create 
resampling context");
+-              av_opt_set_int(m_resampleContext.get(), "in_channel_layout", 
m_codecContext->channel_layout ? 
static_cast<std::int64_t>(m_codecContext->channel_layout) : 
av_get_default_channel_layout(m_codecContext->channels), 0);
+-              av_opt_set_int(m_resampleContext.get(), "out_channel_layout", 
av_get_default_channel_layout(AUDIO_CHANNELS), 0);
+-              av_opt_set_int(m_resampleContext.get(), "in_sample_rate", 
m_codecContext->sample_rate, 0);
+-              av_opt_set_int(m_resampleContext.get(), "out_sample_rate", 
static_cast<int>(m_rate), 0);
+-              av_opt_set_int(m_resampleContext.get(), "in_sample_fmt", 
m_codecContext->sample_fmt, 0);
+-              av_opt_set_int(m_resampleContext.get(), "out_sample_fmt", 
AV_SAMPLE_FMT_S16, 0);
+-              swr_init(m_resampleContext.get());
++
++#if (LIBAVFORMAT_VERSION_INT) >= (AV_VERSION_INT(59,0,0))
++      AVChannelLayout inLayout;
++      AVChannelLayout outLayout;
++      av_channel_layout_default(&outLayout, AUDIO_CHANNELS);
++      if (m_codecContext->ch_layout.order != AV_CHANNEL_ORDER_UNSPEC) {
++              FFMPEG_CHECKED(av_channel_layout_copy, (&inLayout, 
&m_codecContext->ch_layout), __PRETTY_FUNCTION__);
++      }
++      else {
++              av_channel_layout_default(&inLayout, 
m_codecContext->ch_layout.nb_channels);
++      }
++      av_channel_layout_default(&outLayout, AUDIO_CHANNELS);
++      FFMPEG_CHECKED(av_opt_set_chlayout, (m_resampleContext.get(), 
"in_chlayout", &inLayout, 0), __PRETTY_FUNCTION__);
++      FFMPEG_CHECKED(av_opt_set_chlayout, (m_resampleContext.get(), 
"out_chlayout", &outLayout, 0), __PRETTY_FUNCTION__);
++#else
++      FFMPEG_CHECKED(av_opt_set_int, (m_resampleContext.get(), 
"in_channel_layout", m_codecContext->channel_layout ? 
static_cast<std::int64_t>(m_codecContext->channel_layout) : 
av_get_default_channel_layout(m_codecContext->channels), 0), 
__PRETTY_FUNCTION__);
++      FFMPEG_CHECKED(av_opt_set_int, (m_resampleContext.get(), 
"out_channel_layout", av_get_default_channel_layout(AUDIO_CHANNELS), 0), 
__PRETTY_FUNCTION__);
++#endif
++      FFMPEG_CHECKED(av_opt_set_int, (m_resampleContext.get(), 
"in_sample_rate", m_codecContext->sample_rate, 0), __PRETTY_FUNCTION__);
++      FFMPEG_CHECKED(av_opt_set_int, (m_resampleContext.get(), 
"out_sample_rate", static_cast<int>(m_rate), 0), __PRETTY_FUNCTION__);
++      FFMPEG_CHECKED(av_opt_set_sample_fmt, (m_resampleContext.get(), 
"in_sample_fmt", m_codecContext->sample_fmt, 0), __PRETTY_FUNCTION__);
++      FFMPEG_CHECKED(av_opt_set_sample_fmt, (m_resampleContext.get(), 
"out_sample_fmt", AV_SAMPLE_FMT_S16, 0), __PRETTY_FUNCTION__);
++      FFMPEG_CHECKED(swr_init, (m_resampleContext.get()), 
__PRETTY_FUNCTION__);
+       }
+ 
+ double FFmpeg::duration() const { return double(m_formatContext->duration) / 
double(AV_TIME_BASE); }
+@@ -319,7 +332,7 @@ void FFmpeg::handleOneFrame() {
+                       // End of file: no more data to read.
+                       throw Eof();
+               } else if(ret < 0) {
+-                      throw Error(*this, ret);
++                      throw Error(*this, ret, __PRETTY_FUNCTION__);
+               }
+ 
+               if (pkt->stream_index != m_streamId) continue;
+@@ -332,7 +345,7 @@ void FFmpeg::handleOneFrame() {
+                                               // no room for new data, need 
to get more frames out of the decoder by
+                                               // calling 
avcodec_receive_frame()
+                               } else if(ret < 0) {
+-                                              throw Error(*this, ret);
++                                              throw Error(*this, ret, 
__PRETTY_FUNCTION__);
+                               }
+               handleSomeFrames();
+               read_one = true;
+@@ -364,7 +377,7 @@ void FFmpeg::handleSomeFrames() {
+                       // not enough data to decode a frame, go read more and 
feed more to the decoder
+                       break;
+               } else if (ret < 0) {
+-                      throw Error(*this, ret);
++                      throw Error(*this, ret, __PRETTY_FUNCTION__);
+               }
+               // frame is available here
+               if (frame->pts != std::int64_t(AV_NOPTS_VALUE)) {
+diff --git a/game/ffmpeg.hh b/game/ffmpeg.hh
+index 337091f5b6..e3b54a64a9 100644
+--- a/game/ffmpeg.hh
++++ b/game/ffmpeg.hh
+@@ -19,6 +19,7 @@
+ 
+ // ffmpeg forward declarations
+ extern "C" {
++  struct AVChannelLayout;
+   struct AVCodecContext;
+   struct AVFormatContext;
+   struct AVFrame;
+@@ -35,9 +36,17 @@ class FFmpeg {
+   public:
+       // Exceptions thrown by class
+       class Eof: public std::exception {};
+-      class Error;
++      class Error : public std::runtime_error {
++        public:
++              Error(const FFmpeg &self, int errorValue, const char *func): 
std::runtime_error(msgFmt(self, errorValue, func)) {}
++        private:
++              static std::string msgFmt(const FFmpeg &self, int errorValue, 
const char *func);
++      };
+       friend Error;
+ 
++      void inline check(int errorCode, const char* func = "") {
++              if (errorCode < 0) throw Error(*this, errorCode, func);
++      };
+       /// Decode file, depending on media type audio.
+       FFmpeg(fs::path const& filename, int mediaType);
+ 
diff -Nru performous-1.3.0+ds/debian/patches/series 
performous-1.3.0+ds/debian/patches/series
--- performous-1.3.0+ds/debian/patches/series   2024-07-31 09:33:12.000000000 
-0600
+++ performous-1.3.0+ds/debian/patches/series   2024-09-18 15:47:56.000000000 
-0600
@@ -1,2 +1,3 @@
 ced.patch
 no-Werror.patch
+ffmpeg-5.1.patch

Reply via email to