git: a02f5f0aef79 - main - graphics/blender: add support FFMPEG 7

From: Vladimir Druzenko <vvd_at_FreeBSD.org>
Date: Mon, 19 Aug 2024 11:23:40 UTC
The branch main has been updated by vvd:

URL: https://cgit.FreeBSD.org/ports/commit/?id=a02f5f0aef7920b52b7eab7bbd1a2a0056bc0edf

commit a02f5f0aef7920b52b7eab7bbd1a2a0056bc0edf
Author:     Shane <FreeBSD@ShaneWare.Biz>
AuthorDate: 2024-08-19 11:21:27 +0000
Commit:     Vladimir Druzenko <vvd@FreeBSD.org>
CommitDate: 2024-08-19 11:21:27 +0000

    graphics/blender: add support FFMPEG 7
    
    PR:             280829
    Obtained from:  upstream's pool requests:
                    https://projects.blender.org/blender/blender/pulls/121947
                    https://projects.blender.org/blender/blender/pulls/121960
---
 ...xtern_audaspace_plugins_ffmpeg_FFMPEGReader.cpp | 71 ++++++++++++++++++
 ...xtern_audaspace_plugins_ffmpeg_FFMPEGWriter.cpp | 87 ++++++++++++++++++++++
 .../files/patch-intern_ffmpeg_ffmpeg__compat.h     | 18 +++++
 ...atch-source_blender_imbuf_intern_anim__movie.cc | 26 +++++++
 4 files changed, 202 insertions(+)

diff --git a/graphics/blender/files/patch-extern_audaspace_plugins_ffmpeg_FFMPEGReader.cpp b/graphics/blender/files/patch-extern_audaspace_plugins_ffmpeg_FFMPEGReader.cpp
new file mode 100644
index 000000000000..10a1cf924e53
--- /dev/null
+++ b/graphics/blender/files/patch-extern_audaspace_plugins_ffmpeg_FFMPEGReader.cpp
@@ -0,0 +1,71 @@
+--- extern/audaspace/plugins/ffmpeg/FFMPEGReader.cpp.orig	2024-08-18 04:20:22 UTC
++++ extern/audaspace/plugins/ffmpeg/FFMPEGReader.cpp
+@@ -31,6 +31,10 @@ AUD_NAMESPACE_BEGIN
+ #define FFMPEG_OLD_CODE
+ #endif
+ 
++#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100)
++#define HAVE_CH_LAYOUT
++#endif
++
+ SampleFormat FFMPEGReader::convertSampleFormat(AVSampleFormat format)
+ {
+ 	switch(av_get_packed_sample_fmt(format))
+@@ -109,10 +113,16 @@ int FFMPEGReader::decode(AVPacket& packet, Buffer& buf
+ 	{
+ 		auto ret = avcodec_receive_frame(m_codecCtx, m_frame);
+ 
++#ifdef HAVE_CH_LAYOUT
++		int nb_channels = m_codecCtx->ch_layout.nb_channels;
++#else
++		int nb_channels = m_codecCtx->channels;
++#endif
++
+ 		if(ret != 0)
+ 			break;
+ 
+-		int data_size = av_samples_get_buffer_size(nullptr, m_codecCtx->channels, m_frame->nb_samples, m_codecCtx->sample_fmt, 1);
++		int data_size = av_samples_get_buffer_size(nullptr, nb_channels, m_frame->nb_samples, m_codecCtx->sample_fmt, 1);
+ 
+ 		if(buf_size - buf_pos < data_size)
+ 		{
+@@ -122,12 +132,12 @@ int FFMPEGReader::decode(AVPacket& packet, Buffer& buf
+ 
+ 		if(m_tointerleave)
+ 		{
+-			int single_size = data_size / m_codecCtx->channels / m_frame->nb_samples;
+-			for(int channel = 0; channel < m_codecCtx->channels; channel++)
++			int single_size = data_size / nb_channels / m_frame->nb_samples;
++			for(int channel = 0; channel < nb_channels; channel++)
+ 			{
+ 				for(int i = 0; i < m_frame->nb_samples; i++)
+ 				{
+-					std::memcpy(((data_t*)buffer.getBuffer()) + buf_pos + ((m_codecCtx->channels * i) + channel) * single_size,
++					std::memcpy(((data_t*)buffer.getBuffer()) + buf_pos + ((nb_channels * i) + channel) * single_size,
+ 						   m_frame->data[channel] + i * single_size, single_size);
+ 				}
+ 			}
+@@ -207,7 +217,11 @@ void FFMPEGReader::init(int stream)
+ 	if(avcodec_open2(m_codecCtx, aCodec, nullptr) < 0)
+ 		AUD_THROW(FileException, "File couldn't be read, ffmpeg codec couldn't be opened.");
+ 
++#ifdef HAVE_CH_LAYOUT
++	m_specs.channels = (Channels) m_codecCtx->ch_layout.nb_channels;
++#else
+ 	m_specs.channels = (Channels) m_codecCtx->channels;
++#endif
+ 	m_tointerleave = av_sample_fmt_is_planar(m_codecCtx->sample_fmt);
+ 
+ 	switch(av_get_packed_sample_fmt(m_codecCtx->sample_fmt))
+@@ -345,7 +359,11 @@ std::vector<StreamInfo> FFMPEGReader::queryStreams()
+ 			info.specs.rate = m_formatCtx->streams[i]->codec->sample_rate;
+ 			info.specs.format = convertSampleFormat(m_formatCtx->streams[i]->codec->sample_fmt);
+ #else
++#ifdef HAVE_CH_LAYOUT
++			info.specs.channels = Channels(m_formatCtx->streams[i]->codecpar->ch_layout.nb_channels);
++#else
+ 			info.specs.channels = Channels(m_formatCtx->streams[i]->codecpar->channels);
++#endif
+ 			info.specs.rate = m_formatCtx->streams[i]->codecpar->sample_rate;
+ 			info.specs.format = convertSampleFormat(AVSampleFormat(m_formatCtx->streams[i]->codecpar->format));
+ #endif
diff --git a/graphics/blender/files/patch-extern_audaspace_plugins_ffmpeg_FFMPEGWriter.cpp b/graphics/blender/files/patch-extern_audaspace_plugins_ffmpeg_FFMPEGWriter.cpp
new file mode 100644
index 000000000000..f93ef6df1417
--- /dev/null
+++ b/graphics/blender/files/patch-extern_audaspace_plugins_ffmpeg_FFMPEGWriter.cpp
@@ -0,0 +1,87 @@
+--- extern/audaspace/plugins/ffmpeg/FFMPEGWriter.cpp.orig	2024-08-18 04:25:16 UTC
++++ extern/audaspace/plugins/ffmpeg/FFMPEGWriter.cpp
+@@ -34,6 +34,10 @@ AUD_NAMESPACE_BEGIN
+ #define FFMPEG_OLD_CODE
+ #endif
+ 
++#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100)
++#define HAVE_CH_LAYOUT
++#endif
++
+ void FFMPEGWriter::encode()
+ {
+ 	sample_t* data = m_input_buffer.getBuffer();
+@@ -77,8 +81,12 @@ void FFMPEGWriter::encode()
+ 
+ 	m_frame->nb_samples = m_input_samples;
+ 	m_frame->format = m_codecCtx->sample_fmt;
++#ifdef HAVE_CH_LAYOUT
++	av_channel_layout_copy(&m_frame->ch_layout, &m_codecCtx->ch_layout);
++#else
+ 	m_frame->channel_layout = m_codecCtx->channel_layout;
+ 	m_frame->channels = m_specs.channels;
++#endif
+ 
+ 	if(avcodec_fill_audio_frame(m_frame, m_specs.channels, m_codecCtx->sample_fmt, reinterpret_cast<data_t*>(data), m_input_buffer.getSize(), 0) < 0)
+ 		AUD_THROW(FileException, "File couldn't be written, filling the audio frame failed with ffmpeg.");
+@@ -237,6 +245,39 @@ FFMPEGWriter::FFMPEGWriter(const std::string &filename
+ 		break;
+ 	}
+ 
++#ifdef HAVE_CH_LAYOUT
++	AVChannelLayout channel_layout{};
++
++	switch(m_specs.channels)
++	{
++	case CHANNELS_MONO:
++		channel_layout = AV_CHANNEL_LAYOUT_MONO;
++		break;
++	case CHANNELS_STEREO:
++		channel_layout = AV_CHANNEL_LAYOUT_STEREO;
++		break;
++	case CHANNELS_STEREO_LFE:
++		channel_layout = AV_CHANNEL_LAYOUT_2POINT1;
++		break;
++	case CHANNELS_SURROUND4:
++		channel_layout = AV_CHANNEL_LAYOUT_QUAD;
++		break;
++	case CHANNELS_SURROUND5:
++		channel_layout = AV_CHANNEL_LAYOUT_5POINT0_BACK;
++		break;
++	case CHANNELS_SURROUND51:
++		channel_layout = AV_CHANNEL_LAYOUT_5POINT1_BACK;
++		break;
++	case CHANNELS_SURROUND61:
++		channel_layout = AV_CHANNEL_LAYOUT_6POINT1_BACK;
++		break;
++	case CHANNELS_SURROUND71:
++		channel_layout = AV_CHANNEL_LAYOUT_7POINT1;
++		break;
++	default:
++		AUD_THROW(FileException, "File couldn't be written, channel layout not supported.");
++	}
++#else
+ 	uint64_t channel_layout = 0;
+ 
+ 	switch(m_specs.channels)
+@@ -268,6 +309,7 @@ FFMPEGWriter::FFMPEGWriter(const std::string &filename
+ 	default:
+ 		AUD_THROW(FileException, "File couldn't be written, channel layout not supported.");
+ 	}
++#endif
+ 
+ 	try
+ 	{
+@@ -405,8 +447,12 @@ FFMPEGWriter::FFMPEGWriter(const std::string &filename
+ 
+ 		m_codecCtx->codec_type = AVMEDIA_TYPE_AUDIO;
+ 		m_codecCtx->bit_rate = bitrate;
++#ifdef HAVE_CH_LAYOUT
++		av_channel_layout_copy(&m_codecCtx->ch_layout, &channel_layout);
++#else
+ 		m_codecCtx->channel_layout = channel_layout;
+ 		m_codecCtx->channels = m_specs.channels;
++#endif
+ 		m_stream->time_base.num = m_codecCtx->time_base.num = 1;
+ 		m_stream->time_base.den = m_codecCtx->time_base.den = m_codecCtx->sample_rate;
+ 
diff --git a/graphics/blender/files/patch-intern_ffmpeg_ffmpeg__compat.h b/graphics/blender/files/patch-intern_ffmpeg_ffmpeg__compat.h
new file mode 100644
index 000000000000..856ddbff1e3b
--- /dev/null
+++ b/graphics/blender/files/patch-intern_ffmpeg_ffmpeg__compat.h
@@ -0,0 +1,18 @@
+--- intern/ffmpeg/ffmpeg_compat.h.orig	2024-08-18 04:14:52 UTC
++++ intern/ffmpeg/ffmpeg_compat.h
+@@ -141,6 +141,15 @@ int64_t av_get_frame_duration_in_pts_units(const AVFra
+ #endif
+ }
+ 
++FFMPEG_INLINE
++bool av_get_cur_key_frame_pts(const AVFrame *picture) {
++#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(58, 29, 100)
++  return (picture->flags & AV_FRAME_FLAG_KEY);
++#else
++  return (picture->key_frame);
++#endif
++}
++
+ /* -------------------------------------------------------------------- */
+ /** \name Deinterlace code block
+  *
diff --git a/graphics/blender/files/patch-source_blender_imbuf_intern_anim__movie.cc b/graphics/blender/files/patch-source_blender_imbuf_intern_anim__movie.cc
new file mode 100644
index 000000000000..3fd27708541c
--- /dev/null
+++ b/graphics/blender/files/patch-source_blender_imbuf_intern_anim__movie.cc
@@ -0,0 +1,26 @@
+--- source/blender/imbuf/intern/anim_movie.cc.orig	2024-08-18 04:16:01 UTC
++++ source/blender/imbuf/intern/anim_movie.cc
+@@ -653,7 +653,7 @@ static void ffmpeg_decode_store_frame_pts(ImBufAnim *a
+ {
+   anim->cur_pts = av_get_pts_from_frame(anim->pFrame);
+ 
+-  if (anim->pFrame->key_frame) {
++  if (av_get_cur_key_frame_pts(anim->pFrame)) {
+     anim->cur_key_frame_pts = anim->cur_pts;
+   }
+ 
+@@ -1032,10 +1032,9 @@ static int ffmpeg_seek_to_key_frame(ImBufAnim *anim,
+ 
+     AVFormatContext *format_ctx = anim->pFormatCtx;
+ 
+-    if (format_ctx->iformat->read_seek2 || format_ctx->iformat->read_seek) {
+-      ret = av_seek_frame(anim->pFormatCtx, anim->videoStream, seek_pos, AVSEEK_FLAG_BACKWARD);
+-    }
+-    else {
++    int ret = av_seek_frame(anim->pFormatCtx, anim->videoStream, seek_pos, AVSEEK_FLAG_BACKWARD);
++
++    if (ret < 0) {
+       ret = ffmpeg_generic_seek_workaround(anim, &seek_pos, pts_to_search);
+       av_log(anim->pFormatCtx,
+              AV_LOG_DEBUG,
+