Vulkan 在 FFmpeg 中的支持
周末時(shí)候看到一篇推送說(shuō) FFmpeg 升級(jí)到 5.0 版本了。
其中提到 FFmpeg 引入了 Vulkan 驅(qū)動(dòng)的新濾鏡,用于視頻水平、垂直翻轉(zhuǎn)。
看到 FFmpeg 引入了 Vulkan ,想著這是要有什么大動(dòng)作啊,直接利好 Vulkan 嘛?
后來(lái)又仔細(xì)看了下 FFmpeg 的 Changelog ,原來(lái)早在 4.3 版本就已經(jīng)開(kāi)始支持 Vulkan 了。


那時(shí)候就已經(jīng)有濾鏡支持了,比如 scale_vulkan、chromaber_vulkan 等。
而且還支持在 Linux 平臺(tái)上通過(guò) Vulkan 使用 AMD 的高級(jí)媒體框架(AMF)庫(kù),可以用 GPU 來(lái)進(jìn)行 H.264/HEVC 的編碼。(Windows 平臺(tái)用的是 DirectX 接口)
這里提一下 AMF 框架,實(shí)際上我也是第一次接觸這個(gè)。
AMF 全稱(chēng)是 Advanced Media Framework ,翻譯為高級(jí)媒體框架。它是 AMD 公司出品的,為開(kāi)發(fā)人員提供對(duì) GPU 的訪問(wèn)以進(jìn)行多媒體處理,通過(guò) AMF 可以進(jìn)行視頻編解碼、轉(zhuǎn)碼、色彩空間轉(zhuǎn)換等功能。
簡(jiǎn)單說(shuō)就是提供了對(duì)自家顯卡產(chǎn)品能力的調(diào)用,可以用它來(lái)做編解碼的工作。既然 AMD 有了,那么相信 NVIDIA 也有類(lèi)似的產(chǎn)品。
由此可見(jiàn)后面的趨勢(shì):渲染 API 不僅僅是用來(lái)做渲染,還是可以用做編解碼的,畢竟它是可以直接和 GPU 打交道的。
所以 FFmpeg 5.0 中引入了 Vulkan 新濾鏡應(yīng)該也不是什么大新聞了,畢竟在 4.3 版本就已經(jīng)有了支持,只是多了幾個(gè)濾鏡,按照開(kāi)發(fā)人員的話來(lái)說(shuō),就是多了幾個(gè) shader 嘛。
接下來(lái)就看看這幾個(gè)新增的 翻轉(zhuǎn)shader 有何不同之處:
如果不了解 Vulkan 流程的話,建議看看 Vulkan 相關(guān)的文章,畢竟這里面概念挺多的,但很多流程還是固定的,只要抓到重點(diǎn)就好了。
推薦看看如下內(nèi)容,預(yù)先了解一下:
用 Vulkan 渲染寫(xiě)一個(gè) Android GPUImage
【建議收藏】30 分鐘入門(mén) Vulkan (中文翻譯版)
進(jìn)擊的 Vulkan 移動(dòng)開(kāi)發(fā)(一)之今生前世
送書(shū),送書(shū)《Vulkan學(xué)習(xí)指南》
大概的流程:Vulkan 作為 FFmpeg 中的一個(gè)濾鏡,那么它肯定要接收代表解碼后的 AVFrame 數(shù)據(jù),通過(guò)將 AVFrame 數(shù)據(jù)轉(zhuǎn)換為它渲染鏈結(jié)構(gòu)的輸入,經(jīng)過(guò)渲染后,將渲染結(jié)果轉(zhuǎn)換為 AVFrame 數(shù)據(jù)并往下進(jìn)行傳遞。
理解上面的流程,剩下的就是去理解 Vulkan 的渲染鏈了。
核心代碼如下:
static?int?process_frames(AVFilterContext?*avctx,?AVFrame?*outframe,?AVFrame?*inframe)
{
????//?省略起始代碼
????//?得到輸入數(shù)據(jù)
????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?????????//?將輸入數(shù)據(jù)綁定到?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);
????//?設(shè)置好內(nèi)存屏障
????for?(int?i?=?0;?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);
????????//?省略一大串代碼
????}
????//?設(shè)置好?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);
????//?提交到隊(duì)列
????err?=?ff_vk_submit_exec_queue(vkctx,?s->exec);
????if?(err)
????????return?err;
????ff_vk_qf_rotate(&s->qf);
????return?0;
}
以上代碼要是看的費(fèi)勁的話,還是只看核心的 shader 部分吧:

可以看出,做水平或者垂直翻轉(zhuǎn)也只是更改了 texture 采樣坐標(biāo)而已,如果你會(huì) OpenGL 的話,一樣可以做出類(lèi)似的 filter 。

技術(shù)問(wèn)答,學(xué)習(xí)成長(zhǎng),歡迎加入音視頻開(kāi)發(fā)進(jìn)階知識(shí)星球
技術(shù)交流,歡迎加我微信:ezglumes ,拉你入技術(shù)交流群。
私信領(lǐng)取相關(guān)資料
推薦閱讀:
音視頻開(kāi)發(fā)工作經(jīng)驗(yàn)分享 || 視頻版
開(kāi)通專(zhuān)輯 | 細(xì)數(shù)那些年寫(xiě)過(guò)的技術(shù)文章專(zhuān)輯
Android NDK 免費(fèi)視頻在線學(xué)習(xí)?。?!
你想要的音視頻開(kāi)發(fā)資料庫(kù)來(lái)了
推薦幾個(gè)堪稱(chēng)教科書(shū)級(jí)別的 Android 音視頻入門(mén)項(xiàng)目
覺(jué)得不錯(cuò),點(diǎn)個(gè)在看唄~

