mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-10 19:31:12 +00:00
50b2423a2b
Originally vaapivideobufferpool instantiates its own allocator regardless the received configuration, and it relies in custom configuration options to choose which kind of allocator instantiate. This patch transfers the responsibility of the allocator instantiate to vaapipluginbase and pass it to the vaapivideobufferpool through its configuration. * gst/vaapi/gstvaapipluginbase.c + set_dmabuf_allocator(): inserts a dmabuf allocator in the bufferpool + ensure_sinkpad_buffer_pool(): set a normal vaapi video allocator in bufferpool configuration + gst_vaapi_plugin_base_propose_allocation(): call set_dmabuf_allocator() if needed. + gst_vaapi_plugin_base_decide_allocation(): set a normal vaapi video allocator in bufferpool configuration * gst/vaapi/gstvaapivideobufferpool.c + gst_vaapi_video_buffer_pool_set_config(): instead of instantiate the allocator, process the received one through its configuration. * gst/vaapi/gstvaapivideobufferpool.h: removed GST_BUFFER_POOL_OPTION_DMABUF_MEMORY since it is not used anymore. * gst/vaapi/gstvaapivideomemory.c + gst_vaapi_is_dmabuf_allocator(): new helper function to identify a dmabuf allocator with the vaapi qdata. https://bugzilla.gnome.org/show_bug.cgi?id=765435
392 lines
11 KiB
C
392 lines
11 KiB
C
/*
|
|
* gstvaapivideobufferpool.c - Gstreamer/VA video buffer pool
|
|
*
|
|
* Copyright (C) 2013 Intel Corporation
|
|
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public License
|
|
* as published by the Free Software Foundation; either version 2.1
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free
|
|
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#include "gstcompat.h"
|
|
#include "gstvaapivideobufferpool.h"
|
|
#include "gstvaapivideobuffer.h"
|
|
#include "gstvaapivideomemory.h"
|
|
#include "gstvaapipluginutil.h"
|
|
#if (USE_GLX || USE_EGL)
|
|
#include "gstvaapivideometa_texture.h"
|
|
#endif
|
|
|
|
GST_DEBUG_CATEGORY_STATIC (gst_debug_vaapivideopool);
|
|
#define GST_CAT_DEFAULT gst_debug_vaapivideopool
|
|
|
|
G_DEFINE_TYPE (GstVaapiVideoBufferPool,
|
|
gst_vaapi_video_buffer_pool, GST_TYPE_BUFFER_POOL);
|
|
|
|
enum
|
|
{
|
|
PROP_0,
|
|
|
|
PROP_DISPLAY,
|
|
};
|
|
|
|
struct _GstVaapiVideoBufferPoolPrivate
|
|
{
|
|
GstVideoInfo video_info;
|
|
GstAllocator *allocator;
|
|
GstVideoInfo alloc_info;
|
|
GstVaapiDisplay *display;
|
|
guint has_video_meta:1;
|
|
guint has_video_alignment:1;
|
|
guint has_texture_upload_meta:1;
|
|
guint use_dmabuf_memory:1;
|
|
};
|
|
|
|
#define GST_VAAPI_VIDEO_BUFFER_POOL_GET_PRIVATE(obj) \
|
|
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_VAAPI_TYPE_VIDEO_BUFFER_POOL, \
|
|
GstVaapiVideoBufferPoolPrivate))
|
|
|
|
static void
|
|
gst_vaapi_video_buffer_pool_finalize (GObject * object)
|
|
{
|
|
GstVaapiVideoBufferPoolPrivate *const priv =
|
|
GST_VAAPI_VIDEO_BUFFER_POOL (object)->priv;
|
|
|
|
gst_vaapi_display_replace (&priv->display, NULL);
|
|
g_clear_object (&priv->allocator);
|
|
|
|
G_OBJECT_CLASS (gst_vaapi_video_buffer_pool_parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
gst_vaapi_video_buffer_pool_set_property (GObject * object, guint prop_id,
|
|
const GValue * value, GParamSpec * pspec)
|
|
{
|
|
GstVaapiVideoBufferPoolPrivate *const priv =
|
|
GST_VAAPI_VIDEO_BUFFER_POOL (object)->priv;
|
|
|
|
switch (prop_id) {
|
|
case PROP_DISPLAY:
|
|
priv->display = gst_vaapi_display_ref (g_value_get_pointer (value));
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
gst_vaapi_video_buffer_pool_get_property (GObject * object, guint prop_id,
|
|
GValue * value, GParamSpec * pspec)
|
|
{
|
|
GstVaapiVideoBufferPoolPrivate *const priv =
|
|
GST_VAAPI_VIDEO_BUFFER_POOL (object)->priv;
|
|
|
|
switch (prop_id) {
|
|
case PROP_DISPLAY:
|
|
g_value_set_pointer (value, priv->display);
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
fill_video_alignment (GstVaapiVideoBufferPool * pool, GstVideoAlignment * align)
|
|
{
|
|
GstVideoInfo *const vip = &pool->priv->alloc_info;
|
|
guint i;
|
|
|
|
gst_video_alignment_reset (align);
|
|
for (i = 0; i < GST_VIDEO_INFO_N_PLANES (vip); i++)
|
|
align->stride_align[i] =
|
|
(1U << g_bit_nth_lsf (GST_VIDEO_INFO_PLANE_STRIDE (vip, i), 0)) - 1;
|
|
}
|
|
|
|
static const gchar **
|
|
gst_vaapi_video_buffer_pool_get_options (GstBufferPool * pool)
|
|
{
|
|
static const gchar *g_options[] = {
|
|
GST_BUFFER_POOL_OPTION_VIDEO_META,
|
|
GST_BUFFER_POOL_OPTION_VAAPI_VIDEO_META,
|
|
GST_BUFFER_POOL_OPTION_VIDEO_GL_TEXTURE_UPLOAD_META,
|
|
GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT,
|
|
NULL,
|
|
};
|
|
|
|
return g_options;
|
|
}
|
|
|
|
static gboolean
|
|
gst_vaapi_video_buffer_pool_set_config (GstBufferPool * pool,
|
|
GstStructure * config)
|
|
{
|
|
GstVaapiVideoBufferPoolPrivate *const priv =
|
|
GST_VAAPI_VIDEO_BUFFER_POOL (pool)->priv;
|
|
GstCaps *caps;
|
|
GstVideoInfo new_vip;
|
|
const GstVideoInfo *alloc_vip;
|
|
GstVideoAlignment align;
|
|
GstAllocator *allocator;
|
|
|
|
GST_DEBUG_OBJECT (pool, "config %" GST_PTR_FORMAT, config);
|
|
|
|
caps = NULL;
|
|
if (!gst_buffer_pool_config_get_params (config, &caps, NULL, NULL, NULL))
|
|
goto error_invalid_config;
|
|
if (!caps)
|
|
goto error_no_caps;
|
|
if (!gst_video_info_from_caps (&new_vip, caps))
|
|
goto error_invalid_caps;
|
|
|
|
allocator = NULL;
|
|
if (!gst_buffer_pool_config_get_allocator (config, &allocator, NULL))
|
|
goto error_invalid_allocator;
|
|
|
|
if (gst_video_info_changed (&priv->video_info, &new_vip))
|
|
gst_object_replace ((GstObject **) & priv->allocator, NULL);
|
|
priv->video_info = new_vip;
|
|
|
|
if (!gst_buffer_pool_config_has_option (config,
|
|
GST_BUFFER_POOL_OPTION_VAAPI_VIDEO_META))
|
|
goto error_no_vaapi_video_meta_option;
|
|
|
|
/* not our allocator, not our buffers */
|
|
if (allocator) {
|
|
priv->use_dmabuf_memory = gst_vaapi_is_dmabuf_allocator (allocator);
|
|
if (priv->use_dmabuf_memory ||
|
|
g_strcmp0 (allocator->mem_type, GST_VAAPI_VIDEO_MEMORY_NAME) == 0) {
|
|
if (priv->allocator)
|
|
gst_object_unref (priv->allocator);
|
|
if ((priv->allocator = allocator))
|
|
gst_object_ref (allocator);
|
|
alloc_vip = gst_allocator_get_vaapi_video_info (priv->allocator, NULL);
|
|
if (!alloc_vip)
|
|
goto error_create_allocator_info;
|
|
priv->alloc_info = *alloc_vip;
|
|
}
|
|
}
|
|
if (!priv->allocator)
|
|
goto error_no_allocator;
|
|
|
|
priv->has_video_meta = gst_buffer_pool_config_has_option (config,
|
|
GST_BUFFER_POOL_OPTION_VIDEO_META);
|
|
|
|
priv->has_video_alignment = gst_buffer_pool_config_has_option (config,
|
|
GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT);
|
|
if (priv->has_video_alignment) {
|
|
fill_video_alignment (GST_VAAPI_VIDEO_BUFFER_POOL (pool), &align);
|
|
gst_buffer_pool_config_set_video_alignment (config, &align);
|
|
}
|
|
|
|
priv->has_texture_upload_meta = !priv->use_dmabuf_memory
|
|
&& gst_buffer_pool_config_has_option (config,
|
|
GST_BUFFER_POOL_OPTION_VIDEO_GL_TEXTURE_UPLOAD_META);
|
|
|
|
return
|
|
GST_BUFFER_POOL_CLASS
|
|
(gst_vaapi_video_buffer_pool_parent_class)->set_config (pool, config);
|
|
|
|
/* ERRORS */
|
|
error_invalid_config:
|
|
{
|
|
GST_ERROR_OBJECT (pool, "invalid config");
|
|
return FALSE;
|
|
}
|
|
error_no_caps:
|
|
{
|
|
GST_ERROR_OBJECT (pool, "no caps in config");
|
|
return FALSE;
|
|
}
|
|
error_invalid_caps:
|
|
{
|
|
GST_ERROR_OBJECT (pool, "invalid caps %" GST_PTR_FORMAT, caps);
|
|
return FALSE;
|
|
}
|
|
error_invalid_allocator:
|
|
{
|
|
GST_ERROR_OBJECT (pool, "no allocator in config");
|
|
return FALSE;
|
|
}
|
|
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");
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
static GstFlowReturn
|
|
gst_vaapi_video_buffer_pool_alloc_buffer (GstBufferPool * pool,
|
|
GstBuffer ** out_buffer_ptr, GstBufferPoolAcquireParams * params)
|
|
{
|
|
GstVaapiVideoBufferPoolPrivate *const priv =
|
|
GST_VAAPI_VIDEO_BUFFER_POOL (pool)->priv;
|
|
GstVaapiVideoMeta *meta;
|
|
GstMemory *mem;
|
|
GstBuffer *buffer;
|
|
|
|
const gboolean alloc_vaapi_video_meta = !params ||
|
|
!(params->flags & GST_VAAPI_VIDEO_BUFFER_POOL_ACQUIRE_FLAG_NO_ALLOC);
|
|
|
|
if (!priv->allocator)
|
|
goto error_no_allocator;
|
|
|
|
if (alloc_vaapi_video_meta) {
|
|
meta = gst_vaapi_video_meta_new (priv->display);
|
|
if (!meta)
|
|
goto error_create_meta;
|
|
|
|
buffer = gst_vaapi_video_buffer_new (meta);
|
|
} else {
|
|
meta = NULL;
|
|
buffer = gst_vaapi_video_buffer_new_empty ();
|
|
}
|
|
if (!buffer)
|
|
goto error_create_buffer;
|
|
|
|
if (priv->use_dmabuf_memory)
|
|
mem = gst_vaapi_dmabuf_memory_new (priv->allocator, meta);
|
|
else
|
|
mem = gst_vaapi_video_memory_new (priv->allocator, meta);
|
|
if (!mem)
|
|
goto error_create_memory;
|
|
gst_vaapi_video_meta_replace (&meta, NULL);
|
|
gst_buffer_append_memory (buffer, mem);
|
|
|
|
if (priv->has_video_meta) {
|
|
GstVideoInfo *const vip = &priv->alloc_info;
|
|
GstVideoMeta *vmeta;
|
|
|
|
vmeta = gst_buffer_add_video_meta_full (buffer, 0,
|
|
GST_VIDEO_INFO_FORMAT (vip), GST_VIDEO_INFO_WIDTH (vip),
|
|
GST_VIDEO_INFO_HEIGHT (vip), GST_VIDEO_INFO_N_PLANES (vip),
|
|
&GST_VIDEO_INFO_PLANE_OFFSET (vip, 0),
|
|
&GST_VIDEO_INFO_PLANE_STRIDE (vip, 0));
|
|
|
|
if (GST_VAAPI_IS_VIDEO_MEMORY (mem)) {
|
|
vmeta->map = gst_video_meta_map_vaapi_memory;
|
|
vmeta->unmap = gst_video_meta_unmap_vaapi_memory;
|
|
}
|
|
}
|
|
#if (USE_GLX || USE_EGL)
|
|
if (priv->has_texture_upload_meta)
|
|
gst_buffer_add_texture_upload_meta (buffer);
|
|
#endif
|
|
|
|
*out_buffer_ptr = buffer;
|
|
return GST_FLOW_OK;
|
|
|
|
/* ERRORS */
|
|
error_no_allocator:
|
|
{
|
|
GST_ERROR_OBJECT (pool, "no GstAllocator in buffer pool");
|
|
return GST_FLOW_ERROR;
|
|
}
|
|
error_create_meta:
|
|
{
|
|
GST_ERROR_OBJECT (pool, "failed to allocate vaapi video meta");
|
|
return GST_FLOW_ERROR;
|
|
}
|
|
error_create_buffer:
|
|
{
|
|
GST_ERROR_OBJECT (pool, "failed to create video buffer");
|
|
gst_vaapi_video_meta_unref (meta);
|
|
return GST_FLOW_ERROR;
|
|
}
|
|
error_create_memory:
|
|
{
|
|
GST_ERROR_OBJECT (pool, "failed to create video memory");
|
|
gst_buffer_unref (buffer);
|
|
gst_vaapi_video_meta_unref (meta);
|
|
return GST_FLOW_ERROR;
|
|
}
|
|
}
|
|
|
|
static void
|
|
gst_vaapi_video_buffer_pool_reset_buffer (GstBufferPool * pool,
|
|
GstBuffer * buffer)
|
|
{
|
|
GstMemory *const mem = gst_buffer_peek_memory (buffer, 0);
|
|
|
|
/* Release the underlying surface proxy */
|
|
if (GST_VAAPI_IS_VIDEO_MEMORY (mem))
|
|
gst_vaapi_video_memory_reset_surface (GST_VAAPI_VIDEO_MEMORY_CAST (mem));
|
|
|
|
GST_BUFFER_POOL_CLASS (gst_vaapi_video_buffer_pool_parent_class)->reset_buffer
|
|
(pool, buffer);
|
|
}
|
|
|
|
static void
|
|
gst_vaapi_video_buffer_pool_class_init (GstVaapiVideoBufferPoolClass * klass)
|
|
{
|
|
GObjectClass *const object_class = G_OBJECT_CLASS (klass);
|
|
GstBufferPoolClass *const pool_class = GST_BUFFER_POOL_CLASS (klass);
|
|
|
|
GST_DEBUG_CATEGORY_INIT (gst_debug_vaapivideopool,
|
|
"vaapivideopool", 0, "VA-API video pool");
|
|
|
|
g_type_class_add_private (klass, sizeof (GstVaapiVideoBufferPoolPrivate));
|
|
|
|
object_class->finalize = gst_vaapi_video_buffer_pool_finalize;
|
|
object_class->set_property = gst_vaapi_video_buffer_pool_set_property;
|
|
object_class->get_property = gst_vaapi_video_buffer_pool_get_property;
|
|
pool_class->get_options = gst_vaapi_video_buffer_pool_get_options;
|
|
pool_class->set_config = gst_vaapi_video_buffer_pool_set_config;
|
|
pool_class->alloc_buffer = gst_vaapi_video_buffer_pool_alloc_buffer;
|
|
pool_class->reset_buffer = gst_vaapi_video_buffer_pool_reset_buffer;
|
|
|
|
/**
|
|
* GstVaapiVideoBufferPool:display:
|
|
*
|
|
* The #GstVaapiDisplay this object is bound to.
|
|
*/
|
|
g_object_class_install_property
|
|
(object_class,
|
|
PROP_DISPLAY,
|
|
g_param_spec_pointer ("display",
|
|
"Display",
|
|
"The GstVaapiDisplay to use for this video pool",
|
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
|
}
|
|
|
|
static void
|
|
gst_vaapi_video_buffer_pool_init (GstVaapiVideoBufferPool * pool)
|
|
{
|
|
GstVaapiVideoBufferPoolPrivate *const priv =
|
|
GST_VAAPI_VIDEO_BUFFER_POOL_GET_PRIVATE (pool);
|
|
|
|
pool->priv = priv;
|
|
|
|
gst_video_info_init (&priv->video_info);
|
|
}
|
|
|
|
GstBufferPool *
|
|
gst_vaapi_video_buffer_pool_new (GstVaapiDisplay * display)
|
|
{
|
|
return g_object_new (GST_VAAPI_TYPE_VIDEO_BUFFER_POOL,
|
|
"display", display, NULL);
|
|
}
|