2 * gstvaapiupload.c - VA-API video upload element
4 * Copyright (C) 2010-2011 Splitted-Desktop Systems
5 * Copyright (C) 2011-2012 Intel Corporation
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 * SECTION:gstvaapiupload
25 * @short_description: A video to VA flow filter
27 * vaapiupload uploads from raw YUV pixels to VA surfaces suitable
28 * for the vaapisink element, for example.
31 #include "gst/vaapi/sysdeps.h"
33 #include <gst/video/video.h>
34 #include <gst/video/videocontext.h>
35 #include <gst/vaapi/gstvaapivideobuffer.h>
36 #include <gst/vaapi/gstvaapidebug.h>
38 #include "gstvaapiupload.h"
39 #include "gstvaapipluginutil.h"
40 #include "gstvaapipluginbuffer.h"
42 #define GST_PLUGIN_NAME "vaapiupload"
43 #define GST_PLUGIN_DESC "A video to VA flow filter"
45 GST_DEBUG_CATEGORY_STATIC(gst_debug_vaapiupload);
46 #define GST_CAT_DEFAULT gst_debug_vaapiupload
48 /* ElementFactory information */
49 static const GstElementDetails gst_vaapiupload_details =
51 "VA-API colorspace uploader",
52 "Filter/Converter/Video",
54 "Gwenole Beauchesne <gwenole.beauchesne@intel.com>");
56 /* Default templates */
57 static const char gst_vaapiupload_yuv_caps_str[] =
59 "width = (int) [ 1, MAX ], "
60 "height = (int) [ 1, MAX ]; ";
62 static const char gst_vaapiupload_vaapi_caps_str[] =
63 GST_VAAPI_SURFACE_CAPS;
65 static GstStaticPadTemplate gst_vaapiupload_sink_factory =
66 GST_STATIC_PAD_TEMPLATE(
70 GST_STATIC_CAPS(gst_vaapiupload_yuv_caps_str));
72 static GstStaticPadTemplate gst_vaapiupload_src_factory =
73 GST_STATIC_PAD_TEMPLATE(
77 GST_STATIC_CAPS(gst_vaapiupload_vaapi_caps_str));
80 gst_vaapiupload_implements_iface_init(GstImplementsInterfaceClass *iface);
83 gst_video_context_interface_init(GstVideoContextInterface *iface);
85 #define GstVideoContextClass GstVideoContextInterface
86 G_DEFINE_TYPE_WITH_CODE(
89 GST_TYPE_BASE_TRANSFORM,
90 G_IMPLEMENT_INTERFACE(GST_TYPE_IMPLEMENTS_INTERFACE,
91 gst_vaapiupload_implements_iface_init);
92 G_IMPLEMENT_INTERFACE(GST_TYPE_VIDEO_CONTEXT,
93 gst_video_context_interface_init))
96 gst_vaapiupload_start(GstBaseTransform *trans);
99 gst_vaapiupload_stop(GstBaseTransform *trans);
102 gst_vaapiupload_transform(
103 GstBaseTransform *trans,
109 gst_vaapiupload_transform_caps(
110 GstBaseTransform *trans,
111 GstPadDirection direction,
116 gst_vaapiupload_set_caps(
117 GstBaseTransform *trans,
123 gst_vaapiupload_get_unit_size(
124 GstBaseTransform *trans,
130 gst_vaapiupload_sinkpad_buffer_alloc(
139 gst_vaapiupload_prepare_output_buffer(
140 GstBaseTransform *trans,
148 gst_vaapiupload_query(
153 /* GstImplementsInterface interface */
156 gst_vaapiupload_implements_interface_supported(
157 GstImplementsInterface *iface,
161 return (type == GST_TYPE_VIDEO_CONTEXT);
165 gst_vaapiupload_implements_iface_init(GstImplementsInterfaceClass *iface)
167 iface->supported = gst_vaapiupload_implements_interface_supported;
170 /* GstVideoContext interface */
173 gst_vaapiupload_set_video_context(GstVideoContext *context, const gchar *type,
176 GstVaapiUpload * const upload = GST_VAAPIUPLOAD(context);
178 gst_vaapi_set_display(type, value, &upload->display);
180 if (upload->uploader)
181 gst_vaapi_uploader_ensure_display(upload->uploader, upload->display);
185 gst_video_context_interface_init(GstVideoContextInterface *iface)
187 iface->set_context = gst_vaapiupload_set_video_context;
191 gst_vaapiupload_destroy(GstVaapiUpload *upload)
193 g_clear_object(&upload->uploader);
194 g_clear_object(&upload->display);
198 gst_vaapiupload_finalize(GObject *object)
200 gst_vaapiupload_destroy(GST_VAAPIUPLOAD(object));
202 G_OBJECT_CLASS(gst_vaapiupload_parent_class)->finalize(object);
206 gst_vaapiupload_class_init(GstVaapiUploadClass *klass)
208 GObjectClass * const object_class = G_OBJECT_CLASS(klass);
209 GstElementClass * const element_class = GST_ELEMENT_CLASS(klass);
210 GstBaseTransformClass * const trans_class = GST_BASE_TRANSFORM_CLASS(klass);
211 GstPadTemplate *pad_template;
213 GST_DEBUG_CATEGORY_INIT(gst_debug_vaapiupload,
214 GST_PLUGIN_NAME, 0, GST_PLUGIN_DESC);
216 object_class->finalize = gst_vaapiupload_finalize;
218 trans_class->start = gst_vaapiupload_start;
219 trans_class->stop = gst_vaapiupload_stop;
220 trans_class->transform = gst_vaapiupload_transform;
221 trans_class->transform_caps = gst_vaapiupload_transform_caps;
222 trans_class->set_caps = gst_vaapiupload_set_caps;
223 trans_class->get_unit_size = gst_vaapiupload_get_unit_size;
224 trans_class->prepare_output_buffer = gst_vaapiupload_prepare_output_buffer;
226 gst_element_class_set_details_simple(
228 gst_vaapiupload_details.longname,
229 gst_vaapiupload_details.klass,
230 gst_vaapiupload_details.description,
231 gst_vaapiupload_details.author
235 pad_template = gst_static_pad_template_get(&gst_vaapiupload_sink_factory);
236 gst_element_class_add_pad_template(element_class, pad_template);
237 gst_object_unref(pad_template);
240 pad_template = gst_static_pad_template_get(&gst_vaapiupload_src_factory);
241 gst_element_class_add_pad_template(element_class, pad_template);
242 gst_object_unref(pad_template);
246 gst_vaapiupload_init(GstVaapiUpload *upload)
248 GstPad *sinkpad, *srcpad;
250 /* Override buffer allocator on sink pad */
251 sinkpad = gst_element_get_static_pad(GST_ELEMENT(upload), "sink");
252 gst_pad_set_bufferalloc_function(
254 gst_vaapiupload_sinkpad_buffer_alloc
256 gst_pad_set_query_function(sinkpad, gst_vaapiupload_query);
257 g_object_unref(sinkpad);
259 /* Override query on src pad */
260 srcpad = gst_element_get_static_pad(GST_ELEMENT(upload), "src");
261 gst_pad_set_query_function(srcpad, gst_vaapiupload_query);
262 g_object_unref(srcpad);
265 static inline gboolean
266 gst_vaapiupload_ensure_display(GstVaapiUpload *upload)
268 return gst_vaapi_ensure_display(upload, GST_VAAPI_DISPLAY_TYPE_ANY,
273 gst_vaapiupload_ensure_uploader(GstVaapiUpload *upload)
275 if (!gst_vaapiupload_ensure_display(upload))
278 if (!upload->uploader) {
279 upload->uploader = gst_vaapi_uploader_new(upload->display);
280 if (!upload->uploader)
283 if (!gst_vaapi_uploader_ensure_display(upload->uploader, upload->display))
289 gst_vaapiupload_start(GstBaseTransform *trans)
291 GstVaapiUpload * const upload = GST_VAAPIUPLOAD(trans);
293 if (!gst_vaapiupload_ensure_uploader(upload))
299 gst_vaapiupload_stop(GstBaseTransform *trans)
301 GstVaapiUpload * const upload = GST_VAAPIUPLOAD(trans);
303 g_clear_object(&upload->display);
309 gst_vaapiupload_transform(
310 GstBaseTransform *trans,
315 GstVaapiUpload * const upload = GST_VAAPIUPLOAD(trans);
316 if (!gst_vaapi_uploader_process(upload->uploader, inbuf, outbuf))
317 return GST_FLOW_UNEXPECTED;
322 gst_vaapi_get_other_support_caps(GstVaapiUpload *upload)
325 caps = gst_caps_from_string(GST_VIDEO_CAPS_YUV("YUY2"));
330 gst_vaapiupload_transform_caps(
331 GstBaseTransform *trans,
332 GstPadDirection direction,
336 GstVaapiUpload * const upload = GST_VAAPIUPLOAD(trans);
337 GstCaps *out_caps = NULL;
338 GstStructure *structure;
340 g_return_val_if_fail(GST_IS_CAPS(caps), NULL);
342 structure = gst_caps_get_structure(caps, 0);
344 if (direction == GST_PAD_SINK) {
345 if (!gst_structure_has_name(structure, "video/x-raw-yuv"))
347 out_caps = gst_caps_from_string(gst_vaapiupload_vaapi_caps_str);
349 structure = gst_caps_get_structure(out_caps, 0);
352 "type", G_TYPE_STRING, "vaapi",
353 "opengl", G_TYPE_BOOLEAN, USE_GLX,
358 if (!gst_structure_has_name(structure, GST_VAAPI_SURFACE_CAPS_NAME))
360 out_caps = gst_caps_from_string(gst_vaapiupload_yuv_caps_str);
361 if (gst_vaapiupload_ensure_uploader(upload)) {
362 GstCaps *allowed_caps, *inter_caps, *other_caps;
363 allowed_caps = gst_vaapi_uploader_get_caps(upload->uploader);
366 /* can direct copy other YUV to va surface */
367 other_caps = gst_vaapi_get_other_support_caps(upload);
368 gst_caps_merge(allowed_caps, other_caps);
370 inter_caps = gst_caps_intersect(out_caps, allowed_caps);
371 gst_caps_unref(out_caps);
372 out_caps = inter_caps;
376 if (!gst_vaapi_append_surface_caps(out_caps, caps)) {
377 gst_caps_unref(out_caps);
384 gst_vaapiupload_set_caps(
385 GstBaseTransform *trans,
390 GstVaapiUpload * const upload = GST_VAAPIUPLOAD(trans);
392 if (!gst_vaapi_uploader_ensure_caps(upload->uploader, incaps, outcaps))
395 GST_INFO("set caps\nIN caps:\n%" GST_PTR_FORMAT "\nOUT caps:\n%" GST_PTR_FORMAT,
401 gst_vaapiupload_get_unit_size(
402 GstBaseTransform *trans,
407 GstStructure * const structure = gst_caps_get_structure(caps, 0);
408 GstVideoFormat format;
411 if (gst_structure_has_name(structure, GST_VAAPI_SURFACE_CAPS_NAME))
414 if (!gst_video_format_parse_caps(caps, &format, &width, &height))
416 *size = gst_video_format_get_size(format, width, height);
422 gst_vaapiupload_buffer_alloc(
423 GstBaseTransform *trans,
429 GstVaapiUpload * const upload = GST_VAAPIUPLOAD(trans);
432 if (!gst_vaapi_uploader_ensure_display(upload->uploader, upload->display))
433 return GST_FLOW_NOT_SUPPORTED;
434 if (!gst_vaapi_uploader_ensure_caps(upload->uploader, caps, NULL))
435 return GST_FLOW_NOT_SUPPORTED;
437 /* Allocate a regular GstBuffer if direct rendering is not supported */
438 if (!gst_vaapi_uploader_has_direct_rendering(upload->uploader))
440 *pbuf = gst_vaapi_uploader_get_buffer(upload->uploader);
445 gst_vaapiupload_sinkpad_buffer_alloc(
453 GstBaseTransform *trans;
456 trans = GST_BASE_TRANSFORM(gst_pad_get_parent_element(pad));
458 return GST_FLOW_UNEXPECTED;
460 ret = gst_vaapiupload_buffer_alloc(trans, size, caps, pbuf);
461 g_object_unref(trans);
466 gst_vaapiupload_prepare_output_buffer(
467 GstBaseTransform *trans,
474 GstVaapiUpload * const upload = GST_VAAPIUPLOAD(trans);
479 if (!gst_vaapi_uploader_has_direct_rendering(upload->uploader))
480 buffer = gst_vaapi_uploader_get_buffer(upload->uploader);
481 else if (GST_VAAPI_IS_VIDEO_BUFFER(inbuf))
482 buffer = gst_vaapi_video_buffer_new_from_buffer(inbuf);
483 else if (GST_VAAPI_IS_VIDEO_BUFFER(inbuf->parent))
484 buffer = gst_vaapi_video_buffer_new_from_buffer(inbuf->parent);
488 return GST_FLOW_UNEXPECTED;
490 gst_buffer_set_caps(buffer, caps);
491 GST_BUFFER_DATA(buffer) = NULL;
492 GST_BUFFER_SIZE(buffer) = 0;
499 gst_vaapiupload_query(GstPad *pad, GstQuery *query)
501 GstVaapiUpload *upload = GST_VAAPIUPLOAD (gst_pad_get_parent_element (pad));
504 GST_DEBUG ("sharing display %p", upload->display);
506 if (gst_vaapi_reply_to_query (query, upload->display))
509 res = gst_pad_query_default (pad, query);
511 g_object_unref (upload);