From 7a20692364b67809e2a77769fe591557f445c170 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Manuel=20J=C3=A1quez=20Leal?= Date: Fri, 9 Jun 2017 13:05:36 +0200 Subject: [PATCH] plugins: distinguish allocation and negotiation caps The vaapi video decoders might have different allocation caps from the negotiation caps, thus the GstVideoMeta shall use the negotiation caps, not the allocation caps. This was done before reusing gst_allocator_get_vaapi_video_info(), storing there the negotiation caps if they differ from the allocation ones, but this strategy felt short when the allocator had to be reset in the vaapi buffer pool, since we need both. This patch adds gst_allocator_set_vaapi_negotiated_video_info() and gst_allocator_get_vaapi_negotiated_video_info() to store the negotiated video info in the allocator, and distinguish it from the allocation video info. https://bugzilla.gnome.org/show_bug.cgi?id=783599 --- gst/vaapi/gstvaapipluginbase.c | 55 ++++++++++++++--------------- gst/vaapi/gstvaapivideobufferpool.c | 23 ++++++------ gst/vaapi/gstvaapivideomemory.c | 51 ++++++++++++++++++++++++++ gst/vaapi/gstvaapivideomemory.h | 9 +++++ 4 files changed, 98 insertions(+), 40 deletions(-) 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);