Bug#1072444: performous: FTBFS with ffmpeg 7.0: ffmpeg.cc:293:94: error: ‘struct AVCodecContext’ has no member named =?UTF-8?Q?=E2=80=98channel=5Flayout=E2=80=99; ?= did you mean ‘ch_layout’?

Zixing Liu zixing.liu at canonical.com
Thu Sep 26 21:34:21 BST 2024


Package: performous
Version: 1.3.0+ds-1
Followup-For: Bug #1072444
User: ubuntu-devel at 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
-------------- next part --------------
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 at 5.1+
+Author: Gregorio Litenstein <g.litenstein at 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


More information about the Pkg-games-devel mailing list