diff options
author | Lynne <dev@lynne.ee> | 2025-07-11 21:23:24 +0900 |
---|---|---|
committer | Lynne <dev@lynne.ee> | 2025-08-08 01:06:11 +0900 |
commit | b8c92e2893109a8faa52f0e88e94d34f9995caf0 (patch) | |
tree | 3572834a46b97ec000a360cfa6263955deaea2d8 /libavfilter/vf_scale_vulkan.c | |
parent | bc327222e52f7c416233e561dfb33e4bd1eba3ff (diff) | |
download | ffmpeg-b8c92e2893109a8faa52f0e88e94d34f9995caf0.tar.gz |
scale_vulkan: add support for basic Debayering
Diffstat (limited to 'libavfilter/vf_scale_vulkan.c')
-rw-r--r-- | libavfilter/vf_scale_vulkan.c | 64 |
1 files changed, 60 insertions, 4 deletions
diff --git a/libavfilter/vf_scale_vulkan.c b/libavfilter/vf_scale_vulkan.c index 46b1476933..9d550c5180 100644 --- a/libavfilter/vf_scale_vulkan.c +++ b/libavfilter/vf_scale_vulkan.c @@ -27,6 +27,8 @@ #include "colorspace.h" #include "video.h" +extern const char *ff_source_debayer_comp; + enum ScalerFunc { F_BILINEAR = 0, F_NEAREST, @@ -34,6 +36,13 @@ enum ScalerFunc { F_NB, }; +enum DebayerFunc { + DB_BILINEAR = 0, + DB_BILINEAR_HQ, + + DB_NB, +}; + typedef struct ScaleVulkanContext { FFVulkanContext vkctx; @@ -58,6 +67,7 @@ typedef struct ScaleVulkanContext { enum ScalerFunc scaler; enum AVColorRange out_range; + enum DebayerFunc debayer; } ScaleVulkanContext; static const char scale_bilinear[] = { @@ -184,6 +194,25 @@ static int init_scale_shader(ScaleVulkanContext *s, FFVulkanShader *shd, return 0; } +static int init_debayer_shader(ScaleVulkanContext *s, FFVulkanShader *shd, + FFVulkanDescriptorSetBinding *desc, AVFrame *in) +{ + GLSLD(ff_source_debayer_comp); + + GLSLC(0, void main(void)); + GLSLC(0, { ); + if (s->debayer == DB_BILINEAR) + GLSLC(1, debayer_bilinear();); + else if (s->debayer == DB_BILINEAR_HQ) + GLSLC(1, debayer_bilinear_hq();); + GLSLC(0, } ); + + shd->lg_size[0] <<= 1; + shd->lg_size[1] <<= 1; + + return 0; +} + static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) { int err; @@ -197,6 +226,7 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) FFVkSPIRVCompiler *spv; FFVulkanDescriptorSetBinding *desc; + int debayer = s->vkctx.input_format == AV_PIX_FMT_BAYER_RGGB16; int in_planes = av_pix_fmt_count_planes(s->vkctx.input_format); switch (s->scaler) { @@ -222,7 +252,10 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) } RET(ff_vk_exec_pool_init(vkctx, s->qf, &s->e, s->qf->num*4, 0, 0, 0, NULL)); - RET(ff_vk_init_sampler(vkctx, &s->sampler, 0, sampler_mode)); + + if (!debayer) + RET(ff_vk_init_sampler(vkctx, &s->sampler, 0, sampler_mode)); + RET(ff_vk_shader_init(vkctx, &s->shd, "scale", VK_SHADER_STAGE_COMPUTE_BIT, NULL, 0, @@ -232,7 +265,13 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) desc = (FFVulkanDescriptorSetBinding []) { { .name = "input_img", - .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .type = debayer ? + VK_DESCRIPTOR_TYPE_STORAGE_IMAGE : + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .mem_layout = debayer ? + ff_vk_shader_rep_fmt(s->vkctx.input_format, FF_VK_REP_FLOAT) : + NULL, + .mem_quali = "readonly", .dimensions = 2, .elems = in_planes, .stages = VK_SHADER_STAGE_COMPUTE_BIT, @@ -263,7 +302,10 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) ff_vk_shader_add_push_const(&s->shd, 0, sizeof(s->opts), VK_SHADER_STAGE_COMPUTE_BIT); - err = init_scale_shader(s, shd, desc, in); + if (debayer) + err = init_debayer_shader(s, shd, desc, in); + else + err = init_scale_shader(s, shd, desc, in); if (err < 0) goto fail; @@ -361,7 +403,18 @@ static int scale_vulkan_config_output(AVFilterLink *outlink) s->vkctx.output_format = s->vkctx.input_format; } - if (s->vkctx.output_format != s->vkctx.input_format) { + if (s->vkctx.input_format == AV_PIX_FMT_BAYER_RGGB16) { + if (s->vkctx.output_format == s->vkctx.input_format) { + s->vkctx.output_format = AV_PIX_FMT_RGBA64; + } else if (!ff_vk_mt_is_np_rgb(s->vkctx.output_format)) { + av_log(avctx, AV_LOG_ERROR, "Unsupported output format for debayer\n"); + return AVERROR(EINVAL); + } + if (inlink->w != outlink->w || inlink->w != outlink->w) { + av_log(avctx, AV_LOG_ERROR, "Scaling is not supported with debayering\n"); + return AVERROR_PATCHWELCOME; + } + } else if (s->vkctx.output_format != s->vkctx.input_format) { if (!ff_vk_mt_is_np_rgb(s->vkctx.input_format)) { av_log(avctx, AV_LOG_ERROR, "Unsupported input format for conversion\n"); return AVERROR(EINVAL); @@ -406,6 +459,9 @@ static const AVOption scale_vulkan_options[] = { { "scaler", "Scaler function", OFFSET(scaler), AV_OPT_TYPE_INT, {.i64 = F_BILINEAR}, 0, F_NB, .flags = FLAGS, .unit = "scaler" }, { "bilinear", "Bilinear interpolation (fastest)", 0, AV_OPT_TYPE_CONST, {.i64 = F_BILINEAR}, 0, 0, .flags = FLAGS, .unit = "scaler" }, { "nearest", "Nearest (useful for pixel art)", 0, AV_OPT_TYPE_CONST, {.i64 = F_NEAREST}, 0, 0, .flags = FLAGS, .unit = "scaler" }, + { "debayer", "Debayer algorithm to use", OFFSET(debayer), AV_OPT_TYPE_INT, {.i64 = DB_BILINEAR_HQ}, 0, DB_NB, .flags = FLAGS, .unit = "debayer" }, + { "bilinear", "Bilinear debayering (fastest)", 0, AV_OPT_TYPE_CONST, {.i64 = DB_BILINEAR}, 0, 0, .flags = FLAGS, .unit = "debayer" }, + { "bilinear_hq", "Bilinear debayering (high quality)", 0, AV_OPT_TYPE_CONST, {.i64 = DB_BILINEAR_HQ}, 0, 0, .flags = FLAGS, .unit = "debayer" }, { "format", "Output video format (software format of hardware frames)", OFFSET(out_format_string), AV_OPT_TYPE_STRING, .flags = FLAGS }, { "out_range", "Output colour range (from 0 to 2) (default 0)", OFFSET(out_range), AV_OPT_TYPE_INT, {.i64 = AVCOL_RANGE_UNSPECIFIED}, AVCOL_RANGE_UNSPECIFIED, AVCOL_RANGE_JPEG, .flags = FLAGS, .unit = "range" }, { "full", "Full range", 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_JPEG }, 0, 0, FLAGS, .unit = "range" }, |