mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-27 02:30:35 +00:00
ceb60285ea
When interacting with SW elements, the buffers and underlying video memory could be mapped as read/write. However, we need to use those buffers again as plain VA surfaces, we have to make sure the VA image is thus committed back to VA surface memory. This fixes pipelines involving avdec_* and vaapi{postproc,sink}.
875 lines
22 KiB
C
875 lines
22 KiB
C
/*
|
|
* gstvaapivideometa.c - Gst VA video meta
|
|
*
|
|
* Copyright (C) 2010-2011 Splitted-Desktop Systems
|
|
* Author: Gwenole Beauchesne <gwenole.beauchesne@splitted-desktop.com>
|
|
* Copyright (C) 2011-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
|
|
*/
|
|
|
|
/**
|
|
* SECTION:gstvaapivideometa
|
|
* @short_description: VA video meta for GStreamer
|
|
*/
|
|
|
|
#include "gst/vaapi/sysdeps.h"
|
|
#include <gst/vaapi/gstvaapiimagepool.h>
|
|
#include <gst/vaapi/gstvaapisurfacepool.h>
|
|
#include "gstvaapivideometa.h"
|
|
|
|
#if GST_CHECK_VERSION(1,0,0)
|
|
# include "gstvaapivideomemory.h"
|
|
#endif
|
|
|
|
#define GST_VAAPI_VIDEO_META(obj) \
|
|
((GstVaapiVideoMeta *) (obj))
|
|
#define GST_VAAPI_IS_VIDEO_META(obj) \
|
|
(GST_VAAPI_VIDEO_META (obj) != NULL)
|
|
|
|
struct _GstVaapiVideoMeta
|
|
{
|
|
GstBuffer *buffer;
|
|
gint ref_count;
|
|
GstVaapiDisplay *display;
|
|
GstVaapiVideoPool *image_pool;
|
|
GstVaapiImage *image;
|
|
GstVaapiSurfaceProxy *proxy;
|
|
GFunc converter;
|
|
guint render_flags;
|
|
GstVaapiRectangle render_rect;
|
|
guint has_render_rect:1;
|
|
};
|
|
|
|
static gboolean
|
|
ensure_surface_proxy (GstVaapiVideoMeta * meta)
|
|
{
|
|
if (!meta->proxy)
|
|
return FALSE;
|
|
|
|
#if GST_CHECK_VERSION(1,0,0)
|
|
if (meta->buffer) {
|
|
GstMemory *const mem = gst_buffer_peek_memory (meta->buffer, 0);
|
|
|
|
if (GST_VAAPI_IS_VIDEO_MEMORY (mem))
|
|
return gst_vaapi_video_memory_sync (GST_VAAPI_VIDEO_MEMORY_CAST (mem));
|
|
}
|
|
#endif
|
|
return TRUE;
|
|
}
|
|
|
|
static inline void
|
|
set_display (GstVaapiVideoMeta * meta, GstVaapiDisplay * display)
|
|
{
|
|
gst_vaapi_display_replace (&meta->display, display);
|
|
}
|
|
|
|
static inline void
|
|
set_image (GstVaapiVideoMeta * meta, GstVaapiImage * image)
|
|
{
|
|
meta->image = gst_vaapi_object_ref (image);
|
|
set_display (meta, gst_vaapi_object_get_display (GST_VAAPI_OBJECT (image)));
|
|
}
|
|
|
|
static gboolean
|
|
set_image_from_pool (GstVaapiVideoMeta * meta, GstVaapiVideoPool * pool)
|
|
{
|
|
GstVaapiImage *image;
|
|
|
|
image = gst_vaapi_video_pool_get_object (pool);
|
|
if (!image)
|
|
return FALSE;
|
|
|
|
set_image (meta, image);
|
|
meta->image_pool = gst_vaapi_video_pool_ref (pool);
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
set_surface_proxy (GstVaapiVideoMeta * meta, GstVaapiSurfaceProxy * proxy)
|
|
{
|
|
GstVaapiSurface *surface;
|
|
|
|
surface = GST_VAAPI_SURFACE_PROXY_SURFACE (proxy);
|
|
if (!surface)
|
|
return FALSE;
|
|
|
|
meta->proxy = gst_vaapi_surface_proxy_ref (proxy);
|
|
set_display (meta, gst_vaapi_object_get_display (GST_VAAPI_OBJECT (surface)));
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
set_surface_proxy_from_pool (GstVaapiVideoMeta * meta, GstVaapiVideoPool * pool)
|
|
{
|
|
GstVaapiSurfaceProxy *proxy;
|
|
gboolean success;
|
|
|
|
proxy = gst_vaapi_surface_proxy_new_from_pool (GST_VAAPI_SURFACE_POOL (pool));
|
|
if (!proxy)
|
|
return FALSE;
|
|
|
|
success = set_surface_proxy (meta, proxy);
|
|
gst_vaapi_surface_proxy_unref (proxy);
|
|
return success;
|
|
}
|
|
|
|
static void
|
|
gst_vaapi_video_meta_destroy_image (GstVaapiVideoMeta * meta)
|
|
{
|
|
if (meta->image) {
|
|
if (meta->image_pool)
|
|
gst_vaapi_video_pool_put_object (meta->image_pool, meta->image);
|
|
gst_vaapi_object_unref (meta->image);
|
|
meta->image = NULL;
|
|
}
|
|
gst_vaapi_video_pool_replace (&meta->image_pool, NULL);
|
|
}
|
|
|
|
static inline void
|
|
gst_vaapi_video_meta_destroy_proxy (GstVaapiVideoMeta * meta)
|
|
{
|
|
gst_vaapi_surface_proxy_replace (&meta->proxy, NULL);
|
|
}
|
|
|
|
#if !GST_CHECK_VERSION(1,0,0)
|
|
#define GST_VAAPI_TYPE_VIDEO_META gst_vaapi_video_meta_get_type ()
|
|
static GType
|
|
gst_vaapi_video_meta_get_type (void)
|
|
{
|
|
static gsize g_type;
|
|
|
|
if (g_once_init_enter (&g_type)) {
|
|
GType type;
|
|
type = g_boxed_type_register_static ("GstVaapiVideoMeta",
|
|
(GBoxedCopyFunc) gst_vaapi_video_meta_ref,
|
|
(GBoxedFreeFunc) gst_vaapi_video_meta_unref);
|
|
g_once_init_leave (&g_type, type);
|
|
}
|
|
return (GType) g_type;
|
|
}
|
|
#endif
|
|
|
|
static void
|
|
gst_vaapi_video_meta_finalize (GstVaapiVideoMeta * meta)
|
|
{
|
|
gst_vaapi_video_meta_destroy_image (meta);
|
|
gst_vaapi_video_meta_destroy_proxy (meta);
|
|
gst_vaapi_display_replace (&meta->display, NULL);
|
|
}
|
|
|
|
static void
|
|
gst_vaapi_video_meta_init (GstVaapiVideoMeta * meta)
|
|
{
|
|
meta->buffer = NULL;
|
|
meta->ref_count = 1;
|
|
meta->display = NULL;
|
|
meta->image_pool = NULL;
|
|
meta->image = NULL;
|
|
meta->proxy = NULL;
|
|
meta->converter = NULL;
|
|
meta->render_flags = 0;
|
|
meta->has_render_rect = FALSE;
|
|
}
|
|
|
|
static inline GstVaapiVideoMeta *
|
|
_gst_vaapi_video_meta_create (void)
|
|
{
|
|
return g_slice_new (GstVaapiVideoMeta);
|
|
}
|
|
|
|
static inline void
|
|
_gst_vaapi_video_meta_destroy (GstVaapiVideoMeta * meta)
|
|
{
|
|
g_slice_free1 (sizeof (*meta), meta);
|
|
}
|
|
|
|
static inline GstVaapiVideoMeta *
|
|
_gst_vaapi_video_meta_new (void)
|
|
{
|
|
GstVaapiVideoMeta *meta;
|
|
|
|
meta = _gst_vaapi_video_meta_create ();
|
|
if (!meta)
|
|
return NULL;
|
|
gst_vaapi_video_meta_init (meta);
|
|
return meta;
|
|
}
|
|
|
|
static inline void
|
|
_gst_vaapi_video_meta_free (GstVaapiVideoMeta * meta)
|
|
{
|
|
g_atomic_int_inc (&meta->ref_count);
|
|
|
|
gst_vaapi_video_meta_finalize (meta);
|
|
|
|
if (G_LIKELY (g_atomic_int_dec_and_test (&meta->ref_count)))
|
|
_gst_vaapi_video_meta_destroy (meta);
|
|
}
|
|
|
|
/**
|
|
* gst_vaapi_video_meta_copy:
|
|
* @meta: a #GstVaapiVideoMeta
|
|
*
|
|
* Creates a copy of #GstVaapiVideoMeta object @meta. The original
|
|
* @meta object shall not contain any VA objects created from a
|
|
* #GstVaapiVideoPool.
|
|
*
|
|
* Return value: the newly allocated #GstVaapiVideoMeta, or %NULL on error
|
|
*/
|
|
GstVaapiVideoMeta *
|
|
gst_vaapi_video_meta_copy (GstVaapiVideoMeta * meta)
|
|
{
|
|
GstVaapiVideoMeta *copy;
|
|
|
|
g_return_val_if_fail (GST_VAAPI_IS_VIDEO_META (meta), NULL);
|
|
|
|
if (meta->image_pool)
|
|
return NULL;
|
|
|
|
copy = _gst_vaapi_video_meta_create ();
|
|
if (!copy)
|
|
return NULL;
|
|
|
|
copy->buffer = NULL;
|
|
copy->ref_count = 1;
|
|
copy->display = gst_vaapi_display_ref (meta->display);
|
|
copy->image_pool = NULL;
|
|
copy->image = meta->image ? gst_vaapi_object_ref (meta->image) : NULL;
|
|
copy->proxy = meta->proxy ? gst_vaapi_surface_proxy_copy (meta->proxy) : NULL;
|
|
copy->converter = meta->converter;
|
|
copy->render_flags = meta->render_flags;
|
|
|
|
copy->has_render_rect = meta->has_render_rect;
|
|
if (copy->has_render_rect)
|
|
copy->render_rect = meta->render_rect;
|
|
return copy;
|
|
}
|
|
|
|
/**
|
|
* gst_vaapi_video_meta_new:
|
|
* @display: a #GstVaapiDisplay
|
|
*
|
|
* Creates an empty #GstVaapiVideoMeta. The caller is responsible for completing
|
|
* the initialization of the meta with the gst_vaapi_video_meta_set_*()
|
|
* functions.
|
|
*
|
|
* This function shall only be called from within gstreamer-vaapi
|
|
* plugin elements.
|
|
*
|
|
* Return value: the newly allocated #GstVaapiVideoMeta, or %NULL or error
|
|
*/
|
|
GstVaapiVideoMeta *
|
|
gst_vaapi_video_meta_new (GstVaapiDisplay * display)
|
|
{
|
|
GstVaapiVideoMeta *meta;
|
|
|
|
g_return_val_if_fail (display != NULL, NULL);
|
|
|
|
meta = _gst_vaapi_video_meta_new ();
|
|
if (G_UNLIKELY (!meta))
|
|
return NULL;
|
|
|
|
set_display (meta, display);
|
|
return meta;
|
|
}
|
|
|
|
/**
|
|
* gst_vaapi_video_meta_new_from_pool:
|
|
* @pool: a #GstVaapiVideoPool
|
|
*
|
|
* Creates a #GstVaapiVideoMeta with a video object allocated from a @pool.
|
|
* Only #GstVaapiSurfacePool and #GstVaapiImagePool pools are supported.
|
|
*
|
|
* The meta object is destroyed through the last call to
|
|
* gst_vaapi_video_meta_unref() and the video objects are pushed back
|
|
* to their respective pools.
|
|
*
|
|
* Return value: the newly allocated #GstVaapiVideoMeta, or %NULL on error
|
|
*/
|
|
GstVaapiVideoMeta *
|
|
gst_vaapi_video_meta_new_from_pool (GstVaapiVideoPool * pool)
|
|
{
|
|
GstVaapiVideoMeta *meta;
|
|
GstVaapiVideoPoolObjectType object_type;
|
|
|
|
g_return_val_if_fail (pool != NULL, NULL);
|
|
|
|
meta = _gst_vaapi_video_meta_new ();
|
|
if (G_UNLIKELY (!meta))
|
|
return NULL;
|
|
|
|
object_type = gst_vaapi_video_pool_get_object_type (pool);
|
|
switch (object_type) {
|
|
case GST_VAAPI_VIDEO_POOL_OBJECT_TYPE_IMAGE:
|
|
if (!set_image_from_pool (meta, pool))
|
|
goto error;
|
|
break;
|
|
case GST_VAAPI_VIDEO_POOL_OBJECT_TYPE_SURFACE:
|
|
if (!set_surface_proxy_from_pool (meta, pool))
|
|
goto error;
|
|
break;
|
|
default:
|
|
GST_ERROR ("unsupported video buffer pool of type %d", object_type);
|
|
goto error;
|
|
}
|
|
set_display (meta, gst_vaapi_video_pool_get_display (pool));
|
|
return meta;
|
|
|
|
error:
|
|
gst_vaapi_video_meta_unref (meta);
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* gst_vaapi_video_meta_new_with_image:
|
|
* @image: a #GstVaapiImage
|
|
*
|
|
* Creates a #GstVaapiVideoMeta with the specified @image. The resulting
|
|
* meta holds an additional reference to the @image.
|
|
*
|
|
* This function shall only be called from within gstreamer-vaapi
|
|
* plugin elements.
|
|
*
|
|
* Return value: the newly allocated #GstVaapiVideoMeta, or %NULL on error
|
|
*/
|
|
GstVaapiVideoMeta *
|
|
gst_vaapi_video_meta_new_with_image (GstVaapiImage * image)
|
|
{
|
|
GstVaapiVideoMeta *meta;
|
|
|
|
g_return_val_if_fail (image != NULL, NULL);
|
|
|
|
meta = _gst_vaapi_video_meta_new ();
|
|
if (G_UNLIKELY (!meta))
|
|
return NULL;
|
|
|
|
gst_vaapi_video_meta_set_image (meta, image);
|
|
return meta;
|
|
}
|
|
|
|
/**
|
|
* gst_vaapi_video_meta_new_with_surface_proxy:
|
|
* @proxy: a #GstVaapiSurfaceProxy
|
|
*
|
|
* Creates a #GstVaapiVideoMeta with the specified surface @proxy. The
|
|
* resulting meta holds an additional reference to the @proxy.
|
|
*
|
|
* This function shall only be called from within gstreamer-vaapi
|
|
* plugin elements.
|
|
*
|
|
* Return value: the newly allocated #GstVaapiVideoMeta, or %NULL on error
|
|
*/
|
|
GstVaapiVideoMeta *
|
|
gst_vaapi_video_meta_new_with_surface_proxy (GstVaapiSurfaceProxy * proxy)
|
|
{
|
|
GstVaapiVideoMeta *meta;
|
|
|
|
g_return_val_if_fail (proxy != NULL, NULL);
|
|
|
|
meta = _gst_vaapi_video_meta_new ();
|
|
if (G_UNLIKELY (!meta))
|
|
return NULL;
|
|
|
|
gst_vaapi_video_meta_set_surface_proxy (meta, proxy);
|
|
return meta;
|
|
}
|
|
|
|
/**
|
|
* gst_vaapi_video_meta_ref:
|
|
* @meta: a #GstVaapiVideoMeta
|
|
*
|
|
* Atomically increases the reference count of the given @meta by one.
|
|
*
|
|
* Returns: The same @meta argument
|
|
*/
|
|
GstVaapiVideoMeta *
|
|
gst_vaapi_video_meta_ref (GstVaapiVideoMeta * meta)
|
|
{
|
|
g_return_val_if_fail (meta != NULL, NULL);
|
|
|
|
g_atomic_int_inc (&meta->ref_count);
|
|
return meta;
|
|
}
|
|
|
|
/**
|
|
* gst_vaapi_video_meta_unref:
|
|
* @meta: a #GstVaapiVideoMeta
|
|
*
|
|
* Atomically decreases the reference count of the @meta by one. If
|
|
* the reference count reaches zero, the object will be free'd.
|
|
*/
|
|
void
|
|
gst_vaapi_video_meta_unref (GstVaapiVideoMeta * meta)
|
|
{
|
|
g_return_if_fail (meta != NULL);
|
|
g_return_if_fail (meta->ref_count > 0);
|
|
|
|
if (g_atomic_int_dec_and_test (&meta->ref_count))
|
|
_gst_vaapi_video_meta_free (meta);
|
|
}
|
|
|
|
/**
|
|
* gst_vaapi_video_meta_replace:
|
|
* @old_meta_ptr: a pointer to a #GstVaapiVideoMeta
|
|
* @new_meta: a #GstVaapiVideoMeta
|
|
*
|
|
* @new_meta. This means that @old_meta_ptr shall reference a valid
|
|
* Atomically replaces the meta object held in @old_meta_ptr with
|
|
* object. However, @new_meta can be NULL.
|
|
*/
|
|
void
|
|
gst_vaapi_video_meta_replace (GstVaapiVideoMeta ** old_meta_ptr,
|
|
GstVaapiVideoMeta * new_meta)
|
|
{
|
|
GstVaapiVideoMeta *old_meta;
|
|
|
|
g_return_if_fail (old_meta_ptr != NULL);
|
|
|
|
old_meta = g_atomic_pointer_get ((gpointer *) old_meta_ptr);
|
|
|
|
if (old_meta == new_meta)
|
|
return;
|
|
|
|
if (new_meta)
|
|
gst_vaapi_video_meta_ref (new_meta);
|
|
|
|
while (!g_atomic_pointer_compare_and_exchange ((gpointer *) old_meta_ptr,
|
|
old_meta, new_meta))
|
|
old_meta = g_atomic_pointer_get ((gpointer *) old_meta_ptr);
|
|
|
|
if (old_meta)
|
|
gst_vaapi_video_meta_unref (old_meta);
|
|
}
|
|
|
|
/**
|
|
* gst_vaapi_video_meta_get_display:
|
|
* @meta: a #GstVaapiVideoMeta
|
|
*
|
|
* Retrieves the #GstVaapiDisplay the @meta is bound to. The @meta
|
|
* owns the returned #GstVaapiDisplay object so the caller is
|
|
* responsible for calling g_object_ref() when needed.
|
|
*
|
|
* Return value: the #GstVaapiDisplay the @meta is bound to
|
|
*/
|
|
GstVaapiDisplay *
|
|
gst_vaapi_video_meta_get_display (GstVaapiVideoMeta * meta)
|
|
{
|
|
g_return_val_if_fail (GST_VAAPI_IS_VIDEO_META (meta), NULL);
|
|
|
|
return meta->display;
|
|
}
|
|
|
|
/**
|
|
* gst_vaapi_video_meta_get_image:
|
|
* @meta: a #GstVaapiVideoMeta
|
|
*
|
|
* Retrieves the #GstVaapiImage bound to the @meta. The @meta owns
|
|
* the #GstVaapiImage so the caller is responsible for calling
|
|
* gst_vaapi_object_ref() when needed.
|
|
*
|
|
* Return value: the #GstVaapiImage bound to the @meta, or %NULL if
|
|
* there is none
|
|
*/
|
|
GstVaapiImage *
|
|
gst_vaapi_video_meta_get_image (GstVaapiVideoMeta * meta)
|
|
{
|
|
g_return_val_if_fail (GST_VAAPI_IS_VIDEO_META (meta), NULL);
|
|
|
|
return meta->image;
|
|
}
|
|
|
|
/**
|
|
* gst_vaapi_video_meta_set_image:
|
|
* @meta: a #GstVaapiVideoMeta
|
|
* @image: a #GstVaapiImage
|
|
*
|
|
* Binds @image to the @meta. If the @meta contains another image
|
|
* previously allocated from a pool, it's pushed back to its parent
|
|
* pool and the pool is also released.
|
|
*/
|
|
void
|
|
gst_vaapi_video_meta_set_image (GstVaapiVideoMeta * meta, GstVaapiImage * image)
|
|
{
|
|
g_return_if_fail (GST_VAAPI_IS_VIDEO_META (meta));
|
|
|
|
gst_vaapi_video_meta_destroy_image (meta);
|
|
|
|
if (image)
|
|
set_image (meta, image);
|
|
}
|
|
|
|
/**
|
|
* gst_vaapi_video_meta_set_image_from_pool
|
|
* @meta: a #GstVaapiVideoMeta
|
|
* @pool: a #GstVaapiVideoPool
|
|
*
|
|
* Binds a newly allocated video object from the @pool. The @pool
|
|
* shall be of type #GstVaapiImagePool. Previously allocated objects
|
|
* are released and returned to their parent pools, if any.
|
|
*
|
|
* Return value: %TRUE on success
|
|
*/
|
|
gboolean
|
|
gst_vaapi_video_meta_set_image_from_pool (GstVaapiVideoMeta * meta,
|
|
GstVaapiVideoPool * pool)
|
|
{
|
|
g_return_val_if_fail (GST_VAAPI_IS_VIDEO_META (meta), FALSE);
|
|
g_return_val_if_fail (pool != NULL, FALSE);
|
|
g_return_val_if_fail (gst_vaapi_video_pool_get_object_type (pool) ==
|
|
GST_VAAPI_VIDEO_POOL_OBJECT_TYPE_IMAGE, FALSE);
|
|
|
|
gst_vaapi_video_meta_destroy_image (meta);
|
|
|
|
return set_image_from_pool (meta, pool);
|
|
}
|
|
|
|
/**
|
|
* gst_vaapi_video_meta_get_surface:
|
|
* @meta: a #GstVaapiVideoMeta
|
|
*
|
|
* Retrieves the #GstVaapiSurface bound to the @meta. The @meta
|
|
* owns the #GstVaapiSurface so the caller is responsible for calling
|
|
* gst_vaapi_object_ref() when needed.
|
|
*
|
|
* Return value: the #GstVaapiSurface bound to the @meta, or %NULL if
|
|
* there is none
|
|
*/
|
|
GstVaapiSurface *
|
|
gst_vaapi_video_meta_get_surface (GstVaapiVideoMeta * meta)
|
|
{
|
|
g_return_val_if_fail (GST_VAAPI_IS_VIDEO_META (meta), NULL);
|
|
|
|
return ensure_surface_proxy (meta) ? GST_VAAPI_SURFACE_PROXY_SURFACE (meta->
|
|
proxy) : NULL;
|
|
}
|
|
|
|
/**
|
|
* gst_vaapi_video_meta_get_surface_proxy:
|
|
* @meta: a #GstVaapiVideoMeta
|
|
*
|
|
* Retrieves the #GstVaapiSurfaceProxy bound to the @meta. The @meta
|
|
* owns the #GstVaapiSurfaceProxy so the caller is responsible for calling
|
|
* gst_surface_proxy_ref() when needed.
|
|
*
|
|
* Return value: the #GstVaapiSurfaceProxy bound to the @meta, or
|
|
* %NULL if there is none
|
|
*/
|
|
GstVaapiSurfaceProxy *
|
|
gst_vaapi_video_meta_get_surface_proxy (GstVaapiVideoMeta * meta)
|
|
{
|
|
g_return_val_if_fail (GST_VAAPI_IS_VIDEO_META (meta), NULL);
|
|
|
|
return ensure_surface_proxy (meta) ? meta->proxy : NULL;
|
|
}
|
|
|
|
/**
|
|
* gst_vaapi_video_meta_set_surface_proxy:
|
|
* @meta: a #GstVaapiVideoMeta
|
|
* @proxy: a #GstVaapiSurfaceProxy
|
|
*
|
|
* Binds surface @proxy to the @meta. If the @meta contains another
|
|
* surface previously allocated from a pool, it's pushed back to its
|
|
* parent pool and the pool is also released.
|
|
*/
|
|
void
|
|
gst_vaapi_video_meta_set_surface_proxy (GstVaapiVideoMeta * meta,
|
|
GstVaapiSurfaceProxy * proxy)
|
|
{
|
|
const GstVaapiRectangle *crop_rect;
|
|
|
|
g_return_if_fail (GST_VAAPI_IS_VIDEO_META (meta));
|
|
|
|
gst_vaapi_video_meta_destroy_proxy (meta);
|
|
|
|
if (proxy) {
|
|
if (!set_surface_proxy (meta, proxy))
|
|
return;
|
|
|
|
crop_rect = gst_vaapi_surface_proxy_get_crop_rect (proxy);
|
|
if (crop_rect)
|
|
gst_vaapi_video_meta_set_render_rect (meta, crop_rect);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* gst_vaapi_video_meta_get_surface_converter:
|
|
* @meta: a #GstVaapiVideoMeta
|
|
*
|
|
* Retrieves the surface converter bound to the @meta.
|
|
*
|
|
* Return value: the surface converter associated with the video @meta
|
|
*/
|
|
GFunc
|
|
gst_vaapi_video_meta_get_surface_converter (GstVaapiVideoMeta * meta)
|
|
{
|
|
g_return_val_if_fail (GST_VAAPI_IS_VIDEO_META (meta), NULL);
|
|
|
|
return meta->converter;
|
|
}
|
|
|
|
/**
|
|
* gst_vaapi_video_meta_set_surface_converter:
|
|
* @meta: a #GstVaapiVideoMeta
|
|
* @func: a pointer to the surface converter function
|
|
*
|
|
* Sets the @meta surface converter function to @func.
|
|
*/
|
|
void
|
|
gst_vaapi_video_meta_set_surface_converter (GstVaapiVideoMeta * meta,
|
|
GFunc func)
|
|
{
|
|
g_return_if_fail (GST_VAAPI_IS_VIDEO_META (meta));
|
|
|
|
meta->converter = func;
|
|
}
|
|
|
|
/**
|
|
* gst_vaapi_video_meta_get_render_flags:
|
|
* @meta: a #GstVaapiVideoMeta
|
|
*
|
|
* Retrieves the surface render flags bound to the @meta.
|
|
*
|
|
* Return value: a combination for #GstVaapiSurfaceRenderFlags
|
|
*/
|
|
guint
|
|
gst_vaapi_video_meta_get_render_flags (GstVaapiVideoMeta * meta)
|
|
{
|
|
g_return_val_if_fail (GST_VAAPI_IS_VIDEO_META (meta), 0);
|
|
g_return_val_if_fail (meta->proxy != NULL, 0);
|
|
|
|
return meta->render_flags;
|
|
}
|
|
|
|
/**
|
|
* gst_vaapi_video_meta_set_render_flags:
|
|
* @meta: a #GstVaapiVideoMeta
|
|
* @flags: a set of surface render flags
|
|
*
|
|
* Sets #GstVaapiSurfaceRenderFlags to the @meta.
|
|
*/
|
|
void
|
|
gst_vaapi_video_meta_set_render_flags (GstVaapiVideoMeta * meta, guint flags)
|
|
{
|
|
g_return_if_fail (GST_VAAPI_IS_VIDEO_META (meta));
|
|
g_return_if_fail (meta->proxy != NULL);
|
|
|
|
meta->render_flags = flags;
|
|
}
|
|
|
|
/**
|
|
* gst_vaapi_video_meta_get_render_rect:
|
|
* @meta: a #GstVaapiVideoMeta
|
|
*
|
|
* Retrieves the render rectangle bound to the @meta
|
|
*
|
|
* Return value: render rectangle associated with the video meta.
|
|
*/
|
|
const GstVaapiRectangle *
|
|
gst_vaapi_video_meta_get_render_rect (GstVaapiVideoMeta * meta)
|
|
{
|
|
g_return_val_if_fail (GST_VAAPI_IS_VIDEO_META (meta), NULL);
|
|
|
|
if (!meta->has_render_rect)
|
|
return NULL;
|
|
return &meta->render_rect;
|
|
}
|
|
|
|
/**
|
|
* gst_vaapi_video_meta_set_render_rect:
|
|
* @meta: a #GstVaapiVideoMeta
|
|
* @rect: a #GstVaapiRectangle
|
|
*
|
|
* Sets the render rectangle @rect to the @meta.
|
|
*/
|
|
void
|
|
gst_vaapi_video_meta_set_render_rect (GstVaapiVideoMeta * meta,
|
|
const GstVaapiRectangle * rect)
|
|
{
|
|
g_return_if_fail (GST_VAAPI_IS_VIDEO_META (meta));
|
|
|
|
meta->has_render_rect = rect != NULL;
|
|
if (meta->has_render_rect)
|
|
meta->render_rect = *rect;
|
|
}
|
|
|
|
#if GST_CHECK_VERSION(1,0,0)
|
|
|
|
#define GST_VAAPI_VIDEO_META_HOLDER(meta) \
|
|
((GstVaapiVideoMetaHolder *) (meta))
|
|
|
|
typedef struct _GstVaapiVideoMetaHolder GstVaapiVideoMetaHolder;
|
|
struct _GstVaapiVideoMetaHolder
|
|
{
|
|
GstMeta base;
|
|
GstVaapiVideoMeta *meta;
|
|
};
|
|
|
|
static gboolean
|
|
gst_vaapi_video_meta_holder_init (GstVaapiVideoMetaHolder * meta,
|
|
gpointer params, GstBuffer * buffer)
|
|
{
|
|
meta->meta = NULL;
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
gst_vaapi_video_meta_holder_free (GstVaapiVideoMetaHolder * meta,
|
|
GstBuffer * buffer)
|
|
{
|
|
if (meta->meta)
|
|
gst_vaapi_video_meta_unref (meta->meta);
|
|
}
|
|
|
|
static gboolean
|
|
gst_vaapi_video_meta_holder_transform (GstBuffer * dst_buffer, GstMeta * meta,
|
|
GstBuffer * src_buffer, GQuark type, gpointer data)
|
|
{
|
|
GstVaapiVideoMetaHolder *const src_meta = GST_VAAPI_VIDEO_META_HOLDER (meta);
|
|
|
|
if (GST_META_TRANSFORM_IS_COPY (type)) {
|
|
GstVaapiVideoMeta *const dst_meta =
|
|
gst_vaapi_video_meta_copy (src_meta->meta);
|
|
gst_buffer_set_vaapi_video_meta (dst_buffer, dst_meta);
|
|
gst_vaapi_video_meta_unref (dst_meta);
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
GType
|
|
gst_vaapi_video_meta_api_get_type (void)
|
|
{
|
|
static gsize g_type;
|
|
static const gchar *tags[] = { "memory", NULL };
|
|
|
|
if (g_once_init_enter (&g_type)) {
|
|
GType type = gst_meta_api_type_register ("GstVaapiVideoMetaAPI", tags);
|
|
g_once_init_leave (&g_type, type);
|
|
}
|
|
return g_type;
|
|
}
|
|
|
|
#define GST_VAAPI_VIDEO_META_INFO gst_vaapi_video_meta_info_get ()
|
|
static const GstMetaInfo *
|
|
gst_vaapi_video_meta_info_get (void)
|
|
{
|
|
static gsize g_meta_info;
|
|
|
|
if (g_once_init_enter (&g_meta_info)) {
|
|
gsize meta_info =
|
|
GPOINTER_TO_SIZE (gst_meta_register (GST_VAAPI_VIDEO_META_API_TYPE,
|
|
"GstVaapiVideoMeta", sizeof (GstVaapiVideoMetaHolder),
|
|
(GstMetaInitFunction) gst_vaapi_video_meta_holder_init,
|
|
(GstMetaFreeFunction) gst_vaapi_video_meta_holder_free,
|
|
(GstMetaTransformFunction) gst_vaapi_video_meta_holder_transform));
|
|
g_once_init_leave (&g_meta_info, meta_info);
|
|
}
|
|
return GSIZE_TO_POINTER (g_meta_info);
|
|
}
|
|
|
|
GstVaapiVideoMeta *
|
|
gst_buffer_get_vaapi_video_meta (GstBuffer * buffer)
|
|
{
|
|
GstVaapiVideoMeta *meta;
|
|
GstMeta *m;
|
|
|
|
g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
|
|
|
|
m = gst_buffer_get_meta (buffer, GST_VAAPI_VIDEO_META_API_TYPE);
|
|
if (!m)
|
|
return NULL;
|
|
|
|
meta = GST_VAAPI_VIDEO_META_HOLDER (m)->meta;
|
|
if (meta)
|
|
meta->buffer = buffer;
|
|
return meta;
|
|
}
|
|
|
|
void
|
|
gst_buffer_set_vaapi_video_meta (GstBuffer * buffer, GstVaapiVideoMeta * meta)
|
|
{
|
|
GstMeta *m;
|
|
|
|
g_return_if_fail (GST_IS_BUFFER (buffer));
|
|
g_return_if_fail (GST_VAAPI_IS_VIDEO_META (meta));
|
|
|
|
m = gst_buffer_add_meta (buffer, GST_VAAPI_VIDEO_META_INFO, NULL);
|
|
if (m)
|
|
GST_VAAPI_VIDEO_META_HOLDER (m)->meta = gst_vaapi_video_meta_ref (meta);
|
|
}
|
|
#else
|
|
|
|
#define GST_VAAPI_VIDEO_META_QUARK gst_vaapi_video_meta_quark_get ()
|
|
static GQuark
|
|
gst_vaapi_video_meta_quark_get (void)
|
|
{
|
|
static gsize g_quark;
|
|
|
|
if (g_once_init_enter (&g_quark)) {
|
|
gsize quark = (gsize) g_quark_from_static_string ("GstVaapiVideoMeta");
|
|
g_once_init_leave (&g_quark, quark);
|
|
}
|
|
return g_quark;
|
|
}
|
|
|
|
#define META_QUARK meta_quark_get ()
|
|
static GQuark
|
|
meta_quark_get (void)
|
|
{
|
|
static gsize g_quark;
|
|
|
|
if (g_once_init_enter (&g_quark)) {
|
|
gsize quark = (gsize) g_quark_from_static_string ("meta");
|
|
g_once_init_leave (&g_quark, quark);
|
|
}
|
|
return g_quark;
|
|
}
|
|
|
|
GstVaapiVideoMeta *
|
|
gst_buffer_get_vaapi_video_meta (GstBuffer * buffer)
|
|
{
|
|
GstVaapiVideoMeta *meta;
|
|
const GstStructure *structure;
|
|
const GValue *value;
|
|
|
|
g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
|
|
|
|
structure = gst_buffer_get_qdata (buffer, GST_VAAPI_VIDEO_META_QUARK);
|
|
if (!structure)
|
|
return NULL;
|
|
|
|
value = gst_structure_id_get_value (structure, META_QUARK);
|
|
if (!value)
|
|
return NULL;
|
|
|
|
meta = GST_VAAPI_VIDEO_META (g_value_get_boxed (value));
|
|
meta->buffer = buffer;
|
|
return meta;
|
|
}
|
|
|
|
void
|
|
gst_buffer_set_vaapi_video_meta (GstBuffer * buffer, GstVaapiVideoMeta * meta)
|
|
{
|
|
g_return_if_fail (GST_IS_BUFFER (buffer));
|
|
g_return_if_fail (GST_VAAPI_IS_VIDEO_META (meta));
|
|
|
|
gst_buffer_set_qdata (buffer, GST_VAAPI_VIDEO_META_QUARK,
|
|
gst_structure_id_new (GST_VAAPI_VIDEO_META_QUARK,
|
|
META_QUARK, GST_VAAPI_TYPE_VIDEO_META, meta, NULL));
|
|
}
|
|
#endif
|