git: 915391ac40ad - main - multimedia/kodi: Add patch to support FFmpeg 6
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 27 Apr 2023 12:04:19 UTC
The branch main has been updated by diizzy: URL: https://cgit.FreeBSD.org/ports/commit/?id=915391ac40ad0175583f572d999680f5ae8397bc commit 915391ac40ad0175583f572d999680f5ae8397bc Author: Daniel Engberg <diizzy@FreeBSD.org> AuthorDate: 2023-04-27 10:43:32 +0000 Commit: Daniel Engberg <diizzy@FreeBSD.org> CommitDate: 2023-04-27 12:01:44 +0000 multimedia/kodi: Add patch to support FFmpeg 6 Add patch from maintainer PR: 270237 Reviewed by: yrzh <yzrh@noema.org> (maintainer) --- multimedia/kodi/files/patch-ffmpeg6-support | 2150 +++++++++++++++++++++++++++ 1 file changed, 2150 insertions(+) diff --git a/multimedia/kodi/files/patch-ffmpeg6-support b/multimedia/kodi/files/patch-ffmpeg6-support new file mode 100644 index 000000000000..2ab9cbc27a3d --- /dev/null +++ b/multimedia/kodi/files/patch-ffmpeg6-support @@ -0,0 +1,2150 @@ +diff -urN cmake/modules/FindFFMPEG.cmake.orig cmake/modules/FindFFMPEG.cmake +--- cmake/modules/FindFFMPEG.cmake.orig 2023-03-11 22:16:38.000000000 +0000 ++++ cmake/modules/FindFFMPEG.cmake 2023-04-19 10:01:30.831589000 +0000 +@@ -151,14 +151,14 @@ + set(REQUIRED_FFMPEG_VERSION undef) + else() + # required ffmpeg library versions +- set(REQUIRED_FFMPEG_VERSION 4.4.1) +- set(_avcodec_ver ">=58.134.100") +- set(_avfilter_ver ">=7.110.100") +- set(_avformat_ver ">=58.76.100") +- set(_avutil_ver ">=56.70.100") +- set(_postproc_ver ">=55.9.100") +- set(_swresample_ver ">=3.9.100") +- set(_swscale_ver ">=5.9.100") ++ set(REQUIRED_FFMPEG_VERSION 6.0.0) ++ set(_avcodec_ver ">=60.2.100") ++ set(_avfilter_ver ">=9.3.100") ++ set(_avformat_ver ">=60.3.100") ++ set(_avutil_ver ">=58.2.100") ++ set(_postproc_ver ">=57.1.100") ++ set(_swresample_ver ">=4.10.100") ++ set(_swscale_ver ">=7.1.100") + endif() + + # Allows building with external ffmpeg not found in system paths, +diff -urN tools/buildsteps/windows/patches/0001-ffmpeg-windows-configure-detect-openssl.patch.orig tools/buildsteps/windows/patches/0001-ffmpeg-windows-configure-detect-openssl.patch +--- tools/buildsteps/windows/patches/0001-ffmpeg-windows-configure-detect-openssl.patch.orig 2023-03-11 22:16:38.000000000 +0000 ++++ tools/buildsteps/windows/patches/0001-ffmpeg-windows-configure-detect-openssl.patch 2023-04-19 10:01:22.854832000 +0000 +@@ -11,7 +11,7 @@ + index d7a3f507e8..4b85e881b1 100755 + --- a/configure + +++ b/configure +-@@ -6530,6 +6530,8 @@ enabled openssl && { check_pkg_config openssl openssl openssl/ssl.h OP ++@@ -6728,6 +6728,8 @@ enabled openssl && { check_pkg_config openssl openssl openssl/ssl.h OP + check_lib openssl openssl/ssl.h SSL_library_init -lssl -lcrypto || + check_lib openssl openssl/ssl.h SSL_library_init -lssl32 -leay32 || + check_lib openssl openssl/ssl.h SSL_library_init -lssl -lcrypto -lws2_32 -lgdi32 || +diff -urN tools/buildsteps/windows/patches/0002-ffmpeg-windows-configure-fix-zlib-conflict.patch.orig tools/buildsteps/windows/patches/0002-ffmpeg-windows-configure-fix-zlib-conflict.patch +--- tools/buildsteps/windows/patches/0002-ffmpeg-windows-configure-fix-zlib-conflict.patch.orig 2023-03-11 22:16:38.000000000 +0000 ++++ tools/buildsteps/windows/patches/0002-ffmpeg-windows-configure-fix-zlib-conflict.patch 2023-04-19 10:01:22.854952000 +0000 +@@ -11,16 +11,16 @@ + index 4b85e881b1..da457705d1 100755 + --- a/configure + +++ b/configure +-@@ -7627,6 +7627,9 @@ print_config CONFIG_ "$config_files" $CONFIG_LIST \ ++@@ -7825,6 +7825,9 @@ print_config CONFIG_ "$config_files" $CONFIG_LIST \ ++ print_config CONFIG_ "$config_files" $CONFIG_LIST \ + $CONFIG_EXTRA \ +- $ALL_COMPONENTS \ + + +echo "#if defined(HAVE_UNISTD_H) && HAVE_UNISTD_H == 0" >> $TMPH + +echo "#undef HAVE_UNISTD_H" >> $TMPH + +echo "#endif" >> $TMPH + echo "#endif /* FFMPEG_CONFIG_H */" >> $TMPH +- echo "endif # FFMPEG_CONFIG_MAK" >> ffbuild/config.mak + ++ # Do not overwrite an unchanged config.h to avoid superfluous rebuilds. + -- + 2.29.2 + +diff -urN tools/buildsteps/windows/patches/0003-ffmpeg-windows-configure-allow-building-static.patch.orig tools/buildsteps/windows/patches/0003-ffmpeg-windows-configure-allow-building-static.patch +--- tools/buildsteps/windows/patches/0003-ffmpeg-windows-configure-allow-building-static.patch.orig 2023-03-11 22:16:38.000000000 +0000 ++++ tools/buildsteps/windows/patches/0003-ffmpeg-windows-configure-allow-building-static.patch 2023-04-19 10:01:22.855081000 +0000 +@@ -11,7 +11,7 @@ + index da457705d1..e3a8f45ff4 100755 + --- a/configure + +++ b/configure +-@@ -5440,6 +5440,8 @@ case $target_os in ++@@ -5566,6 +5566,8 @@ case $target_os in + enabled shared && ! enabled small && test_cmd $windres --version && enable gnu_windres + enabled x86_32 && check_ldflags -Wl,--large-address-aware + shlibdir_default="$bindir_default" +@@ -20,7 +20,7 @@ + SLIBPREF="" + SLIBSUF=".dll" + SLIBNAME_WITH_VERSION='$(SLIBPREF)$(FULLNAME)-$(LIBVERSION)$(SLIBSUF)' +-@@ -5489,6 +5491,8 @@ case $target_os in ++@@ -5615,6 +5617,8 @@ case $target_os in + fi + enabled x86_32 && check_ldflags -LARGEADDRESSAWARE + shlibdir_default="$bindir_default" +diff -urN tools/buildsteps/windows/patches/0004-ffmpeg-windows-configure-detect-libdav1d.patch.orig tools/buildsteps/windows/patches/0004-ffmpeg-windows-configure-detect-libdav1d.patch +--- tools/buildsteps/windows/patches/0004-ffmpeg-windows-configure-detect-libdav1d.patch.orig 2023-03-11 22:16:38.000000000 +0000 ++++ tools/buildsteps/windows/patches/0004-ffmpeg-windows-configure-detect-libdav1d.patch 2023-04-19 10:01:22.855205000 +0000 +@@ -11,7 +11,7 @@ + index e3a8f45ff4..983d7e1078 100755 + --- a/configure + +++ b/configure +-@@ -6358,7 +6358,7 @@ enabled libcelt && require libcelt celt/celt.h celt_decode -lcelt0 && ++@@ -6541,7 +6541,7 @@ enabled libcelt && require libcelt celt/celt.h celt_decode -lcelt0 && + die "ERROR: libcelt must be installed and version must be >= 0.11.0."; } + enabled libcaca && require_pkg_config libcaca caca caca.h caca_create_canvas + enabled libcodec2 && require libcodec2 codec2/codec2.h codec2_create -lcodec2 +diff -urN tools/depends/target/ffmpeg/CMakeLists.txt.orig tools/depends/target/ffmpeg/CMakeLists.txt +--- tools/depends/target/ffmpeg/CMakeLists.txt.orig 2023-03-11 22:16:38.000000000 +0000 ++++ tools/depends/target/ffmpeg/CMakeLists.txt 2023-04-19 10:01:22.854687000 +0000 +@@ -92,6 +92,7 @@ + elseif(CORE_SYSTEM_NAME STREQUAL darwin_embedded) + list(APPEND ffmpeg_conf --disable-crystalhd + --enable-videotoolbox ++ --disable-filter=yadif_videotoolbox + --target-os=darwin + ) + elseif(CORE_SYSTEM_NAME STREQUAL osx) +diff -urN tools/depends/target/ffmpeg/FFMPEG-VERSION.orig tools/depends/target/ffmpeg/FFMPEG-VERSION +--- tools/depends/target/ffmpeg/FFMPEG-VERSION.orig 2023-03-11 22:16:38.000000000 +0000 ++++ tools/depends/target/ffmpeg/FFMPEG-VERSION 2023-04-19 10:02:41.108169000 +0000 +@@ -1,5 +1,5 @@ + LIBNAME=ffmpeg +-BASE_URL=https://github.com/xbmc/FFmpeg +-VERSION=4.4.1-Nexus-Alpha1 ++VERSION=6.0 + ARCHIVE=$(LIBNAME)-$(VERSION).tar.gz +-SHA512=8beb04d577b5251e74b0d52f4d130997a8ba94bbd488c7c8309e6b45095c27807e150212888ce3a384b23dff52f8df1a7bde5407bae924ddc363f8125c0616c5 ++SHA512=b3214328f2792364353f38c6b46a71d4970c071d8656b20780abf0e02950167d0933eae825c09102cf8fb19fc679ac444bf1f41a448b624eaa5ea6b0f0bdf4f5 ++ +diff -urN xbmc/cdrip/EncoderFFmpeg.cpp.orig xbmc/cdrip/EncoderFFmpeg.cpp +--- xbmc/cdrip/EncoderFFmpeg.cpp.orig 2023-03-11 22:16:38.000000000 +0000 ++++ xbmc/cdrip/EncoderFFmpeg.cpp 2023-04-19 10:01:22.848595000 +0000 +@@ -11,6 +11,7 @@ + #include "ServiceBroker.h" + #include "addons/Addon.h" + #include "addons/AddonManager.h" ++#include "cores/FFmpeg.h" + #include "settings/Settings.h" + #include "settings/SettingsComponent.h" + #include "utils/StringUtils.h" +@@ -19,24 +20,9 @@ + #include "utils/log.h" + + using namespace KODI::CDRIP; ++using FFMPEG_HELP_TOOLS::FFMpegErrorToString; ++using FFMPEG_HELP_TOOLS::FFMpegException; + +-namespace +-{ +- +-struct EncoderException : public std::exception +-{ +- std::string s; +- template<typename... Args> +- EncoderException(const std::string& fmt, Args&&... args) +- : s(StringUtils::Format(fmt, std::forward<Args>(args)...)) +- { +- } +- ~EncoderException() throw() {} // Updated +- const char* what() const throw() { return s.c_str(); } +-}; +- +-} /* namespace */ +- + bool CEncoderFFmpeg::Init() + { + try +@@ -54,7 +40,7 @@ + } + else + { +- throw EncoderException("Could not get add-on: {}", addonId); ++ throw FFMpegException("Could not get add-on: {}", addonId); + } + + // Hack fix about PTS on generated files. +@@ -66,50 +52,50 @@ + else if (addonId == "audioencoder.kodi.builtin.wma") + m_samplesCountMultiply = 1000; + else +- throw EncoderException("Internal add-on id \"{}\" not known as usable", addonId); ++ throw FFMpegException("Internal add-on id \"{}\" not known as usable", addonId); + + const std::string filename = URIUtils::GetFileName(m_strFile); + + m_formatCtx = avformat_alloc_context(); + if (!m_formatCtx) +- throw EncoderException("Could not allocate output format context"); ++ throw FFMpegException("Could not allocate output format context"); + + m_bcBuffer = static_cast<uint8_t*>(av_malloc(BUFFER_SIZE + AV_INPUT_BUFFER_PADDING_SIZE)); + if (!m_bcBuffer) +- throw EncoderException("Could not allocate buffer"); ++ throw FFMpegException("Could not allocate buffer"); + + m_formatCtx->pb = avio_alloc_context(m_bcBuffer, BUFFER_SIZE, AVIO_FLAG_WRITE, this, nullptr, + avio_write_callback, avio_seek_callback); + if (!m_formatCtx->pb) +- throw EncoderException("Failed to allocate ByteIOContext"); ++ throw FFMpegException("Failed to allocate ByteIOContext"); + + /* Guess the desired container format based on the file extension. */ + m_formatCtx->oformat = av_guess_format(nullptr, filename.c_str(), nullptr); + if (!m_formatCtx->oformat) +- throw EncoderException("Could not find output file format"); ++ throw FFMpegException("Could not find output file format"); + + m_formatCtx->url = av_strdup(filename.c_str()); + if (!m_formatCtx->url) +- throw EncoderException("Could not allocate url"); ++ throw FFMpegException("Could not allocate url"); + + /* Find the encoder to be used by its name. */ +- AVCodec* codec = avcodec_find_encoder(m_formatCtx->oformat->audio_codec); ++ const AVCodec* codec = avcodec_find_encoder(m_formatCtx->oformat->audio_codec); + if (!codec) +- throw EncoderException("Unable to find a suitable FFmpeg encoder"); ++ throw FFMpegException("Unable to find a suitable FFmpeg encoder"); + + /* Create a new audio stream in the output file container. */ + m_stream = avformat_new_stream(m_formatCtx, nullptr); + if (!m_stream) +- throw EncoderException("Failed to allocate AVStream context"); ++ throw FFMpegException("Failed to allocate AVStream context"); + + m_codecCtx = avcodec_alloc_context3(codec); + if (!m_codecCtx) +- throw EncoderException("Failed to allocate the encoder context"); ++ throw FFMpegException("Failed to allocate the encoder context"); + + /* Set the basic encoder parameters. + * The input file's sample rate is used to avoid a sample rate conversion. */ +- m_codecCtx->channels = m_iInChannels; +- m_codecCtx->channel_layout = av_get_default_channel_layout(m_iInChannels); ++ av_channel_layout_uninit(&m_codecCtx->ch_layout); ++ av_channel_layout_default(&m_codecCtx->ch_layout, m_iInChannels); + m_codecCtx->sample_rate = m_iInSampleRate; + m_codecCtx->sample_fmt = codec->sample_fmts[0]; + m_codecCtx->bit_rate = bitrate; +@@ -128,14 +114,14 @@ + + int err = avcodec_open2(m_codecCtx, codec, nullptr); + if (err < 0) +- throw EncoderException("Failed to open the codec {} (error '{}')", +- codec->long_name ? codec->long_name : codec->name, +- FFmpegErrorToString(err)); ++ throw FFMpegException("Failed to open the codec {} (error '{}')", ++ codec->long_name ? codec->long_name : codec->name, ++ FFMpegErrorToString(err)); + + err = avcodec_parameters_from_context(m_stream->codecpar, m_codecCtx); + if (err < 0) +- throw EncoderException("Failed to copy encoder parameters to output stream (error '{}')", +- FFmpegErrorToString(err)); ++ throw FFMpegException("Failed to copy encoder parameters to output stream (error '{}')", ++ FFMpegErrorToString(err)); + + m_inFormat = GetInputFormat(m_iInBitsPerSample); + m_outFormat = m_codecCtx->sample_fmt; +@@ -150,44 +136,48 @@ + + m_bufferFrame = av_frame_alloc(); + if (!m_bufferFrame || !m_buffer) +- throw EncoderException("Failed to allocate necessary buffers"); ++ throw FFMpegException("Failed to allocate necessary buffers"); + + m_bufferFrame->nb_samples = m_codecCtx->frame_size; + m_bufferFrame->format = m_inFormat; +- m_bufferFrame->channel_layout = m_codecCtx->channel_layout; ++ ++ av_channel_layout_uninit(&m_bufferFrame->ch_layout); ++ av_channel_layout_copy(&m_bufferFrame->ch_layout, &m_codecCtx->ch_layout); ++ + m_bufferFrame->sample_rate = m_codecCtx->sample_rate; + + err = av_frame_get_buffer(m_bufferFrame, 0); + if (err < 0) +- throw EncoderException("Could not allocate output frame samples (error '{}')", +- FFmpegErrorToString(err)); ++ throw FFMpegException("Could not allocate output frame samples (error '{}')", ++ FFMpegErrorToString(err)); + + avcodec_fill_audio_frame(m_bufferFrame, m_iInChannels, m_inFormat, m_buffer, m_neededBytes, 0); + + if (m_needConversion) + { +- m_swrCtx = swr_alloc_set_opts(nullptr, m_codecCtx->channel_layout, m_outFormat, +- m_codecCtx->sample_rate, m_codecCtx->channel_layout, m_inFormat, ++ int ret = swr_alloc_set_opts2(&m_swrCtx, &m_codecCtx->ch_layout, m_outFormat, ++ m_codecCtx->sample_rate, &m_codecCtx->ch_layout, m_inFormat, + m_codecCtx->sample_rate, 0, nullptr); +- if (!m_swrCtx || swr_init(m_swrCtx) < 0) +- throw EncoderException("Failed to initialize the resampler"); ++ if (ret || swr_init(m_swrCtx) < 0) ++ throw FFMpegException("Failed to initialize the resampler"); + + m_resampledBufferSize = + av_samples_get_buffer_size(nullptr, m_iInChannels, m_neededFrames, m_outFormat, 0); + m_resampledBuffer = static_cast<uint8_t*>(av_malloc(m_resampledBufferSize)); + m_resampledFrame = av_frame_alloc(); + if (!m_resampledBuffer || !m_resampledFrame) +- throw EncoderException("Failed to allocate a frame for resampling"); ++ throw FFMpegException("Failed to allocate a frame for resampling"); + + m_resampledFrame->nb_samples = m_neededFrames; + m_resampledFrame->format = m_outFormat; +- m_resampledFrame->channel_layout = m_codecCtx->channel_layout; ++ av_channel_layout_uninit(&m_resampledFrame->ch_layout); ++ av_channel_layout_copy(&m_resampledFrame->ch_layout, &m_codecCtx->ch_layout); + m_resampledFrame->sample_rate = m_codecCtx->sample_rate; + + err = av_frame_get_buffer(m_resampledFrame, 0); + if (err < 0) +- throw EncoderException("Could not allocate output resample frame samples (error '{}')", +- FFmpegErrorToString(err)); ++ throw FFMpegException("Could not allocate output resample frame samples (error '{}')", ++ FFMpegErrorToString(err)); + + avcodec_fill_audio_frame(m_resampledFrame, m_iInChannels, m_outFormat, m_resampledBuffer, + m_resampledBufferSize, 0); +@@ -204,7 +194,7 @@ + /* write the header */ + err = avformat_write_header(m_formatCtx, nullptr); + if (err != 0) +- throw EncoderException("Failed to write the header (error '{}')", FFmpegErrorToString(err)); ++ throw FFMpegException("Failed to write the header (error '{}')", FFMpegErrorToString(err)); + + CLog::Log(LOGDEBUG, "CEncoderFFmpeg::{} - Successfully initialized with muxer {} and codec {}", + __func__, +@@ -212,16 +202,19 @@ + : m_formatCtx->oformat->name, + codec->long_name ? codec->long_name : codec->name); + } +- catch (EncoderException& caught) ++ catch (const FFMpegException& caught) + { + CLog::Log(LOGERROR, "CEncoderFFmpeg::{} - {}", __func__, caught.what()); + + av_freep(&m_buffer); ++ av_channel_layout_uninit(&m_bufferFrame->ch_layout); + av_frame_free(&m_bufferFrame); + swr_free(&m_swrCtx); ++ av_channel_layout_uninit(&m_resampledFrame->ch_layout); + av_frame_free(&m_resampledFrame); + av_freep(&m_resampledBuffer); + av_free(m_bcBuffer); ++ av_channel_layout_uninit(&m_codecCtx->ch_layout); + avcodec_free_context(&m_codecCtx); + if (m_formatCtx) + { +@@ -299,7 +292,7 @@ + if (swr_convert(m_swrCtx, m_resampledFrame->data, m_neededFrames, + const_cast<const uint8_t**>(m_bufferFrame->extended_data), + m_neededFrames) < 0) +- throw EncoderException("Error resampling audio"); ++ throw FFMpegException("Error resampling audio"); + + frame = m_resampledFrame; + } +@@ -316,8 +309,8 @@ + m_bufferSize = 0; + err = avcodec_send_frame(m_codecCtx, frame); + if (err < 0) +- throw EncoderException("Error sending a frame for encoding (error '{}')", __func__, +- FFmpegErrorToString(err)); ++ throw FFMpegException("Error sending a frame for encoding (error '{}')", ++ FFMpegErrorToString(err)); + + while (err >= 0) + { +@@ -329,19 +322,18 @@ + } + else if (err < 0) + { +- throw EncoderException("Error during encoding (error '{}')", __func__, +- FFmpegErrorToString(err)); ++ throw FFMpegException("Error during encoding (error '{}')", FFMpegErrorToString(err)); + } + + err = av_write_frame(m_formatCtx, pkt); + if (err < 0) +- throw EncoderException("Failed to write the frame data (error '{}')", __func__, +- FFmpegErrorToString(err)); ++ throw FFMpegException("Failed to write the frame data (error '{}')", ++ FFMpegErrorToString(err)); + + av_packet_unref(pkt); + } + } +- catch (EncoderException& caught) ++ catch (const FFMpegException& caught) + { + CLog::Log(LOGERROR, "CEncoderFFmpeg::{} - {}", __func__, caught.what()); + } +@@ -366,8 +358,10 @@ + + /* Flush if needed */ + av_freep(&m_buffer); ++ av_channel_layout_uninit(&m_bufferFrame->ch_layout); + av_frame_free(&m_bufferFrame); + swr_free(&m_swrCtx); ++ av_channel_layout_uninit(&m_resampledFrame->ch_layout); + av_frame_free(&m_resampledFrame); + av_freep(&m_resampledBuffer); + m_needConversion = false; +@@ -379,6 +373,7 @@ + + /* cleanup */ + av_free(m_bcBuffer); ++ av_channel_layout_uninit(&m_codecCtx->ch_layout); + avcodec_free_context(&m_codecCtx); + av_freep(&m_formatCtx->pb); + avformat_free_context(m_formatCtx); +@@ -400,14 +395,6 @@ + case 32: + return AV_SAMPLE_FMT_S32; + default: +- throw EncoderException("Invalid input bits per sample"); ++ throw FFMpegException("Invalid input bits per sample"); + } +-} +- +-std::string CEncoderFFmpeg::FFmpegErrorToString(int err) +-{ +- std::string text; +- text.reserve(AV_ERROR_MAX_STRING_SIZE); +- av_strerror(err, text.data(), AV_ERROR_MAX_STRING_SIZE); +- return text; + } +diff -urN xbmc/cdrip/EncoderFFmpeg.h.orig xbmc/cdrip/EncoderFFmpeg.h +--- xbmc/cdrip/EncoderFFmpeg.h.orig 2023-03-11 22:16:38.000000000 +0000 ++++ xbmc/cdrip/EncoderFFmpeg.h 2023-04-19 10:01:22.835616000 +0000 +@@ -39,7 +39,6 @@ + void SetTag(const std::string& tag, const std::string& value); + bool WriteFrame(); + AVSampleFormat GetInputFormat(int inBitsPerSample); +- std::string FFmpegErrorToString(int err); + + AVFormatContext* m_formatCtx{nullptr}; + AVCodecContext* m_codecCtx{nullptr}; +diff -urN xbmc/cores/AudioEngine/Encoders/AEEncoderFFmpeg.cpp.orig xbmc/cores/AudioEngine/Encoders/AEEncoderFFmpeg.cpp +--- xbmc/cores/AudioEngine/Encoders/AEEncoderFFmpeg.cpp.orig 2023-03-11 22:16:38.000000000 +0000 ++++ xbmc/cores/AudioEngine/Encoders/AEEncoderFFmpeg.cpp 2023-04-19 10:01:22.848879000 +0000 +@@ -10,14 +10,25 @@ + #define DTS_ENCODE_BITRATE 1411200 + + #include "cores/AudioEngine/Encoders/AEEncoderFFmpeg.h" +-#include "cores/AudioEngine/Utils/AEUtil.h" ++ + #include "ServiceBroker.h" +-#include "utils/log.h" ++#include "cores/AudioEngine/Utils/AEUtil.h" ++#include "cores/FFmpeg.h" + #include "settings/Settings.h" + #include "settings/SettingsComponent.h" +-#include <string.h> ++#include "utils/log.h" ++ ++extern "C" ++{ ++#include <libavutil/channel_layout.h> ++} ++ + #include <cassert> ++#include <string.h> + ++using FFMPEG_HELP_TOOLS::FFMpegErrorToString; ++using FFMPEG_HELP_TOOLS::FFMpegException; ++ + CAEEncoderFFmpeg::CAEEncoderFFmpeg() : m_CodecCtx(NULL), m_SwrCtx(NULL) + { + } +@@ -26,6 +37,7 @@ + { + Reset(); + swr_free(&m_SwrCtx); ++ av_channel_layout_uninit(&m_CodecCtx->ch_layout); + avcodec_free_context(&m_CodecCtx); + } + +@@ -81,7 +93,7 @@ + + bool ac3 = CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_AUDIOOUTPUT_AC3PASSTHROUGH); + +- AVCodec *codec = NULL; ++ const AVCodec* codec = nullptr; + + /* fallback to ac3 if we support it, we might not have DTS support */ + if (ac3) +@@ -102,7 +114,8 @@ + + m_CodecCtx->bit_rate = m_BitRate; + m_CodecCtx->sample_rate = format.m_sampleRate; +- m_CodecCtx->channel_layout = AV_CH_LAYOUT_5POINT1_BACK; ++ av_channel_layout_uninit(&m_CodecCtx->ch_layout); ++ av_channel_layout_from_mask(&m_CodecCtx->ch_layout, AV_CH_LAYOUT_5POINT1_BACK); + + /* select a suitable data format */ + if (codec->sample_fmts) +@@ -179,22 +192,28 @@ + LOGERROR, + "CAEEncoderFFmpeg::Initialize - Unable to find a suitable data format for the codec ({})", + m_CodecName); ++ av_channel_layout_uninit(&m_CodecCtx->ch_layout); + avcodec_free_context(&m_CodecCtx); + return false; + } + } + +- m_CodecCtx->channels = BuildChannelLayout(m_CodecCtx->channel_layout, m_Layout); ++ uint64_t mask = m_CodecCtx->ch_layout.u.mask; ++ av_channel_layout_uninit(&m_CodecCtx->ch_layout); ++ av_channel_layout_from_mask(&m_CodecCtx->ch_layout, mask); ++ m_CodecCtx->ch_layout.nb_channels = BuildChannelLayout(mask, m_Layout); + + /* open the codec */ + if (avcodec_open2(m_CodecCtx, codec, NULL)) + { ++ av_channel_layout_uninit(&m_CodecCtx->ch_layout); + avcodec_free_context(&m_CodecCtx); + return false; + } + + format.m_frames = m_CodecCtx->frame_size; +- format.m_frameSize = m_CodecCtx->channels * (CAEUtil::DataFormatToBits(format.m_dataFormat) >> 3); ++ int channels = m_CodecCtx->ch_layout.nb_channels; ++ format.m_frameSize = channels * (CAEUtil::DataFormatToBits(format.m_dataFormat) >> 3); + format.m_channelLayout = m_Layout; + + m_CurrentFormat = format; +@@ -204,14 +223,14 @@ + + if (m_NeedConversion) + { +- m_SwrCtx = swr_alloc_set_opts(NULL, +- m_CodecCtx->channel_layout, m_CodecCtx->sample_fmt, m_CodecCtx->sample_rate, +- m_CodecCtx->channel_layout, AV_SAMPLE_FMT_FLT, m_CodecCtx->sample_rate, +- 0, NULL); +- if (!m_SwrCtx || swr_init(m_SwrCtx) < 0) ++ int ret = swr_alloc_set_opts2(&m_SwrCtx, &m_CodecCtx->ch_layout, m_CodecCtx->sample_fmt, ++ m_CodecCtx->sample_rate, &m_CodecCtx->ch_layout, ++ AV_SAMPLE_FMT_FLT, m_CodecCtx->sample_rate, 0, NULL); ++ if (ret || swr_init(m_SwrCtx) < 0) + { + CLog::Log(LOGERROR, "CAEEncoderFFmpeg::Initialize - Failed to initialise resampler."); + swr_free(&m_SwrCtx); ++ av_channel_layout_uninit(&m_CodecCtx->ch_layout); + avcodec_free_context(&m_CodecCtx); + return false; + } +@@ -242,62 +261,78 @@ + + int CAEEncoderFFmpeg::Encode(uint8_t *in, int in_size, uint8_t *out, int out_size) + { +- int got_output; +- AVFrame *frame; ++ int size = 0; ++ int err = AVERROR_UNKNOWN; ++ AVFrame* frame = nullptr; ++ AVPacket* pkt = nullptr; + + if (!m_CodecCtx) +- return 0; ++ return size; + +- /* allocate the input frame +- * sadly, we have to alloc/dealloc it everytime since we have no guarantee the +- * data argument will be constant over iterated calls and the frame needs to +- * setup pointers inside data */ +- frame = av_frame_alloc(); +- if (!frame) +- return 0; ++ try ++ { ++ /* allocate the input frame and output packet ++ * sadly, we have to alloc/dealloc it everytime since we have no guarantee the ++ * data argument will be constant over iterated calls and the frame needs to ++ * setup pointers inside data */ ++ frame = av_frame_alloc(); ++ pkt = av_packet_alloc(); ++ if (!frame || !pkt) ++ throw FFMpegException( ++ "Failed to allocate \"AVFrame\" or \"AVPacket\" for encoding (error '{}')", ++ strerror(errno)); + +- frame->nb_samples = m_CodecCtx->frame_size; +- frame->format = m_CodecCtx->sample_fmt; +- frame->channel_layout = m_CodecCtx->channel_layout; +- frame->channels = m_CodecCtx->channels; ++ frame->nb_samples = m_CodecCtx->frame_size; ++ frame->format = m_CodecCtx->sample_fmt; ++ av_channel_layout_uninit(&frame->ch_layout); ++ av_channel_layout_copy(&frame->ch_layout, &m_CodecCtx->ch_layout); ++ int channelNum = m_CodecCtx->ch_layout.nb_channels; + +- avcodec_fill_audio_frame(frame, m_CodecCtx->channels, m_CodecCtx->sample_fmt, +- in, in_size, 0); ++ avcodec_fill_audio_frame(frame, channelNum, m_CodecCtx->sample_fmt, in, in_size, 0); + +- /* initialize the output packet */ +- AVPacket* pkt = av_packet_alloc(); +- if (!pkt) +- { +- CLog::Log(LOGERROR, "CAEEncoderFFmpeg::{} - av_packet_alloc failed: {}", __FUNCTION__, +- strerror(errno)); +- av_frame_free(&frame); +- return 0; +- } ++ pkt->size = out_size; ++ pkt->data = out; + +- pkt->size = out_size; +- pkt->data = out; ++ /* encode it */ ++ err = avcodec_send_frame(m_CodecCtx, frame); ++ if (err < 0) ++ throw FFMpegException("Error sending a frame for encoding (error '{}')", ++ FFMpegErrorToString(err)); + +- /* encode it */ +- int ret = avcodec_encode_audio2(m_CodecCtx, pkt, frame, &got_output); ++ while (err >= 0) ++ { ++ err = avcodec_receive_packet(m_CodecCtx, pkt); ++ if (err == AVERROR(EAGAIN) || err == AVERROR_EOF) ++ { ++ av_channel_layout_uninit(&frame->ch_layout); ++ av_frame_free(&frame); ++ av_packet_free(&pkt); ++ return (err == AVERROR(EAGAIN)) ? -1 : 0; ++ } ++ else if (err < 0) ++ { ++ throw FFMpegException("Error during encoding (error '{}')", FFMpegErrorToString(err)); ++ } + +- int size = pkt->size; ++ av_packet_unref(pkt); ++ } + ++ size = pkt->size; ++ } ++ catch (const FFMpegException& caught) ++ { ++ CLog::Log(LOGERROR, "CAEEncoderFFmpeg::{} - {}", __func__, caught.what()); ++ } ++ + /* free temporary data */ + av_frame_free(&frame); + + /* free the packet */ + av_packet_free(&pkt); + +- if (ret < 0 || !got_output) +- { +- CLog::Log(LOGERROR, "CAEEncoderFFmpeg::Encode - Encoding failed"); +- return 0; +- } +- + /* return the number of frames used */ + return size; + } +- + + int CAEEncoderFFmpeg::GetData(uint8_t **data) + { +diff -urN xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp.orig xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp +--- xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp.orig 2023-03-11 22:16:38.000000000 +0000 ++++ xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAE.cpp 2023-04-19 10:01:22.849708000 +0000 +@@ -16,17 +16,16 @@ + #include "ActiveAESound.h" + #include "ActiveAEStream.h" + #include "ServiceBroker.h" ++#include "cores/AudioEngine/AEResampleFactory.h" ++#include "cores/AudioEngine/Encoders/AEEncoderFFmpeg.h" + #include "cores/AudioEngine/Interfaces/IAudioCallback.h" +-#include "cores/AudioEngine/Utils/AEUtil.h" + #include "cores/AudioEngine/Utils/AEStreamData.h" + #include "cores/AudioEngine/Utils/AEStreamInfo.h" +-#include "cores/AudioEngine/AEResampleFactory.h" +-#include "cores/AudioEngine/Encoders/AEEncoderFFmpeg.h" +- ++#include "cores/AudioEngine/Utils/AEUtil.h" + #include "settings/Settings.h" + #include "settings/SettingsComponent.h" +-#include "windowing/WinSystem.h" + #include "utils/log.h" ++#include "windowing/WinSystem.h" + + using namespace std::chrono_literals; + +@@ -3043,8 +3042,8 @@ + AVFormatContext *fmt_ctx = nullptr; + AVCodecContext *dec_ctx = nullptr; + AVIOContext *io_ctx; +- AVInputFormat *io_fmt = nullptr; +- AVCodec *dec = nullptr; ++ const AVInputFormat* io_fmt = nullptr; ++ const AVCodec* dec = nullptr; + SampleConfig config; + + // No custom deleter until sound is registered +@@ -3096,8 +3095,8 @@ + AVCodecID codecId = fmt_ctx->streams[0]->codecpar->codec_id; + dec = avcodec_find_decoder(codecId); + config.sample_rate = fmt_ctx->streams[0]->codecpar->sample_rate; +- config.channels = fmt_ctx->streams[0]->codecpar->channels; +- config.channel_layout = fmt_ctx->streams[0]->codecpar->channel_layout; ++ config.channels = fmt_ctx->streams[0]->codecpar->ch_layout.nb_channels; ++ config.channel_layout = fmt_ctx->streams[0]->codecpar->ch_layout.u.mask; + } + } + if (dec == nullptr) +@@ -3113,10 +3112,14 @@ + + dec_ctx = avcodec_alloc_context3(dec); + dec_ctx->sample_rate = config.sample_rate; +- dec_ctx->channels = config.channels; ++ AVChannelLayout layout = {}; + if (!config.channel_layout) +- config.channel_layout = av_get_default_channel_layout(config.channels); +- dec_ctx->channel_layout = config.channel_layout; ++ av_channel_layout_default(&layout, config.channels); ++ else ++ av_channel_layout_from_mask(&layout, config.channel_layout); ++ config.channel_layout = layout.u.mask; ++ av_channel_layout_copy(&dec_ctx->ch_layout, &layout); ++ av_channel_layout_uninit(&layout); + + AVPacket* avpkt = av_packet_alloc(); + if (!avpkt) +@@ -3183,6 +3186,7 @@ + + av_packet_free(&avpkt); + av_frame_free(&decoded_frame); ++ av_channel_layout_uninit(&dec_ctx->ch_layout); + avcodec_free_context(&dec_ctx); + avformat_close_input(&fmt_ctx); + if (io_ctx) +diff -urN xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEFilter.cpp.orig xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEFilter.cpp +--- xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEFilter.cpp.orig 2023-03-11 22:16:38.000000000 +0000 ++++ xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEFilter.cpp 2023-04-19 10:01:22.849964000 +0000 +@@ -12,8 +12,8 @@ + #include <algorithm> + + extern "C" { +-#include <libavfilter/avfilter.h> + #include <libavcodec/avcodec.h> ++#include <libavfilter/avfilter.h> + #include <libavfilter/buffersink.h> + #include <libavfilter/buffersrc.h> + #include <libswresample/swresample.h> +@@ -171,7 +171,10 @@ + } + + if (m_pOutFrame) ++ { ++ av_channel_layout_uninit(&m_pOutFrame->ch_layout); + av_frame_free(&m_pOutFrame); ++ } + + if (m_pConvertFrame) + av_frame_free(&m_pConvertFrame); +@@ -205,10 +208,9 @@ + if (!frame) + return -1; + +- int channels = av_get_channel_layout_nb_channels(m_channelLayout); +- +- frame->channel_layout = m_channelLayout; +- frame->channels = channels; ++ av_channel_layout_uninit(&frame->ch_layout); ++ av_channel_layout_from_mask(&frame->ch_layout, m_channelLayout); ++ int channels = frame->ch_layout.nb_channels; + frame->sample_rate = m_sampleRate; + frame->nb_samples = src_samples; + frame->format = m_sampleFormat; +@@ -224,6 +226,7 @@ + src_buffer[0], src_bufsize, 16); + if (result < 0) + { ++ av_channel_layout_uninit(&frame->ch_layout); + av_frame_free(&frame); + CLog::Log(LOGERROR, "CActiveAEFilter::ProcessFilter - avcodec_fill_audio_frame failed"); + m_filterEof = true; +@@ -231,6 +234,7 @@ + } + + result = av_buffersrc_write_frame(m_pFilterCtxIn, frame); ++ av_channel_layout_uninit(&frame->ch_layout); + av_frame_free(&frame); + if (result < 0) + { +@@ -284,7 +288,8 @@ + { + av_frame_unref(m_pOutFrame); + m_pOutFrame->format = m_sampleFormat; +- m_pOutFrame->channel_layout = m_channelLayout; ++ av_channel_layout_uninit(&m_pOutFrame->ch_layout); ++ av_channel_layout_from_mask(&m_pOutFrame->ch_layout, m_channelLayout); + m_pOutFrame->sample_rate = m_sampleRate; + result = swr_convert_frame(m_pConvertCtx, m_pOutFrame, m_pConvertFrame); + av_frame_unref(m_pConvertFrame); +@@ -302,7 +307,10 @@ + + if (m_hasData) + { +- int channels = av_get_channel_layout_nb_channels(m_channelLayout); ++ AVChannelLayout layout = {}; ++ av_channel_layout_from_mask(&layout, m_channelLayout); ++ int channels = layout.nb_channels; ++ av_channel_layout_uninit(&layout); + int planes = av_sample_fmt_is_planar(m_sampleFormat) ? channels : 1; + int samples = std::min(dst_samples, m_pOutFrame->nb_samples - m_sampleOffset); + int bytes = samples * av_get_bytes_per_sample(m_sampleFormat) * channels / planes; +diff -urN xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp.orig xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp +--- xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp.orig 2023-03-11 22:16:38.000000000 +0000 ++++ xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResampleFFMPEG.cpp 2023-04-19 10:01:22.850224000 +0000 +@@ -49,15 +49,30 @@ + m_doesResample = true; + + if (m_dst_chan_layout == 0) +- m_dst_chan_layout = av_get_default_channel_layout(m_dst_channels); ++ { ++ AVChannelLayout layout = {}; ++ av_channel_layout_default(&layout, m_dst_channels); ++ m_dst_chan_layout = layout.u.mask; ++ av_channel_layout_uninit(&layout); ++ } + if (m_src_chan_layout == 0) +- m_src_chan_layout = av_get_default_channel_layout(m_src_channels); ++ { ++ AVChannelLayout layout = {}; ++ av_channel_layout_default(&layout, m_src_channels); ++ m_src_chan_layout = layout.u.mask; ++ av_channel_layout_uninit(&layout); ++ } + +- m_pContext = swr_alloc_set_opts(NULL, m_dst_chan_layout, m_dst_fmt, m_dst_rate, +- m_src_chan_layout, m_src_fmt, m_src_rate, +- 0, NULL); ++ AVChannelLayout dstChLayout = {}; ++ AVChannelLayout srcChLayout = {}; + +- if (!m_pContext) ++ av_channel_layout_from_mask(&dstChLayout, m_dst_chan_layout); ++ av_channel_layout_from_mask(&srcChLayout, m_src_chan_layout); ++ ++ int ret = swr_alloc_set_opts2(&m_pContext, &dstChLayout, m_dst_fmt, m_dst_rate, &srcChLayout, ++ m_src_fmt, m_src_rate, 0, NULL); ++ ++ if (ret) + { + CLog::Log(LOGERROR, "CActiveAEResampleFFMPEG::Init - create context failed"); + return false; +@@ -126,10 +141,12 @@ + else if (upmix && m_src_channels == 2 && m_dst_channels > 2) + { + memset(m_rematrix, 0, sizeof(m_rematrix)); ++ av_channel_layout_uninit(&dstChLayout); ++ av_channel_layout_from_mask(&dstChLayout, m_dst_chan_layout); + for (int out=0; out<m_dst_channels; out++) + { +- uint64_t out_chan = av_channel_layout_extract_channel(m_dst_chan_layout, out); +- switch(out_chan) ++ AVChannel outChan = av_channel_layout_channel_from_index(&dstChLayout, out); ++ switch (outChan) + { + case AV_CH_FRONT_LEFT: + case AV_CH_BACK_LEFT: +@@ -153,6 +170,8 @@ + break; + } + } ++ ++ av_channel_layout_uninit(&dstChLayout); + + if (swr_set_matrix(m_pContext, (const double*)m_rematrix, AE_CH_MAX) < 0) + { +diff -urN xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEStream.cpp.orig xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEStream.cpp +--- xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEStream.cpp.orig 2023-03-11 22:16:38.000000000 +0000 ++++ xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEStream.cpp 2023-04-19 10:01:22.844169000 +0000 +@@ -88,7 +88,7 @@ + for(unsigned int i=0; i<m_format.m_channelLayout.Count(); i++) + { + avLast = avCur; +- avCur = CAEUtil::GetAVChannel(m_format.m_channelLayout[i]); ++ avCur = CAEUtil::GetAVChannelMask(m_format.m_channelLayout[i]); + if(avCur < avLast) + { + needRemap = true; +diff -urN xbmc/cores/AudioEngine/Utils/AEUtil.cpp.orig xbmc/cores/AudioEngine/Utils/AEUtil.cpp +--- xbmc/cores/AudioEngine/Utils/AEUtil.cpp.orig 2023-03-11 22:16:38.000000000 +0000 ++++ xbmc/cores/AudioEngine/Utils/AEUtil.cpp 2023-04-19 10:01:22.850463000 +0000 +@@ -19,10 +19,6 @@ + #include <xmmintrin.h> + #endif + +-extern "C" { +-#include <libavutil/channel_layout.h> +-} +- + void AEDelayStatus::SetDelay(double d) + { + delay = d; +@@ -550,34 +546,64 @@ + } + } + +-uint64_t CAEUtil::GetAVChannel(enum AEChannel aechannel) ++uint64_t CAEUtil::GetAVChannelMask(enum AEChannel aechannel) + { ++ enum AVChannel ch = GetAVChannel(aechannel); ++ if (ch == AV_CHAN_NONE) ++ return 0; ++ return (1ULL << ch); ++} ++ ++enum AVChannel CAEUtil::GetAVChannel(enum AEChannel aechannel) ++{ + switch (aechannel) + { +- case AE_CH_FL: return AV_CH_FRONT_LEFT; +- case AE_CH_FR: return AV_CH_FRONT_RIGHT; +- case AE_CH_FC: return AV_CH_FRONT_CENTER; +- case AE_CH_LFE: return AV_CH_LOW_FREQUENCY; +- case AE_CH_BL: return AV_CH_BACK_LEFT; +- case AE_CH_BR: return AV_CH_BACK_RIGHT; +- case AE_CH_FLOC: return AV_CH_FRONT_LEFT_OF_CENTER; +- case AE_CH_FROC: return AV_CH_FRONT_RIGHT_OF_CENTER; +- case AE_CH_BC: return AV_CH_BACK_CENTER; +- case AE_CH_SL: return AV_CH_SIDE_LEFT; +- case AE_CH_SR: return AV_CH_SIDE_RIGHT; +- case AE_CH_TC: return AV_CH_TOP_CENTER; +- case AE_CH_TFL: return AV_CH_TOP_FRONT_LEFT; +- case AE_CH_TFC: return AV_CH_TOP_FRONT_CENTER; +- case AE_CH_TFR: return AV_CH_TOP_FRONT_RIGHT; +- case AE_CH_TBL: return AV_CH_TOP_BACK_LEFT; +- case AE_CH_TBC: return AV_CH_TOP_BACK_CENTER; +- case AE_CH_TBR: return AV_CH_TOP_BACK_RIGHT; +- default: +- return 0; ++ case AE_CH_FL: ++ return AV_CHAN_FRONT_LEFT; ++ case AE_CH_FR: ++ return AV_CHAN_FRONT_RIGHT; ++ case AE_CH_FC: ++ return AV_CHAN_FRONT_CENTER; ++ case AE_CH_LFE: ++ return AV_CHAN_LOW_FREQUENCY; ++ case AE_CH_BL: ++ return AV_CHAN_BACK_LEFT; ++ case AE_CH_BR: ++ return AV_CHAN_BACK_RIGHT; ++ case AE_CH_FLOC: ++ return AV_CHAN_FRONT_LEFT_OF_CENTER; ++ case AE_CH_FROC: ++ return AV_CHAN_FRONT_RIGHT_OF_CENTER; ++ case AE_CH_BC: ++ return AV_CHAN_BACK_CENTER; ++ case AE_CH_SL: ++ return AV_CHAN_SIDE_LEFT; ++ case AE_CH_SR: ++ return AV_CHAN_SIDE_RIGHT; ++ case AE_CH_TC: ++ return AV_CHAN_TOP_CENTER; ++ case AE_CH_TFL: ++ return AV_CHAN_TOP_FRONT_LEFT; ++ case AE_CH_TFC: ++ return AV_CHAN_TOP_FRONT_CENTER; ++ case AE_CH_TFR: ++ return AV_CHAN_TOP_FRONT_RIGHT; ++ case AE_CH_TBL: *** 1189 LINES SKIPPED ***