2 * Copyright (C) 2021 Intel Corporation
3 * Author: He Junyan <junyan.he@intel.com>
4 * Author: Víctor Jáquez <vjaquez@igalia.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library 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 GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
26 #include "gstvaencoder.h"
29 #include "gstvacaps.h"
30 #include "gstvadisplay_priv.h"
32 #define VA_ENTRYPOINT_FLAG(entry) (1U << G_PASTE(VAEntrypoint, entry))
34 typedef struct _GstVaProfileConfig GstVaProfileConfig;
36 struct _GstVaProfileConfig
39 guint32 entrypoints; /* bits map of GstVaapiEntrypoint */
46 GArray *available_profiles;
48 GstCaps *sinkpad_caps;
49 GstVaDisplay *display;
53 VAEntrypoint entrypoint;
59 GstBufferPool *recon_pool;
62 GST_DEBUG_CATEGORY_STATIC (gst_va_encoder_debug);
63 #define GST_CAT_DEFAULT gst_va_encoder_debug
65 #define gst_va_encoder_parent_class parent_class
66 G_DEFINE_TYPE_WITH_CODE (GstVaEncoder, gst_va_encoder, GST_TYPE_OBJECT,
67 GST_DEBUG_CATEGORY_INIT (gst_va_encoder_debug, "vaencoder", 0,
82 static GParamSpec *g_properties[N_PROPERTIES];
85 _destroy_buffer (GstVaDisplay * display, VABufferID buffer)
89 VADisplay dpy = gst_va_display_get_va_dpy (display);
91 status = vaDestroyBuffer (dpy, buffer);
92 if (status != VA_STATUS_SUCCESS) {
94 GST_WARNING ("Failed to destroy the buffer: %s", vaErrorStr (status));
101 _create_buffer (GstVaEncoder * self, gint type, gpointer data, gsize size)
104 VADisplay dpy = gst_va_display_get_va_dpy (self->display);
108 GST_OBJECT_LOCK (self);
109 context = self->context;
110 GST_OBJECT_UNLOCK (self);
112 dpy = gst_va_display_get_va_dpy (self->display);
113 status = vaCreateBuffer (dpy, context, type, size, 1, data, &buffer);
114 if (status != VA_STATUS_SUCCESS) {
115 GST_ERROR_OBJECT (self, "vaCreateBuffer: %s", vaErrorStr (status));
116 return VA_INVALID_ID;
123 gst_va_encoder_set_property (GObject * object, guint prop_id,
124 const GValue * value, GParamSpec * pspec)
126 GstVaEncoder *self = GST_VA_ENCODER (object);
128 GST_OBJECT_LOCK (self);
132 g_assert (!self->display);
133 self->display = g_value_dup_object (value);
137 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
141 GST_OBJECT_UNLOCK (self);
145 gst_va_encoder_get_property (GObject * object, guint prop_id, GValue * value,
148 GstVaEncoder *self = GST_VA_ENCODER (object);
150 GST_OBJECT_LOCK (self);
154 g_value_set_object (value, self->display);
157 g_value_set_int (value, self->profile);
159 case PROP_ENTRYPOINT:
160 g_value_set_int (value, self->entrypoint);
163 g_value_set_uint (value, self->rt_format);
166 g_value_set_int (value, self->coded_width);
169 g_value_set_int (value, self->coded_height);
171 case PROP_CODED_BUF_SIZE:
172 g_value_set_int (value, self->codedbuf_size);
175 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
179 GST_OBJECT_UNLOCK (self);
183 gst_va_encoder_init (GstVaEncoder * self)
185 self->profile = VAProfileNone;
186 self->entrypoint = 0;
187 self->config = VA_INVALID_ID;
188 self->context = VA_INVALID_ID;
190 self->coded_width = 0;
191 self->coded_height = 0;
192 self->codedbuf_size = 0;
193 g_clear_pointer (&self->recon_pool, gst_object_unref);
196 static inline gboolean
197 _is_open_unlocked (GstVaEncoder * self)
199 return (self->config != VA_INVALID_ID && self->profile != VAProfileNone);
203 gst_va_encoder_is_open (GstVaEncoder * self)
207 g_return_val_if_fail (GST_IS_VA_ENCODER (self), FALSE);
209 GST_OBJECT_LOCK (self);
210 ret = _is_open_unlocked (self);
211 GST_OBJECT_UNLOCK (self);
216 gst_va_encoder_close (GstVaEncoder * self)
220 VAConfigID config = VA_INVALID_ID;
221 VAContextID context = VA_INVALID_ID;
222 GstBufferPool *recon_pool = NULL;
224 g_return_val_if_fail (GST_IS_VA_ENCODER (self), FALSE);
226 GST_OBJECT_LOCK (self);
227 if (!_is_open_unlocked (self)) {
228 GST_OBJECT_UNLOCK (self);
232 config = self->config;
233 context = self->context;
235 recon_pool = self->recon_pool;
236 self->recon_pool = NULL;
238 gst_va_encoder_init (self);
239 GST_OBJECT_UNLOCK (self);
241 gst_buffer_pool_set_active (recon_pool, FALSE);
242 g_clear_pointer (&recon_pool, gst_object_unref);
244 dpy = gst_va_display_get_va_dpy (self->display);
246 if (context != VA_INVALID_ID) {
247 status = vaDestroyContext (dpy, context);
248 if (status != VA_STATUS_SUCCESS)
249 GST_ERROR_OBJECT (self, "vaDestroyContext: %s", vaErrorStr (status));
252 status = vaDestroyConfig (dpy, config);
253 if (status != VA_STATUS_SUCCESS)
254 GST_ERROR_OBJECT (self, "vaDestroyConfig: %s", vaErrorStr (status));
256 gst_caps_replace (&self->srcpad_caps, NULL);
257 gst_caps_replace (&self->sinkpad_caps, NULL);
263 _get_surface_formats (GstVaDisplay * display, VAConfigID config)
266 GstVideoFormat format;
267 VASurfaceAttrib *attribs;
268 guint i, attrib_count;
270 attribs = gst_va_get_surface_attribs (display, config, &attrib_count);
274 formats = g_array_new (FALSE, FALSE, sizeof (GstVideoFormat));
276 for (i = 0; i < attrib_count; i++) {
277 if (attribs[i].value.type != VAGenericValueTypeInteger)
279 switch (attribs[i].type) {
280 case VASurfaceAttribPixelFormat:
281 format = gst_va_video_format_from_va_fourcc (attribs[i].value.value.i);
282 if (format != GST_VIDEO_FORMAT_UNKNOWN)
283 g_array_append_val (formats, format);
292 if (formats->len == 0) {
293 g_array_unref (formats);
300 static GstBufferPool *
301 _create_reconstruct_pool (GstVaDisplay * display, GArray * surface_formats,
302 GstVideoFormat format, gint coded_width, gint coded_height,
305 GstAllocator *allocator = NULL;
306 guint usage_hint = VA_SURFACE_ATTRIB_USAGE_HINT_ENCODER;
308 GstAllocationParams params = { 0, };
311 GstCaps *caps = NULL;
313 gst_video_info_set_format (&info, format, coded_width, coded_height);
315 size = GST_VIDEO_INFO_SIZE (&info);
317 caps = gst_video_info_to_caps (&info);
318 gst_caps_set_features_simple (caps,
319 gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_VA));
321 allocator = gst_va_allocator_new (display, surface_formats);
323 gst_allocation_params_init (¶ms);
325 pool = gst_va_pool_new_with_config (caps, size, 0, max_buffers, usage_hint,
326 GST_VA_FEATURE_AUTO, allocator, ¶ms);
328 gst_clear_object (&allocator);
329 gst_clear_caps (&caps);
335 gst_va_encoder_open (GstVaEncoder * self, VAProfile profile,
336 VAEntrypoint entrypoint, GstVideoFormat video_format, guint rt_format,
337 gint coded_width, gint coded_height, gint codedbuf_size,
338 guint max_reconstruct_surfaces, guint rc_ctrl, guint32 packed_headers)
341 VAConfigAttrib attribs[3] = {
342 { .type = VAConfigAttribRTFormat, .value = rt_format, },
343 { .type = VAConfigAttribRateControl, .value = rc_ctrl, },
346 VAConfigID config = VA_INVALID_ID;
347 VAContextID context = VA_INVALID_ID;
349 GArray *surface_formats = NULL;
351 GstBufferPool *recon_pool = NULL;
352 guint attrib_idx = 2;
354 g_return_val_if_fail (GST_IS_VA_ENCODER (self), FALSE);
355 g_return_val_if_fail (codedbuf_size > 0, FALSE);
357 if (gst_va_encoder_is_open (self))
360 if (!gst_va_encoder_has_profile_and_entrypoint (self, profile, entrypoint)) {
361 GST_ERROR_OBJECT (self, "Unsupported profile: %d, entrypoint: %d",
362 profile, entrypoint);
366 if (packed_headers > 0) {
367 attribs[attrib_idx].type = VAConfigAttribEncPackedHeaders;
368 attribs[attrib_idx].value = packed_headers;
372 dpy = gst_va_display_get_va_dpy (self->display);
374 status = vaCreateConfig (dpy, profile, entrypoint, attribs, attrib_idx,
376 if (status != VA_STATUS_SUCCESS) {
377 GST_ERROR_OBJECT (self, "vaCreateConfig: %s", vaErrorStr (status));
381 surface_formats = _get_surface_formats (self->display, config);
382 if (!surface_formats) {
383 GST_ERROR_OBJECT (self, "Failed to get surface formats");
387 recon_pool = _create_reconstruct_pool (self->display, surface_formats,
388 video_format, coded_width, coded_height, max_reconstruct_surfaces);
390 GST_ERROR_OBJECT (self, "Failed to create reconstruct pool");
393 gst_buffer_pool_set_active (recon_pool, TRUE);
395 status = vaCreateContext (dpy, config, coded_width, coded_height,
396 VA_PROGRESSIVE, NULL, 0, &context);
397 if (status != VA_STATUS_SUCCESS) {
398 GST_ERROR_OBJECT (self, "vaCreateConfig: %s", vaErrorStr (status));
402 GST_OBJECT_LOCK (self);
404 self->config = config;
405 self->context = context;
406 self->profile = profile;
407 self->entrypoint = entrypoint;
408 self->rt_format = rt_format;
409 self->coded_width = coded_width;
410 self->coded_height = coded_height;
411 self->codedbuf_size = codedbuf_size;
412 gst_object_replace ((GstObject **) & self->recon_pool,
413 (GstObject *) recon_pool);
415 GST_OBJECT_UNLOCK (self);
417 g_clear_pointer (&recon_pool, gst_object_unref);
418 /* now we should return now only this profile's caps */
419 gst_caps_replace (&self->srcpad_caps, NULL);
424 g_clear_pointer (&recon_pool, gst_object_unref);
426 if (config != VA_INVALID_ID)
427 vaDestroyConfig (dpy, config);
429 if (context != VA_INVALID_ID)
430 vaDestroyContext (dpy, context);
436 gst_va_encoder_dispose (GObject * object)
438 GstVaEncoder *self = GST_VA_ENCODER (object);
440 gst_va_encoder_close (self);
442 g_clear_pointer (&self->available_profiles, g_array_unref);
443 gst_clear_object (&self->display);
445 G_OBJECT_CLASS (parent_class)->dispose (object);
449 gst_va_encoder_class_init (GstVaEncoderClass * klass)
451 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
453 gobject_class->set_property = gst_va_encoder_set_property;
454 gobject_class->get_property = gst_va_encoder_get_property;
455 gobject_class->dispose = gst_va_encoder_dispose;
457 g_properties[PROP_DISPLAY] =
458 g_param_spec_object ("display", "GstVaDisplay", "GstVADisplay object",
460 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
462 g_properties[PROP_PROFILE] =
463 g_param_spec_int ("va-profile", "VAProfile", "VA Profile",
464 VAProfileNone, 50, VAProfileNone,
465 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
467 g_properties[PROP_ENTRYPOINT] =
468 g_param_spec_int ("va-entrypoint", "VAEntrypoint", "VA Entrypoint",
469 0, 14, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
471 g_properties[PROP_CHROMA] =
472 g_param_spec_uint ("va-rt-format", "VARTFormat", "VA RT Fromat or chroma",
473 VA_RT_FORMAT_YUV420, VA_RT_FORMAT_PROTECTED, VA_RT_FORMAT_YUV420,
474 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
476 g_properties[PROP_WIDTH] =
477 g_param_spec_int ("coded-width", "coded-picture-width",
478 "coded picture width", 0, G_MAXINT, 0,
479 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
481 g_properties[PROP_HEIGHT] =
482 g_param_spec_int ("coded-height", "coded-picture-height",
483 "coded picture height", 0, G_MAXINT, 0,
484 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
486 g_properties[PROP_CODED_BUF_SIZE] =
487 g_param_spec_int ("coded-buf-size", "coded-buffer-size",
488 "coded buffer size", 0, G_MAXINT, 0,
489 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
491 g_object_class_install_properties (gobject_class, N_PROPERTIES, g_properties);
495 gst_va_encoder_initialize (GstVaEncoder * self, guint32 codec)
497 GArray *enc_profiles = NULL;
500 if (self->available_profiles)
503 enc_profiles = gst_va_display_get_profiles (self->display, codec,
504 VAEntrypointEncSlice);
509 self->available_profiles =
510 g_array_new (FALSE, FALSE, sizeof (GstVaProfileConfig));
513 for (i = 0; i < enc_profiles->len; i++) {
514 GstVaProfileConfig config;
516 config.profile = g_array_index (enc_profiles, VAProfile, i);
517 config.entrypoints = VA_ENTRYPOINT_FLAG (EncSlice);
518 g_array_append_val (self->available_profiles, config);
522 g_clear_pointer (&enc_profiles, g_array_unref);
524 if (self->available_profiles->len == 0)
531 gst_va_encoder_new (GstVaDisplay * display, guint32 codec)
535 g_return_val_if_fail (GST_IS_VA_DISPLAY (display), NULL);
537 self = g_object_new (GST_TYPE_VA_ENCODER, "display", display, NULL);
538 if (!gst_va_encoder_initialize (self, codec))
539 gst_clear_object (&self);
545 gst_va_encoder_has_profile_and_entrypoint (GstVaEncoder * self,
546 VAProfile profile, VAEntrypoint entrypoint)
548 GstVaProfileConfig *config;
551 g_return_val_if_fail (GST_IS_VA_ENCODER (self), FALSE);
553 if (profile == VAProfileNone)
556 for (i = 0; i < self->available_profiles->len; i++) {
557 config = &g_array_index (self->available_profiles, GstVaProfileConfig, i);
558 if (config->profile == profile) {
562 if (config->entrypoints & (1U << entrypoint))
566 if (i == self->available_profiles->len)
573 gst_va_encoder_get_max_slice_num (GstVaEncoder * self,
574 VAProfile profile, VAEntrypoint entrypoint)
578 VAConfigAttrib attrib = {.type = VAConfigAttribEncMaxSlices };
580 g_return_val_if_fail (GST_IS_VA_ENCODER (self), -1);
582 if (profile == VAProfileNone)
585 if (entrypoint != VAEntrypointEncSlice)
588 dpy = gst_va_display_get_va_dpy (self->display);
589 status = vaGetConfigAttributes (dpy, profile, entrypoint, &attrib, 1);
590 if (status != VA_STATUS_SUCCESS) {
591 GST_WARNING_OBJECT (self, "Failed to query encoding slices: %s",
592 vaErrorStr (status));
596 if (attrib.value == VA_ATTRIB_NOT_SUPPORTED) {
597 GST_WARNING_OBJECT (self, "Driver does not support encoding picture as "
606 gst_va_encoder_get_max_num_reference (GstVaEncoder * self,
607 VAProfile profile, VAEntrypoint entrypoint,
608 guint32 * list0, guint32 * list1)
612 VAConfigAttrib attrib = {.type = VAConfigAttribEncMaxRefFrames };
614 g_return_val_if_fail (GST_IS_VA_ENCODER (self), FALSE);
616 if (profile == VAProfileNone)
619 if (entrypoint != VAEntrypointEncSlice)
622 dpy = gst_va_display_get_va_dpy (self->display);
623 status = vaGetConfigAttributes (dpy, profile, entrypoint, &attrib, 1);
624 if (status != VA_STATUS_SUCCESS) {
625 GST_WARNING_OBJECT (self, "Failed to query reference frames: %s",
626 vaErrorStr (status));
630 if (attrib.value == VA_ATTRIB_NOT_SUPPORTED) {
640 *list0 = attrib.value & 0xffff;
642 *list1 = (attrib.value >> 16) & 0xffff;
648 gst_va_encoder_get_rate_control_mode (GstVaEncoder * self,
649 VAProfile profile, VAEntrypoint entrypoint)
653 VAConfigAttrib attrib = {.type = VAConfigAttribRateControl };
655 g_return_val_if_fail (GST_IS_VA_ENCODER (self), 0);
657 if (profile == VAProfileNone)
660 if (entrypoint != VAEntrypointEncSlice)
663 dpy = gst_va_display_get_va_dpy (self->display);
664 status = vaGetConfigAttributes (dpy, profile, entrypoint, &attrib, 1);
665 if (status != VA_STATUS_SUCCESS) {
666 GST_WARNING_OBJECT (self, "Failed to query rate control mode: %s",
667 vaErrorStr (status));
671 if (attrib.value == VA_ATTRIB_NOT_SUPPORTED) {
672 GST_WARNING_OBJECT (self, "Driver does not support any rate control modes");
680 gst_va_encoder_get_quality_level (GstVaEncoder * self,
681 VAProfile profile, VAEntrypoint entrypoint)
685 VAConfigAttrib attrib = {.type = VAConfigAttribEncQualityRange };
687 g_return_val_if_fail (GST_IS_VA_ENCODER (self), 0);
689 if (profile == VAProfileNone)
692 if (entrypoint != VAEntrypointEncSlice)
695 dpy = gst_va_display_get_va_dpy (self->display);
696 status = vaGetConfigAttributes (dpy, profile, entrypoint, &attrib, 1);
697 if (status != VA_STATUS_SUCCESS) {
698 GST_WARNING_OBJECT (self, "Failed to query the quality level: %s",
699 vaErrorStr (status));
703 if (attrib.value == VA_ATTRIB_NOT_SUPPORTED) {
704 GST_WARNING_OBJECT (self, "Driver does not support quality attribute");
712 gst_va_encoder_has_trellis (GstVaEncoder * self,
713 VAProfile profile, VAEntrypoint entrypoint)
717 VAConfigAttrib attrib = {.type = VAConfigAttribEncQuantization };
719 g_return_val_if_fail (GST_IS_VA_ENCODER (self), FALSE);
721 if (profile == VAProfileNone)
724 if (entrypoint != VAEntrypointEncSlice)
727 dpy = gst_va_display_get_va_dpy (self->display);
728 status = vaGetConfigAttributes (dpy, profile, entrypoint, &attrib, 1);
729 if (status != VA_STATUS_SUCCESS) {
730 GST_WARNING_OBJECT (self, "Failed to query the trellis: %s",
731 vaErrorStr (status));
735 if (attrib.value == VA_ATTRIB_NOT_SUPPORTED) {
736 GST_WARNING_OBJECT (self, "Driver does not support trellis");
740 return attrib.value & VA_ENC_QUANTIZATION_TRELLIS_SUPPORTED;
744 gst_va_encoder_get_rtformat (GstVaEncoder * self,
745 VAProfile profile, VAEntrypoint entrypoint)
749 VAConfigAttrib attrib = {.type = VAConfigAttribRTFormat };
751 if (profile == VAProfileNone)
754 if (entrypoint != VAEntrypointEncSlice)
757 dpy = gst_va_display_get_va_dpy (self->display);
758 status = vaGetConfigAttributes (dpy, profile, entrypoint, &attrib, 1);
759 if (status != VA_STATUS_SUCCESS) {
760 GST_ERROR_OBJECT (self, "Failed to query rt format: %s",
761 vaErrorStr (status));
765 if (attrib.value == VA_ATTRIB_NOT_SUPPORTED) {
766 GST_WARNING_OBJECT (self, "Driver does not support any rt format");
774 gst_va_encoder_get_packed_headers (GstVaEncoder * self, VAProfile profile,
775 VAEntrypoint entrypoint)
779 VAConfigAttrib attrib = {.type = VAConfigAttribEncPackedHeaders };
781 if (profile == VAProfileNone)
784 if (entrypoint != VAEntrypointEncSlice)
787 dpy = gst_va_display_get_va_dpy (self->display);
788 status = vaGetConfigAttributes (dpy, profile, entrypoint, &attrib, 1);
789 if (status != VA_STATUS_SUCCESS) {
790 GST_ERROR_OBJECT (self, "Failed to query packed headers: %s",
791 vaErrorStr (status));
795 if (attrib.value == VA_ATTRIB_NOT_SUPPORTED) {
796 GST_WARNING_OBJECT (self, "Driver does not support any packed headers");
803 /* Add packed header such as SPS, PPS, SEI, etc. If adding slice header,
804 it is attached to the last slice parameter. */
806 gst_va_encoder_add_packed_header (GstVaEncoder * self, GstVaEncodePicture * pic,
807 gint type, gpointer data, gsize size_in_bits, gboolean has_emulation_bytes)
810 VAEncPackedHeaderParameterBuffer param = {
812 .bit_length = size_in_bits,
813 .has_emulation_bytes = has_emulation_bytes,
816 g_return_val_if_fail (GST_IS_VA_ENCODER (self), FALSE);
817 g_return_val_if_fail (self->context != VA_INVALID_ID, FALSE);
818 g_return_val_if_fail (pic && data && size_in_bits > 0, FALSE);
819 g_return_val_if_fail (type >= VAEncPackedHeaderSequence
820 && type <= VAEncPackedHeaderRawData, FALSE);
822 if (!gst_va_encoder_is_open (self)) {
823 GST_ERROR_OBJECT (self, "encoder has not been opened yet");
827 buffer = _create_buffer (self, VAEncPackedHeaderParameterBufferType, ¶m,
829 if (buffer == VA_INVALID_ID)
832 g_array_append_val (pic->params, buffer);
834 buffer = _create_buffer (self, VAEncPackedHeaderDataBufferType, data,
835 (size_in_bits + 7) / 8);
836 if (buffer == VA_INVALID_ID)
839 g_array_append_val (pic->params, buffer);
845 gst_va_encoder_add_param (GstVaEncoder * self, GstVaEncodePicture * pic,
846 VABufferType type, gpointer data, gsize size)
850 g_return_val_if_fail (GST_IS_VA_ENCODER (self), FALSE);
851 g_return_val_if_fail (self->context != VA_INVALID_ID, FALSE);
852 g_return_val_if_fail (pic && data && size > 0, FALSE);
854 if (!gst_va_encoder_is_open (self)) {
855 GST_ERROR_OBJECT (self, "encoder has not been opened yet");
859 buffer = _create_buffer (self, type, data, size);
860 if (buffer == VA_INVALID_ID)
863 g_array_append_val (pic->params, buffer);
869 gst_va_encoder_get_surface_formats (GstVaEncoder * self)
871 g_return_val_if_fail (GST_IS_VA_ENCODER (self), NULL);
873 if (!gst_va_encoder_is_open (self))
876 return _get_surface_formats (self->display, self->config);
880 _get_codec_caps (GstVaEncoder * self)
882 GstCaps *sinkpad_caps = NULL, *srcpad_caps = NULL;
884 if (!gst_va_encoder_is_open (self)
885 && GST_IS_VA_DISPLAY_WRAPPED (self->display)) {
886 if (gst_va_caps_from_profiles (self->display, self->available_profiles,
887 VAEntrypointEncSlice, &sinkpad_caps, &srcpad_caps)) {
888 gst_caps_replace (&self->sinkpad_caps, sinkpad_caps);
889 gst_caps_replace (&self->srcpad_caps, srcpad_caps);
890 gst_caps_unref (srcpad_caps);
891 gst_caps_unref (sinkpad_caps);
901 gst_va_encoder_get_sinkpad_caps (GstVaEncoder * self)
903 GstCaps *sinkpad_caps = NULL;
905 g_return_val_if_fail (GST_IS_VA_ENCODER (self), FALSE);
907 if (g_atomic_pointer_get (&self->sinkpad_caps))
908 return gst_caps_ref (self->sinkpad_caps);
910 if (_get_codec_caps (self))
911 return gst_caps_ref (self->sinkpad_caps);
913 if (gst_va_encoder_is_open (self)) {
914 sinkpad_caps = gst_va_create_raw_caps_from_config (self->display,
916 gst_caps_replace (&self->sinkpad_caps, sinkpad_caps);
917 gst_caps_unref (sinkpad_caps);
919 return gst_caps_ref (self->sinkpad_caps);
926 gst_va_encoder_get_srcpad_caps (GstVaEncoder * self)
928 g_return_val_if_fail (GST_IS_VA_ENCODER (self), FALSE);
930 if (g_atomic_pointer_get (&self->srcpad_caps))
931 return gst_caps_ref (self->srcpad_caps);
933 if (_get_codec_caps (self))
934 return gst_caps_ref (self->srcpad_caps);
936 if (gst_va_encoder_is_open (self)) {
938 VAEntrypoint entrypoint;
941 GST_OBJECT_LOCK (self);
942 profile = self->profile;
943 entrypoint = self->entrypoint;
944 GST_OBJECT_UNLOCK (self);
946 caps = gst_va_create_coded_caps (self->display, profile, entrypoint, NULL);
948 gst_caps_replace (&self->srcpad_caps, caps);
949 return gst_caps_ref (self->srcpad_caps);
957 _destroy_all_buffers (GstVaEncodePicture * pic)
963 g_return_val_if_fail (GST_IS_VA_DISPLAY (pic->display), FALSE);
965 for (i = 0; i < pic->params->len; i++) {
966 buffer = g_array_index (pic->params, VABufferID, i);
967 ret &= _destroy_buffer (pic->display, buffer);
969 pic->params = g_array_set_size (pic->params, 0);
975 gst_va_encoder_encode (GstVaEncoder * self, GstVaEncodePicture * pic)
981 gboolean ret = FALSE;
983 g_return_val_if_fail (pic, FALSE);
985 GST_OBJECT_LOCK (self);
987 if (!_is_open_unlocked (self)) {
988 GST_OBJECT_UNLOCK (self);
989 GST_ERROR_OBJECT (self, "encoder has not been opened yet");
993 context = self->context;
994 GST_OBJECT_UNLOCK (self);
996 surface = gst_va_encode_picture_get_raw_surface (pic);
997 if (surface == VA_INVALID_ID) {
998 GST_ERROR_OBJECT (self, "Encode picture without valid raw surface");
1002 GST_TRACE_OBJECT (self, "Encode the surface %#x", surface);
1004 dpy = gst_va_display_get_va_dpy (self->display);
1006 status = vaBeginPicture (dpy, context, surface);
1007 if (status != VA_STATUS_SUCCESS) {
1008 GST_WARNING_OBJECT (self, "vaBeginPicture: %s", vaErrorStr (status));
1012 if (pic->params->len > 0) {
1013 status = vaRenderPicture (dpy, context, (VABufferID *) pic->params->data,
1015 if (status != VA_STATUS_SUCCESS) {
1016 GST_WARNING_OBJECT (self, "vaRenderPicture: %s", vaErrorStr (status));
1021 status = vaEndPicture (dpy, context);
1022 ret = (status == VA_STATUS_SUCCESS);
1024 GST_WARNING_OBJECT (self, "vaEndPicture: %s", vaErrorStr (status));
1027 _destroy_all_buffers (pic);
1033 _destroy_all_buffers (pic);
1034 status = vaEndPicture (dpy, context);
1041 gst_va_encode_picture_get_reconstruct_surface (GstVaEncodePicture * pic)
1043 g_return_val_if_fail (pic, VA_INVALID_ID);
1044 g_return_val_if_fail (pic->reconstruct_buffer, VA_INVALID_ID);
1046 return gst_va_buffer_get_surface (pic->reconstruct_buffer);
1050 gst_va_encode_picture_get_raw_surface (GstVaEncodePicture * pic)
1052 g_return_val_if_fail (pic, VA_INVALID_ID);
1053 g_return_val_if_fail (pic->raw_buffer, VA_INVALID_ID);
1055 return gst_va_buffer_get_surface (pic->raw_buffer);
1058 GstVaEncodePicture *
1059 gst_va_encode_picture_new (GstVaEncoder * self, GstBuffer * raw_buffer)
1061 GstVaEncodePicture *pic;
1062 VABufferID coded_buffer;
1066 GstBufferPool *recon_pool = NULL;
1067 GstBuffer *reconstruct_buffer = NULL;
1069 GstBufferPoolAcquireParams buffer_pool_params = {
1070 .flags = GST_BUFFER_POOL_ACQUIRE_FLAG_DONTWAIT,
1073 g_return_val_if_fail (self && GST_IS_VA_ENCODER (self), NULL);
1074 g_return_val_if_fail (raw_buffer && GST_IS_BUFFER (raw_buffer), NULL);
1076 GST_OBJECT_LOCK (self);
1078 if (!_is_open_unlocked (self)) {
1079 GST_OBJECT_UNLOCK (self);
1080 GST_ERROR_OBJECT (self, "encoder has not been opened yet");
1084 if (self->codedbuf_size <= 0) {
1085 GST_ERROR_OBJECT (self, "codedbuf_size: %d, is invalid",
1086 self->codedbuf_size);
1087 GST_OBJECT_UNLOCK (self);
1090 codedbuf_size = self->codedbuf_size;
1092 recon_pool = gst_object_ref (self->recon_pool);
1094 GST_OBJECT_UNLOCK (self);
1096 ret = gst_buffer_pool_acquire_buffer (recon_pool, &reconstruct_buffer,
1097 &buffer_pool_params);
1098 gst_clear_object (&recon_pool);
1100 if (ret != GST_FLOW_OK) {
1101 GST_ERROR_OBJECT (self, "Failed to create the reconstruct picture");
1102 gst_clear_buffer (&reconstruct_buffer);
1106 dpy = gst_va_display_get_va_dpy (self->display);
1107 status = vaCreateBuffer (dpy, self->context, VAEncCodedBufferType,
1108 codedbuf_size, 1, NULL, &coded_buffer);
1109 if (status != VA_STATUS_SUCCESS) {
1110 GST_ERROR_OBJECT (self, "vaCreateBuffer: %s", vaErrorStr (status));
1111 gst_clear_buffer (&reconstruct_buffer);
1115 pic = g_slice_new (GstVaEncodePicture);
1116 pic->raw_buffer = gst_buffer_ref (raw_buffer);
1117 pic->reconstruct_buffer = reconstruct_buffer;
1118 pic->display = gst_object_ref (self->display);
1119 pic->coded_buffer = coded_buffer;
1121 pic->params = g_array_sized_new (FALSE, FALSE, sizeof (VABufferID), 8);
1127 gst_va_encode_picture_free (GstVaEncodePicture * pic)
1129 g_return_if_fail (pic);
1131 _destroy_all_buffers (pic);
1133 if (pic->coded_buffer != VA_INVALID_ID)
1134 _destroy_buffer (pic->display, pic->coded_buffer);
1136 gst_buffer_unref (pic->raw_buffer);
1137 gst_buffer_unref (pic->reconstruct_buffer);
1139 g_clear_pointer (&pic->params, g_array_unref);
1140 gst_clear_object (&pic->display);
1142 g_slice_free (GstVaEncodePicture, pic);
1146 * GstVaEncoderRateControl:
1151 gst_va_encoder_rate_control_get_type (void)
1153 static gsize type = 0;
1154 static const GEnumValue values[] = {
1155 {VA_RC_CBR, "Constant Bitrate", "cbr"},
1156 {VA_RC_VBR, "Variable Bitrate", "vbr"},
1157 {VA_RC_VCM, "Video Conferencing Mode (Non HRD compliant)", "vcm"},
1158 {VA_RC_CQP, "Constant Quantizer", "cqp"},
1159 /* {VA_RC_VBR_CONSTRAINED, "VBR with peak rate higher than average bitrate", */
1160 /* "vbr-constrained"}, */
1161 /* {VA_RC_ICQ, "Intelligent Constant Quality", "icq"}, */
1162 /* {VA_RC_MB, "Macroblock based rate control", "mb"}, */
1163 /* {VA_RC_CFS, "Constant Frame Size", "cfs"}, */
1164 /* {VA_RC_PARALLEL, "Parallel BRC", "parallel"}, */
1165 /* {VA_RC_QVBR, "Quality defined VBR", "qvbr"}, */
1166 /* {VA_RC_AVBR, "Average VBR", "avbr"}, */
1170 if (g_once_init_enter (&type)) {
1171 GType _type = g_enum_register_static ("GstVaEncoderRateControl", values);
1172 g_once_init_leave (&type, _type);