2 * gstvaapiblend.c - Video processing blend
4 * Copyright (C) 2019 Intel Corporation
5 * Author: U. Artie Eoff <ullysses.a.eoff@intel.com>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public License
9 * as published by the Free Software Foundation; either version 2.1
10 * of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301 USA
24 #include "gstvaapicompat.h"
25 #include "gstvaapiblend.h"
26 #include "gstvaapiutils.h"
27 #include "gstvaapivalue.h"
28 #include "gstvaapidisplay_priv.h"
29 #include "gstvaapisurface_priv.h"
33 GstObject parent_instance;
35 GstVaapiDisplay *display;
38 VAContextID va_context;
43 typedef struct _GstVaapiBlendClass GstVaapiBlendClass;
44 struct _GstVaapiBlendClass
46 GstObjectClass parent_class;
49 GST_DEBUG_CATEGORY_STATIC (gst_debug_vaapi_blend);
50 #ifndef GST_DISABLE_GST_DEBUG
51 #define GST_CAT_DEFAULT gst_debug_vaapi_blend
53 #define GST_CAT_DEFAULT NULL
56 G_DEFINE_TYPE_WITH_CODE (GstVaapiBlend, gst_vaapi_blend, GST_TYPE_OBJECT,
57 GST_DEBUG_CATEGORY_INIT (gst_debug_vaapi_blend, "vaapiblend", 0,
66 gst_vaapi_blend_set_property (GObject * object, guint property_id,
67 const GValue * value, GParamSpec * pspec)
69 GstVaapiBlend *const blend = GST_VAAPI_BLEND (object);
71 switch (property_id) {
73 GstVaapiDisplay *display = g_value_get_object (value);;
75 if (GST_VAAPI_DISPLAY_HAS_VPP (display)) {
76 blend->display = gst_object_ref (display);
78 GST_WARNING_OBJECT (blend, "GstVaapiDisplay doesn't support VPP");
84 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
89 gst_vaapi_blend_get_property (GObject * object, guint property_id,
90 GValue * value, GParamSpec * pspec)
92 GstVaapiBlend *const blend = GST_VAAPI_BLEND (object);
94 switch (property_id) {
96 g_value_set_object (value, blend->display);
99 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
104 gst_vaapi_blend_finalize (GObject * object)
106 GstVaapiBlend *const blend = GST_VAAPI_BLEND (object);
111 GST_VAAPI_DISPLAY_LOCK (blend->display);
113 if (blend->va_context != VA_INVALID_ID) {
114 vaDestroyContext (GST_VAAPI_DISPLAY_VADISPLAY (blend->display),
116 blend->va_context = VA_INVALID_ID;
119 if (blend->va_config != VA_INVALID_ID) {
120 vaDestroyConfig (GST_VAAPI_DISPLAY_VADISPLAY (blend->display),
122 blend->va_config = VA_INVALID_ID;
125 GST_VAAPI_DISPLAY_UNLOCK (blend->display);
127 gst_vaapi_display_replace (&blend->display, NULL);
130 G_OBJECT_CLASS (gst_vaapi_blend_parent_class)->finalize (object);
134 gst_vaapi_blend_class_init (GstVaapiBlendClass * klass)
136 GObjectClass *const object_class = G_OBJECT_CLASS (klass);
138 object_class->set_property = gst_vaapi_blend_set_property;
139 object_class->get_property = gst_vaapi_blend_get_property;
140 object_class->finalize = gst_vaapi_blend_finalize;
142 g_object_class_install_property (object_class, PROP_DISPLAY,
143 g_param_spec_object ("display", "Gst VA-API Display",
144 "The VA-API display object to use", GST_TYPE_VAAPI_DISPLAY,
145 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME));
149 gst_vaapi_blend_init (GstVaapiBlend * blend)
151 blend->display = NULL;
152 blend->va_config = VA_INVALID_ID;
153 blend->va_context = VA_INVALID_ID;
158 gst_vaapi_blend_initialize (GstVaapiBlend * blend)
161 VAProcPipelineCaps pipeline_caps = { 0, };
166 status = vaCreateConfig (GST_VAAPI_DISPLAY_VADISPLAY (blend->display),
167 VAProfileNone, VAEntrypointVideoProc, NULL, 0, &blend->va_config);
168 if (!vaapi_check_status (status, "vaCreateConfig() [VPP]"))
171 status = vaCreateContext (GST_VAAPI_DISPLAY_VADISPLAY (blend->display),
172 blend->va_config, 0, 0, 0, NULL, 0, &blend->va_context);
173 if (!vaapi_check_status (status, "vaCreateContext() [VPP]"))
176 #if VA_CHECK_VERSION(1,1,0)
178 vaQueryVideoProcPipelineCaps (GST_VAAPI_DISPLAY_VADISPLAY
179 (blend->display), blend->va_context, NULL, 0, &pipeline_caps);
180 if (vaapi_check_status (status, "vaQueryVideoProcPipelineCaps()"))
181 blend->flags = pipeline_caps.blend_flags;
183 if (!(blend->flags & VA_BLEND_GLOBAL_ALPHA)) {
184 GST_WARNING_OBJECT (blend, "VPP does not support global alpha blending");
195 gst_vaapi_blend_new (GstVaapiDisplay * display)
197 GstVaapiBlend *blend = g_object_new (GST_TYPE_VAAPI_BLEND,
198 "display", display, NULL);
200 if (!gst_vaapi_blend_initialize (blend)) {
201 gst_object_unref (blend);
209 gst_vaapi_blend_replace (GstVaapiBlend ** old_blend_ptr,
210 GstVaapiBlend * new_blend)
212 g_return_if_fail (old_blend_ptr != NULL);
214 gst_object_replace ((GstObject **) old_blend_ptr, GST_OBJECT (new_blend));
218 gst_vaapi_blend_process_unlocked (GstVaapiBlend * blend,
219 GstVaapiSurface * output, GstVaapiBlendSurfaceNextFunc next,
223 VADisplay va_display;
224 GstVaapiBlendSurface *current;
226 va_display = GST_VAAPI_DISPLAY_VADISPLAY (blend->display);
228 va_status = vaBeginPicture (va_display, blend->va_context,
229 GST_VAAPI_SURFACE_ID (output));
230 if (!vaapi_check_status (va_status, "vaBeginPicture()"))
233 current = next (user_data);
234 for (; current; current = next (user_data)) {
235 VAProcPipelineParameterBuffer *param = NULL;
236 VABufferID id = VA_INVALID_ID;
237 VARectangle src_rect = { 0, };
238 VARectangle dst_rect = { 0, };
239 #if VA_CHECK_VERSION(1,1,0)
240 VABlendState blend_state;
243 if (!current->surface)
246 /* Build surface region (source) */
247 src_rect.width = GST_VAAPI_SURFACE_WIDTH (current->surface);
248 src_rect.height = GST_VAAPI_SURFACE_HEIGHT (current->surface);
250 if ((current->crop->x + current->crop->width > src_rect.width) ||
251 (current->crop->y + current->crop->height > src_rect.height))
253 src_rect.x = current->crop->x;
254 src_rect.y = current->crop->y;
255 src_rect.width = current->crop->width;
256 src_rect.height = current->crop->height;
259 /* Build output region (target) */
260 dst_rect.x = current->target.x;
261 dst_rect.y = current->target.y;
262 dst_rect.width = current->target.width;
263 dst_rect.height = current->target.height;
265 if (!vaapi_create_buffer (va_display, blend->va_context,
266 VAProcPipelineParameterBufferType, sizeof (*param), NULL, &id,
267 (gpointer *) & param))
270 memset (param, 0, sizeof (*param));
272 param->surface = GST_VAAPI_SURFACE_ID (current->surface);
273 param->surface_region = &src_rect;
274 param->output_region = &dst_rect;
275 param->output_background_color = 0xff000000;
277 #if VA_CHECK_VERSION(1,1,0)
278 blend_state.flags = VA_BLEND_GLOBAL_ALPHA;
279 blend_state.global_alpha = current->alpha;
280 param->blend_state = &blend_state;
283 vaapi_unmap_buffer (va_display, id, NULL);
285 va_status = vaRenderPicture (va_display, blend->va_context, &id, 1);
286 vaapi_destroy_buffer (va_display, &id);
287 if (!vaapi_check_status (va_status, "vaRenderPicture()"))
291 va_status = vaEndPicture (va_display, blend->va_context);
292 if (!vaapi_check_status (va_status, "vaEndPicture()"))
299 * gst_vaapi_blend_process:
300 * @blend: a #GstVaapiBlend instance.
301 * @output: a #GstVaapiSurface to be composed.
302 * @next: a function to fetch the next #GstVaapiBlendSurface to
304 * @data: state storage for @next.
306 * This function will process all the input surfaces defined through
307 * #GstVaapiBlendSurface and will blend them onto the @output surface.
309 * Returns: %TRUE if the blend process succeed; otherwise %FALSE.
312 gst_vaapi_blend_process (GstVaapiBlend * blend, GstVaapiSurface * output,
313 GstVaapiBlendSurfaceNextFunc next, gpointer user_data)
317 g_return_val_if_fail (blend != NULL, FALSE);
318 g_return_val_if_fail (output != NULL, FALSE);
319 g_return_val_if_fail (next != NULL, FALSE);
321 GST_VAAPI_DISPLAY_LOCK (blend->display);
322 result = gst_vaapi_blend_process_unlocked (blend, output, next, user_data);
323 GST_VAAPI_DISPLAY_UNLOCK (blend->display);