| 937 | } |
| 938 | |
| 939 | static FilterGraph BuildVulkanDirectTransformGraph(AVBufferRef* main_hw_frames_context, |
| 940 | double fps, |
| 941 | int input_width, |
| 942 | int input_height) { |
| 943 | FilterGraph filter_graph; |
| 944 | filter_graph.graph = avfilter_graph_alloc(); |
| 945 | if (!filter_graph.graph) |
| 946 | throw std::runtime_error("Unable to allocate direct Vulkan filter graph"); |
| 947 | |
| 948 | const AVFilter* buffer_filter = avfilter_get_by_name("buffer"); |
| 949 | const AVFilter* hflip_filter = avfilter_get_by_name("hflip_vulkan"); |
| 950 | const AVFilter* sink_filter = avfilter_get_by_name("buffersink"); |
| 951 | if (!buffer_filter || !hflip_filter || !sink_filter) |
| 952 | throw std::runtime_error("Required direct Vulkan filters are not available"); |
| 953 | |
| 954 | std::ostringstream args; |
| 955 | args << "video_size=" << input_width << "x" << input_height |
| 956 | << ":pix_fmt=" << AV_PIX_FMT_VULKAN |
| 957 | << ":time_base=1/" << std::max(1, static_cast<int>(std::lround(fps))) |
| 958 | << ":pixel_aspect=1/1"; |
| 959 | CheckAv(avfilter_graph_create_filter(&filter_graph.main_source, buffer_filter, "main_in", |
| 960 | args.str().c_str(), nullptr, filter_graph.graph), |
| 961 | "avfilter_graph_create_filter direct main source"); |
| 962 | CheckAv(avfilter_graph_create_filter(&filter_graph.sink, sink_filter, "sink", |
| 963 | nullptr, nullptr, filter_graph.graph), |
| 964 | "avfilter_graph_create_filter direct sink"); |
| 965 | |
| 966 | AVBufferSrcParameters* main_params = av_buffersrc_parameters_alloc(); |
| 967 | if (!main_params) |
| 968 | throw std::runtime_error("Unable to allocate direct buffer source parameters"); |
| 969 | main_params->format = AV_PIX_FMT_VULKAN; |
| 970 | main_params->width = input_width; |
| 971 | main_params->height = input_height; |
| 972 | main_params->time_base = AVRational{1, std::max(1, static_cast<int>(std::lround(fps)))}; |
| 973 | main_params->hw_frames_ctx = av_buffer_ref(main_hw_frames_context); |
| 974 | CheckAv(av_buffersrc_parameters_set(filter_graph.main_source, main_params), |
| 975 | "av_buffersrc_parameters_set direct main"); |
| 976 | av_free(main_params); |
| 977 | |
| 978 | AVFilterContext* transform = nullptr; |
| 979 | CheckAv(avfilter_graph_create_filter(&transform, hflip_filter, "hflip", |
| 980 | nullptr, nullptr, filter_graph.graph), |
| 981 | "avfilter_graph_create_filter direct hflip"); |
| 982 | CheckAv(avfilter_link(filter_graph.main_source, 0, transform, 0), "avfilter_link direct main"); |
| 983 | CheckAv(avfilter_link(transform, 0, filter_graph.sink, 0), "avfilter_link direct sink"); |
| 984 | CheckAv(avfilter_graph_config(filter_graph.graph, nullptr), "avfilter_graph_config direct"); |
| 985 | return filter_graph; |
| 986 | } |
| 987 | |
| 988 | static std::vector<uint32_t> LoadSpirvFile(const std::string& path) { |
| 989 | std::ifstream stream(path, std::ios::binary | std::ios::ate); |