2 * gstvaapicontext.c - VA context abstraction
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:gstvaapicontext
25 * @short_description: VA context abstraction
30 #include "gstvaapicompat.h"
31 #include "gstvaapicontext.h"
32 #include "gstvaapisurface.h"
33 #include "gstvaapisurface_priv.h"
34 #include "gstvaapisurfacepool.h"
35 #include "gstvaapiimage.h"
36 #include "gstvaapisubpicture.h"
37 #include "gstvaapiminiobject.h"
38 #include "gstvaapiutils.h"
39 #include "gstvaapi_priv.h"
42 #include "gstvaapidebug.h"
44 G_DEFINE_TYPE(GstVaapiContext, gst_vaapi_context, GST_VAAPI_TYPE_OBJECT)
46 #define GST_VAAPI_CONTEXT_GET_PRIVATE(obj) \
47 (G_TYPE_INSTANCE_GET_PRIVATE((obj), \
48 GST_VAAPI_TYPE_CONTEXT, \
49 GstVaapiContextPrivate))
51 typedef struct _GstVaapiOverlayRectangle GstVaapiOverlayRectangle;
52 struct _GstVaapiOverlayRectangle {
53 GstVaapiContext *context;
54 GstVaapiSubpicture *subpicture;
55 GstVaapiRectangle render_rect;
58 GstBuffer *rect_buffer;
59 GstVideoOverlayRectangle *rect;
60 guint is_associated : 1;
63 /* XXX: optimize for the effective number of reference frames */
64 struct _GstVaapiContextPrivate {
67 GstVaapiVideoPool *surfaces_pool;
68 GPtrArray *overlays[2];
70 GstVaapiProfile profile;
71 GstVaapiEntrypoint entrypoint;
75 guint is_constructed : 1;
89 get_max_ref_frames(GstVaapiProfile profile)
93 switch (gst_vaapi_profile_get_codec(profile)) {
94 case GST_VAAPI_CODEC_H264: ref_frames = 16; break;
95 case GST_VAAPI_CODEC_JPEG: ref_frames = 0; break;
96 default: ref_frames = 2; break;
102 gst_video_overlay_rectangle_replace(GstVideoOverlayRectangle **old_rect_ptr,
103 GstVideoOverlayRectangle *new_rect)
105 gst_mini_object_replace((GstMiniObject **)old_rect_ptr,
106 GST_MINI_OBJECT_CAST(new_rect));
109 static inline GstBuffer *
110 gst_video_overlay_rectangle_get_pixels_raw(GstVideoOverlayRectangle *rect)
112 guint width, height, stride, flags;
114 flags = gst_video_overlay_rectangle_get_flags(rect);
116 /* Try to retrieve the original buffer that was passed to
117 gst_video_overlay_rectangle_new_argb(). This will only work if
118 there was no previous user that required pixels with non native
120 return gst_video_overlay_rectangle_get_pixels_unscaled_argb(rect,
121 &width, &height, &stride, flags);
124 #define overlay_rectangle_ref(overlay) \
125 gst_vaapi_mini_object_ref(GST_VAAPI_MINI_OBJECT(overlay))
127 #define overlay_rectangle_unref(overlay) \
128 gst_vaapi_mini_object_unref(GST_VAAPI_MINI_OBJECT(overlay))
130 #define overlay_rectangle_replace(old_overlay_ptr, new_overlay) \
131 gst_vaapi_mini_object_replace((GstVaapiMiniObject **)(old_overlay_ptr), \
132 (GstVaapiMiniObject *)(new_overlay))
135 overlay_rectangle_finalize(GstVaapiOverlayRectangle *overlay);
138 overlay_rectangle_associate(GstVaapiOverlayRectangle *overlay);
141 overlay_rectangle_deassociate(GstVaapiOverlayRectangle *overlay);
143 static inline const GstVaapiMiniObjectClass *
144 overlay_rectangle_class(void)
146 static const GstVaapiMiniObjectClass GstVaapiOverlayRectangleClass = {
147 sizeof(GstVaapiOverlayRectangle),
148 (GDestroyNotify)overlay_rectangle_finalize
150 return &GstVaapiOverlayRectangleClass;
153 static GstVaapiOverlayRectangle *
154 overlay_rectangle_new(GstVideoOverlayRectangle *rect, GstVaapiContext *context,
157 GstVaapiOverlayRectangle *overlay;
158 GstVaapiRectangle *render_rect;
162 overlay = (GstVaapiOverlayRectangle *)
163 gst_vaapi_mini_object_new0(overlay_rectangle_class());
167 overlay->context = context;
168 overlay->seq_num = gst_video_overlay_rectangle_get_seqnum(rect);
169 overlay->layer_id = layer_id;
170 overlay->rect = gst_video_overlay_rectangle_ref(rect);
172 gst_buffer_replace(&overlay->rect_buffer,
173 gst_video_overlay_rectangle_get_pixels_raw(rect));
174 if (!overlay->rect_buffer)
177 overlay->subpicture = gst_vaapi_subpicture_new_from_overlay_rectangle(
178 GST_VAAPI_OBJECT_DISPLAY(context), rect);
179 if (!overlay->subpicture)
182 gst_video_overlay_rectangle_get_render_rectangle(rect,
183 &x, &y, &width, &height);
184 render_rect = &overlay->render_rect;
187 render_rect->width = width;
188 render_rect->height = height;
192 overlay_rectangle_unref(overlay);
197 overlay_rectangle_finalize(GstVaapiOverlayRectangle *overlay)
199 gst_buffer_replace(&overlay->rect_buffer, NULL);
200 gst_video_overlay_rectangle_unref(overlay->rect);
202 if (overlay->subpicture) {
203 overlay_rectangle_deassociate(overlay);
204 g_object_unref(overlay->subpicture);
205 overlay->subpicture = NULL;
210 overlay_rectangle_associate(GstVaapiOverlayRectangle *overlay)
212 GstVaapiSubpicture * const subpicture = overlay->subpicture;
213 GPtrArray * const surfaces = overlay->context->priv->surfaces;
214 guint i, n_associated;
216 if (overlay->is_associated)
220 for (i = 0; i < surfaces->len; i++) {
221 GstVaapiSurface * const surface = g_ptr_array_index(surfaces, i);
222 if (gst_vaapi_surface_associate_subpicture(surface, subpicture,
223 NULL, &overlay->render_rect))
227 overlay->is_associated = TRUE;
228 return n_associated == surfaces->len;
232 overlay_rectangle_deassociate(GstVaapiOverlayRectangle *overlay)
234 GstVaapiSubpicture * const subpicture = overlay->subpicture;
235 GPtrArray * const surfaces = overlay->context->priv->surfaces;
236 guint i, n_associated;
238 if (!overlay->is_associated)
241 n_associated = surfaces->len;
242 for (i = 0; i < surfaces->len; i++) {
243 GstVaapiSurface * const surface = g_ptr_array_index(surfaces, i);
244 if (gst_vaapi_surface_deassociate_subpicture(surface, subpicture))
248 overlay->is_associated = FALSE;
249 return n_associated == 0;
253 overlay_rectangle_changed_pixels(GstVaapiOverlayRectangle *overlay,
254 GstVideoOverlayRectangle *rect)
256 guint width, height, stride, flags;
259 if (overlay->seq_num == gst_video_overlay_rectangle_get_seqnum(rect))
262 flags = to_GstVideoOverlayFormatFlags(
263 gst_vaapi_subpicture_get_flags(overlay->subpicture));
265 buffer = gst_video_overlay_rectangle_get_pixels_unscaled_argb(rect,
266 &width, &height, &stride, flags);
267 return GST_BUFFER_DATA(overlay->rect_buffer) != GST_BUFFER_DATA(buffer);
271 overlay_rectangle_changed_render_rect(GstVaapiOverlayRectangle *overlay,
272 GstVideoOverlayRectangle *rect)
274 GstVaapiRectangle * const render_rect = &overlay->render_rect;
278 gst_video_overlay_rectangle_get_render_rectangle(rect,
279 &x, &y, &width, &height);
281 if (x == render_rect->x &&
282 y == render_rect->y &&
283 width == render_rect->width &&
284 height == render_rect->height)
289 render_rect->width = width;
290 render_rect->height = height;
294 static inline gboolean
295 overlay_rectangle_update_global_alpha(GstVaapiOverlayRectangle *overlay,
296 GstVideoOverlayRectangle *rect)
298 #ifdef HAVE_GST_VIDEO_OVERLAY_HWCAPS
299 const guint flags = gst_video_overlay_rectangle_get_flags(rect);
300 if (!(flags & GST_VIDEO_OVERLAY_FORMAT_FLAG_GLOBAL_ALPHA))
303 return gst_vaapi_subpicture_set_global_alpha(overlay->subpicture,
304 gst_video_overlay_rectangle_get_global_alpha(rect));
308 overlay_rectangle_update(GstVaapiOverlayRectangle *overlay,
309 GstVideoOverlayRectangle *rect, gboolean *reassociate_ptr)
311 if (overlay_rectangle_changed_pixels(overlay, rect))
313 if (overlay_rectangle_changed_render_rect(overlay, rect))
314 *reassociate_ptr = TRUE;
315 if (!overlay_rectangle_update_global_alpha(overlay, rect))
317 gst_video_overlay_rectangle_replace(&overlay->rect, rect);
321 static inline GPtrArray *
324 return g_ptr_array_new_with_free_func(
325 (GDestroyNotify)gst_vaapi_mini_object_unref);
329 overlay_destroy(GPtrArray **overlay_ptr)
331 GPtrArray * const overlay = *overlay_ptr;
335 g_ptr_array_unref(overlay);
340 overlay_clear(GPtrArray *overlay)
342 if (overlay && overlay->len > 0)
343 g_ptr_array_remove_range(overlay, 0, overlay->len);
346 static GstVaapiOverlayRectangle *
347 overlay_lookup(GPtrArray *overlays, GstVideoOverlayRectangle *rect)
351 for (i = 0; i < overlays->len; i++) {
352 GstVaapiOverlayRectangle * const overlay =
353 g_ptr_array_index(overlays, i);
355 if (overlay->rect == rect)
362 overlay_reassociate(GPtrArray *overlays)
366 for (i = 0; i < overlays->len; i++)
367 overlay_rectangle_deassociate(g_ptr_array_index(overlays, i));
369 for (i = 0; i < overlays->len; i++) {
370 if (!overlay_rectangle_associate(g_ptr_array_index(overlays, i)))
377 gst_vaapi_context_clear_overlay(GstVaapiContext *context)
379 GstVaapiContextPrivate * const priv = context->priv;
381 overlay_clear(priv->overlays[0]);
382 overlay_clear(priv->overlays[1]);
383 priv->overlay_id = 0;
387 gst_vaapi_context_destroy_overlay(GstVaapiContext *context)
389 gst_vaapi_context_clear_overlay(context);
393 unref_surface_cb(gpointer data, gpointer user_data)
395 GstVaapiSurface * const surface = GST_VAAPI_SURFACE(data);
397 gst_vaapi_surface_set_parent_context(surface, NULL);
398 g_object_unref(surface);
402 gst_vaapi_context_destroy_surfaces(GstVaapiContext *context)
404 GstVaapiContextPrivate * const priv = context->priv;
406 gst_vaapi_context_destroy_overlay(context);
408 if (priv->surfaces) {
409 g_ptr_array_foreach(priv->surfaces, unref_surface_cb, NULL);
410 g_ptr_array_free(priv->surfaces, TRUE);
411 priv->surfaces = NULL;
414 g_clear_object(&priv->surfaces_pool);
418 gst_vaapi_context_destroy(GstVaapiContext *context)
420 GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(context);
421 GstVaapiContextPrivate * const priv = context->priv;
422 VAContextID context_id;
425 context_id = GST_VAAPI_OBJECT_ID(context);
426 GST_DEBUG("context %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS(context_id));
428 if (context_id != VA_INVALID_ID) {
429 GST_VAAPI_DISPLAY_LOCK(display);
430 status = vaDestroyContext(
431 GST_VAAPI_DISPLAY_VADISPLAY(display),
434 GST_VAAPI_DISPLAY_UNLOCK(display);
435 if (!vaapi_check_status(status, "vaDestroyContext()"))
436 g_warning("failed to destroy context %" GST_VAAPI_ID_FORMAT,
437 GST_VAAPI_ID_ARGS(context_id));
438 GST_VAAPI_OBJECT_ID(context) = VA_INVALID_ID;
441 if (priv->config_id != VA_INVALID_ID) {
442 GST_VAAPI_DISPLAY_LOCK(display);
443 status = vaDestroyConfig(
444 GST_VAAPI_DISPLAY_VADISPLAY(display),
447 GST_VAAPI_DISPLAY_UNLOCK(display);
448 if (!vaapi_check_status(status, "vaDestroyConfig()"))
449 g_warning("failed to destroy config %" GST_VAAPI_ID_FORMAT,
450 GST_VAAPI_ID_ARGS(priv->config_id));
451 priv->config_id = VA_INVALID_ID;
456 gst_vaapi_context_create_overlay(GstVaapiContext *context)
458 GstVaapiContextPrivate * const priv = context->priv;
460 if (!priv->overlays[0] || !priv->overlays[1])
463 gst_vaapi_context_clear_overlay(context);
468 gst_vaapi_context_create_surfaces(GstVaapiContext *context)
470 GstVaapiContextPrivate * const priv = context->priv;
472 GstVaapiSurface *surface;
473 guint i, num_surfaces;
475 /* Number of scratch surfaces beyond those used as reference */
476 const guint SCRATCH_SURFACES_COUNT = 4;
478 if (!gst_vaapi_context_create_overlay(context))
481 if (!priv->surfaces) {
482 priv->surfaces = g_ptr_array_new();
487 if (!priv->surfaces_pool) {
488 caps = gst_caps_new_simple(
489 GST_VAAPI_SURFACE_CAPS_NAME,
490 "type", G_TYPE_STRING, "vaapi",
491 "width", G_TYPE_INT, priv->width,
492 "height", G_TYPE_INT, priv->height,
497 priv->surfaces_pool = gst_vaapi_surface_pool_new(
498 GST_VAAPI_OBJECT_DISPLAY(context),
501 gst_caps_unref(caps);
502 if (!priv->surfaces_pool)
506 num_surfaces = priv->ref_frames + SCRATCH_SURFACES_COUNT;
507 gst_vaapi_video_pool_set_capacity(priv->surfaces_pool, num_surfaces);
509 for (i = priv->surfaces->len; i < num_surfaces; i++) {
510 surface = gst_vaapi_surface_new(
511 GST_VAAPI_OBJECT_DISPLAY(context),
512 GST_VAAPI_CHROMA_TYPE_YUV420,
513 priv->width, priv->height
517 g_ptr_array_add(priv->surfaces, surface);
518 if (!gst_vaapi_video_pool_add_object(priv->surfaces_pool, surface))
525 gst_vaapi_context_create(GstVaapiContext *context)
527 GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(context);
528 GstVaapiContextPrivate * const priv = context->priv;
529 VAProfile va_profile;
530 VAEntrypoint va_entrypoint;
531 VAConfigAttrib attrib;
532 VAContextID context_id;
533 VASurfaceID surface_id;
535 GArray *surfaces = NULL;
536 gboolean success = FALSE;
539 if (!priv->surfaces && !gst_vaapi_context_create_surfaces(context))
542 surfaces = g_array_sized_new(
551 for (i = 0; i < priv->surfaces->len; i++) {
552 GstVaapiSurface * const surface = g_ptr_array_index(priv->surfaces, i);
555 surface_id = GST_VAAPI_OBJECT_ID(surface);
556 g_array_append_val(surfaces, surface_id);
558 assert(surfaces->len == priv->surfaces->len);
560 if (!priv->profile || !priv->entrypoint)
562 va_profile = gst_vaapi_profile_get_va_profile(priv->profile);
563 va_entrypoint = gst_vaapi_entrypoint_get_va_entrypoint(priv->entrypoint);
565 GST_VAAPI_DISPLAY_LOCK(display);
566 attrib.type = VAConfigAttribRTFormat;
567 status = vaGetConfigAttributes(
568 GST_VAAPI_DISPLAY_VADISPLAY(display),
573 GST_VAAPI_DISPLAY_UNLOCK(display);
574 if (!vaapi_check_status(status, "vaGetConfigAttributes()"))
576 if (!(attrib.value & VA_RT_FORMAT_YUV420))
579 GST_VAAPI_DISPLAY_LOCK(display);
580 status = vaCreateConfig(
581 GST_VAAPI_DISPLAY_VADISPLAY(display),
587 GST_VAAPI_DISPLAY_UNLOCK(display);
588 if (!vaapi_check_status(status, "vaCreateConfig()"))
591 GST_VAAPI_DISPLAY_LOCK(display);
592 status = vaCreateContext(
593 GST_VAAPI_DISPLAY_VADISPLAY(display),
595 priv->width, priv->height,
597 (VASurfaceID *)surfaces->data, surfaces->len,
600 GST_VAAPI_DISPLAY_UNLOCK(display);
601 if (!vaapi_check_status(status, "vaCreateContext()"))
604 GST_DEBUG("context %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS(context_id));
605 GST_VAAPI_OBJECT_ID(context) = context_id;
609 g_array_free(surfaces, TRUE);
614 gst_vaapi_context_finalize(GObject *object)
616 GstVaapiContext * const context = GST_VAAPI_CONTEXT(object);
617 GstVaapiContextPrivate * const priv = context->priv;
619 overlay_destroy(&priv->overlays[0]);
620 overlay_destroy(&priv->overlays[1]);
621 gst_vaapi_context_destroy(context);
622 gst_vaapi_context_destroy_surfaces(context);
624 G_OBJECT_CLASS(gst_vaapi_context_parent_class)->finalize(object);
628 gst_vaapi_context_set_property(
635 GstVaapiContext * const context = GST_VAAPI_CONTEXT(object);
636 GstVaapiContextPrivate * const priv = context->priv;
640 gst_vaapi_context_set_profile(context, g_value_get_uint(value));
642 case PROP_ENTRYPOINT:
643 priv->entrypoint = g_value_get_uint(value);
646 priv->width = g_value_get_uint(value);
649 priv->height = g_value_get_uint(value);
651 case PROP_REF_FRAMES:
652 priv->ref_frames = g_value_get_uint(value);
655 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
661 gst_vaapi_context_get_property(
668 GstVaapiContext * const context = GST_VAAPI_CONTEXT(object);
669 GstVaapiContextPrivate * const priv = context->priv;
673 g_value_set_uint(value, gst_vaapi_context_get_profile(context));
675 case PROP_ENTRYPOINT:
676 g_value_set_uint(value, gst_vaapi_context_get_entrypoint(context));
679 g_value_set_uint(value, priv->width);
682 g_value_set_uint(value, priv->height);
684 case PROP_REF_FRAMES:
685 g_value_set_uint(value, priv->ref_frames);
688 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
694 gst_vaapi_context_class_init(GstVaapiContextClass *klass)
696 GObjectClass * const object_class = G_OBJECT_CLASS(klass);
698 g_type_class_add_private(klass, sizeof(GstVaapiContextPrivate));
700 object_class->finalize = gst_vaapi_context_finalize;
701 object_class->set_property = gst_vaapi_context_set_property;
702 object_class->get_property = gst_vaapi_context_get_property;
704 g_object_class_install_property
707 g_param_spec_uint("profile",
709 "The profile used for decoding",
713 g_object_class_install_property
716 g_param_spec_uint("entrypoint",
718 "The decoder entrypoint",
720 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
722 g_object_class_install_property
725 g_param_spec_uint("width",
727 "The width of decoded surfaces",
729 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
731 g_object_class_install_property
734 g_param_spec_uint("height",
736 "The height of the decoded surfaces",
738 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
740 g_object_class_install_property
743 g_param_spec_uint("ref-frames",
745 "The number of reference frames",
747 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
751 gst_vaapi_context_init(GstVaapiContext *context)
753 GstVaapiContextPrivate *priv = GST_VAAPI_CONTEXT_GET_PRIVATE(context);
755 context->priv = priv;
756 priv->config_id = VA_INVALID_ID;
757 priv->surfaces = NULL;
758 priv->surfaces_pool = NULL;
759 priv->overlays[0] = overlay_new();
760 priv->overlays[1] = overlay_new();
762 priv->entrypoint = 0;
765 priv->ref_frames = 0;
769 * gst_vaapi_context_new:
770 * @display: a #GstVaapiDisplay
771 * @profile: a #GstVaapiProfile
772 * @entrypoint: a #GstVaapiEntrypoint
773 * @width: coded width from the bitstream
774 * @height: coded height from the bitstream
776 * Creates a new #GstVaapiContext with the specified codec @profile
779 * Return value: the newly allocated #GstVaapiContext object
782 gst_vaapi_context_new(
783 GstVaapiDisplay *display,
784 GstVaapiProfile profile,
785 GstVaapiEntrypoint entrypoint,
790 GstVaapiContextInfo info;
792 info.profile = profile;
793 info.entrypoint = entrypoint;
795 info.height = height;
796 info.ref_frames = get_max_ref_frames(profile);
797 return gst_vaapi_context_new_full(display, &info);
801 * gst_vaapi_context_new_full:
802 * @display: a #GstVaapiDisplay
803 * @cip: a pointer to the #GstVaapiContextInfo
805 * Creates a new #GstVaapiContext with the configuration specified by
806 * @cip, thus including profile, entry-point, encoded size and maximum
807 * number of reference frames reported by the bitstream.
809 * Return value: the newly allocated #GstVaapiContext object
812 gst_vaapi_context_new_full(GstVaapiDisplay *display, GstVaapiContextInfo *cip)
814 GstVaapiContext *context;
816 g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
817 g_return_val_if_fail(cip->profile, NULL);
818 g_return_val_if_fail(cip->entrypoint, NULL);
819 g_return_val_if_fail(cip->width > 0, NULL);
820 g_return_val_if_fail(cip->height > 0, NULL);
822 context = g_object_new(
823 GST_VAAPI_TYPE_CONTEXT,
825 "id", GST_VAAPI_ID(VA_INVALID_ID),
826 "profile", cip->profile,
827 "entrypoint", cip->entrypoint,
829 "height", cip->height,
830 "ref-frames", cip->ref_frames,
833 if (!context->priv->is_constructed) {
834 g_object_unref(context);
841 * gst_vaapi_context_reset:
842 * @context: a #GstVaapiContext
843 * @profile: a #GstVaapiProfile
844 * @entrypoint: a #GstVaapiEntrypoint
845 * @width: coded width from the bitstream
846 * @height: coded height from the bitstream
848 * Resets @context to the specified codec @profile and @entrypoint.
849 * The surfaces will be reallocated if the coded size changed.
851 * Return value: %TRUE on success
854 gst_vaapi_context_reset(
855 GstVaapiContext *context,
856 GstVaapiProfile profile,
857 GstVaapiEntrypoint entrypoint,
862 GstVaapiContextPrivate * const priv = context->priv;
863 GstVaapiContextInfo info;
865 info.profile = profile;
866 info.entrypoint = entrypoint;
868 info.height = height;
869 info.ref_frames = priv->ref_frames;
871 return gst_vaapi_context_reset_full(context, &info);
875 * gst_vaapi_context_reset_full:
876 * @context: a #GstVaapiContext
877 * @cip: a pointer to the new #GstVaapiContextInfo details
879 * Resets @context to the configuration specified by @cip, thus
880 * including profile, entry-point, encoded size and maximum number of
881 * reference frames reported by the bitstream.
883 * Return value: %TRUE on success
886 gst_vaapi_context_reset_full(GstVaapiContext *context, GstVaapiContextInfo *cip)
888 GstVaapiContextPrivate * const priv = context->priv;
889 gboolean size_changed, codec_changed;
891 size_changed = priv->width != cip->width || priv->height != cip->height;
893 gst_vaapi_context_destroy_surfaces(context);
894 priv->width = cip->width;
895 priv->height = cip->height;
898 codec_changed = priv->profile != cip->profile || priv->entrypoint != cip->entrypoint;
900 gst_vaapi_context_destroy(context);
901 priv->profile = cip->profile;
902 priv->entrypoint = cip->entrypoint;
905 if (size_changed && !gst_vaapi_context_create_surfaces(context))
908 if (codec_changed && !gst_vaapi_context_create(context))
911 priv->is_constructed = TRUE;
916 * gst_vaapi_context_get_id:
917 * @context: a #GstVaapiContext
919 * Returns the underlying VAContextID of the @context.
921 * Return value: the underlying VA context id
924 gst_vaapi_context_get_id(GstVaapiContext *context)
926 g_return_val_if_fail(GST_VAAPI_IS_CONTEXT(context), VA_INVALID_ID);
928 return GST_VAAPI_OBJECT_ID(context);
932 * gst_vaapi_context_get_profile:
933 * @context: a #GstVaapiContext
935 * Returns the VA profile used by the @context.
937 * Return value: the VA profile used by the @context
940 gst_vaapi_context_get_profile(GstVaapiContext *context)
942 g_return_val_if_fail(GST_VAAPI_IS_CONTEXT(context), 0);
944 return context->priv->profile;
948 * gst_vaapi_context_set_profile:
949 * @context: a #GstVaapiContext
950 * @profile: the new #GstVaapiProfile to use
952 * Sets the new @profile to use with the @context. If @profile matches
953 * the previous profile, this call has no effect. Otherwise, the
954 * underlying VA context is recreated, while keeping the previously
955 * allocated surfaces.
957 * Return value: %TRUE on success
960 gst_vaapi_context_set_profile(GstVaapiContext *context, GstVaapiProfile profile)
962 g_return_val_if_fail(GST_VAAPI_IS_CONTEXT(context), FALSE);
963 g_return_val_if_fail(profile, FALSE);
965 return gst_vaapi_context_reset(context,
967 context->priv->entrypoint,
968 context->priv->width,
969 context->priv->height);
973 * gst_vaapi_context_get_entrypoint:
974 * @context: a #GstVaapiContext
976 * Returns the VA entrypoint used by the @context
978 * Return value: the VA entrypoint used by the @context
981 gst_vaapi_context_get_entrypoint(GstVaapiContext *context)
983 g_return_val_if_fail(GST_VAAPI_IS_CONTEXT(context), 0);
985 return context->priv->entrypoint;
989 * gst_vaapi_context_get_size:
990 * @context: a #GstVaapiContext
991 * @pwidth: return location for the width, or %NULL
992 * @pheight: return location for the height, or %NULL
994 * Retrieves the size of the surfaces attached to @context.
997 gst_vaapi_context_get_size(
998 GstVaapiContext *context,
1003 g_return_if_fail(GST_VAAPI_IS_CONTEXT(context));
1006 *pwidth = context->priv->width;
1009 *pheight = context->priv->height;
1013 * gst_vaapi_context_get_surface:
1014 * @context: a #GstVaapiContext
1016 * Acquires a free surface. The returned surface but be released with
1017 * gst_vaapi_context_put_surface(). This function returns %NULL if
1018 * there is no free surface available in the pool. The surfaces are
1019 * pre-allocated during context creation though.
1021 * Return value: a free surface, or %NULL if none is available
1024 gst_vaapi_context_get_surface(GstVaapiContext *context)
1026 GstVaapiSurface *surface;
1028 g_return_val_if_fail(GST_VAAPI_IS_CONTEXT(context), NULL);
1030 surface = gst_vaapi_video_pool_get_object(context->priv->surfaces_pool);
1034 gst_vaapi_surface_set_parent_context(surface, context);
1039 * gst_vaapi_context_get_surface_count:
1040 * @context: a #GstVaapiContext
1042 * Retrieves the number of free surfaces left in the pool.
1044 * Return value: the number of free surfaces available in the pool
1047 gst_vaapi_context_get_surface_count(GstVaapiContext *context)
1049 g_return_val_if_fail(GST_VAAPI_IS_CONTEXT(context), 0);
1051 return gst_vaapi_video_pool_get_size(context->priv->surfaces_pool);
1055 * gst_vaapi_context_put_surface:
1056 * @context: a #GstVaapiContext
1057 * @surface: the #GstVaapiSurface to release
1059 * Releases a surface acquired by gst_vaapi_context_get_surface().
1062 gst_vaapi_context_put_surface(GstVaapiContext *context, GstVaapiSurface *surface)
1064 g_return_if_fail(GST_VAAPI_IS_CONTEXT(context));
1065 g_return_if_fail(GST_VAAPI_IS_SURFACE(surface));
1067 gst_vaapi_surface_set_parent_context(surface, NULL);
1068 gst_vaapi_video_pool_put_object(context->priv->surfaces_pool, surface);
1072 * gst_vaapi_context_find_surface_by_id:
1073 * @context: a #GstVaapiContext
1074 * @id: the VA surface id to find
1076 * Finds VA surface by @id in the list of surfaces attached to the @context.
1078 * Return value: the matching #GstVaapiSurface object, or %NULL if
1082 gst_vaapi_context_find_surface_by_id(GstVaapiContext *context, GstVaapiID id)
1084 GstVaapiContextPrivate *priv;
1085 GstVaapiSurface *surface;
1088 g_return_val_if_fail(GST_VAAPI_IS_CONTEXT(context), NULL);
1090 priv = context->priv;
1091 g_return_val_if_fail(priv->surfaces, NULL);
1093 for (i = 0; i < priv->surfaces->len; i++) {
1094 surface = g_ptr_array_index(priv->surfaces, i);
1095 if (GST_VAAPI_OBJECT_ID(surface) == id)
1102 * gst_vaapi_context_apply_composition:
1103 * @context: a #GstVaapiContext
1104 * @composition: a #GstVideoOverlayComposition
1106 * Applies video composition planes to all surfaces bound to @context.
1107 * This helper function resets any additional subpictures the user may
1108 * have associated himself. A %NULL @composition will also clear all
1109 * the existing subpictures.
1111 * Return value: %TRUE if all composition planes could be applied,
1115 gst_vaapi_context_apply_composition(
1116 GstVaapiContext *context,
1117 GstVideoOverlayComposition *composition
1120 GstVaapiContextPrivate *priv;
1121 GPtrArray *curr_overlay, *next_overlay;
1122 guint i, n_rectangles;
1123 gboolean reassociate = FALSE;
1125 g_return_val_if_fail(GST_VAAPI_IS_CONTEXT(context), FALSE);
1127 priv = context->priv;
1129 if (!priv->surfaces)
1133 gst_vaapi_context_clear_overlay(context);
1137 curr_overlay = priv->overlays[priv->overlay_id];
1138 next_overlay = priv->overlays[priv->overlay_id ^ 1];
1139 overlay_clear(next_overlay);
1141 n_rectangles = gst_video_overlay_composition_n_rectangles(composition);
1142 for (i = 0; i < n_rectangles; i++) {
1143 GstVideoOverlayRectangle * const rect =
1144 gst_video_overlay_composition_get_rectangle(composition, i);
1145 GstVaapiOverlayRectangle *overlay;
1147 overlay = overlay_lookup(curr_overlay, rect);
1148 if (overlay && overlay_rectangle_update(overlay, rect, &reassociate)) {
1149 overlay_rectangle_ref(overlay);
1150 if (overlay->layer_id != i)
1154 overlay = overlay_rectangle_new(rect, context, i);
1156 GST_WARNING("could not create VA overlay rectangle");
1161 g_ptr_array_add(next_overlay, overlay);
1164 overlay_clear(curr_overlay);
1165 priv->overlay_id ^= 1;
1167 if (reassociate && !overlay_reassociate(next_overlay))
1172 gst_vaapi_context_clear_overlay(context);