public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
From: Dominik 'Rathann' Mierzejewski <dominik@greysector.net>
To: git-commits@fedoraproject.org
Subject: [rpms/gpac] f45: fix building with FFmpeg 9
Date: Tue, 25 Aug 2026 13:05:54 GMT	[thread overview]
Message-ID: <178766315468.1.3664181045254173900.rpms-gpac-3caf22d6cfac@fedoraproject.org> (raw)

A new commit has been pushed.

Repo   : rpms/gpac
Branch : f45
Commit : 3caf22d6cfac60cf4c39ef8bb6daa1b89bf4528a
Author : Dominik 'Rathann' Mierzejewski <dominik@greysector.net>
Date   : 2026-08-18T21:49:04+02:00
Stats  : +326/-1 in 2 file(s)
URL    : https://src.fedoraproject.org/rpms/gpac/c/3caf22d6cfac60cf4c39ef8bb6daa1b89bf4528a?branch=f45

Log:
fix building with FFmpeg 9

---
diff --git a/gpac-ffmpeg9.patch b/gpac-ffmpeg9.patch
new file mode 100644
index 0000000..f5f6b96
--- /dev/null
+++ b/gpac-ffmpeg9.patch
@@ -0,0 +1,320 @@
+From 89dbea46046035c5c0fe33ffe63e2083ab33e868 Mon Sep 17 00:00:00 2001
+From: Romain Bouqueau <romain.bouqueau.pro@gmail.com>
+Date: Sun, 9 Aug 2026 21:48:15 -0400
+Subject: [PATCH 1/3] ffmpeg9 compat: builds until ffmpeg6 where other
+ non-ifdef-ed errors happen anyway
+
+---
+ src/filters/ff_enc.c | 74 ++++++++++++++++++++++++++------------------
+ 1 file changed, 44 insertions(+), 30 deletions(-)
+
+diff --git a/src/filters/ff_enc.c b/src/filters/ff_enc.c
+index 78345df5af..59792fb457 100644
+--- a/src/filters/ff_enc.c
++++ b/src/filters/ff_enc.c
+@@ -1671,14 +1671,16 @@ static GF_Err ffenc_configure_pid_ex(GF_Filter *filter, GF_FilterPid *pid, Bool
+ 		if (ctx->pfmt) {
+ 			u32 ff_pfmt = ffmpeg_pixfmt_from_gpac(ctx->pfmt, GF_FALSE);
+ 			i=0;
+-			while (codec->pix_fmts) {
+-				if (codec->pix_fmts[i] == AV_PIX_FMT_NONE) break;
+-				if (codec->pix_fmts[i] == ff_pfmt) {
++			const enum AVPixelFormat* codec_pix_fmts = NULL;
++			avcodec_get_supported_config(NULL, codec, AV_CODEC_CONFIG_PIX_FORMAT, 0, (const void**)&codec_pix_fmts, NULL);
++			while (codec_pix_fmts) {
++				if (codec_pix_fmts[i] == AV_PIX_FMT_NONE) break;
++				if (codec_pix_fmts[i] == ff_pfmt) {
+ 					force_pfmt = ff_pfmt;
+ 					break;
+ 				}
+ 				//handle pixel formats aliases
+-				if (ffmpeg_pixfmt_to_gpac(codec->pix_fmts[i], GF_TRUE) == ctx->pfmt) {
++				if (ffmpeg_pixfmt_to_gpac(codec_pix_fmts[i], GF_TRUE) == ctx->pfmt) {
+ 					force_pfmt = ctx->pixel_fmt;
+ 					break;
+ 				}
+@@ -1695,15 +1697,17 @@ static GF_Err ffenc_configure_pid_ex(GF_Filter *filter, GF_FilterPid *pid, Bool
+ 		if (force_pfmt == AV_PIX_FMT_NONE) {
+ 			change_input_fmt = AV_PIX_FMT_NONE;
+ 			i=0;
+-			while (codec->pix_fmts) {
+-				if (codec->pix_fmts[i] == AV_PIX_FMT_NONE) break;
+-				if (codec->pix_fmts[i] == ctx->pixel_fmt) {
++			const enum AVPixelFormat* codec_pix_fmts = NULL;
++			avcodec_get_supported_config(NULL, codec, AV_CODEC_CONFIG_PIX_FORMAT, 0, (const void**)&codec_pix_fmts, NULL);
++			while (codec_pix_fmts) {
++				if (codec_pix_fmts[i] == AV_PIX_FMT_NONE) break;
++				if (codec_pix_fmts[i] == ctx->pixel_fmt) {
+ 					change_input_fmt = ctx->pixel_fmt;
+ 					break;
+ 				}
+ 				//handle pixel formats aliases
+-				if (ffmpeg_pixfmt_to_gpac(codec->pix_fmts[i], GF_TRUE) == pfmt) {
+-					ctx->pixel_fmt = change_input_fmt = codec->pix_fmts[i];
++				if (ffmpeg_pixfmt_to_gpac(codec_pix_fmts[i], GF_TRUE) == pfmt) {
++					ctx->pixel_fmt = change_input_fmt = codec_pix_fmts[i];
+ 					break;
+ 				}
+ 				i++;
+@@ -1724,9 +1728,11 @@ static GF_Err ffenc_configure_pid_ex(GF_Filter *filter, GF_FilterPid *pid, Bool
+ 					if (codec_alt==codec) continue;
+ 					if (codec_alt->id == codec_id) {
+ 						i=0;
+-						while (codec_alt->pix_fmts) {
+-							if (codec_alt->pix_fmts[i] == AV_PIX_FMT_NONE) break;
+-							if (codec_alt->pix_fmts[i] == ctx->pixel_fmt) {
++					const enum AVPixelFormat* codec_alt_pix_fmts = NULL;
++					avcodec_get_supported_config(NULL, codec_alt, AV_CODEC_CONFIG_PIX_FORMAT, 0, (const void**)&codec_alt_pix_fmts, NULL);
++						while (codec_alt_pix_fmts) {
++							if (codec_alt_pix_fmts[i] == AV_PIX_FMT_NONE) break;
++							if (codec_alt_pix_fmts[i] == ctx->pixel_fmt) {
+ 								change_input_fmt = ctx->pixel_fmt;
+ 								GF_LOG(GF_LOG_WARNING, GF_LOG_CODEC, ("[FFEnc] Reassigning codec from %s to %s to match pixel format\n", codec->name, codec_alt->name ));
+ 								codec = codec_alt;
+@@ -1746,10 +1752,12 @@ static GF_Err ffenc_configure_pid_ex(GF_Filter *filter, GF_FilterPid *pid, Bool
+ 				ff_pmft = AV_PIX_FMT_NONE;
+ 				i=0;
+ 				//find a mapped pixel format
+-				while (codec->pix_fmts) {
+-					if (codec->pix_fmts[i] == AV_PIX_FMT_NONE) break;
+-					if (ffmpeg_pixfmt_to_gpac(codec->pix_fmts[i], GF_TRUE)) {
+-						ff_pmft = codec->pix_fmts[i];
++				const enum AVPixelFormat* codec_pix_fmts = NULL;
++				avcodec_get_supported_config(NULL, codec, AV_CODEC_CONFIG_PIX_FORMAT, 0, (const void**)&codec_pix_fmts, NULL);
++				while (codec_pix_fmts) {
++					if (codec_pix_fmts[i] == AV_PIX_FMT_NONE) break;
++					if (ffmpeg_pixfmt_to_gpac(codec_pix_fmts[i], GF_TRUE)) {
++						ff_pmft = codec_pix_fmts[i];
+ 						break;
+ 					}
+ 					i++;
+@@ -1793,21 +1801,25 @@ static GF_Err ffenc_configure_pid_ex(GF_Filter *filter, GF_FilterPid *pid, Bool
+ 		//check audio format
+ 		ctx->sample_fmt = ffmpeg_audio_fmt_from_gpac(afmt);
+ 		change_input_fmt = AV_SAMPLE_FMT_NONE;
+-		while (codec->sample_fmts) {
+-			if (codec->sample_fmts[i] == AV_SAMPLE_FMT_NONE) break;
+-			if (codec->sample_fmts[i] == ctx->sample_fmt) {
++		const enum AVSampleFormat *codec_sample_fmts = NULL;
++		avcodec_get_supported_config(NULL, codec, AV_CODEC_CONFIG_SAMPLE_FORMAT, 0, (const void**)&codec_sample_fmts, NULL);
++		while (codec_sample_fmts) {
++			if (codec_sample_fmts[i] == AV_SAMPLE_FMT_NONE) break;
++			if (codec_sample_fmts[i] == ctx->sample_fmt) {
+ 				change_input_fmt = ctx->sample_fmt;
+ 				break;
+ 			}
+ 			i++;
+ 		}
+ 		i=0;
+-		if (!codec->supported_samplerates)
++		const int *codec_supported_samplerates = NULL;
++		avcodec_get_supported_config(NULL, codec, AV_CODEC_CONFIG_SAMPLE_RATE, 0, (const void**)&codec_supported_samplerates, NULL);
++		if (!codec_supported_samplerates)
+ 			change_input_sr = ctx->sample_rate;
+ 
+-		while (codec->supported_samplerates) {
+-			if (!codec->supported_samplerates[i]) break;
+-			if (codec->supported_samplerates[i]==ctx->sample_rate) {
++		while (codec_supported_samplerates) {
++			if (!codec_supported_samplerates[i]) break;
++			if (codec_supported_samplerates[i]==ctx->sample_rate) {
+ 				change_input_sr = ctx->sample_rate;
+ 				break;
+ 			}
+@@ -1832,12 +1844,14 @@ static GF_Err ffenc_configure_pid_ex(GF_Filter *filter, GF_FilterPid *pid, Bool
+ 			i++;
+ 		}
+ #else
+-		if (!codec->ch_layouts)
++		const AVChannelLayout *codec_ch_layouts = NULL;
++		avcodec_get_supported_config(NULL, codec, AV_CODEC_CONFIG_CHANNEL_LAYOUT, 0, (const void**)&codec_ch_layouts, NULL);
++		if (!codec_ch_layouts)
+ 			change_chan_layout = ctx->channel_layout;
+ 
+-		while (codec->ch_layouts) {
+-			if (!codec->ch_layouts[i].nb_channels) break;
+-			if (codec->ch_layouts[i].u.mask == ff_ch_layout) {
++		while (codec_ch_layouts) {
++			if (!codec_ch_layouts[i].nb_channels) break;
++			if (codec_ch_layouts[i].u.mask == ff_ch_layout) {
+ 				change_chan_layout = ctx->channel_layout;
+ 				break;
+ 			}
+@@ -1855,19 +1869,19 @@ static GF_Err ffenc_configure_pid_ex(GF_Filter *filter, GF_FilterPid *pid, Bool
+ 			|| (ctx->channel_layout != change_chan_layout)
+ 		) {
+ 			if (ctx->sample_fmt != change_input_fmt) {
+-				ctx->sample_fmt = codec->sample_fmts ? codec->sample_fmts[0] : AV_SAMPLE_FMT_S16;
++				ctx->sample_fmt = codec_sample_fmts ? codec_sample_fmts[0] : AV_SAMPLE_FMT_S16;
+ 				afmt = ffmpeg_audio_fmt_to_gpac(ctx->sample_fmt);
+ 				gf_filter_pid_negotiate_property(ctx->in_pid, GF_PROP_PID_AUDIO_FORMAT, &PROP_UINT(afmt) );
+ 			}
+ 			if (ctx->sample_rate != change_input_sr) {
+-				gf_filter_pid_negotiate_property(ctx->in_pid, GF_PROP_PID_SAMPLE_RATE, &PROP_UINT(codec->supported_samplerates[0]) );
++				gf_filter_pid_negotiate_property(ctx->in_pid, GF_PROP_PID_SAMPLE_RATE, &PROP_UINT(codec_supported_samplerates[0]) );
+ 			}
+ 			if (ctx->channel_layout != change_chan_layout) {
+ 				if (!change_chan_layout) {
+ #ifdef FFMPEG_OLD_CHLAYOUT
+ 					change_chan_layout = ffmpeg_channel_layout_to_gpac(codec->channel_layouts[0]);
+ #else
+-					change_chan_layout = ffmpeg_channel_layout_to_gpac(codec->ch_layouts[0].u.mask);
++					change_chan_layout = ffmpeg_channel_layout_to_gpac(codec_ch_layouts[0].u.mask);
+ #endif
+ 				}
+ 				u32 nb_chans = gf_audio_fmt_get_num_channels_from_layout(change_chan_layout);
+
+From aecc4a4af093d7113edd5881a8b95eefd1da94d6 Mon Sep 17 00:00:00 2001
+From: Romain Bouqueau <romain.bouqueau.pro@gmail.com>
+Date: Mon, 10 Aug 2026 08:02:30 -0400
+Subject: [PATCH 2/3] ffmpeg9 removed libpostproc in ALLFFLIBS
+ (https://github.com/FFmpeg/FFmpeg/commit/12497766410135f27012077e78b3bdcfc704f7ca)
+ and we don't really test it anyway
+
+---
+ configure | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/configure b/configure
+index 8e0479a4d8..40ba5251f3 100755
+--- a/configure
++++ b/configure
+@@ -1717,7 +1717,7 @@ config_package faad "faad2" "" "-lfaad -lm" "" '#include <faad.h>
+ int main( void ) { NeAACDecOpen(); return 0; }'
+ 
+ 
+-ffmpeg_lflags="-lz -lavcodec -lavformat -lavutil -lswscale -lpostproc"
++ffmpeg_lflags="-lz -lavcodec -lavformat -lavutil -lswscale"
+ ffmpeg_pck_names="libavcodec libavformat libswscale libavutil"
+ 
+ if test "$is_em" = "yes" ; then
+
+From 596affc92c14d84cb9a86cb2af06b403c96d7397 Mon Sep 17 00:00:00 2001
+From: Romain Bouqueau <romain.bouqueau.pro@gmail.com>
+Date: Mon, 10 Aug 2026 08:22:22 -0400
+Subject: [PATCH 3/3] ffmpeg9: add ifdef around api change
+ (avcodec_get_supported_config/FFMPEG_HAS_GET_SUPPORTED_CONFIG)
+
+---
+ src/filters/ff_common.h |  4 ++++
+ src/filters/ff_enc.c    | 36 ++++++++++++++++++++++++++++++++----
+ 2 files changed, 36 insertions(+), 4 deletions(-)
+
+diff --git a/src/filters/ff_common.h b/src/filters/ff_common.h
+index 54f37016c7..8424b67153 100644
+--- a/src/filters/ff_common.h
++++ b/src/filters/ff_common.h
+@@ -68,6 +68,10 @@
+ #define FFMPEG_OLD_CHLAYOUT
+ #endif
+ 
++#if AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, LIBAVCODEC_VERSION_MINOR, LIBAVCODEC_VERSION_MICRO) > AV_VERSION_INT(61, 100, 13)
++#define FFMPEG_HAS_GET_SUPPORTED_CONFIG
++#endif
++
+ 
+ GF_FilterArgs ffmpeg_arg_translate(const struct AVOption *opt);
+ void ffmpeg_setup_logs(u32 log_class);
+diff --git a/src/filters/ff_enc.c b/src/filters/ff_enc.c
+index 59792fb457..13db0b144b 100644
+--- a/src/filters/ff_enc.c
++++ b/src/filters/ff_enc.c
+@@ -1672,7 +1672,11 @@ static GF_Err ffenc_configure_pid_ex(GF_Filter *filter, GF_FilterPid *pid, Bool
+ 			u32 ff_pfmt = ffmpeg_pixfmt_from_gpac(ctx->pfmt, GF_FALSE);
+ 			i=0;
+ 			const enum AVPixelFormat* codec_pix_fmts = NULL;
++#ifdef FFMPEG_HAS_GET_SUPPORTED_CONFIG
+ 			avcodec_get_supported_config(NULL, codec, AV_CODEC_CONFIG_PIX_FORMAT, 0, (const void**)&codec_pix_fmts, NULL);
++#else
++			codec_pix_fmts = codec->pix_fmts;
++#endif
+ 			while (codec_pix_fmts) {
+ 				if (codec_pix_fmts[i] == AV_PIX_FMT_NONE) break;
+ 				if (codec_pix_fmts[i] == ff_pfmt) {
+@@ -1698,7 +1702,11 @@ static GF_Err ffenc_configure_pid_ex(GF_Filter *filter, GF_FilterPid *pid, Bool
+ 			change_input_fmt = AV_PIX_FMT_NONE;
+ 			i=0;
+ 			const enum AVPixelFormat* codec_pix_fmts = NULL;
++#ifdef FFMPEG_HAS_GET_SUPPORTED_CONFIG
+ 			avcodec_get_supported_config(NULL, codec, AV_CODEC_CONFIG_PIX_FORMAT, 0, (const void**)&codec_pix_fmts, NULL);
++#else
++			codec_pix_fmts = codec->pix_fmts;
++#endif
+ 			while (codec_pix_fmts) {
+ 				if (codec_pix_fmts[i] == AV_PIX_FMT_NONE) break;
+ 				if (codec_pix_fmts[i] == ctx->pixel_fmt) {
+@@ -1728,8 +1736,12 @@ static GF_Err ffenc_configure_pid_ex(GF_Filter *filter, GF_FilterPid *pid, Bool
+ 					if (codec_alt==codec) continue;
+ 					if (codec_alt->id == codec_id) {
+ 						i=0;
+-					const enum AVPixelFormat* codec_alt_pix_fmts = NULL;
+-					avcodec_get_supported_config(NULL, codec_alt, AV_CODEC_CONFIG_PIX_FORMAT, 0, (const void**)&codec_alt_pix_fmts, NULL);
++						const enum AVPixelFormat* codec_alt_pix_fmts = NULL;
++#ifdef FFMPEG_HAS_GET_SUPPORTED_CONFIG
++						avcodec_get_supported_config(NULL, codec_alt, AV_CODEC_CONFIG_PIX_FORMAT, 0, (const void**)&codec_alt_pix_fmts, NULL);
++#else
++						codec_alt_pix_fmts = codec_alt->pix_fmts;
++#endif
+ 						while (codec_alt_pix_fmts) {
+ 							if (codec_alt_pix_fmts[i] == AV_PIX_FMT_NONE) break;
+ 							if (codec_alt_pix_fmts[i] == ctx->pixel_fmt) {
+@@ -1753,7 +1765,11 @@ static GF_Err ffenc_configure_pid_ex(GF_Filter *filter, GF_FilterPid *pid, Bool
+ 				i=0;
+ 				//find a mapped pixel format
+ 				const enum AVPixelFormat* codec_pix_fmts = NULL;
++#ifdef FFMPEG_HAS_GET_SUPPORTED_CONFIG
+ 				avcodec_get_supported_config(NULL, codec, AV_CODEC_CONFIG_PIX_FORMAT, 0, (const void**)&codec_pix_fmts, NULL);
++#else
++				codec_pix_fmts = codec->pix_fmts;
++#endif
+ 				while (codec_pix_fmts) {
+ 					if (codec_pix_fmts[i] == AV_PIX_FMT_NONE) break;
+ 					if (ffmpeg_pixfmt_to_gpac(codec_pix_fmts[i], GF_TRUE)) {
+@@ -1802,7 +1818,11 @@ static GF_Err ffenc_configure_pid_ex(GF_Filter *filter, GF_FilterPid *pid, Bool
+ 		ctx->sample_fmt = ffmpeg_audio_fmt_from_gpac(afmt);
+ 		change_input_fmt = AV_SAMPLE_FMT_NONE;
+ 		const enum AVSampleFormat *codec_sample_fmts = NULL;
++#ifdef FFMPEG_HAS_GET_SUPPORTED_CONFIG
+ 		avcodec_get_supported_config(NULL, codec, AV_CODEC_CONFIG_SAMPLE_FORMAT, 0, (const void**)&codec_sample_fmts, NULL);
++#else
++		codec_sample_fmts = codec->sample_fmts;
++#endif
+ 		while (codec_sample_fmts) {
+ 			if (codec_sample_fmts[i] == AV_SAMPLE_FMT_NONE) break;
+ 			if (codec_sample_fmts[i] == ctx->sample_fmt) {
+@@ -1813,7 +1833,11 @@ static GF_Err ffenc_configure_pid_ex(GF_Filter *filter, GF_FilterPid *pid, Bool
+ 		}
+ 		i=0;
+ 		const int *codec_supported_samplerates = NULL;
++#ifdef FFMPEG_HAS_GET_SUPPORTED_CONFIG
+ 		avcodec_get_supported_config(NULL, codec, AV_CODEC_CONFIG_SAMPLE_RATE, 0, (const void**)&codec_supported_samplerates, NULL);
++#else
++		codec_supported_samplerates = codec->supported_samplerates;
++#endif
+ 		if (!codec_supported_samplerates)
+ 			change_input_sr = ctx->sample_rate;
+ 
+@@ -1843,9 +1867,13 @@ static GF_Err ffenc_configure_pid_ex(GF_Filter *filter, GF_FilterPid *pid, Bool
+ 			}
+ 			i++;
+ 		}
+-#else
++#else /* !FFMPEG_OLD_CHLAYOUT */
+ 		const AVChannelLayout *codec_ch_layouts = NULL;
++# ifdef FFMPEG_HAS_GET_SUPPORTED_CONFIG
+ 		avcodec_get_supported_config(NULL, codec, AV_CODEC_CONFIG_CHANNEL_LAYOUT, 0, (const void**)&codec_ch_layouts, NULL);
++# else
++		codec_ch_layouts = codec->ch_layouts;
++# endif
+ 		if (!codec_ch_layouts)
+ 			change_chan_layout = ctx->channel_layout;
+ 
+@@ -1857,7 +1885,7 @@ static GF_Err ffenc_configure_pid_ex(GF_Filter *filter, GF_FilterPid *pid, Bool
+ 			}
+ 			i++;
+ 		}
+-#endif
++#endif /* !FFMPEG_OLD_CHLAYOUT */
+ 		//vorbis in ffmpeg currently requires stereo but channel_layouts is not set
+ 		if (ctx->codecid==GF_CODECID_VORBIS) {
+ 			change_chan_layout = gf_audio_fmt_get_layout_from_cicp(gf_audio_fmt_get_cicp_layout(2, 0, 0));

diff --git a/gpac.spec b/gpac.spec
index d6e0c93..5860475 100644
--- a/gpac.spec
+++ b/gpac.spec
@@ -3,7 +3,7 @@
 Name:        gpac
 Summary:     MPEG-4 multimedia framework
 Version:     26.07.0
-Release:     1%{?dist}
+Release:     2%{?dist}
 License:     LGPL-2.0-or-later
 URL:         https://gpac.io/
 Source0:     https://github.com/gpac/gpac/archive/v%{version}/gpac-%{version}.tar.gz
@@ -16,6 +16,8 @@ Patch1:      gpac-norpath.patch
 Patch2:      gpac-strcpy.patch
 # fix building SVGGen binary
 Patch3:      gpac-svggen.patch
+# fix building with FFmpeg 9
+Patch4:      https://github.com/gpac/gpac/pull/3853.patch#/gpac-ffmpeg9.patch
 
 BuildRequires:  SDL2-devel
 BuildRequires:  a52dec-devel
@@ -199,6 +201,9 @@ rm %{buildroot}%{_includedir}/gpac/00_doxy.h
 
 
 %changelog
+* Tue Aug 18 2026 Dominik Mierzejewski <dominik@greysector.net> - 26.07.0-2
+- fix building with FFmpeg 9
+
 * Sat Aug 15 2026 Dominik Mierzejewski <dominik@greysector.net> - 26.07.0-1
 - update to 26.07.0 (resolves rhbz#2514277)
 - fix building sggen binaries

                 reply	other threads:[~2026-08-25 13:05 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=178766315468.1.3664181045254173900.rpms-gpac-3caf22d6cfac@fedoraproject.org \
    --to=dominik@greysector.net \
    --cc=git-commits@fedoraproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox