Drop introspection annotations since they require gtk-doc >= 1.12.
[platform/upstream/gstreamer-vaapi.git] / gst-libs / gst / vaapi / gstvaapidisplay.c
1 /*
2  *  gstvaapidisplay.c - VA display abstraction
3  *
4  *  gstreamer-vaapi (C) 2010 Splitted-Desktop Systems
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
19  */
20
21 /**
22  * SECTION:gst-vaapi-display
23  * @short_description:
24  */
25
26 #include "config.h"
27 #include "gstvaapiutils.h"
28 #include "gstvaapidisplay.h"
29 #include <va/va_backend.h>
30
31 #define DEBUG 1
32 #include "gstvaapidebug.h"
33
34 GST_DEBUG_CATEGORY(gst_debug_vaapi);
35
36 G_DEFINE_TYPE(GstVaapiDisplay, gst_vaapi_display, G_TYPE_OBJECT);
37
38 #define GST_VAAPI_DISPLAY_GET_PRIVATE(obj)                      \
39     (G_TYPE_INSTANCE_GET_PRIVATE((obj),                         \
40                                  GST_VAAPI_TYPE_DISPLAY,        \
41                                  GstVaapiDisplayPrivate))
42
43 struct _GstVaapiDisplayPrivate {
44     GStaticMutex        mutex;
45     VADisplay           display;
46     guint               width;
47     guint               height;
48     guint               width_mm;
49     guint               height_mm;
50     guint               par_n;
51     guint               par_d;
52     gboolean            create_display;
53     GArray             *profiles;
54     GArray             *image_formats;
55     GArray             *subpicture_formats;
56 };
57
58 enum {
59     PROP_0,
60
61     PROP_DISPLAY,
62     PROP_WIDTH,
63     PROP_HEIGHT
64 };
65
66 /* Append GstVaapiImageFormat to formats array */
67 static inline void
68 append_format(GArray *formats, GstVaapiImageFormat format)
69 {
70     g_array_append_val(formats, format);
71 }
72
73 /* Append VAImageFormats to formats array */
74 static void
75 append_formats(GArray *formats, const VAImageFormat *va_formats, guint n)
76 {
77     GstVaapiImageFormat format;
78     gboolean has_YV12 = FALSE;
79     gboolean has_I420 = FALSE;
80     guint i;
81
82     for (i = 0; i < n; i++) {
83         const VAImageFormat * const va_format = &va_formats[i];
84
85         format = gst_vaapi_image_format(va_format);
86         if (!format) {
87             GST_DEBUG("unsupported format %" GST_FOURCC_FORMAT,
88                       GST_FOURCC_ARGS(va_format->fourcc));
89             continue;
90         }
91
92         switch (format) {
93         case GST_VAAPI_IMAGE_YV12:
94             has_YV12 = TRUE;
95             break;
96         case GST_VAAPI_IMAGE_I420:
97             has_I420 = TRUE;
98             break;
99         default:
100             break;
101         }
102         append_format(formats, format);
103     }
104
105     /* Append I420 (resp. YV12) format if YV12 (resp. I420) is not
106        supported by the underlying driver */
107     if (has_YV12 && !has_I420)
108         append_format(formats, GST_VAAPI_IMAGE_I420);
109     else if (has_I420 && !has_YV12)
110         append_format(formats, GST_VAAPI_IMAGE_YV12);
111 }
112
113 /* Sort image formats. Prefer YUV formats first */
114 static gint
115 compare_yuv_formats(gconstpointer a, gconstpointer b)
116 {
117     const GstVaapiImageFormat fmt1 = *(GstVaapiImageFormat *)a;
118     const GstVaapiImageFormat fmt2 = *(GstVaapiImageFormat *)b;
119
120     const gboolean is_fmt1_yuv = gst_vaapi_image_format_is_yuv(fmt1);
121     const gboolean is_fmt2_yuv = gst_vaapi_image_format_is_yuv(fmt2);
122
123     if (is_fmt1_yuv != is_fmt2_yuv)
124         return is_fmt1_yuv ? -1 : 1;
125
126     return ((gint)gst_vaapi_image_format_get_score(fmt1) -
127             (gint)gst_vaapi_image_format_get_score(fmt2));
128 }
129
130 /* Sort subpicture formats. Prefer RGB formats first */
131 static gint
132 compare_rgb_formats(gconstpointer a, gconstpointer b)
133 {
134     const GstVaapiImageFormat fmt1 = *(GstVaapiImageFormat *)a;
135     const GstVaapiImageFormat fmt2 = *(GstVaapiImageFormat *)b;
136
137     const gboolean is_fmt1_rgb = gst_vaapi_image_format_is_rgb(fmt1);
138     const gboolean is_fmt2_rgb = gst_vaapi_image_format_is_rgb(fmt2);
139
140     if (is_fmt1_rgb != is_fmt2_rgb)
141         return is_fmt1_rgb ? -1 : 1;
142
143     return ((gint)gst_vaapi_image_format_get_score(fmt1) -
144             (gint)gst_vaapi_image_format_get_score(fmt2));
145 }
146
147 /* Check if profiles array contains profile */
148 static inline gboolean
149 find_profile(GArray *profiles, VAProfile profile)
150 {
151     guint i;
152
153     for (i = 0; i < profiles->len; i++)
154         if (g_array_index(profiles, VAProfile, i) == profile)
155             return TRUE;
156     return FALSE;
157 }
158
159 /* Check if formats array contains format */
160 static inline gboolean
161 find_format(GArray *formats, GstVaapiImageFormat format)
162 {
163     guint i;
164
165     for (i = 0; i < formats->len; i++)
166         if (g_array_index(formats, GstVaapiImageFormat, i) == format)
167             return TRUE;
168     return FALSE;
169 }
170
171 /* Convert formats array to GstCaps */
172 static GstCaps *
173 get_caps(GArray *formats)
174 {
175     GstVaapiImageFormat format;
176     GstCaps *out_caps, *caps;
177     guint i;
178
179     out_caps = gst_caps_new_empty();
180     if (!out_caps)
181         return NULL;
182
183     for (i = 0; i < formats->len; i++) {
184         format = g_array_index(formats, GstVaapiImageFormat, i);
185         caps   = gst_vaapi_image_format_get_caps(format);
186         if (caps)
187             gst_caps_append(out_caps, caps);
188     }
189     return out_caps;
190 }
191
192 static void
193 gst_vaapi_display_calculate_pixel_aspect_ratio(GstVaapiDisplay *display)
194 {
195     GstVaapiDisplayPrivate * const priv = display->priv;
196     gdouble ratio, delta;
197     gint i, index;
198
199     static const gint par[][2] = {
200         {1, 1},         /* regular screen            */
201         {16, 15},       /* PAL TV                    */
202         {11, 10},       /* 525 line Rec.601 video    */
203         {54, 59},       /* 625 line Rec.601 video    */
204         {64, 45},       /* 1280x1024 on 16:9 display */
205         {5, 3},         /* 1280x1024 on  4:3 display */
206         {4, 3}          /*  800x600  on 16:9 display */
207     };
208
209     /* First, calculate the "real" ratio based on the X values;
210      * which is the "physical" w/h divided by the w/h in pixels of the
211      * display */
212     if (!priv->width || !priv->height || !priv->width_mm || !priv->height_mm)
213         ratio = 1.0;
214     else
215         ratio = (gdouble)(priv->width_mm * priv->height) /
216             (priv->height_mm * priv->width);
217     GST_DEBUG("calculated pixel aspect ratio: %f", ratio);
218
219     /* Now, find the one from par[][2] with the lowest delta to the real one */
220 #define DELTA(idx) (ABS(ratio - ((gdouble)par[idx][0] / par[idx][1])))
221     delta = DELTA(0);
222     index = 0;
223
224     for (i = 1; i < G_N_ELEMENTS(par); i++) {
225         const gdouble this_delta = DELTA(i);
226         if (this_delta < delta) {
227             index = i;
228             delta = this_delta;
229         }
230     }
231 #undef DELTA
232
233     priv->par_n = par[index][0];
234     priv->par_d = par[index][1];
235 }
236
237 static void
238 gst_vaapi_display_destroy(GstVaapiDisplay *display)
239 {
240     GstVaapiDisplayPrivate * const priv = display->priv;
241
242     if (priv->profiles) {
243         g_array_free(priv->profiles, TRUE);
244         priv->profiles = NULL;
245     }
246
247     if (priv->image_formats) {
248         g_array_free(priv->image_formats, TRUE);
249         priv->image_formats = NULL;
250     }
251
252     if (priv->subpicture_formats) {
253         g_array_free(priv->subpicture_formats, TRUE);
254         priv->subpicture_formats = NULL;
255     }
256
257     if (priv->display) {
258         vaTerminate(priv->display);
259         priv->display = NULL;
260     }
261
262     if (priv->create_display) {
263         GstVaapiDisplayClass *klass = GST_VAAPI_DISPLAY_GET_CLASS(display);
264         if (klass->close_display)
265             klass->close_display(display);
266     }
267 }
268
269 static gboolean
270 gst_vaapi_display_create(GstVaapiDisplay *display)
271 {
272     GstVaapiDisplayPrivate * const priv = display->priv;
273     gboolean            has_errors      = TRUE;
274     VAProfile          *profiles        = NULL;
275     VAImageFormat      *formats         = NULL;
276     unsigned int       *flags           = NULL;
277     gint                i, n, major_version, minor_version;
278     VAStatus            status;
279
280     if (!priv->display && priv->create_display) {
281         GstVaapiDisplayClass *klass = GST_VAAPI_DISPLAY_GET_CLASS(display);
282         if (klass->open_display && !klass->open_display(display))
283             return FALSE;
284         if (klass->get_display)
285             priv->display = klass->get_display(display);
286         if (klass->get_size)
287             klass->get_size(display, &priv->width, &priv->height);
288         if (klass->get_size_mm)
289             klass->get_size_mm(display, &priv->width_mm, &priv->height_mm);
290         gst_vaapi_display_calculate_pixel_aspect_ratio(display);
291     }
292     if (!priv->display)
293         return FALSE;
294
295     status = vaInitialize(priv->display, &major_version, &minor_version);
296     if (!vaapi_check_status(status, "vaInitialize()"))
297         goto end;
298     GST_DEBUG("VA-API version %d.%d", major_version, minor_version);
299
300     /* VA profiles */
301     profiles = g_new(VAProfile, vaMaxNumProfiles(priv->display));
302     if (!profiles)
303         goto end;
304     status = vaQueryConfigProfiles(priv->display, profiles, &n);
305     if (!vaapi_check_status(status, "vaQueryConfigProfiles()"))
306         goto end;
307
308     GST_DEBUG("%d profiles", n);
309     for (i = 0; i < n; i++)
310         GST_DEBUG("  %s", string_of_VAProfile(profiles[i]));
311
312     priv->profiles = g_array_new(FALSE, FALSE, sizeof(VAProfile));
313     if (!priv->profiles)
314         goto end;
315     g_array_append_vals(priv->profiles, profiles, n);
316
317     /* VA image formats */
318     formats = g_new(VAImageFormat, vaMaxNumImageFormats(priv->display));
319     if (!formats)
320         goto end;
321     status = vaQueryImageFormats(priv->display, formats, &n);
322     if (!vaapi_check_status(status, "vaQueryImageFormats()"))
323         goto end;
324
325     GST_DEBUG("%d image formats", n);
326     for (i = 0; i < n; i++)
327         GST_DEBUG("  %s", string_of_FOURCC(formats[i].fourcc));
328
329     priv->image_formats =
330         g_array_new(FALSE, FALSE, sizeof(GstVaapiImageFormat));
331     if (!priv->image_formats)
332         goto end;
333     append_formats(priv->image_formats, formats, n);
334     g_array_sort(priv->image_formats, compare_yuv_formats);
335
336     /* VA subpicture formats */
337     n = vaMaxNumSubpictureFormats(priv->display);
338     formats = g_renew(VAImageFormat, formats, n);
339     flags   = g_new(guint, n);
340     if (!formats || !flags)
341         goto end;
342     status = vaQuerySubpictureFormats(priv->display, formats, flags, &n);
343     if (!vaapi_check_status(status, "vaQuerySubpictureFormats()"))
344         goto end;
345
346     GST_DEBUG("%d subpicture formats", n);
347     for (i = 0; i < n; i++)
348         GST_DEBUG("  %s", string_of_FOURCC(formats[i].fourcc));
349
350     priv->subpicture_formats =
351         g_array_new(FALSE, FALSE, sizeof(GstVaapiImageFormat));
352     if (!priv->subpicture_formats)
353         goto end;
354     append_formats(priv->subpicture_formats, formats, n);
355     g_array_sort(priv->subpicture_formats, compare_rgb_formats);
356
357     has_errors = FALSE;
358 end:
359     g_free(profiles);
360     g_free(formats);
361     g_free(flags);
362     return !has_errors;
363 }
364
365 static void
366 gst_vaapi_display_lock_default(GstVaapiDisplay *display)
367 {
368     g_static_mutex_lock(&display->priv->mutex);
369 }
370
371 static void
372 gst_vaapi_display_unlock_default(GstVaapiDisplay *display)
373 {
374     g_static_mutex_unlock(&display->priv->mutex);
375 }
376
377 static void
378 gst_vaapi_display_finalize(GObject *object)
379 {
380     GstVaapiDisplay * const display = GST_VAAPI_DISPLAY(object);
381
382     gst_vaapi_display_destroy(display);
383
384     G_OBJECT_CLASS(gst_vaapi_display_parent_class)->finalize(object);
385 }
386
387 static void
388 gst_vaapi_display_set_property(
389     GObject      *object,
390     guint         prop_id,
391     const GValue *value,
392     GParamSpec   *pspec
393 )
394 {
395     GstVaapiDisplay * const display = GST_VAAPI_DISPLAY(object);
396
397     switch (prop_id) {
398     case PROP_DISPLAY:
399         display->priv->display = g_value_get_pointer(value);
400         break;
401     default:
402         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
403         break;
404     }
405 }
406
407 static void
408 gst_vaapi_display_get_property(
409     GObject    *object,
410     guint       prop_id,
411     GValue     *value,
412     GParamSpec *pspec
413 )
414 {
415     GstVaapiDisplay * const display = GST_VAAPI_DISPLAY(object);
416
417     switch (prop_id) {
418     case PROP_DISPLAY:
419         g_value_set_pointer(value, gst_vaapi_display_get_display(display));
420         break;
421     case PROP_WIDTH:
422         g_value_set_uint(value, gst_vaapi_display_get_width(display));
423         break;
424     case PROP_HEIGHT:
425         g_value_set_uint(value, gst_vaapi_display_get_height(display));
426         break;
427     default:
428         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
429         break;
430     }
431 }
432
433 static void
434 gst_vaapi_display_constructed(GObject *object)
435 {
436     GstVaapiDisplay * const display = GST_VAAPI_DISPLAY(object);
437     GObjectClass *parent_class;
438
439     display->priv->create_display = display->priv->display == NULL;
440     gst_vaapi_display_create(display);
441
442     parent_class = G_OBJECT_CLASS(gst_vaapi_display_parent_class);
443     if (parent_class->constructed)
444         parent_class->constructed(object);
445 }
446
447 static void
448 gst_vaapi_display_class_init(GstVaapiDisplayClass *klass)
449 {
450     GObjectClass * const object_class = G_OBJECT_CLASS(klass);
451     GstVaapiDisplayClass * const dpy_class = GST_VAAPI_DISPLAY_CLASS(klass);
452
453     GST_DEBUG_CATEGORY_INIT(gst_debug_vaapi, "vaapi", 0, "VA-API helper");
454
455     g_type_class_add_private(klass, sizeof(GstVaapiDisplayPrivate));
456
457     object_class->finalize      = gst_vaapi_display_finalize;
458     object_class->set_property  = gst_vaapi_display_set_property;
459     object_class->get_property  = gst_vaapi_display_get_property;
460     object_class->constructed   = gst_vaapi_display_constructed;
461
462     dpy_class->lock_display     = gst_vaapi_display_lock_default;
463     dpy_class->unlock_display   = gst_vaapi_display_unlock_default;
464
465     g_object_class_install_property
466         (object_class,
467          PROP_DISPLAY,
468          g_param_spec_pointer("display",
469                               "VA display",
470                               "VA display",
471                               G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
472
473     g_object_class_install_property
474         (object_class,
475          PROP_WIDTH,
476          g_param_spec_uint("width",
477                            "Width",
478                            "The display width",
479                            1, G_MAXUINT32, 1,
480                            G_PARAM_READABLE));
481
482     g_object_class_install_property
483         (object_class,
484          PROP_HEIGHT,
485          g_param_spec_uint("height",
486                            "height",
487                            "The display height",
488                            1, G_MAXUINT32, 1,
489                            G_PARAM_READABLE));
490 }
491
492 static void
493 gst_vaapi_display_init(GstVaapiDisplay *display)
494 {
495     GstVaapiDisplayPrivate *priv = GST_VAAPI_DISPLAY_GET_PRIVATE(display);
496
497     display->priv               = priv;
498     priv->display               = NULL;
499     priv->width                 = 0;
500     priv->height                = 0;
501     priv->width_mm              = 0;
502     priv->height_mm             = 0;
503     priv->par_n                 = 1;
504     priv->par_d                 = 1;
505     priv->create_display        = TRUE;
506     priv->profiles              = NULL;
507     priv->image_formats         = NULL;
508     priv->subpicture_formats    = NULL;
509
510     g_static_mutex_init(&priv->mutex);
511 }
512
513 /**
514  * gst_vaapi_display_new_with_display:
515  * @va_display: a #VADisplay
516  *
517  * Creates a new #GstVaapiDisplay, using @va_display as the VA
518  * display.
519  *
520  * Return value: the newly created #GstVaapiDisplay object
521  */
522 GstVaapiDisplay *
523 gst_vaapi_display_new_with_display(VADisplay va_display)
524 {
525     return g_object_new(GST_VAAPI_TYPE_DISPLAY,
526                         "display", va_display,
527                         NULL);
528 }
529
530 /**
531  * gst_vaapi_display_lock:
532  * @display: a #GstVaapiDisplay
533  *
534  * Locks @display. If @display is already locked by another thread,
535  * the current thread will block until @display is unlocked by the
536  * other thread.
537  */
538 void
539 gst_vaapi_display_lock(GstVaapiDisplay *display)
540 {
541     GstVaapiDisplayClass *klass;
542
543     g_return_if_fail(GST_VAAPI_IS_DISPLAY(display));
544
545     klass = GST_VAAPI_DISPLAY_GET_CLASS(display);
546     if (klass->lock_display)
547         klass->lock_display(display);
548 }
549
550 /**
551  * gst_vaapi_display_unlock:
552  * @display: a #GstVaapiDisplay
553  *
554  * Unlocks @display. If another thread is blocked in a
555  * gst_vaapi_display_lock() call for @display, it will be woken and
556  * can lock @display itself.
557  */
558 void
559 gst_vaapi_display_unlock(GstVaapiDisplay *display)
560 {
561     GstVaapiDisplayClass *klass;
562
563     g_return_if_fail(GST_VAAPI_IS_DISPLAY(display));
564
565     klass = GST_VAAPI_DISPLAY_GET_CLASS(display);
566     if (klass->unlock_display)
567         klass->unlock_display(display);
568 }
569
570 /**
571  * gst_vaapi_display_get_display:
572  * @display: a #GstVaapiDisplay
573  *
574  * Returns the #VADisplay bound to @display.
575  *
576  * Return value: the #VADisplay
577  */
578 VADisplay
579 gst_vaapi_display_get_display(GstVaapiDisplay *display)
580 {
581     g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
582
583     return display->priv->display;
584 }
585
586 /**
587  * gst_vaapi_display_get_width:
588  * @display: a #GstVaapiDisplay
589  *
590  * Retrieves the width of a #GstVaapiDisplay.
591  *
592  * Return value: the width of the @display, in pixels
593  */
594 guint
595 gst_vaapi_display_get_width(GstVaapiDisplay *display)
596 {
597     g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), 0);
598
599     return display->priv->width;
600 }
601
602 /**
603  * gst_vaapi_display_get_height:
604  * @display: a #GstVaapiDisplay
605  *
606  * Retrieves the height of a #GstVaapiDisplay
607  *
608  * Return value: the height of the @display, in pixels
609  */
610 guint
611 gst_vaapi_display_get_height(GstVaapiDisplay *display)
612 {
613     g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), 0);
614
615     return display->priv->height;
616 }
617
618 /**
619  * gst_vaapi_display_get_size:
620  * @display: a #GstVaapiDisplay
621  * @pwidth: return location for the width, or %NULL
622  * @pheight: return location for the height, or %NULL
623  *
624  * Retrieves the dimensions of a #GstVaapiDisplay.
625  */
626 void
627 gst_vaapi_display_get_size(GstVaapiDisplay *display, guint *pwidth, guint *pheight)
628 {
629     g_return_if_fail(GST_VAAPI_DISPLAY(display));
630
631     if (pwidth)
632         *pwidth = display->priv->width;
633
634     if (pheight)
635         *pheight = display->priv->height;
636 }
637
638 /**
639  * gst_vaapi_display_get_pixel_aspect_ratio:
640  * @display: a #GstVaapiDisplay
641  * @par_n: return location for the numerator of pixel aspect ratio, or %NULL
642  * @par_d: return location for the denominator of pixel aspect ratio, or %NULL
643  *
644  * Retrieves the pixel aspect ratio of a #GstVaapiDisplay.
645  */
646 void
647 gst_vaapi_display_get_pixel_aspect_ratio(
648     GstVaapiDisplay *display,
649     guint           *par_n,
650     guint           *par_d
651 )
652 {
653     g_return_if_fail(GST_VAAPI_IS_DISPLAY(display));
654
655     if (par_n)
656         *par_n = display->priv->par_n;
657
658     if (par_d)
659         *par_d = display->priv->par_d;
660 }
661
662 /**
663  * gst_vaapi_display_has_profile:
664  * @display: a #GstVaapiDisplay
665  * @profile: a #VAProfile
666  *
667  * Returns whether VA @display supports @profile.
668  *
669  * Return value: %TRUE if VA @display supports @profile
670  */
671 gboolean
672 gst_vaapi_display_has_profile(GstVaapiDisplay *display, VAProfile profile)
673 {
674     g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), FALSE);
675
676     return find_profile(display->priv->profiles, profile);
677 }
678
679 /**
680  * gst_vaapi_display_get_image_caps:
681  * @display: a #GstVaapiDisplay
682  *
683  * Gets the supported image formats for gst_vaapi_surface_get_image()
684  * or gst_vaapi_surface_put_image() as #GstCaps capabilities.
685  *
686  * Note that this method does not necessarily map image formats
687  * returned by vaQueryImageFormats(). The set of capabilities can be
688  * stripped down, if gstreamer-vaapi does not support the format, or
689  * expanded to cover compatible formats not exposed by the underlying
690  * driver. e.g. I420 can be supported even if the driver only exposes
691  * YV12.
692  *
693  * Return value: a newly allocated #GstCaps object, possibly empty
694  */
695 GstCaps *
696 gst_vaapi_display_get_image_caps(GstVaapiDisplay *display)
697 {
698     g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
699
700     return get_caps(display->priv->image_formats);
701 }
702
703 /**
704  * gst_vaapi_display_has_image_format:
705  * @display: a #GstVaapiDisplay
706  * @format: a #GstVaapiFormat
707  *
708  * Returns whether VA @display supports @format image format.
709  *
710  * Return value: %TRUE if VA @display supports @format image format
711  */
712 gboolean
713 gst_vaapi_display_has_image_format(
714     GstVaapiDisplay    *display,
715     GstVaapiImageFormat format
716 )
717 {
718     g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), FALSE);
719     g_return_val_if_fail(format, FALSE);
720
721     return find_format(display->priv->image_formats, format);
722 }
723
724 /**
725  * gst_vaapi_display_get_subpicture_caps:
726  * @display: a #GstVaapiDisplay
727  *
728  * Gets the supported subpicture formats as #GstCaps capabilities.
729  *
730  * Note that this method does not necessarily map subpicture formats
731  * returned by vaQuerySubpictureFormats(). The set of capabilities can
732  * be stripped down if gstreamer-vaapi does not support the
733  * format. e.g. this is the case for paletted formats like IA44.
734  *
735  * Return value: a newly allocated #GstCaps object, possibly empty
736  */
737 GstCaps *
738 gst_vaapi_display_get_subpicture_caps(GstVaapiDisplay *display)
739 {
740     g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
741
742     return get_caps(display->priv->subpicture_formats);
743 }
744
745 /**
746  * gst_vaapi_display_has_subpicture_format:
747  * @display: a #GstVaapiDisplay
748  * @format: a #GstVaapiFormat
749  *
750  * Returns whether VA @display supports @format subpicture format.
751  *
752  * Return value: %TRUE if VA @display supports @format subpicture format
753  */
754 gboolean
755 gst_vaapi_display_has_subpicture_format(
756     GstVaapiDisplay    *display,
757     GstVaapiImageFormat format
758 )
759 {
760     g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), FALSE);
761     g_return_val_if_fail(format, FALSE);
762
763     return find_format(display->priv->subpicture_formats, format);
764 }