• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #include "vulkan_filter.h"
20 
vulkan_filter_set_device(AVFilterContext * avctx,AVBufferRef * device)21 static int vulkan_filter_set_device(AVFilterContext *avctx,
22                                     AVBufferRef *device)
23 {
24     FFVulkanContext *s = avctx->priv;
25 
26     av_buffer_unref(&s->device_ref);
27 
28     s->device_ref = av_buffer_ref(device);
29     if (!s->device_ref)
30         return AVERROR(ENOMEM);
31 
32     s->device = (AVHWDeviceContext*)s->device_ref->data;
33     s->hwctx  = s->device->hwctx;
34 
35     return 0;
36 }
37 
vulkan_filter_set_frames(AVFilterContext * avctx,AVBufferRef * frames)38 static int vulkan_filter_set_frames(AVFilterContext *avctx,
39                                     AVBufferRef *frames)
40 {
41     FFVulkanContext *s = avctx->priv;
42 
43     av_buffer_unref(&s->frames_ref);
44 
45     s->frames_ref = av_buffer_ref(frames);
46     if (!s->frames_ref)
47         return AVERROR(ENOMEM);
48 
49     return 0;
50 }
51 
ff_vk_filter_config_input(AVFilterLink * inlink)52 int ff_vk_filter_config_input(AVFilterLink *inlink)
53 {
54     int err;
55     AVFilterContext *avctx = inlink->dst;
56     FFVulkanContext *s = avctx->priv;
57     FFVulkanFunctions *vk = &s->vkfn;
58     AVHWFramesContext *input_frames;
59 
60     if (!inlink->hw_frames_ctx) {
61         av_log(avctx, AV_LOG_ERROR, "Vulkan filtering requires a "
62                "hardware frames context on the input.\n");
63         return AVERROR(EINVAL);
64     }
65 
66     /* Extract the device and default output format from the first input. */
67     if (avctx->inputs[0] != inlink)
68         return 0;
69 
70     input_frames = (AVHWFramesContext *)inlink->hw_frames_ctx->data;
71     if (input_frames->format != AV_PIX_FMT_VULKAN)
72         return AVERROR(EINVAL);
73 
74     err = vulkan_filter_set_device(avctx, input_frames->device_ref);
75     if (err < 0)
76         return err;
77     err = vulkan_filter_set_frames(avctx, inlink->hw_frames_ctx);
78     if (err < 0)
79         return err;
80 
81     s->extensions = ff_vk_extensions_to_mask(s->hwctx->enabled_dev_extensions,
82                                              s->hwctx->nb_enabled_dev_extensions);
83 
84     err = ff_vk_load_functions(s->device, &s->vkfn, s->extensions, 1, 1);
85     if (err < 0)
86         return err;
87 
88     vk->GetPhysicalDeviceProperties(s->hwctx->phys_dev, &s->props);
89     vk->GetPhysicalDeviceMemoryProperties(s->hwctx->phys_dev, &s->mprops);
90 
91     /* Default output parameters match input parameters. */
92     s->input_format = input_frames->sw_format;
93     if (s->output_format == AV_PIX_FMT_NONE)
94         s->output_format = input_frames->sw_format;
95     if (!s->output_width)
96         s->output_width  = inlink->w;
97     if (!s->output_height)
98         s->output_height = inlink->h;
99 
100     return 0;
101 }
102 
ff_vk_filter_config_output_inplace(AVFilterLink * outlink)103 int ff_vk_filter_config_output_inplace(AVFilterLink *outlink)
104 {
105     int err;
106     AVFilterContext *avctx = outlink->src;
107     FFVulkanContext *s = avctx->priv;
108 
109     av_buffer_unref(&outlink->hw_frames_ctx);
110 
111     if (!s->device_ref) {
112         if (!avctx->hw_device_ctx) {
113             av_log(avctx, AV_LOG_ERROR, "Vulkan filtering requires a "
114                    "Vulkan device.\n");
115             return AVERROR(EINVAL);
116         }
117 
118         err = vulkan_filter_set_device(avctx, avctx->hw_device_ctx);
119         if (err < 0)
120             return err;
121     }
122 
123     outlink->hw_frames_ctx = av_buffer_ref(s->frames_ref);
124     if (!outlink->hw_frames_ctx)
125         return AVERROR(ENOMEM);
126 
127     outlink->w = s->output_width;
128     outlink->h = s->output_height;
129 
130     return 0;
131 }
132 
ff_vk_filter_config_output(AVFilterLink * outlink)133 int ff_vk_filter_config_output(AVFilterLink *outlink)
134 {
135     int err;
136     AVFilterContext *avctx = outlink->src;
137     FFVulkanContext *s = avctx->priv;
138     AVBufferRef *output_frames_ref;
139     AVHWFramesContext *output_frames;
140 
141     av_buffer_unref(&outlink->hw_frames_ctx);
142 
143     if (!s->device_ref) {
144         if (!avctx->hw_device_ctx) {
145             av_log(avctx, AV_LOG_ERROR, "Vulkan filtering requires a "
146                    "Vulkan device.\n");
147             return AVERROR(EINVAL);
148         }
149 
150         err = vulkan_filter_set_device(avctx, avctx->hw_device_ctx);
151         if (err < 0)
152             return err;
153     }
154 
155     output_frames_ref = av_hwframe_ctx_alloc(s->device_ref);
156     if (!output_frames_ref) {
157         err = AVERROR(ENOMEM);
158         goto fail;
159     }
160     output_frames = (AVHWFramesContext*)output_frames_ref->data;
161 
162     output_frames->format    = AV_PIX_FMT_VULKAN;
163     output_frames->sw_format = s->output_format;
164     output_frames->width     = s->output_width;
165     output_frames->height    = s->output_height;
166 
167     err = av_hwframe_ctx_init(output_frames_ref);
168     if (err < 0) {
169         av_log(avctx, AV_LOG_ERROR, "Failed to initialise output "
170                "frames: %d.\n", err);
171         goto fail;
172     }
173 
174     outlink->hw_frames_ctx = output_frames_ref;
175     outlink->w = s->output_width;
176     outlink->h = s->output_height;
177 
178     return 0;
179 fail:
180     av_buffer_unref(&output_frames_ref);
181     return err;
182 }
183 
ff_vk_filter_init(AVFilterContext * avctx)184 int ff_vk_filter_init(AVFilterContext *avctx)
185 {
186     FFVulkanContext *s = avctx->priv;
187 
188     s->output_format = AV_PIX_FMT_NONE;
189 
190     return 0;
191 }
192