va: Fix struct empty initialization syntax
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-bad / sys / va / gstvadecoder.c
1 /* GStreamer
2  * Copyright (C) 2020 Igalia, S.L.
3  *     Author: Víctor Jáquez <vjaquez@igalia.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include "gstvadecoder.h"
26
27 #include <gst/va/gstva.h>
28 #include <gst/va/gstvavideoformat.h>
29
30 #include "gstvacaps.h"
31 #include "gstvadisplay_priv.h"
32 #include "gstvaprofile.h"
33
34 struct _GstVaDecoder
35 {
36   GstObject parent;
37
38   GArray *available_profiles;
39   GstCaps *srcpad_caps;
40   GstCaps *sinkpad_caps;
41   GstVaDisplay *display;
42   VAConfigID config;
43   VAContextID context;
44   VAProfile profile;
45   guint rt_format;
46   gint coded_width;
47   gint coded_height;
48 };
49
50 GST_DEBUG_CATEGORY_STATIC (gst_va_decoder_debug);
51 #define GST_CAT_DEFAULT gst_va_decoder_debug
52
53 #define gst_va_decoder_parent_class parent_class
54 G_DEFINE_TYPE_WITH_CODE (GstVaDecoder, gst_va_decoder, GST_TYPE_OBJECT,
55     GST_DEBUG_CATEGORY_INIT (gst_va_decoder_debug, "vadecoder", 0,
56         "VA Decoder"));
57
58 enum
59 {
60   PROP_DISPLAY = 1,
61   PROP_PROFILE,
62   PROP_WIDTH,
63   PROP_HEIGHT,
64   PROP_CHROMA,
65   N_PROPERTIES
66 };
67
68 static GParamSpec *g_properties[N_PROPERTIES];
69
70 static gboolean _destroy_buffers (GstVaDecodePicture * pic);
71
72 static void
73 gst_va_decoder_set_property (GObject * object, guint prop_id,
74     const GValue * value, GParamSpec * pspec)
75 {
76   GstVaDecoder *self = GST_VA_DECODER (object);
77
78   switch (prop_id) {
79     case PROP_DISPLAY:{
80       g_assert (!self->display);
81       self->display = g_value_dup_object (value);
82       break;
83     }
84     default:
85       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
86       break;
87   }
88 }
89
90 static void
91 gst_va_decoder_get_property (GObject * object, guint prop_id, GValue * value,
92     GParamSpec * pspec)
93 {
94   GstVaDecoder *self = GST_VA_DECODER (object);
95
96   switch (prop_id) {
97     case PROP_DISPLAY:
98       g_value_set_object (value, self->display);
99       break;
100     case PROP_PROFILE:
101       g_value_set_int (value, self->profile);
102       break;
103     case PROP_CHROMA:
104       g_value_set_uint (value, self->rt_format);
105       break;
106     case PROP_WIDTH:
107       g_value_set_int (value, self->coded_width);
108       break;
109     case PROP_HEIGHT:
110       g_value_set_int (value, self->coded_height);
111       break;
112     default:
113       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
114       break;
115   }
116 }
117
118 static void
119 gst_va_decoder_dispose (GObject * object)
120 {
121   GstVaDecoder *self = GST_VA_DECODER (object);
122
123   if (!gst_va_decoder_close (self))
124     GST_WARNING_OBJECT (self, "VaDecoder is not successfully closed");
125
126   g_clear_pointer (&self->available_profiles, g_array_unref);
127   gst_clear_object (&self->display);
128
129   G_OBJECT_CLASS (parent_class)->dispose (object);
130 }
131
132 static void
133 gst_va_decoder_class_init (GstVaDecoderClass * klass)
134 {
135   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
136
137   gobject_class->set_property = gst_va_decoder_set_property;
138   gobject_class->get_property = gst_va_decoder_get_property;
139   gobject_class->dispose = gst_va_decoder_dispose;
140
141   g_properties[PROP_DISPLAY] =
142       g_param_spec_object ("display", "GstVaDisplay", "GstVaDisplay object",
143       GST_TYPE_VA_DISPLAY,
144       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
145
146   g_properties[PROP_PROFILE] =
147       g_param_spec_int ("va-profile", "VAProfile", "VA Profile",
148       VAProfileNone, 50, VAProfileNone,
149       G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
150
151   g_properties[PROP_CHROMA] =
152       g_param_spec_uint ("va-rt-format", "VARTFormat", "VA RT Format",
153       VA_RT_FORMAT_YUV420, VA_RT_FORMAT_PROTECTED, VA_RT_FORMAT_YUV420,
154       G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
155
156   g_properties[PROP_WIDTH] =
157       g_param_spec_int ("coded-width", "coded-picture-width",
158       "coded picture width", 0, G_MAXINT, 0,
159       G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
160
161   g_properties[PROP_HEIGHT] =
162       g_param_spec_int ("coded-height", "coded-picture-height",
163       "coded picture height", 0, G_MAXINT, 0,
164       G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
165
166   g_object_class_install_properties (gobject_class, N_PROPERTIES, g_properties);
167 }
168
169 static void
170 gst_va_decoder_init (GstVaDecoder * self)
171 {
172   self->profile = VAProfileNone;
173   self->config = VA_INVALID_ID;
174   self->context = VA_INVALID_ID;
175   self->rt_format = 0;
176   self->coded_width = 0;
177   self->coded_height = 0;
178 }
179
180 static gboolean
181 gst_va_decoder_initialize (GstVaDecoder * self, guint32 codec)
182 {
183   if (self->available_profiles)
184     return FALSE;
185
186   self->available_profiles = gst_va_display_get_profiles (self->display, codec,
187       VAEntrypointVLD);
188
189   return (self->available_profiles != NULL);
190 }
191
192 GstVaDecoder *
193 gst_va_decoder_new (GstVaDisplay * display, guint32 codec)
194 {
195   GstVaDecoder *self;
196
197   g_return_val_if_fail (GST_IS_VA_DISPLAY (display), NULL);
198
199   self = g_object_new (GST_TYPE_VA_DECODER, "display", display, NULL);
200   if (!gst_va_decoder_initialize (self, codec))
201     gst_clear_object (&self);
202
203   return self;
204 }
205
206 gboolean
207 gst_va_decoder_is_open (GstVaDecoder * self)
208 {
209   gboolean ret;
210
211   g_return_val_if_fail (GST_IS_VA_DECODER (self), FALSE);
212
213   GST_OBJECT_LOCK (self);
214   ret = (self->config != VA_INVALID_ID && self->profile != VAProfileNone);
215   GST_OBJECT_UNLOCK (self);
216   return ret;
217 }
218
219 gboolean
220 gst_va_decoder_open (GstVaDecoder * self, VAProfile profile, guint rt_format)
221 {
222   VAConfigAttrib attrib = {
223     .type = VAConfigAttribRTFormat,
224     .value = rt_format,
225   };
226   VAConfigID config;
227   VADisplay dpy;
228   VAStatus status;
229
230   g_return_val_if_fail (GST_IS_VA_DECODER (self), FALSE);
231
232   if (gst_va_decoder_is_open (self))
233     return TRUE;
234
235   if (!gst_va_decoder_has_profile (self, profile)) {
236     GST_ERROR_OBJECT (self, "Unsupported profile: %s",
237         gst_va_profile_name (profile));
238     return FALSE;
239   }
240
241   dpy = gst_va_display_get_va_dpy (self->display);
242   status = vaCreateConfig (dpy, profile, VAEntrypointVLD, &attrib, 1, &config);
243   if (status != VA_STATUS_SUCCESS) {
244     GST_ERROR_OBJECT (self, "vaCreateConfig: %s", vaErrorStr (status));
245     return FALSE;
246   }
247
248   GST_OBJECT_LOCK (self);
249   self->config = config;
250   self->profile = profile;
251   self->rt_format = rt_format;
252   GST_OBJECT_UNLOCK (self);
253
254   /* now we should return now only this profile's caps */
255   gst_caps_replace (&self->srcpad_caps, NULL);
256
257   return TRUE;
258 }
259
260 gboolean
261 gst_va_decoder_close (GstVaDecoder * self)
262 {
263   VADisplay dpy;
264   VAStatus status;
265
266   g_return_val_if_fail (GST_IS_VA_DECODER (self), FALSE);
267
268   if (!gst_va_decoder_is_open (self))
269     return TRUE;
270
271   dpy = gst_va_display_get_va_dpy (self->display);
272
273   if (self->context != VA_INVALID_ID) {
274     status = vaDestroyContext (dpy, self->context);
275     if (status != VA_STATUS_SUCCESS)
276       GST_ERROR_OBJECT (self, "vaDestroyContext: %s", vaErrorStr (status));
277   }
278
279   status = vaDestroyConfig (dpy, self->config);
280   if (status != VA_STATUS_SUCCESS) {
281     GST_ERROR_OBJECT (self, "vaDestroyConfig: %s", vaErrorStr (status));
282     return FALSE;
283   }
284
285   GST_OBJECT_LOCK (self);
286   gst_va_decoder_init (self);
287   GST_OBJECT_UNLOCK (self);
288
289   gst_caps_replace (&self->srcpad_caps, NULL);
290   gst_caps_replace (&self->sinkpad_caps, NULL);
291
292   return TRUE;
293 }
294
295 gboolean
296 gst_va_decoder_set_frame_size_with_surfaces (GstVaDecoder * self,
297     gint coded_width, gint coded_height, GArray * surfaces)
298 {
299   VAContextID context;
300   VADisplay dpy;
301   VAStatus status;
302   VASurfaceID *render_targets = NULL;
303   gint num_render_targets = 0;
304
305   g_return_val_if_fail (GST_IS_VA_DECODER (self), FALSE);
306
307   GST_OBJECT_LOCK (self);
308   if (self->context != VA_INVALID_ID) {
309     GST_OBJECT_UNLOCK (self);
310     GST_INFO_OBJECT (self, "decoder already has a context");
311     return TRUE;
312   }
313   GST_OBJECT_UNLOCK (self);
314
315   if (!gst_va_decoder_is_open (self)) {
316     GST_ERROR_OBJECT (self, "decoder has not been opened yet");
317     return FALSE;
318   }
319
320   if (surfaces) {
321     num_render_targets = surfaces->len;
322     render_targets = (VASurfaceID *) surfaces->data;
323   }
324
325   dpy = gst_va_display_get_va_dpy (self->display);
326
327   status = vaCreateContext (dpy, self->config, coded_width, coded_height,
328       VA_PROGRESSIVE, render_targets, num_render_targets, &context);
329
330   if (status != VA_STATUS_SUCCESS) {
331     GST_ERROR_OBJECT (self, "vaDestroyConfig: %s", vaErrorStr (status));
332     return FALSE;
333   }
334
335   GST_OBJECT_LOCK (self);
336   self->context = context;
337   self->coded_width = coded_width;
338   self->coded_height = coded_height;
339   GST_OBJECT_UNLOCK (self);
340
341   return TRUE;
342 }
343
344 gboolean
345 gst_va_decoder_set_frame_size (GstVaDecoder * self, gint coded_width,
346     gint coded_height)
347 {
348   return gst_va_decoder_set_frame_size_with_surfaces (self, coded_width,
349       coded_height, NULL);
350 }
351
352 /* This function is only used by codecs where frame size can change
353  * without a context reset, as for example VP9 */
354 gboolean
355 gst_va_decoder_update_frame_size (GstVaDecoder * self, gint coded_width,
356     gint coded_height)
357 {
358   g_return_val_if_fail (GST_IS_VA_DECODER (self), FALSE);
359
360   if (!gst_va_decoder_is_open (self)) {
361     GST_ERROR_OBJECT (self, "decoder has not been opened yet");
362     return FALSE;
363   }
364
365   GST_OBJECT_LOCK (self);
366   if (self->context == VA_INVALID_ID) {
367     GST_OBJECT_UNLOCK (self);
368     GST_INFO_OBJECT (self, "decoder does not have a context");
369     return FALSE;
370   }
371   GST_OBJECT_UNLOCK (self);
372
373
374   GST_OBJECT_LOCK (self);
375   self->coded_width = coded_width;
376   self->coded_height = coded_height;
377   GST_OBJECT_UNLOCK (self);
378
379   return TRUE;
380 }
381
382 static gboolean
383 _get_codec_caps (GstVaDecoder * self)
384 {
385   GstCaps *sinkpad_caps = NULL, *srcpad_caps = NULL;
386
387   if (!gst_va_decoder_is_open (self)
388       && GST_IS_VA_DISPLAY_WRAPPED (self->display)) {
389     if (gst_va_caps_from_profiles (self->display, self->available_profiles,
390             VAEntrypointVLD, &sinkpad_caps, &srcpad_caps)) {
391       gst_caps_replace (&self->sinkpad_caps, sinkpad_caps);
392       gst_caps_replace (&self->srcpad_caps, srcpad_caps);
393       gst_caps_unref (srcpad_caps);
394       gst_caps_unref (sinkpad_caps);
395
396       return TRUE;
397     }
398   }
399
400   return FALSE;
401 }
402
403 GstCaps *
404 gst_va_decoder_get_srcpad_caps (GstVaDecoder * self)
405 {
406   GstCaps *srcpad_caps = NULL;
407
408   g_return_val_if_fail (GST_IS_VA_DECODER (self), FALSE);
409
410   if (g_atomic_pointer_get (&self->srcpad_caps))
411     return gst_caps_ref (self->srcpad_caps);
412
413   if (_get_codec_caps (self))
414     return gst_caps_ref (self->srcpad_caps);
415
416   if (gst_va_decoder_is_open (self)) {
417     srcpad_caps = gst_va_create_raw_caps_from_config (self->display,
418         self->config);
419     if (!srcpad_caps) {
420       GST_WARNING_OBJECT (self, "Invalid configuration caps");
421       return NULL;
422     }
423     gst_caps_replace (&self->srcpad_caps, srcpad_caps);
424     gst_caps_unref (srcpad_caps);
425
426     return gst_caps_ref (self->srcpad_caps);
427   }
428
429   return NULL;
430 }
431
432 GstCaps *
433 gst_va_decoder_get_sinkpad_caps (GstVaDecoder * self)
434 {
435   g_return_val_if_fail (GST_IS_VA_DECODER (self), FALSE);
436
437   if (g_atomic_pointer_get (&self->sinkpad_caps))
438     return gst_caps_ref (self->sinkpad_caps);
439
440   if (_get_codec_caps (self))
441     return gst_caps_ref (self->sinkpad_caps);
442
443   return NULL;
444 }
445
446 gboolean
447 gst_va_decoder_has_profile (GstVaDecoder * self, VAProfile profile)
448 {
449   gint i;
450
451   g_return_val_if_fail (GST_IS_VA_DECODER (self), FALSE);
452
453   if (profile == VAProfileNone)
454     return FALSE;
455
456   for (i = 0; i < self->available_profiles->len; i++) {
457     if (g_array_index (self->available_profiles, VAProfile, i) == profile)
458       return TRUE;
459   }
460
461   return FALSE;
462 }
463
464 gint
465 gst_va_decoder_get_mem_types (GstVaDecoder * self)
466 {
467   VASurfaceAttrib *attribs;
468   guint i, attrib_count;
469   gint ret = 0;
470
471   g_return_val_if_fail (GST_IS_VA_DECODER (self), 0);
472
473   if (!gst_va_decoder_is_open (self))
474     return 0;
475
476   attribs = gst_va_get_surface_attribs (self->display, self->config,
477       &attrib_count);
478   if (!attribs)
479     return 0;
480
481   for (i = 0; i < attrib_count; i++) {
482     if (attribs[i].value.type != VAGenericValueTypeInteger)
483       continue;
484     switch (attribs[i].type) {
485       case VASurfaceAttribMemoryType:
486         ret = attribs[i].value.value.i;
487         break;
488       default:
489         break;
490     }
491   }
492
493   g_free (attribs);
494
495   return ret;
496 }
497
498 GArray *
499 gst_va_decoder_get_surface_formats (GstVaDecoder * self)
500 {
501   GArray *formats;
502   GstVideoFormat format;
503   VASurfaceAttrib *attribs;
504   guint i, attrib_count;
505
506   g_return_val_if_fail (GST_IS_VA_DECODER (self), NULL);
507
508   if (!gst_va_decoder_is_open (self))
509     return NULL;
510
511   attribs = gst_va_get_surface_attribs (self->display, self->config,
512       &attrib_count);
513   if (!attribs)
514     return NULL;
515
516   formats = g_array_new (FALSE, FALSE, sizeof (GstVideoFormat));
517
518   for (i = 0; i < attrib_count; i++) {
519     if (attribs[i].value.type != VAGenericValueTypeInteger)
520       continue;
521     switch (attribs[i].type) {
522       case VASurfaceAttribPixelFormat:
523         format = gst_va_video_format_from_va_fourcc (attribs[i].value.value.i);
524         if (format != GST_VIDEO_FORMAT_UNKNOWN)
525           g_array_append_val (formats, format);
526         break;
527       default:
528         break;
529     }
530   }
531
532   g_free (attribs);
533
534   if (formats->len == 0) {
535     g_array_unref (formats);
536     return NULL;
537   }
538
539   return formats;
540 }
541
542 gboolean
543 gst_va_decoder_add_param_buffer (GstVaDecoder * self, GstVaDecodePicture * pic,
544     gint type, gpointer data, gsize size)
545 {
546   VABufferID buffer;
547   VADisplay dpy;
548   VAStatus status;
549
550   g_return_val_if_fail (GST_IS_VA_DECODER (self), FALSE);
551   g_return_val_if_fail (self->context != VA_INVALID_ID, FALSE);
552   g_return_val_if_fail (pic && data && size > 0, FALSE);
553
554   dpy = gst_va_display_get_va_dpy (self->display);
555   status = vaCreateBuffer (dpy, self->context, type, size, 1, data, &buffer);
556   if (status != VA_STATUS_SUCCESS) {
557     GST_ERROR_OBJECT (self, "vaCreateBuffer: %s", vaErrorStr (status));
558     return FALSE;
559   }
560
561   g_array_append_val (pic->buffers, buffer);
562   return TRUE;
563 }
564
565 gboolean
566 gst_va_decoder_add_slice_buffer_with_n_params (GstVaDecoder * self,
567     GstVaDecodePicture * pic, gpointer params_data, gsize params_size,
568     guint params_num, gpointer slice_data, gsize slice_size)
569 {
570   VABufferID params_buffer, slice_buffer;
571   VADisplay dpy;
572   VAStatus status;
573
574   g_return_val_if_fail (GST_IS_VA_DECODER (self), FALSE);
575   g_return_val_if_fail (self->context != VA_INVALID_ID, FALSE);
576   g_return_val_if_fail (pic && slice_data && slice_size > 0
577       && params_data && params_size > 0, FALSE);
578
579   dpy = gst_va_display_get_va_dpy (self->display);
580   status = vaCreateBuffer (dpy, self->context, VASliceParameterBufferType,
581       params_size, params_num, params_data, &params_buffer);
582   if (status != VA_STATUS_SUCCESS) {
583     GST_ERROR_OBJECT (self, "vaCreateBuffer: %s", vaErrorStr (status));
584     return FALSE;
585   }
586
587   status = vaCreateBuffer (dpy, self->context, VASliceDataBufferType,
588       slice_size, 1, slice_data, &slice_buffer);
589   if (status != VA_STATUS_SUCCESS) {
590     GST_ERROR_OBJECT (self, "vaCreateBuffer: %s", vaErrorStr (status));
591     return FALSE;
592   }
593
594   g_array_append_val (pic->slices, params_buffer);
595   g_array_append_val (pic->slices, slice_buffer);
596
597   return TRUE;
598 }
599
600 gboolean
601 gst_va_decoder_add_slice_buffer (GstVaDecoder * self, GstVaDecodePicture * pic,
602     gpointer params_data, gsize params_size, gpointer slice_data,
603     gsize slice_size)
604 {
605   return gst_va_decoder_add_slice_buffer_with_n_params (self, pic, params_data,
606       params_size, 1, slice_data, slice_size);
607 }
608
609 gboolean
610 gst_va_decoder_decode_with_aux_surface (GstVaDecoder * self,
611     GstVaDecodePicture * pic, gboolean use_aux)
612 {
613   VADisplay dpy;
614   VAStatus status;
615   VASurfaceID surface = VA_INVALID_ID;
616   gboolean ret = FALSE;
617
618   g_return_val_if_fail (GST_IS_VA_DECODER (self), FALSE);
619   g_return_val_if_fail (self->context != VA_INVALID_ID, FALSE);
620   g_return_val_if_fail (pic, FALSE);
621
622   if (use_aux) {
623     surface = gst_va_decode_picture_get_aux_surface (pic);
624   } else {
625     surface = gst_va_decode_picture_get_surface (pic);
626   }
627   if (surface == VA_INVALID_ID) {
628     GST_ERROR_OBJECT (self, "Decode picture without VASurfaceID");
629     return FALSE;
630   }
631
632   GST_TRACE_OBJECT (self, "Decode to surface %#x", surface);
633
634   dpy = gst_va_display_get_va_dpy (self->display);
635
636   status = vaBeginPicture (dpy, self->context, surface);
637   if (status != VA_STATUS_SUCCESS) {
638     GST_WARNING_OBJECT (self, "vaBeginPicture: %s", vaErrorStr (status));
639     goto fail_end_pic;
640   }
641
642   if (pic->buffers->len > 0) {
643     status = vaRenderPicture (dpy, self->context,
644         (VABufferID *) pic->buffers->data, pic->buffers->len);
645     if (status != VA_STATUS_SUCCESS) {
646       GST_WARNING_OBJECT (self, "vaRenderPicture: %s", vaErrorStr (status));
647       goto fail_end_pic;
648     }
649   }
650
651   if (pic->slices->len > 0) {
652     status = vaRenderPicture (dpy, self->context,
653         (VABufferID *) pic->slices->data, pic->slices->len);
654     if (status != VA_STATUS_SUCCESS) {
655       GST_WARNING_OBJECT (self, "vaRenderPicture: %s", vaErrorStr (status));
656       goto fail_end_pic;
657     }
658   }
659
660   status = vaEndPicture (dpy, self->context);
661   if (status != VA_STATUS_SUCCESS)
662     GST_WARNING_OBJECT (self, "vaEndPicture: %s", vaErrorStr (status));
663   else
664     ret = TRUE;
665
666 bail:
667   _destroy_buffers (pic);
668
669   return ret;
670
671 fail_end_pic:
672   {
673     status = vaEndPicture (dpy, self->context);
674     goto bail;
675   }
676 }
677
678 gboolean
679 gst_va_decoder_decode (GstVaDecoder * self, GstVaDecodePicture * pic)
680 {
681   return gst_va_decoder_decode_with_aux_surface (self, pic, FALSE);
682 }
683
684 gboolean
685 gst_va_decoder_config_is_equal (GstVaDecoder * self, VAProfile new_profile,
686     guint new_rtformat, gint new_width, gint new_height)
687 {
688   gboolean ret;
689
690   g_return_val_if_fail (GST_IS_VA_DECODER (self), FALSE);
691
692   /* @TODO: Check if current buffers are large enough, and reuse
693    * them */
694   GST_OBJECT_LOCK (self);
695   ret = (self->profile == new_profile && self->rt_format == new_rtformat
696       && self->coded_width == new_width && self->coded_height == new_height);
697   GST_OBJECT_UNLOCK (self);
698
699   return ret;
700 }
701
702 gboolean
703 gst_va_decoder_get_config (GstVaDecoder * self, VAProfile * profile,
704     guint * rt_format, gint * width, gint * height)
705 {
706   g_return_val_if_fail (GST_IS_VA_DECODER (self), FALSE);
707
708   if (!gst_va_decoder_is_open (self))
709     return FALSE;
710
711   GST_OBJECT_LOCK (self);
712   if (profile)
713     *profile = self->profile;
714   if (rt_format)
715     *rt_format = self->rt_format;
716   if (width)
717     *width = self->coded_width;
718   if (height)
719     *height = self->coded_height;
720   GST_OBJECT_UNLOCK (self);
721
722   return TRUE;
723 }
724
725 static gboolean
726 _destroy_buffers (GstVaDecodePicture * pic)
727 {
728   VABufferID buffer;
729   VADisplay dpy;
730   VAStatus status;
731   guint i;
732   gboolean ret = TRUE;
733
734   g_return_val_if_fail (GST_IS_VA_DISPLAY (pic->display), FALSE);
735
736   dpy = gst_va_display_get_va_dpy (pic->display);
737
738   if (pic->buffers) {
739     for (i = 0; i < pic->buffers->len; i++) {
740       buffer = g_array_index (pic->buffers, VABufferID, i);
741       status = vaDestroyBuffer (dpy, buffer);
742       if (status != VA_STATUS_SUCCESS) {
743         ret = FALSE;
744         GST_WARNING ("Failed to destroy parameter buffer: %s",
745             vaErrorStr (status));
746       }
747     }
748
749     pic->buffers = g_array_set_size (pic->buffers, 0);
750   }
751
752   if (pic->slices) {
753     for (i = 0; i < pic->slices->len; i++) {
754       buffer = g_array_index (pic->slices, VABufferID, i);
755       status = vaDestroyBuffer (dpy, buffer);
756       if (status != VA_STATUS_SUCCESS) {
757         ret = FALSE;
758         GST_WARNING ("Failed to destroy slice buffer: %s", vaErrorStr (status));
759       }
760     }
761
762     pic->slices = g_array_set_size (pic->slices, 0);
763   }
764
765   return ret;
766 }
767
768 GstVaDecodePicture *
769 gst_va_decode_picture_new (GstVaDecoder * self, GstBuffer * buffer)
770 {
771   GstVaDecodePicture *pic;
772
773   g_return_val_if_fail (buffer && GST_IS_BUFFER (buffer), NULL);
774   g_return_val_if_fail (self && GST_IS_VA_DECODER (self), NULL);
775
776   pic = g_slice_new (GstVaDecodePicture);
777   pic->gstbuffer = gst_buffer_ref (buffer);
778   pic->buffers = g_array_sized_new (FALSE, FALSE, sizeof (VABufferID), 16);
779   pic->slices = g_array_sized_new (FALSE, FALSE, sizeof (VABufferID), 64);
780   pic->display = gst_object_ref (self->display);
781
782   return pic;
783 }
784
785 VASurfaceID
786 gst_va_decode_picture_get_surface (GstVaDecodePicture * pic)
787 {
788   g_return_val_if_fail (pic, VA_INVALID_ID);
789   g_return_val_if_fail (pic->gstbuffer, VA_INVALID_ID);
790
791   return gst_va_buffer_get_surface (pic->gstbuffer);
792 }
793
794 VASurfaceID
795 gst_va_decode_picture_get_aux_surface (GstVaDecodePicture * pic)
796 {
797   g_return_val_if_fail (pic, VA_INVALID_ID);
798   g_return_val_if_fail (pic->gstbuffer, VA_INVALID_ID);
799
800   return gst_va_buffer_get_aux_surface (pic->gstbuffer);
801 }
802
803 void
804 gst_va_decode_picture_free (GstVaDecodePicture * pic)
805 {
806   g_return_if_fail (pic);
807
808   _destroy_buffers (pic);
809
810   gst_buffer_unref (pic->gstbuffer);
811   g_clear_pointer (&pic->buffers, g_array_unref);
812   g_clear_pointer (&pic->slices, g_array_unref);
813   gst_clear_object (&pic->display);
814
815   g_slice_free (GstVaDecodePicture, pic);
816 }
817
818 GstVaDecodePicture *
819 gst_va_decode_picture_dup (GstVaDecodePicture * pic)
820 {
821   GstVaDecodePicture *dup;
822
823   g_return_val_if_fail (pic, NULL);
824
825   dup = g_slice_new0 (GstVaDecodePicture);
826
827   dup->display = gst_object_ref (pic->display);
828   /* dups only need gstbuffer */
829   dup->gstbuffer = gst_buffer_ref (pic->gstbuffer);
830   return dup;
831 }