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
This commit is contained in:
Víctor Manuel Jáquez Leal 2017-06-09 13:05:36 +02:00
parent 36cf510ce8
commit 7a20692364
4 changed files with 98 additions and 40 deletions

View file

@ -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++) {
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 (alloc_vi, i);
GST_VIDEO_INFO_PLANE_OFFSET (image_info, 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);
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;

View file

@ -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");

View file

@ -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

View file

@ -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);