前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Vulkan 在 FFmpeg 中的支持

Vulkan 在 FFmpeg 中的支持

作者头像
音视频开发进阶
发布2022-03-11 20:48:21
1.3K0
发布2022-03-11 20:48:21
举报
文章被收录于专栏:进击的多媒体开发

周末时候看到一篇推送说 FFmpeg 升级到 5.0 版本了。

其中提到 FFmpeg 引入了 Vulkan 驱动的新滤镜,用于视频水平、垂直翻转。

看到 FFmpeg 引入了 Vulkan ,想着这是要有什么大动作啊,直接利好 Vulkan 嘛?

后来又仔细看了下 FFmpeg 的 Changelog ,原来早在 4.3 版本就已经开始支持 Vulkan 了。

那时候就已经有滤镜支持了,比如 scale_vulkan、chromaber_vulkan 等。

而且还支持在 Linux 平台上通过 Vulkan 使用 AMD 的高级媒体框架(AMF)库,可以用 GPU 来进行 H.264/HEVC 的编码。(Windows 平台用的是 DirectX 接口)

这里提一下 AMF 框架,实际上我也是第一次接触这个。

AMF 全称是 Advanced Media Framework ,翻译为高级媒体框架。它是 AMD 公司出品的,为开发人员提供对 GPU 的访问以进行多媒体处理,通过 AMF 可以进行视频编解码、转码、色彩空间转换等功能。

简单说就是提供了对自家显卡产品能力的调用,可以用它来做编解码的工作。既然 AMD 有了,那么相信 NVIDIA 也有类似的产品。

由此可见后面的趋势:渲染 API 不仅仅是用来做渲染,还是可以用做编解码的,毕竟它是可以直接和 GPU 打交道的。

所以 FFmpeg 5.0 中引入了 Vulkan 新滤镜应该也不是什么大新闻了,毕竟在 4.3 版本就已经有了支持,只是多了几个滤镜,按照开发人员的话来说,就是多了几个 shader 嘛

接下来就看看这几个新增的 翻转shader 有何不同之处:

如果不了解 Vulkan 流程的话,建议看看 Vulkan 相关的文章,毕竟这里面概念挺多的,但很多流程还是固定的,只要抓到重点就好了。

大概的流程:Vulkan 作为 FFmpeg 中的一个滤镜,那么它肯定要接收代表解码后的 AVFrame 数据,通过将 AVFrame 数据转换为它渲染链结构的输入,经过渲染后,将渲染结果转换为 AVFrame 数据并往下进行传递。

理解上面的流程,剩下的就是去理解 Vulkan 的渲染链了。

核心代码如下:

代码语言:javascript
复制
static int process_frames(AVFilterContext *avctx, AVFrame *outframe, AVFrame *inframe)
{
    // 省略起始代码
    // 得到输入数据
    AVVkFrame *in = (AVVkFrame *)inframe->data[0];
    AVVkFrame *out = (AVVkFrame *)outframe->data[0];
    const int planes = av_pix_fmt_count_planes(s->vkctx.output_format);
    const VkFormat *input_formats = av_vkfmt_from_pixfmt(s->vkctx.input_format);
    const VkFormat *output_formats = av_vkfmt_from_pixfmt(s->vkctx.output_format);

    ff_vk_start_exec_recording(vkctx, s->exec);
    cmd_buf = ff_vk_get_exec_buf(s->exec);

    for (int i = 0; i < planes; i++) {
        // 将输入数据绑定到 ImageView 上
        RET(ff_vk_create_imageview(vkctx, s->exec,
                                   &s->input_images[i].imageView, in->img[i],
                                   input_formats[i],
                                   ff_comp_identity_map));

        RET(ff_vk_create_imageview(vkctx, s->exec,
                                   &s->output_images[i].imageView, out->img[i],
                                   output_formats[i],
                                   ff_comp_identity_map));

        s->input_images[i].imageLayout  = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
        s->output_images[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
    }
    // 绑定资源描述符
    ff_vk_update_descriptor_set(vkctx, s->pl, 0);
    // 设置好内存屏障
    for (int i = 0; i < planes; i++) {
        // 省略一大串代码
        vk->CmdPipelineBarrier(cmd_buf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
                               VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0,
                               0, NULL, 0, NULL, FF_ARRAY_ELEMS(barriers), barriers);
        // 省略一大串代码
    }
    // 设置好 pipeline 和 资源描述符集 descriptorSet
    ff_vk_bind_pipeline_exec(vkctx, s->exec, s->pl);
    vk->CmdDispatch(cmd_buf, FFALIGN(s->vkctx.output_width, CGS)/CGS,
                    s->vkctx.output_height, 1);

    ff_vk_add_exec_dep(vkctx, s->exec, inframe, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
    ff_vk_add_exec_dep(vkctx, s->exec, outframe, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
    // 提交到队列
    err = ff_vk_submit_exec_queue(vkctx, s->exec);
    if (err)
        return err;
    ff_vk_qf_rotate(&s->qf);
    return 0;
}

以上代码要是看的费劲的话,还是只看核心的 shader 部分吧:

可以看出,做水平或者垂直翻转也只是更改了 texture 采样坐标而已,如果你会 OpenGL 的话,一样可以做出类似的 filter 。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-01-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 音视频开发进阶 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
多媒体处理
多媒体处理(Multimedia Processing,MMP)是数据万象推出的音视频处理服务,集成音视频转码、极速高清、精彩集锦、超分辨率、数字水印等能力,满足传媒、文旅、电商等各行业多媒体处理需求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档