FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavfilter/vf_stack_vaapi.c
Date: 2024-05-03 05:27:13
Exec Total Coverage
Lines: 0 112 0.0%
Functions: 0 5 0.0%
Branches: 0 48 0.0%

Line Branch Exec Source
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 /**
20 * @file
21 * Hardware accelerated hstack, vstack and xstack filters based on VA-API
22 */
23
24 #include "config_components.h"
25
26 #include "libavutil/opt.h"
27 #include "libavutil/common.h"
28 #include "libavutil/pixdesc.h"
29 #include "libavutil/eval.h"
30 #include "libavutil/hwcontext.h"
31 #include "libavutil/avstring.h"
32 #include "libavutil/avassert.h"
33 #include "libavutil/imgutils.h"
34 #include "libavutil/mathematics.h"
35 #include "libavutil/parseutils.h"
36 #include "libavutil/mem.h"
37
38 #include "internal.h"
39 #include "filters.h"
40 #include "formats.h"
41 #include "video.h"
42 #include "framesync.h"
43 #include "vaapi_vpp.h"
44
45 #define HSTACK_NAME "hstack_vaapi"
46 #define VSTACK_NAME "vstack_vaapi"
47 #define XSTACK_NAME "xstack_vaapi"
48 #define HWContext VAAPIVPPContext
49 #define StackHWContext StackVAAPIContext
50 #include "stack_internal.h"
51
52 typedef struct StackVAAPIContext {
53 StackBaseContext base;
54
55 VARectangle *rects;
56 } StackVAAPIContext;
57
58 static int process_frame(FFFrameSync *fs)
59 {
60 AVFilterContext *avctx = fs->parent;
61 AVFilterLink *outlink = avctx->outputs[0];
62 StackVAAPIContext *sctx = fs->opaque;
63 VAAPIVPPContext *vppctx = fs->opaque;
64 AVFrame *oframe, *iframe;
65 VAProcPipelineParameterBuffer *params = NULL;
66 VARectangle *irect = NULL;
67 int ret = 0;
68
69 if (vppctx->va_context == VA_INVALID_ID)
70 return AVERROR(EINVAL);
71
72 oframe = ff_get_video_buffer(outlink, outlink->w, outlink->h);
73 if (!oframe)
74 return AVERROR(ENOMEM);
75
76 irect = av_calloc(avctx->nb_inputs, sizeof(*irect));
77 params = av_calloc(avctx->nb_inputs, sizeof(*params));
78 if (!irect || !params) {
79 ret = AVERROR(ENOMEM);
80 goto fail;
81 }
82
83 for (int i = 0; i < avctx->nb_inputs; i++) {
84 ret = ff_framesync_get_frame(fs, i, &iframe, 0);
85 if (ret)
86 goto fail;
87
88 if (i == 0) {
89 ret = av_frame_copy_props(oframe, iframe);
90 if (ret < 0)
91 goto fail;
92 }
93
94 ret = ff_vaapi_vpp_init_params(avctx, &params[i], iframe, oframe);
95 if (ret)
96 goto fail;
97
98 av_log(avctx, AV_LOG_DEBUG, "stack input %d: %s, %ux%u (%"PRId64").\n",
99 i, av_get_pix_fmt_name(iframe->format),
100 iframe->width, iframe->height, iframe->pts);
101 irect[i].x = 0;
102 irect[i].y = 0;
103 irect[i].width = iframe->width;
104 irect[i].height = iframe->height;
105 params[i].surface_region = &irect[i];
106 params[i].surface = (VASurfaceID)(uintptr_t)iframe->data[3];
107 params[i].output_region = &sctx->rects[i];
108
109 if (sctx->base.fillcolor_enable)
110 params[i].output_background_color = (sctx->base.fillcolor[3] << 24 |
111 sctx->base.fillcolor[0] << 16 |
112 sctx->base.fillcolor[1] << 8 |
113 sctx->base.fillcolor[2]);
114 }
115
116 oframe->pts = av_rescale_q(sctx->base.fs.pts, sctx->base.fs.time_base, outlink->time_base);
117 oframe->sample_aspect_ratio = outlink->sample_aspect_ratio;
118
119 ret = ff_vaapi_vpp_render_pictures(avctx, params, avctx->nb_inputs, oframe);
120 if (ret)
121 goto fail;
122
123 av_freep(&irect);
124 av_freep(&params);
125 return ff_filter_frame(outlink, oframe);
126
127 fail:
128 av_freep(&irect);
129 av_freep(&params);
130 av_frame_free(&oframe);
131 return ret;
132 }
133
134 static int config_output(AVFilterLink *outlink)
135 {
136 AVFilterContext *avctx = outlink->src;
137 StackVAAPIContext *sctx = avctx->priv;
138 VAAPIVPPContext *vppctx = avctx->priv;
139 AVFilterLink *inlink0 = avctx->inputs[0];
140 AVHWFramesContext *hwfc0 = NULL;
141 int ret;
142
143 if (inlink0->format != AV_PIX_FMT_VAAPI || !inlink0->hw_frames_ctx || !inlink0->hw_frames_ctx->data) {
144 av_log(avctx, AV_LOG_ERROR, "Software pixel format is not supported.\n");
145 return AVERROR(EINVAL);
146 }
147
148 hwfc0 = (AVHWFramesContext *)inlink0->hw_frames_ctx->data;
149
150 for (int i = 1; i < sctx->base.nb_inputs; i++) {
151 AVFilterLink *inlink = avctx->inputs[i];
152 AVHWFramesContext *hwfc = NULL;
153
154 if (inlink->format != AV_PIX_FMT_VAAPI || !inlink->hw_frames_ctx || !inlink->hw_frames_ctx->data) {
155 av_log(avctx, AV_LOG_ERROR, "Software pixel format is not supported.\n");
156 return AVERROR(EINVAL);
157 }
158
159 hwfc = (AVHWFramesContext *)inlink->hw_frames_ctx->data;
160
161 if (hwfc0->sw_format != hwfc->sw_format) {
162 av_log(avctx, AV_LOG_ERROR, "All inputs should have the same underlying software pixel format.\n");
163 return AVERROR(EINVAL);
164 }
165
166 if (hwfc0->device_ctx != hwfc->device_ctx) {
167 av_log(avctx, AV_LOG_ERROR, "All inputs should have the same underlying vaapi devices.\n");
168 return AVERROR(EINVAL);
169 }
170 }
171
172 ff_vaapi_vpp_config_input(inlink0);
173 vppctx->output_format = hwfc0->sw_format;
174
175 ret = config_comm_output(outlink);
176 if (ret < 0)
177 return ret;
178
179 for (int i = 0; i < sctx->base.nb_inputs; i++) {
180 sctx->rects[i].x = sctx->base.regions[i].x;
181 sctx->rects[i].y = sctx->base.regions[i].y;
182 sctx->rects[i].width = sctx->base.regions[i].width;
183 sctx->rects[i].height = sctx->base.regions[i].height;
184 }
185
186 vppctx->output_width = outlink->w;
187 vppctx->output_height = outlink->h;
188
189 return ff_vaapi_vpp_config_output(outlink);
190 }
191
192 static int vaapi_stack_init(AVFilterContext *avctx)
193 {
194 StackVAAPIContext *sctx = avctx->priv;
195 VAAPIVPPContext *vppctx = avctx->priv;
196 int ret;
197
198 ret = stack_init(avctx);
199 if (ret)
200 return ret;
201
202 /* stack region */
203 sctx->rects = av_calloc(sctx->base.nb_inputs, sizeof(*sctx->rects));
204 if (!sctx->rects)
205 return AVERROR(ENOMEM);
206
207 ff_vaapi_vpp_ctx_init(avctx);
208 vppctx->output_format = AV_PIX_FMT_NONE;
209
210 return 0;
211 }
212
213 static av_cold void vaapi_stack_uninit(AVFilterContext *avctx)
214 {
215 StackVAAPIContext *sctx = avctx->priv;
216
217 stack_uninit(avctx);
218
219 av_freep(&sctx->rects);
220 }
221
222 static int vaapi_stack_query_formats(AVFilterContext *avctx)
223 {
224 static const enum AVPixelFormat pixel_formats[] = {
225 AV_PIX_FMT_VAAPI,
226 AV_PIX_FMT_NONE,
227 };
228
229 return ff_set_common_formats_from_list(avctx, pixel_formats);
230 }
231
232 #include "stack_internal.c"
233
234 #if CONFIG_HSTACK_VAAPI_FILTER
235
236 DEFINE_HSTACK_OPTIONS(vaapi);
237 DEFINE_STACK_FILTER(hstack, vaapi, "VA-API", 0);
238
239 #endif
240
241 #if CONFIG_VSTACK_VAAPI_FILTER
242
243 DEFINE_VSTACK_OPTIONS(vaapi);
244 DEFINE_STACK_FILTER(vstack, vaapi, "VA-API", 0);
245
246 #endif
247
248 #if CONFIG_XSTACK_VAAPI_FILTER
249
250 DEFINE_XSTACK_OPTIONS(vaapi);
251 DEFINE_STACK_FILTER(xstack, vaapi, "VA-API", 0);
252
253 #endif
254