diff --git a/gst/vaapi/gstvaapipluginbase.c b/gst/vaapi/gstvaapipluginbase.c index 8c2b84aa50..e7270b8cdd 100644 --- a/gst/vaapi/gstvaapipluginbase.c +++ b/gst/vaapi/gstvaapipluginbase.c @@ -567,24 +567,10 @@ ensure_srcpad_allocator (GstVaapiPluginBase * plugin, GstVideoInfo * vinfo, GstCaps * caps) { gboolean different_caps; - GstVideoInfo vi; GstVaapiImageUsageFlags usage_flag = GST_VAAPI_IMAGE_USAGE_FLAG_NATIVE_FORMATS; - /* the received caps are the "allocation caps" which may be - * different from the "negotiation caps". In this case, we should - * indicate the allocator to store the negotiation caps since they - * are the one should be used for frame mapping with GstVideoMeta */ - different_caps = GST_IS_VIDEO_DECODER (plugin) && plugin->srcpad_caps && - !gst_caps_is_strictly_equal (plugin->srcpad_caps, caps); - - if (different_caps) { - vi = plugin->srcpad_info; - } else { - vi = *vinfo; - } - - if (!reset_allocator (plugin->srcpad_allocator, &vi)) + if (!reset_allocator (plugin->srcpad_allocator, vinfo)) return TRUE; plugin->srcpad_allocator = NULL; @@ -609,22 +595,33 @@ ensure_srcpad_allocator (GstVaapiPluginBase * plugin, GstVideoInfo * vinfo, if (!plugin->srcpad_allocator) goto error_create_allocator; + /* the received caps are the "allocation caps" which may be + * different from the "negotiation caps". In this case, we should + * indicate the allocator to store the negotiation caps since they + * are the one should be used for frame mapping with GstVideoMeta */ + different_caps = GST_IS_VIDEO_DECODER (plugin) && plugin->srcpad_caps && + !gst_caps_is_strictly_equal (plugin->srcpad_caps, caps); + if (different_caps) { - guint i, flags = 0; - const GstVideoInfo *alloc_vi = - gst_allocator_get_vaapi_video_info (plugin->srcpad_allocator, &flags); - /* update the planes and the size with the allocator image info, - * but not the resolution */ - if (alloc_vi) { - for (i = 0; i < GST_VIDEO_INFO_N_PLANES (alloc_vi); i++) { - GST_VIDEO_INFO_PLANE_OFFSET (&vi, i) = - GST_VIDEO_INFO_PLANE_OFFSET (alloc_vi, i); - GST_VIDEO_INFO_PLANE_STRIDE (&vi, i) = - GST_VIDEO_INFO_PLANE_STRIDE (alloc_vi, i); - } - GST_VIDEO_INFO_SIZE (&vi) = GST_VIDEO_INFO_SIZE (alloc_vi); - gst_allocator_set_vaapi_video_info (plugin->srcpad_allocator, &vi, flags); + guint i; + GstVideoInfo vi = plugin->srcpad_info; + const GstVideoInfo *image_info = + gst_allocator_get_vaapi_video_info (plugin->srcpad_allocator, NULL); + + g_assert (image_info); /* both allocators should set its video + * info */ + + /* update the planes and the size with the allocator image/surface + * info, but not the resolution */ + for (i = 0; i < GST_VIDEO_INFO_N_PLANES (image_info); i++) { + GST_VIDEO_INFO_PLANE_OFFSET (&vi, i) = + GST_VIDEO_INFO_PLANE_OFFSET (image_info, i); + GST_VIDEO_INFO_PLANE_STRIDE (&vi, i) = + GST_VIDEO_INFO_PLANE_STRIDE (image_info, i); } + GST_VIDEO_INFO_SIZE (&vi) = GST_VIDEO_INFO_SIZE (image_info); + gst_allocator_set_vaapi_negotiated_video_info (plugin->srcpad_allocator, + &vi); } return TRUE; diff --git a/gst/vaapi/gstvaapivideobufferpool.c b/gst/vaapi/gstvaapivideobufferpool.c index f0b6ec4c06..c1c4fba1a6 100644 --- a/gst/vaapi/gstvaapivideobufferpool.c +++ b/gst/vaapi/gstvaapivideobufferpool.c @@ -137,6 +137,7 @@ gst_vaapi_video_buffer_pool_set_config (GstBufferPool * pool, GstCaps *caps; GstVideoInfo new_allocation_vinfo; const GstVideoInfo *allocator_vinfo; + const GstVideoInfo *negotiated_vinfo; GstVideoAlignment align; GstAllocator *allocator; gboolean ret, updated = FALSE; @@ -176,9 +177,16 @@ gst_vaapi_video_buffer_pool_set_config (GstBufferPool * pool, gst_allocator_set_vaapi_video_info (allocator, &new_allocation_vinfo, surface_alloc_flags); } else if (!priv->use_dmabuf_memory && (vinfo_changed || !allocator)) { + negotiated_vinfo = + gst_allocator_get_vaapi_negotiated_video_info (allocator); + /* let's destroy the other allocator and create a new one */ allocator = gst_vaapi_video_allocator_new (priv->display, &new_allocation_vinfo, surface_alloc_flags, 0); + if (negotiated_vinfo) { + gst_allocator_set_vaapi_negotiated_video_info (allocator, + negotiated_vinfo); + } gst_buffer_pool_config_set_allocator (config, allocator, NULL); gst_object_unref (allocator); } @@ -197,11 +205,10 @@ gst_vaapi_video_buffer_pool_set_config (GstBufferPool * pool, gst_object_unref (priv->allocator); if ((priv->allocator = allocator)) gst_object_ref (allocator); - allocator_vinfo = - gst_allocator_get_vaapi_video_info (priv->allocator, NULL); - if (!allocator_vinfo) - goto error_create_allocator_info; - priv->vmeta_vinfo = *allocator_vinfo; + negotiated_vinfo = + gst_allocator_get_vaapi_negotiated_video_info (priv->allocator); + priv->vmeta_vinfo = (negotiated_vinfo) ? + *negotiated_vinfo : priv->allocation_vinfo; } if (GST_VIDEO_INFO_SIZE (&priv->vmeta_vinfo) != size) { gst_buffer_pool_config_set_params (config, caps, @@ -273,12 +280,6 @@ error_no_vaapi_video_meta_option: GST_ERROR_OBJECT (pool, "no GstVaapiVideoMeta option in config"); return FALSE; } -error_create_allocator_info: - { - GST_ERROR_OBJECT (pool, - "failed to create GstVaapiVideoAllocator `video-info'"); - return FALSE; - } error_no_allocator: { GST_ERROR_OBJECT (pool, "no allocator defined"); diff --git a/gst/vaapi/gstvaapivideomemory.c b/gst/vaapi/gstvaapivideomemory.c index 17c7a0dad9..6b26d02ac3 100644 --- a/gst/vaapi/gstvaapivideomemory.c +++ b/gst/vaapi/gstvaapivideomemory.c @@ -1185,6 +1185,19 @@ surface_alloc_flags_quark_get (void) return g_quark; } +#define NEGOTIATED_VINFO_QUARK negotiated_vinfo_quark_get () +static GQuark +negotiated_vinfo_quark_get (void) +{ + static gsize g_quark; + + if (g_once_init_enter (&g_quark)) { + gsize quark = (gsize) g_quark_from_static_string ("negotiated-vinfo"); + g_once_init_leave (&g_quark, quark); + } + return g_quark; +} + /** * gst_allocator_get_vaapi_video_info: * @allocator: a #GstAllocator @@ -1254,6 +1267,44 @@ gst_allocator_set_vaapi_video_info (GstAllocator * allocator, return TRUE; } +/** + * gst_allocator_set_vaapi_negotiated_video_info: + * @allocator: a #GstAllocator + * @negotiated_vinfo: the negotiated #GstVideoInfo to store + * + * Stores as GObject's qdata the @negotiated_vinfo in the allocator + * instance. + * + * The @negotiated_vinfo is different of the @alloc_info from + * gst_allocator_set_vaapi_video_info(), and might not be set. + **/ +void +gst_allocator_set_vaapi_negotiated_video_info (GstAllocator * allocator, + const GstVideoInfo * negotiated_vinfo) +{ + g_return_if_fail (allocator && GST_IS_ALLOCATOR (allocator)); + g_return_if_fail (negotiated_vinfo); + + g_object_set_qdata_full (G_OBJECT (allocator), NEGOTIATED_VINFO_QUARK, + gst_video_info_copy (negotiated_vinfo), + (GDestroyNotify) gst_video_info_free); +} + +/** + * gst_allocator_get_vaapi_negotiated_video_info: + * @allocator: a #GstAllocator + * + * Returns: the stored negotiation #GstVideoInfo, if it was stored + * previously. Otherwise, %NULL + **/ +GstVideoInfo * +gst_allocator_get_vaapi_negotiated_video_info (GstAllocator * allocator) +{ + g_return_val_if_fail (GST_IS_ALLOCATOR (allocator), NULL); + + return g_object_get_qdata (G_OBJECT (allocator), NEGOTIATED_VINFO_QUARK); +} + /** * gst_vaapi_is_dmabuf_allocator: * @allocator: an #GstAllocator diff --git a/gst/vaapi/gstvaapivideomemory.h b/gst/vaapi/gstvaapivideomemory.h index 47c72eb67e..dcc998d456 100644 --- a/gst/vaapi/gstvaapivideomemory.h +++ b/gst/vaapi/gstvaapivideomemory.h @@ -278,6 +278,15 @@ gboolean gst_allocator_set_vaapi_video_info (GstAllocator * allocator, const GstVideoInfo * alloc_info, guint surface_alloc_flags); +G_GNUC_INTERNAL +void +gst_allocator_set_vaapi_negotiated_video_info (GstAllocator * allocator, + const GstVideoInfo * negotiated_vinfo); + +G_GNUC_INTERNAL +GstVideoInfo * +gst_allocator_get_vaapi_negotiated_video_info (GstAllocator * allocator); + G_GNUC_INTERNAL gboolean gst_vaapi_is_dmabuf_allocator (GstAllocator * allocator);