Commit 108b495d87 for ffmpeg

commit 108b495d87d317cb719ed2b878aa494c2e077845
Author: TADANO Tokumei <aimingoff@pc.nifty.jp>
Date:   Sun Aug 23 01:23:56 2026 +0900

    avfilter/v360_vulkan: adjust fov parameters

    The default values of former code for h_fov, v_fov, ih_fov, iv_fov
    are constantly defined for any projection.
    This fix treats the default values as similar to v360 filter.
    It calculate the default values as suitable for each projection.

    Signed-off-by: TADANO Tokumei <aimingoff@pc.nifty.jp>

diff --git a/libavfilter/vf_v360_vulkan.c b/libavfilter/vf_v360_vulkan.c
index 8a86a880fd..4111daa6bf 100644
--- a/libavfilter/vf_v360_vulkan.c
+++ b/libavfilter/vf_v360_vulkan.c
@@ -83,6 +83,9 @@ static void multiply_matrix(float c[4][4], const float a[4][4], const float b[4]
     }
 }

+#define degree2radian(degree) ((degree) * M_PI / 180.f)
+#define radian2degree(radian) ((radian) * 180.f / M_PI)
+
 static inline void calculate_iflat_range(int in, float ih_fov, float iv_fov,
                                          float *iflat_range)
 {
@@ -161,10 +164,102 @@ static inline void calculate_rotation_matrix(float yaw, float pitch, float roll,
     multiply_matrix(rot_mat, temp, m[rotation_order[2]]);
 }

-static void config_params(AVFilterContext *ctx)
+static void config_params(AVFilterContext *ctx, AVFilterLink *inlink)
 {
     V360VulkanContext *s = ctx->priv;

+    switch (s->in) {
+    case FLAT: {
+        float sar = inlink->sample_aspect_ratio.num ?
+                    (float) inlink->sample_aspect_ratio.num / inlink->sample_aspect_ratio.den : 1;
+        if (s->ih_fov == 0.f && s->iv_fov == 0.f) {
+            s->ih_fov = 90.f;
+            s->iv_fov = radian2degree(2.f * atanf((float)inlink->h / sar / inlink->w));
+        }
+        else if (s->ih_fov == 0.f || s->ih_fov >= 180.f) {
+            if (s->iv_fov >= 180.f)
+                s->ih_fov = s->iv_fov = 180.f;
+            else
+                s->iv_fov = radian2degree(2.f * atanf((float)inlink->h / sar / inlink->w * tanf(degree2radian(s->ih_fov) / 2.f)));
+        }
+        else if (s->iv_fov == 0.f || s->iv_fov >= 180.f) {
+            if (s->ih_fov >= 180.f)
+                s->ih_fov = s->iv_fov = 180.f;
+            else
+                s->ih_fov = radian2degree(2.f * atanf((float)inlink->w * sar / inlink->h * tanf(degree2radian(s->iv_fov) / 2.f)));
+        }
+        break;
+    }
+    case STEREOGRAPHIC:
+    case DUAL_FISHEYE:
+    case FISHEYE:
+        if (s->ih_fov == 0.f)
+            s->ih_fov = 180.f;
+        if (s->iv_fov == 0.f)
+            s->iv_fov = 180.f;
+        break;
+    case EQUIRECTANGULAR: /* unchangeable */
+        s->ih_fov = 360.f;
+        s->iv_fov = 180.f;
+        break;
+    default:
+        if (s->ih_fov == 0.f)
+            s->ih_fov = 360.f;
+        if (s->iv_fov == 0.f)
+            s->iv_fov = 180.f;
+        break;
+    }
+
+    switch (s->out) {
+    case FLAT:
+        if (s->width > 0 && s->height > 0 &&
+            (s->h_fov == 0.f || s->h_fov >= 180.f || s->v_fov == 0.f || s->v_fov >= 180.f)) {
+            if (s->h_fov == 0.f && s->v_fov == 0.f) {
+                s->h_fov = 90.f;
+                s->v_fov = radian2degree(2.f * atanf((float)s->height / s->width));
+            }
+            else if (s->h_fov == 0.f || s->h_fov >= 180.f) {
+                if (s->v_fov >= 180.f)
+                    s->h_fov = s->v_fov = 180.f;
+                else
+                    s->v_fov = radian2degree(2.f * atanf((float)s->height / s->width * tanf(degree2radian(s->h_fov) / 2.f)));
+            }
+            else if (s->v_fov == 0.f || s->v_fov >= 180.f) {
+                if (s->h_fov >= 180.f)
+                    s->h_fov = s->v_fov = 180.f;
+                else
+                    s->h_fov = radian2degree(2.f * atanf((float)s->width / s->height * tanf(degree2radian(s->v_fov) / 2.f)));
+            }
+        }
+        else {
+            if (s->h_fov >= 180.f || s->v_fov >= 180.f) {
+                s->h_fov = 180.f;
+                s->v_fov = 180.f;
+            }
+            else {
+                if (s->h_fov == 0.f)
+                    s->h_fov = 90.f;
+                if (s->v_fov == 0.f)
+                    s->v_fov = 45.f;
+            }
+        }
+        break;
+    case STEREOGRAPHIC:
+    case DUAL_FISHEYE:
+    case FISHEYE:
+        if (s->h_fov == 0.f)
+            s->h_fov = 180.f;
+        if (s->v_fov == 0.f)
+            s->v_fov = 180.f;
+        break;
+    default:
+        if (s->h_fov == 0.f)
+            s->h_fov = 360.f;
+        if (s->v_fov == 0.f)
+            s->v_fov = 180.f;
+        break;
+    }
+
     for (int order = 0; order < NB_RORDERS; order++) {
         const char c = s->rorder[order];
         int rorder;
@@ -308,9 +403,10 @@ static int process_command(AVFilterContext *ctx, const char *cmd, const char *ar
                            char *res, int res_len, int flags)
 {
     int err;
+    AVFilterLink *inlink = ctx->inputs[0];

     RET(ff_filter_process_command(ctx, cmd, args, res, res_len, flags));
-    config_params(ctx);
+    config_params(ctx, inlink);

 fail:
     return err;
@@ -320,8 +416,9 @@ static av_cold int v360_vulkan_config_output(AVFilterLink *outlink)
 {
     int err;
     AVFilterContext *ctx = outlink->src;
+    AVFilterLink *inlink = ctx->inputs[0];

-    config_params(ctx);
+    config_params(ctx, inlink);

     RET(ff_vk_filter_config_output(outlink));

@@ -373,10 +470,10 @@ static const AVOption v360_vulkan_options[] = {
     {     "pitch", "pitch rotation",                   OFFSET(pitch), AV_OPT_TYPE_FLOAT,  {.dbl = 0.0f},     -180.f,               180.f, DYNAMIC, "pitch" },
     {      "roll", "roll rotation",                     OFFSET(roll), AV_OPT_TYPE_FLOAT,  {.dbl = 0.0f},     -180.f,               180.f, DYNAMIC, "roll" },
     {    "rorder", "rotation order",                  OFFSET(rorder), AV_OPT_TYPE_STRING, {.str = "ypr"},         0,                   0, DYNAMIC, "rorder" },
-    {     "h_fov", "set output horizontal FOV angle",  OFFSET(h_fov), AV_OPT_TYPE_FLOAT,  {.dbl = 90.0f},  0.00001f,              360.0f, DYNAMIC, "h_fov" },
-    {     "v_fov", "set output vertical FOV angle",    OFFSET(v_fov), AV_OPT_TYPE_FLOAT,  {.dbl = 45.0f},  0.00001f,              360.0f, DYNAMIC, "v_fov" },
-    {    "ih_fov", "set input horizontal FOV angle",  OFFSET(ih_fov), AV_OPT_TYPE_FLOAT,  {.dbl = 90.0f},  0.00001f,              360.0f, DYNAMIC, "ih_fov" },
-    {    "iv_fov", "set input vertical FOV angle",    OFFSET(iv_fov), AV_OPT_TYPE_FLOAT,  {.dbl = 45.0f},  0.00001f,              360.0f, DYNAMIC, "iv_fov" },
+    {     "h_fov", "set output horizontal FOV angle",  OFFSET(h_fov), AV_OPT_TYPE_FLOAT,  {.dbl = 0.0f},       0.0f,              360.0f, DYNAMIC, "h_fov" },
+    {     "v_fov", "set output vertical FOV angle",    OFFSET(v_fov), AV_OPT_TYPE_FLOAT,  {.dbl = 0.0f},       0.0f,              360.0f, DYNAMIC, "v_fov" },
+    {    "ih_fov", "set input horizontal FOV angle",  OFFSET(ih_fov), AV_OPT_TYPE_FLOAT,  {.dbl = 0.0f},       0.0f,              360.0f, DYNAMIC, "ih_fov" },
+    {    "iv_fov", "set input vertical FOV angle",    OFFSET(iv_fov), AV_OPT_TYPE_FLOAT,  {.dbl = 0.0f},       0.0f,              360.0f, DYNAMIC, "iv_fov" },

     { NULL },
 };