Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
From: Lynne via ffmpeg-devel <ffmpeg-devel@ffmpeg.org>
To: ffmpeg-devel@ffmpeg.org
Cc: Lynne <code@ffmpeg.org>
Subject: [FFmpeg-devel] [PR] swscale: add preliminary support for Vulkan (PR #22265)
Date: Mon, 23 Feb 2026 14:37:38 -0000
Message-ID: <177185745889.25.517727238862405330@29965ddac10e> (raw)

PR #22265 opened by Lynne
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22265
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22265.patch

This PR implements preliminary support for Vulkan. It adds a new API to attach a hardware device (not specific to Vulkan, lets support for other APIs too). It initializes a SPIR-V compiler. And finally, it creates a hardware frames context (and frame pool) to output Vulkan frames.

The code is only active and compiled if CONFIG_UNSTABLE has been set.

The plan for SPIR-V is to use a new SPIR-V assembler I wrote: https://code.ffmpeg.org/Lynne/spindle
libglslang/libshaderc will only be used as a fallback during development/debugging and will be removed once the new SPIR-V assembler is used.


>From ab754c5e8b9344dc59bed78fee6448680f506784 Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Sat, 7 Feb 2026 21:51:44 +0100
Subject: [PATCH 1/5] swscale: add a function to attach a Vulkan device

Necessary for filtering.

Sponsored-by: Sovereign Tech Fund
---
 libswscale/Makefile           |  2 ++
 libswscale/swscale.c          |  1 +
 libswscale/swscale.h          |  6 ++++++
 libswscale/swscale_internal.h |  8 ++++++++
 libswscale/utils.c            | 18 ++++++++++++++++++
 libswscale/vulkan.c           | 19 +++++++++++++++++++
 6 files changed, 54 insertions(+)
 create mode 100644 libswscale/vulkan.c

diff --git a/libswscale/Makefile b/libswscale/Makefile
index bde1144897..dc4323fef5 100644
--- a/libswscale/Makefile
+++ b/libswscale/Makefile
@@ -33,6 +33,8 @@ OBJS-$(CONFIG_UNSTABLE) +=                              \
        ops_memcpy.o                                     \
        ops_optimizer.o                                  \
 
+OBJS-$(CONFIG_VULKAN) += vulkan.o
+
 # Objects duplicated from other libraries for shared builds
 SHLIBOBJS                    += log2_tab.o half2float.o
 
diff --git a/libswscale/swscale.c b/libswscale/swscale.c
index 219382505c..77d935572a 100644
--- a/libswscale/swscale.c
+++ b/libswscale/swscale.c
@@ -34,6 +34,7 @@
 #include "config.h"
 #include "swscale_internal.h"
 #include "swscale.h"
+#include "libavutil/hwcontext_vulkan.h"
 
 DECLARE_ALIGNED(8, const uint8_t, ff_dither_8x8_128)[9][8] = {
     {  36, 68,  60, 92,  34, 66,  58, 90, },
diff --git a/libswscale/swscale.h b/libswscale/swscale.h
index 495d500f14..0847480d7f 100644
--- a/libswscale/swscale.h
+++ b/libswscale/swscale.h
@@ -262,6 +262,12 @@ SwsContext *sws_alloc_context(void);
  */
 void sws_free_context(SwsContext **ctx);
 
+/**
+ * Attach a hardware device to the context.
+ * Required to be called if either the input or output frames are hardware.
+ */
+int sws_context_attach_hwcontext(SwsContext *ctx, AVBufferRef *hwctx);
+
 /***************************
  * Supported frame formats *
  ***************************/
diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h
index 5c58272664..d5ec961d60 100644
--- a/libswscale/swscale_internal.h
+++ b/libswscale/swscale_internal.h
@@ -37,6 +37,8 @@
 #include "libavutil/pixfmt.h"
 #include "libavutil/pixdesc.h"
 #include "libavutil/slicethread.h"
+#include "libavutil/vulkan.h"
+
 #if HAVE_ALTIVEC
 #include "libavutil/ppc/util_altivec.h"
 #endif
@@ -326,6 +328,10 @@ typedef void (*planarX2_YV12_fn)(uint8_t *dst, uint8_t *dst2,
 struct SwsSlice;
 struct SwsFilterDescriptor;
 
+typedef struct SwsInternalVulkan {
+    FFVulkanContext ctx;
+} SwsInternalVulkan;
+
 /* This struct should be aligned on at least a 32-byte boundary. */
 struct SwsInternal {
     /* Currently active user-facing options. Also contains AVClass */
@@ -701,6 +707,8 @@ struct SwsInternal {
     int          color_conversion_warned;
 
     Half2FloatTables *h2f_tables;
+
+    SwsInternalVulkan vk;
 };
 //FIXME check init (where 0)
 
diff --git a/libswscale/utils.c b/libswscale/utils.c
index 52095ab2c7..b710af5891 100644
--- a/libswscale/utils.c
+++ b/libswscale/utils.c
@@ -57,6 +57,7 @@
 #include "libavutil/x86/asm.h"
 #include "libavutil/x86/cpu.h"
 #include "libavutil/loongarch/cpu.h"
+#include "config_components.h"
 
 #include "rgb2rgb.h"
 #include "swscale.h"
@@ -2252,6 +2253,20 @@ fail:
     return NULL;
 }
 
+int sws_context_attach_hwcontext(SwsContext *sws, AVBufferRef *hwctx)
+{
+#if CONFIG_VULKAN
+    SwsInternal *c = sws_internal(sws);
+    int err = ff_vk_init(&c->vk.ctx, sws, hwctx, NULL);
+    if (err < 0)
+        return err;
+
+    return 0;
+#else
+    return AVERROR(ENOTSUP);
+#endif
+}
+
 void sws_freeContext(SwsContext *sws)
 {
     SwsInternal *c = sws_internal(sws);
@@ -2330,6 +2345,9 @@ void sws_freeContext(SwsContext *sws)
     av_freep(&c->xyz_scratch);
 
     ff_free_filters(c);
+#if CONFIG_VULKAN
+    ff_vk_uninit(&c->vk.ctx);
+#endif
 
     av_free(c);
 }
diff --git a/libswscale/vulkan.c b/libswscale/vulkan.c
new file mode 100644
index 0000000000..fc8a1fa47b
--- /dev/null
+++ b/libswscale/vulkan.c
@@ -0,0 +1,19 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/vulkan.c"
-- 
2.52.0


>From f6bb5c18e8db74c1b4a0b8b4b45114113492ae89 Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Sun, 8 Feb 2026 11:21:52 +0100
Subject: [PATCH 2/5] swscale: initialize a GLSL compilation context, if
 supported

Sponsored-by: Sovereign Tech Fund
---
 libavutil/vulkan_spirv.h      |  1 +
 libswscale/Makefile           |  2 ++
 libswscale/swscale_internal.h |  2 ++
 libswscale/utils.c            | 18 ++++++++++++++++++
 libswscale/vulkan_glslang.c   | 19 +++++++++++++++++++
 libswscale/vulkan_shaderc.c   | 19 +++++++++++++++++++
 6 files changed, 61 insertions(+)
 create mode 100644 libswscale/vulkan_glslang.c
 create mode 100644 libswscale/vulkan_shaderc.c

diff --git a/libavutil/vulkan_spirv.h b/libavutil/vulkan_spirv.h
index c13b50f8e7..0bdcf8962f 100644
--- a/libavutil/vulkan_spirv.h
+++ b/libavutil/vulkan_spirv.h
@@ -22,6 +22,7 @@
 #include "vulkan.h"
 
 #include "config.h"
+#include "config_components.h"
 
 typedef struct FFVkSPIRVCompiler {
     void *priv;
diff --git a/libswscale/Makefile b/libswscale/Makefile
index dc4323fef5..217d8e4e14 100644
--- a/libswscale/Makefile
+++ b/libswscale/Makefile
@@ -34,6 +34,8 @@ OBJS-$(CONFIG_UNSTABLE) +=                              \
        ops_optimizer.o                                  \
 
 OBJS-$(CONFIG_VULKAN) += vulkan.o
+OBJS-$(CONFIG_LIBGLSLANG) += vulkan_glslang.o
+OBJS-$(CONFIG_LIBSHADERC) += vulkan_shaderc.o
 
 # Objects duplicated from other libraries for shared builds
 SHLIBOBJS                    += log2_tab.o half2float.o
diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h
index d5ec961d60..94e6f21959 100644
--- a/libswscale/swscale_internal.h
+++ b/libswscale/swscale_internal.h
@@ -38,6 +38,7 @@
 #include "libavutil/pixdesc.h"
 #include "libavutil/slicethread.h"
 #include "libavutil/vulkan.h"
+#include "libavutil/vulkan_spirv.h"
 
 #if HAVE_ALTIVEC
 #include "libavutil/ppc/util_altivec.h"
@@ -330,6 +331,7 @@ struct SwsFilterDescriptor;
 
 typedef struct SwsInternalVulkan {
     FFVulkanContext ctx;
+    FFVkSPIRVCompiler *spvc;
 } SwsInternalVulkan;
 
 /* This struct should be aligned on at least a 32-byte boundary. */
diff --git a/libswscale/utils.c b/libswscale/utils.c
index b710af5891..5716a0fb7c 100644
--- a/libswscale/utils.c
+++ b/libswscale/utils.c
@@ -2261,6 +2261,20 @@ int sws_context_attach_hwcontext(SwsContext *sws, AVBufferRef *hwctx)
     if (err < 0)
         return err;
 
+#if CONFIG_LIBSHADERC
+    c->vk.spvc = ff_vk_shaderc_init();
+    if (!c->vk.spvc) {
+        ff_vk_uninit(&c->vk.ctx);
+        return AVERROR(ENOMEM);
+    }
+#elif CONFIG_LIBGLSLANG
+    c->vk.spvc = ff_vk_glslang_init();
+    if (!c->vk.spvc) {
+        ff_vk_uninit(&c->vk.ctx);
+        return AVERROR(ENOMEM);
+    }
+#endif
+
     return 0;
 #else
     return AVERROR(ENOTSUP);
@@ -2348,6 +2362,10 @@ void sws_freeContext(SwsContext *sws)
 #if CONFIG_VULKAN
     ff_vk_uninit(&c->vk.ctx);
 #endif
+#if CONFIG_LIBSHADERC || CONFIG_LIBGLSLANG
+    if (c->vk.spvc)
+        c->vk.spvc->uninit(&c->vk.spvc);
+#endif
 
     av_free(c);
 }
diff --git a/libswscale/vulkan_glslang.c b/libswscale/vulkan_glslang.c
new file mode 100644
index 0000000000..9aa41567a3
--- /dev/null
+++ b/libswscale/vulkan_glslang.c
@@ -0,0 +1,19 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/vulkan_glslang.c"
diff --git a/libswscale/vulkan_shaderc.c b/libswscale/vulkan_shaderc.c
new file mode 100644
index 0000000000..9f60bf4dfd
--- /dev/null
+++ b/libswscale/vulkan_shaderc.c
@@ -0,0 +1,19 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/vulkan_shaderc.c"
-- 
2.52.0


>From 2e5ca59857b180602139ecb0e41a74b43660a792 Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Sun, 15 Feb 2026 16:24:21 +0100
Subject: [PATCH 3/5] lavu/vulkan: don't redefine RET, if already defined

RET is a very common name for a define that we use in some other parts
of our codebase.

Sponsored-by: Sovereign Tech Fund
---
 libavutil/vulkan.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/libavutil/vulkan.h b/libavutil/vulkan.h
index 9d1a53e2be..806c5c879d 100644
--- a/libavutil/vulkan.h
+++ b/libavutil/vulkan.h
@@ -65,11 +65,13 @@
     } while (0)
 
 /* Helper, pretty much every Vulkan return value needs to be checked */
+#ifndef RET
 #define RET(x)                                                                 \
     do {                                                                       \
         if ((err = (x)) < 0)                                                   \
             goto fail;                                                         \
     } while (0)
+#endif
 
 /* Convenience macros for specialization lists */
 #define SPEC_LIST_MAX 256
-- 
2.52.0


>From 8df59b043ad1ac0a7eea4bffc02a1cc4e84eee7c Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Sun, 15 Feb 2026 17:59:04 +0100
Subject: [PATCH 4/5] swscale: add support for outputting Vulkan frames

Sponsored-by: Sovereign Tech Fund
---
 libswscale/swscale.c          | 47 ++++++++++++++++++++++++++++++++---
 libswscale/swscale_internal.h |  2 ++
 libswscale/utils.c            |  3 +++
 3 files changed, 48 insertions(+), 4 deletions(-)

diff --git a/libswscale/swscale.c b/libswscale/swscale.c
index 77d935572a..0448e9654f 100644
--- a/libswscale/swscale.c
+++ b/libswscale/swscale.c
@@ -1210,6 +1210,32 @@ void sws_frame_end(SwsContext *sws)
     c->src_ranges.nb_ranges = 0;
 }
 
+static int sws_hwframe_ref_init(SwsContext *sws)
+{
+    int err;
+    SwsInternal *c = sws_internal(sws);
+
+    av_buffer_unref(&c->vk.hwframe_ref);
+    c->vk.hwframe_ref = av_hwframe_ctx_alloc(c->vk.ctx.device_ref);
+    if (!c->vk.hwframe_ref)
+        return AVERROR(ENOMEM);
+
+    AVHWFramesContext *hwfc = (AVHWFramesContext *)c->vk.hwframe_ref->data;
+    hwfc->format = AV_PIX_FMT_VULKAN;
+    hwfc->sw_format = sws->dst_format;
+    hwfc->width = sws->dst_w;
+    hwfc->height = sws->dst_h;
+
+    err = av_hwframe_ctx_init(c->vk.hwframe_ref);
+    if (err) {
+        av_log(sws, AV_LOG_ERROR, "AVHWFramesContext init failed: %s!\n",
+               av_err2str(err));
+        return err;
+    }
+
+    return 0;
+}
+
 int sws_frame_start(SwsContext *sws, AVFrame *dst, const AVFrame *src)
 {
     SwsInternal *c = sws_internal(sws);
@@ -1222,11 +1248,24 @@ int sws_frame_start(SwsContext *sws, AVFrame *dst, const AVFrame *src)
     if (!dst->buf[0]) {
         dst->width  = sws->dst_w;
         dst->height = sws->dst_h;
-        dst->format = sws->dst_format;
 
-        ret = av_frame_get_buffer(dst, 0);
-        if (ret < 0)
-            return ret;
+        if (c->vk.initialized) {
+            dst->format = AV_PIX_FMT_VULKAN;
+            if (!c->vk.hwframe_ref) {
+                ret = sws_hwframe_ref_init(sws);
+                if (ret < 0)
+                    return ret;
+            }
+            ret = av_hwframe_get_buffer(c->vk.hwframe_ref, dst, 0);
+            if (ret < 0)
+                return ret;
+        } else {
+            dst->format = sws->dst_format;
+            ret = av_frame_get_buffer(dst, 0);
+            if (ret < 0)
+                return ret;
+        }
+
         allocated = 1;
     }
 
diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h
index 94e6f21959..5af48b5149 100644
--- a/libswscale/swscale_internal.h
+++ b/libswscale/swscale_internal.h
@@ -332,6 +332,8 @@ struct SwsFilterDescriptor;
 typedef struct SwsInternalVulkan {
     FFVulkanContext ctx;
     FFVkSPIRVCompiler *spvc;
+    AVBufferRef *hwframe_ref;
+    int initialized;
 } SwsInternalVulkan;
 
 /* This struct should be aligned on at least a 32-byte boundary. */
diff --git a/libswscale/utils.c b/libswscale/utils.c
index 5716a0fb7c..fa184dbdbb 100644
--- a/libswscale/utils.c
+++ b/libswscale/utils.c
@@ -2275,6 +2275,8 @@ int sws_context_attach_hwcontext(SwsContext *sws, AVBufferRef *hwctx)
     }
 #endif
 
+    c->vk.initialized = 1;
+
     return 0;
 #else
     return AVERROR(ENOTSUP);
@@ -2360,6 +2362,7 @@ void sws_freeContext(SwsContext *sws)
 
     ff_free_filters(c);
 #if CONFIG_VULKAN
+    av_buffer_unref(&c->vk.hwframe_ref);
     ff_vk_uninit(&c->vk.ctx);
 #endif
 #if CONFIG_LIBSHADERC || CONFIG_LIBGLSLANG
-- 
2.52.0


>From 7ee58801be5644de8a21294b4df7e0a63d10a2c6 Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Mon, 23 Feb 2026 15:24:26 +0100
Subject: [PATCH 5/5] swscale: only enable the Vulkan code if CONFIG_UNSTABLE
 is set

Sponsored-by: Sovereign Tech Fund
---
 libswscale/swscale.c          | 7 ++++++-
 libswscale/swscale_internal.h | 4 ++++
 libswscale/utils.c            | 4 +++-
 3 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/libswscale/swscale.c b/libswscale/swscale.c
index 0448e9654f..820520e839 100644
--- a/libswscale/swscale.c
+++ b/libswscale/swscale.c
@@ -1210,6 +1210,7 @@ void sws_frame_end(SwsContext *sws)
     c->src_ranges.nb_ranges = 0;
 }
 
+#if CONFIG_UNSTABLE
 static int sws_hwframe_ref_init(SwsContext *sws)
 {
     int err;
@@ -1235,6 +1236,7 @@ static int sws_hwframe_ref_init(SwsContext *sws)
 
     return 0;
 }
+#endif
 
 int sws_frame_start(SwsContext *sws, AVFrame *dst, const AVFrame *src)
 {
@@ -1249,6 +1251,7 @@ int sws_frame_start(SwsContext *sws, AVFrame *dst, const AVFrame *src)
         dst->width  = sws->dst_w;
         dst->height = sws->dst_h;
 
+#if CONFIG_UNSTABLE
         if (c->vk.initialized) {
             dst->format = AV_PIX_FMT_VULKAN;
             if (!c->vk.hwframe_ref) {
@@ -1259,7 +1262,9 @@ int sws_frame_start(SwsContext *sws, AVFrame *dst, const AVFrame *src)
             ret = av_hwframe_get_buffer(c->vk.hwframe_ref, dst, 0);
             if (ret < 0)
                 return ret;
-        } else {
+        } else
+#endif
+        {
             dst->format = sws->dst_format;
             ret = av_frame_get_buffer(dst, 0);
             if (ret < 0)
diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h
index 5af48b5149..a671b5d3fe 100644
--- a/libswscale/swscale_internal.h
+++ b/libswscale/swscale_internal.h
@@ -329,12 +329,14 @@ typedef void (*planarX2_YV12_fn)(uint8_t *dst, uint8_t *dst2,
 struct SwsSlice;
 struct SwsFilterDescriptor;
 
+#if CONFIG_UNSTABLE
 typedef struct SwsInternalVulkan {
     FFVulkanContext ctx;
     FFVkSPIRVCompiler *spvc;
     AVBufferRef *hwframe_ref;
     int initialized;
 } SwsInternalVulkan;
+#endif
 
 /* This struct should be aligned on at least a 32-byte boundary. */
 struct SwsInternal {
@@ -712,7 +714,9 @@ struct SwsInternal {
 
     Half2FloatTables *h2f_tables;
 
+#if CONFIG_UNSTABLE
     SwsInternalVulkan vk;
+#endif
 };
 //FIXME check init (where 0)
 
diff --git a/libswscale/utils.c b/libswscale/utils.c
index fa184dbdbb..7b518596f3 100644
--- a/libswscale/utils.c
+++ b/libswscale/utils.c
@@ -2255,7 +2255,7 @@ fail:
 
 int sws_context_attach_hwcontext(SwsContext *sws, AVBufferRef *hwctx)
 {
-#if CONFIG_VULKAN
+#if CONFIG_UNSTABLE && CONFIG_VULKAN
     SwsInternal *c = sws_internal(sws);
     int err = ff_vk_init(&c->vk.ctx, sws, hwctx, NULL);
     if (err < 0)
@@ -2361,6 +2361,7 @@ void sws_freeContext(SwsContext *sws)
     av_freep(&c->xyz_scratch);
 
     ff_free_filters(c);
+#if CONFIG_UNSTABLE
 #if CONFIG_VULKAN
     av_buffer_unref(&c->vk.hwframe_ref);
     ff_vk_uninit(&c->vk.ctx);
@@ -2368,6 +2369,7 @@ void sws_freeContext(SwsContext *sws)
 #if CONFIG_LIBSHADERC || CONFIG_LIBGLSLANG
     if (c->vk.spvc)
         c->vk.spvc->uninit(&c->vk.spvc);
+#endif
 #endif
 
     av_free(c);
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org

                 reply	other threads:[~2026-02-23 15:33 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=177185745889.25.517727238862405330@29965ddac10e \
    --to=ffmpeg-devel@ffmpeg.org \
    --cc=code@ffmpeg.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

Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
		ffmpegdev@gitmailbox.com
	public-inbox-index ffmpegdev

Example config snippet for mirrors.


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git