2 * gstvaapisurface.c - VA surface abstraction
4 * Copyright (C) 2010-2011 Splitted-Desktop Systems
5 * Copyright (C) 2011 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:gstvaapisurface
25 * @short_description: VA surface abstraction
29 #include "gstvaapicompat.h"
30 #include "gstvaapiutils.h"
31 #include "gstvaapisurface.h"
32 #include "gstvaapisurface_priv.h"
33 #include "gstvaapicontext.h"
34 #include "gstvaapiimage.h"
35 #include "gstvaapi_priv.h"
38 #include "gstvaapidebug.h"
40 G_DEFINE_TYPE(GstVaapiSurface, gst_vaapi_surface, GST_VAAPI_TYPE_OBJECT);
42 #define GST_VAAPI_SURFACE_GET_PRIVATE(obj) \
43 (G_TYPE_INSTANCE_GET_PRIVATE((obj), \
44 GST_VAAPI_TYPE_SURFACE, \
45 GstVaapiSurfacePrivate))
47 struct _GstVaapiSurfacePrivate {
50 GstVaapiChromaType chroma_type;
51 GPtrArray *subpictures;
52 GstVaapiContext *parent_context;
65 _gst_vaapi_surface_associate_subpicture(
66 GstVaapiSurface *surface,
67 GstVaapiSubpicture *subpicture,
68 const GstVaapiRectangle *src_rect,
69 const GstVaapiRectangle *dst_rect
73 _gst_vaapi_surface_deassociate_subpicture(
74 GstVaapiSurface *surface,
75 GstVaapiSubpicture *subpicture
79 destroy_subpicture_cb(gpointer subpicture, gpointer surface)
81 _gst_vaapi_surface_deassociate_subpicture(surface, subpicture);
82 g_object_unref(subpicture);
86 gst_vaapi_surface_destroy_subpictures(GstVaapiSurface *surface)
88 GstVaapiSurfacePrivate * const priv = surface->priv;
90 if (priv->subpictures) {
91 g_ptr_array_foreach(priv->subpictures, destroy_subpicture_cb, surface);
92 g_ptr_array_free(priv->subpictures, TRUE);
93 priv->subpictures = NULL;
98 gst_vaapi_surface_destroy(GstVaapiSurface *surface)
100 GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(surface);
101 VASurfaceID surface_id;
104 surface_id = GST_VAAPI_OBJECT_ID(surface);
105 GST_DEBUG("surface %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS(surface_id));
107 gst_vaapi_surface_destroy_subpictures(surface);
108 gst_vaapi_surface_set_parent_context(surface, NULL);
110 if (surface_id != VA_INVALID_SURFACE) {
111 GST_VAAPI_DISPLAY_LOCK(display);
112 status = vaDestroySurfaces(
113 GST_VAAPI_DISPLAY_VADISPLAY(display),
116 GST_VAAPI_DISPLAY_UNLOCK(display);
117 if (!vaapi_check_status(status, "vaDestroySurfaces()"))
118 g_warning("failed to destroy surface %" GST_VAAPI_ID_FORMAT,
119 GST_VAAPI_ID_ARGS(surface_id));
120 GST_VAAPI_OBJECT_ID(surface) = VA_INVALID_SURFACE;
125 gst_vaapi_surface_create(GstVaapiSurface *surface)
127 GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(surface);
128 GstVaapiSurfacePrivate * const priv = surface->priv;
129 VASurfaceID surface_id;
133 switch (priv->chroma_type) {
134 case GST_VAAPI_CHROMA_TYPE_YUV420:
135 format = VA_RT_FORMAT_YUV420;
137 case GST_VAAPI_CHROMA_TYPE_YUV422:
138 format = VA_RT_FORMAT_YUV422;
140 case GST_VAAPI_CHROMA_TYPE_YUV444:
141 format = VA_RT_FORMAT_YUV444;
144 GST_DEBUG("unsupported chroma-type %u\n", priv->chroma_type);
148 GST_VAAPI_DISPLAY_LOCK(display);
149 status = vaCreateSurfaces(
150 GST_VAAPI_DISPLAY_VADISPLAY(display),
156 GST_VAAPI_DISPLAY_UNLOCK(display);
157 if (!vaapi_check_status(status, "vaCreateSurfaces()"))
160 GST_DEBUG("surface %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS(surface_id));
161 GST_VAAPI_OBJECT_ID(surface) = surface_id;
166 gst_vaapi_surface_finalize(GObject *object)
168 gst_vaapi_surface_destroy(GST_VAAPI_SURFACE(object));
170 G_OBJECT_CLASS(gst_vaapi_surface_parent_class)->finalize(object);
174 gst_vaapi_surface_set_property(
181 GstVaapiSurface * const surface = GST_VAAPI_SURFACE(object);
182 GstVaapiSurfacePrivate * const priv = surface->priv;
186 priv->width = g_value_get_uint(value);
189 priv->height = g_value_get_uint(value);
191 case PROP_CHROMA_TYPE:
192 priv->chroma_type = g_value_get_uint(value);
194 case PROP_PARENT_CONTEXT:
195 gst_vaapi_surface_set_parent_context(surface, g_value_get_object(value));
198 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
204 gst_vaapi_surface_get_property(
211 GstVaapiSurface * const surface = GST_VAAPI_SURFACE(object);
215 g_value_set_uint(value, gst_vaapi_surface_get_width(surface));
218 g_value_set_uint(value, gst_vaapi_surface_get_height(surface));
220 case PROP_CHROMA_TYPE:
221 g_value_set_uint(value, gst_vaapi_surface_get_chroma_type(surface));
223 case PROP_PARENT_CONTEXT:
224 g_value_set_object(value, gst_vaapi_surface_get_parent_context(surface));
227 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
233 gst_vaapi_surface_constructed(GObject *object)
235 GstVaapiSurface * const surface = GST_VAAPI_SURFACE(object);
236 GstVaapiSurfaceClass * const klass = GST_VAAPI_SURFACE_GET_CLASS(object);
237 GObjectClass *parent_class;
240 klass->create(surface);
242 parent_class = G_OBJECT_CLASS(gst_vaapi_surface_parent_class);
243 if (parent_class->constructed)
244 parent_class->constructed(object);
248 gst_vaapi_surface_class_init(GstVaapiSurfaceClass *klass)
250 GObjectClass * const object_class = G_OBJECT_CLASS(klass);
252 g_type_class_add_private(klass, sizeof(GstVaapiSurfacePrivate));
254 object_class->finalize = gst_vaapi_surface_finalize;
255 object_class->set_property = gst_vaapi_surface_set_property;
256 object_class->get_property = gst_vaapi_surface_get_property;
257 object_class->constructed = gst_vaapi_surface_constructed;
259 klass->create = gst_vaapi_surface_create;
261 g_object_class_install_property
264 g_param_spec_uint("width",
266 "The width of the surface",
268 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
270 g_object_class_install_property
273 g_param_spec_uint("height",
275 "The height of the surface",
277 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
279 g_object_class_install_property
282 g_param_spec_uint("chroma-type",
284 "The chroma type of the surface",
286 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
288 g_object_class_install_property
291 g_param_spec_object("parent-context",
293 "The parent context, if any",
294 GST_VAAPI_TYPE_CONTEXT,
295 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
299 gst_vaapi_surface_init(GstVaapiSurface *surface)
301 GstVaapiSurfacePrivate *priv = GST_VAAPI_SURFACE_GET_PRIVATE(surface);
303 surface->priv = priv;
306 priv->chroma_type = 0;
307 priv->subpictures = NULL;
308 priv->parent_context = NULL;
312 * gst_vaapi_surface_new:
313 * @display: a #GstVaapiDisplay
314 * @chroma_type: the surface chroma format
315 * @width: the requested surface width
316 * @height: the requested surface height
318 * Creates a new #GstVaapiSurface with the specified chroma format and
321 * Return value: the newly allocated #GstVaapiSurface object
324 gst_vaapi_surface_new(
325 GstVaapiDisplay *display,
326 GstVaapiChromaType chroma_type,
331 GST_DEBUG("size %ux%u, chroma type 0x%x", width, height, chroma_type);
333 return g_object_new(GST_VAAPI_TYPE_SURFACE,
335 "id", GST_VAAPI_ID(VA_INVALID_ID),
338 "chroma-type", chroma_type,
343 * gst_vaapi_surface_get_id:
344 * @surface: a #GstVaapiSurface
346 * Returns the underlying VASurfaceID of the @surface.
348 * Return value: the underlying VA surface id
351 gst_vaapi_surface_get_id(GstVaapiSurface *surface)
353 g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), VA_INVALID_SURFACE);
355 return GST_VAAPI_OBJECT_ID(surface);
359 * gst_vaapi_surface_get_chroma_type:
360 * @surface: a #GstVaapiSurface
362 * Returns the #GstVaapiChromaType the @surface was created with.
364 * Return value: the #GstVaapiChromaType
367 gst_vaapi_surface_get_chroma_type(GstVaapiSurface *surface)
369 g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), 0);
371 return surface->priv->chroma_type;
375 * gst_vaapi_surface_get_width:
376 * @surface: a #GstVaapiSurface
378 * Returns the @surface width.
380 * Return value: the surface width, in pixels
383 gst_vaapi_surface_get_width(GstVaapiSurface *surface)
385 g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), 0);
387 return surface->priv->width;
391 * gst_vaapi_surface_get_height:
392 * @surface: a #GstVaapiSurface
394 * Returns the @surface height.
396 * Return value: the surface height, in pixels.
399 gst_vaapi_surface_get_height(GstVaapiSurface *surface)
401 g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), 0);
403 return surface->priv->height;
407 * gst_vaapi_surface_get_size:
408 * @surface: a #GstVaapiSurface
409 * @pwidth: return location for the width, or %NULL
410 * @pheight: return location for the height, or %NULL
412 * Retrieves the dimensions of a #GstVaapiSurface.
415 gst_vaapi_surface_get_size(
416 GstVaapiSurface *surface,
421 g_return_if_fail(GST_VAAPI_IS_SURFACE(surface));
424 *pwidth = gst_vaapi_surface_get_width(surface);
427 *pheight = gst_vaapi_surface_get_height(surface);
431 * gst_vaapi_surface_set_parent_context:
432 * @surface: a #GstVaapiSurface
433 * @context: a #GstVaapiContext
435 * Sets new parent context, or clears any parent context if @context
436 * is %NULL. This function owns an extra reference to the context,
437 * which will be released when the surface is destroyed.
440 gst_vaapi_surface_set_parent_context(
441 GstVaapiSurface *surface,
442 GstVaapiContext *context
445 GstVaapiSurfacePrivate *priv;
447 g_return_if_fail(GST_VAAPI_IS_SURFACE(surface));
449 priv = surface->priv;
451 g_clear_object(&priv->parent_context);
454 priv->parent_context = g_object_ref(context);
458 * gst_vaapi_surface_get_parent_context:
459 * @surface: a #GstVaapiSurface
461 * Retrieves the parent #GstVaapiContext, or %NULL if there is
462 * none. The surface shall still own a reference to the context.
463 * i.e. the caller shall not unreference the returned context object.
465 * Return value: the parent context, if any.
468 gst_vaapi_surface_get_parent_context(GstVaapiSurface *surface)
470 g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), NULL);
472 return surface->priv->parent_context;
476 * gst_vaapi_surface_derive_image:
477 * @surface: a #GstVaapiSurface
479 * Derives a #GstVaapiImage from the @surface. This image buffer can
480 * then be mapped/unmapped for direct CPU access. This operation is
481 * only possible if the underlying implementation supports direct
482 * rendering capabilities and internal surface formats that can be
483 * represented with a #GstVaapiImage.
485 * When the operation is not possible, the function returns %NULL and
486 * the user should then fallback to using gst_vaapi_surface_get_image()
487 * or gst_vaapi_surface_put_image() to accomplish the same task in an
488 * indirect manner (additional copy).
490 * An image created with gst_vaapi_surface_derive_image() should be
491 * unreferenced when it's no longer needed. The image and image buffer
492 * data structures will be destroyed. However, the surface contents
493 * will remain unchanged until destroyed through the last call to
496 * Return value: the newly allocated #GstVaapiImage object, or %NULL
500 gst_vaapi_surface_derive_image(GstVaapiSurface *surface)
502 GstVaapiDisplay *display;
506 g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), NULL);
508 display = GST_VAAPI_OBJECT_DISPLAY(surface);
509 va_image.image_id = VA_INVALID_ID;
510 va_image.buf = VA_INVALID_ID;
512 GST_VAAPI_DISPLAY_LOCK(display);
513 status = vaDeriveImage(
514 GST_VAAPI_DISPLAY_VADISPLAY(display),
515 GST_VAAPI_OBJECT_ID(surface),
518 GST_VAAPI_DISPLAY_UNLOCK(display);
519 if (!vaapi_check_status(status, "vaDeriveImage()"))
521 if (va_image.image_id == VA_INVALID_ID || va_image.buf == VA_INVALID_ID)
524 return gst_vaapi_image_new_with_image(display, &va_image);
528 * gst_vaapi_surface_get_image
529 * @surface: a #GstVaapiSurface
530 * @image: a #GstVaapiImage
532 * Retrieves surface data into a #GstVaapiImage. The @image must have
533 * a format supported by the @surface.
535 * Return value: %TRUE on success
538 gst_vaapi_surface_get_image(GstVaapiSurface *surface, GstVaapiImage *image)
540 GstVaapiDisplay *display;
545 g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), FALSE);
546 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
548 display = GST_VAAPI_OBJECT_DISPLAY(surface);
552 gst_vaapi_image_get_size(image, &width, &height);
553 if (width != surface->priv->width || height != surface->priv->height)
556 image_id = GST_VAAPI_OBJECT_ID(image);
557 if (image_id == VA_INVALID_ID)
560 GST_VAAPI_DISPLAY_LOCK(display);
562 GST_VAAPI_DISPLAY_VADISPLAY(display),
563 GST_VAAPI_OBJECT_ID(surface),
567 GST_VAAPI_DISPLAY_UNLOCK(display);
568 if (!vaapi_check_status(status, "vaGetImage()"))
575 * gst_vaapi_surface_put_image:
576 * @surface: a #GstVaapiSurface
577 * @image: a #GstVaapiImage
579 * Copies data from a #GstVaapiImage into a @surface. The @image must
580 * have a format supported by the @surface.
582 * Return value: %TRUE on success
585 gst_vaapi_surface_put_image(GstVaapiSurface *surface, GstVaapiImage *image)
587 GstVaapiDisplay *display;
592 g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), FALSE);
593 g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
595 display = GST_VAAPI_OBJECT_DISPLAY(surface);
599 gst_vaapi_image_get_size(image, &width, &height);
600 if (width != surface->priv->width || height != surface->priv->height)
603 image_id = GST_VAAPI_OBJECT_ID(image);
604 if (image_id == VA_INVALID_ID)
607 GST_VAAPI_DISPLAY_LOCK(display);
609 GST_VAAPI_DISPLAY_VADISPLAY(display),
610 GST_VAAPI_OBJECT_ID(surface),
615 GST_VAAPI_DISPLAY_UNLOCK(display);
616 if (!vaapi_check_status(status, "vaPutImage()"))
623 * gst_vaapi_surface_associate_subpicture:
624 * @surface: a #GstVaapiSurface
625 * @subpicture: a #GstVaapiSubpicture
626 * @src_rect: the sub-rectangle of the source subpicture
627 * image to extract and process. If %NULL, the entire image will be used.
628 * @dst_rect: the sub-rectangle of the destination
629 * surface into which the image is rendered. If %NULL, the entire
630 * surface will be used.
632 * Associates the @subpicture with the @surface. The @src_rect
633 * coordinates and size are relative to the source image bound to
634 * @subpicture. The @dst_rect coordinates and size are relative to the
635 * target @surface. Note that the @surface holds an additional
636 * reference to the @subpicture.
638 * Return value: %TRUE on success
641 gst_vaapi_surface_associate_subpicture(
642 GstVaapiSurface *surface,
643 GstVaapiSubpicture *subpicture,
644 const GstVaapiRectangle *src_rect,
645 const GstVaapiRectangle *dst_rect
650 g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), FALSE);
651 g_return_val_if_fail(GST_VAAPI_IS_SUBPICTURE(subpicture), FALSE);
653 if (!surface->priv->subpictures) {
654 surface->priv->subpictures = g_ptr_array_new();
655 if (!surface->priv->subpictures)
659 if (g_ptr_array_remove_fast(surface->priv->subpictures, subpicture)) {
660 success = _gst_vaapi_surface_deassociate_subpicture(surface, subpicture);
661 g_object_unref(subpicture);
666 success = _gst_vaapi_surface_associate_subpicture(
675 g_ptr_array_add(surface->priv->subpictures, g_object_ref(subpicture));
680 _gst_vaapi_surface_associate_subpicture(
681 GstVaapiSurface *surface,
682 GstVaapiSubpicture *subpicture,
683 const GstVaapiRectangle *src_rect,
684 const GstVaapiRectangle *dst_rect
687 GstVaapiDisplay *display;
688 GstVaapiRectangle src_rect_default, dst_rect_default;
689 GstVaapiImage *image;
690 VASurfaceID surface_id;
693 display = GST_VAAPI_OBJECT_DISPLAY(surface);
697 surface_id = GST_VAAPI_OBJECT_ID(surface);
698 if (surface_id == VA_INVALID_SURFACE)
702 image = gst_vaapi_subpicture_get_image(subpicture);
705 src_rect = &src_rect_default;
706 src_rect_default.x = 0;
707 src_rect_default.y = 0;
708 gst_vaapi_image_get_size(
710 &src_rect_default.width,
711 &src_rect_default.height
716 dst_rect = &dst_rect_default;
717 dst_rect_default.x = 0;
718 dst_rect_default.y = 0;
719 dst_rect_default.width = surface->priv->width;
720 dst_rect_default.height = surface->priv->height;
723 GST_VAAPI_DISPLAY_LOCK(display);
724 status = vaAssociateSubpicture(
725 GST_VAAPI_DISPLAY_VADISPLAY(display),
726 GST_VAAPI_OBJECT_ID(subpicture),
728 src_rect->x, src_rect->y, src_rect->width, src_rect->height,
729 dst_rect->x, dst_rect->y, dst_rect->width, dst_rect->height,
732 GST_VAAPI_DISPLAY_UNLOCK(display);
733 if (!vaapi_check_status(status, "vaAssociateSubpicture()"))
740 * gst_vaapi_surface_deassociate_subpicture:
741 * @surface: a #GstVaapiSurface
742 * @subpicture: a #GstVaapiSubpicture
744 * Deassociates @subpicture from @surface. Other associations are kept.
746 * Return value: %TRUE on success
749 gst_vaapi_surface_deassociate_subpicture(
750 GstVaapiSurface *surface,
751 GstVaapiSubpicture *subpicture
756 g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), FALSE);
757 g_return_val_if_fail(GST_VAAPI_IS_SUBPICTURE(subpicture), FALSE);
759 if (!surface->priv->subpictures)
762 /* First, check subpicture was really associated with this surface */
763 if (!g_ptr_array_remove_fast(surface->priv->subpictures, subpicture)) {
764 GST_DEBUG("subpicture %" GST_VAAPI_ID_FORMAT " was not bound to "
765 "surface %" GST_VAAPI_ID_FORMAT,
766 GST_VAAPI_ID_ARGS(GST_VAAPI_OBJECT_ID(subpicture)),
767 GST_VAAPI_ID_ARGS(GST_VAAPI_OBJECT_ID(surface)));
771 success = _gst_vaapi_surface_deassociate_subpicture(surface, subpicture);
772 g_object_unref(subpicture);
777 _gst_vaapi_surface_deassociate_subpicture(
778 GstVaapiSurface *surface,
779 GstVaapiSubpicture *subpicture
782 GstVaapiDisplay *display;
783 VASurfaceID surface_id;
786 display = GST_VAAPI_OBJECT_DISPLAY(surface);
790 surface_id = GST_VAAPI_OBJECT_ID(surface);
791 if (surface_id == VA_INVALID_SURFACE)
794 GST_VAAPI_DISPLAY_LOCK(display);
795 status = vaDeassociateSubpicture(
796 GST_VAAPI_DISPLAY_VADISPLAY(display),
797 GST_VAAPI_OBJECT_ID(subpicture),
800 GST_VAAPI_DISPLAY_UNLOCK(display);
801 if (!vaapi_check_status(status, "vaDeassociateSubpicture()"))
808 * gst_vaapi_surface_sync:
809 * @surface: a #GstVaapiSurface
811 * Blocks until all pending operations on the @surface have been
814 * Return value: %TRUE on success
817 gst_vaapi_surface_sync(GstVaapiSurface *surface)
819 GstVaapiDisplay *display;
822 g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), FALSE);
824 display = GST_VAAPI_OBJECT_DISPLAY(surface);
828 GST_VAAPI_DISPLAY_LOCK(display);
829 status = vaSyncSurface(
830 GST_VAAPI_DISPLAY_VADISPLAY(display),
831 GST_VAAPI_OBJECT_ID(surface)
833 GST_VAAPI_DISPLAY_UNLOCK(display);
834 if (!vaapi_check_status(status, "vaSyncSurface()"))
841 * gst_vaapi_surface_query_status:
842 * @surface: a #GstVaapiSurface
843 * @pstatus: return location for the #GstVaapiSurfaceStatus
845 * Finds out any pending operations on the @surface. The
846 * #GstVaapiSurfaceStatus flags are returned into @pstatus.
848 * Return value: %TRUE on success
851 gst_vaapi_surface_query_status(
852 GstVaapiSurface *surface,
853 GstVaapiSurfaceStatus *pstatus
856 VASurfaceStatus surface_status;
859 g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), FALSE);
861 GST_VAAPI_OBJECT_LOCK_DISPLAY(surface);
862 status = vaQuerySurfaceStatus(
863 GST_VAAPI_OBJECT_VADISPLAY(surface),
864 GST_VAAPI_OBJECT_ID(surface),
867 GST_VAAPI_OBJECT_UNLOCK_DISPLAY(surface);
868 if (!vaapi_check_status(status, "vaQuerySurfaceStatus()"))
872 *pstatus = to_GstVaapiSurfaceStatus(surface_status);
877 * gst_vaapi_surface_set_subpictures_from_composition:
878 * @surface: a #GstVaapiSurface
879 * @compostion: a #GstVideoOverlayCompositon
880 * @propagate_context: a flag specifying whether to apply composition
881 * to the parent context, if any
883 * Helper to update the subpictures from #GstVideoOverlayCompositon. Sending
884 * a NULL composition will clear all the current subpictures. Note that this
885 * method will clear existing subpictures.
887 * Return value: %TRUE on success
890 gst_vaapi_surface_set_subpictures_from_composition(
891 GstVaapiSurface *surface,
892 GstVideoOverlayComposition *composition,
893 gboolean propagate_context
896 GstVaapiDisplay *display;
897 guint n, nb_rectangles;
899 g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), FALSE);
901 if (propagate_context) {
902 GstVaapiContext * const context = surface->priv->parent_context;
904 return gst_vaapi_context_apply_composition(context, composition);
907 display = GST_VAAPI_OBJECT_DISPLAY(surface);
911 /* Clear current subpictures */
912 gst_vaapi_surface_destroy_subpictures(surface);
917 nb_rectangles = gst_video_overlay_composition_n_rectangles (composition);
919 /* Overlay all the rectangles cantained in the overlay composition */
920 for (n = 0; n < nb_rectangles; ++n) {
921 GstVideoOverlayRectangle *rect;
922 GstVaapiRectangle sub_rect;
923 GstVaapiSubpicture *subpicture;
925 rect = gst_video_overlay_composition_get_rectangle (composition, n);
926 subpicture = gst_vaapi_subpicture_new_from_overlay_rectangle (display,
929 gst_video_overlay_rectangle_get_render_rectangle (rect,
930 (gint *)&sub_rect.x, (gint *)&sub_rect.y,
931 &sub_rect.width, &sub_rect.height);
933 if (!gst_vaapi_surface_associate_subpicture (surface, subpicture,
935 GST_WARNING ("could not render overlay rectangle %p", rect);
936 g_object_unref (subpicture);
939 g_object_unref (subpicture);