vaapisink: add support for raw YUV buffers.

Add new GstVaapiUploader helper to upload raw YUV buffers to VA surfaces.
It is up to the caller to negotiate source caps (for images) and output
caps (for surfaces). gst_vaapi_uploader_has_direct_rendering() is available
to help decide between the creation of a GstVaapiVideoBuffer or a regular
GstBuffer on sink pads.

Signed-off-by: Zhao Halley <halley.zhao@intel.com>
Signed-off-by: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
This commit is contained in:
Gwenole Beauchesne 2012-11-20 14:28:55 +01:00
parent c38c0853eb
commit 499e0dd981
6 changed files with 593 additions and 6 deletions

1
NEWS
View file

@ -5,6 +5,7 @@ Copyright (C) 2011 Collabora
Version 0.5.0 - DD.Dec.2012
* Require glib >= 2.31.2
* Add support for raw YUV buffers in vaapisink (+Halley Zhao)
* Fix memory leak in GstVaapiVideoBuffer for images and surfaces (Feng Yuan)
Version 0.4.1 - 20.Nov.2012

View file

@ -38,6 +38,7 @@ libgstvaapi_la_SOURCES = \
gstvaapipostproc.c \
gstvaapisink.c \
gstvaapiupload.c \
gstvaapiuploader.c \
$(NULL)
noinst_HEADERS = \
@ -48,6 +49,7 @@ noinst_HEADERS = \
gstvaapipostproc.h \
gstvaapisink.h \
gstvaapiupload.h \
gstvaapiuploader.h \
$(NULL)
libgstvaapi_la_CFLAGS = \

View file

@ -72,12 +72,18 @@ static const GstElementDetails gst_vaapisink_details =
"Gwenole Beauchesne <gwenole.beauchesne@intel.com>");
/* Default template */
static const char gst_vaapisink_sink_caps_str[] =
"video/x-raw-yuv, "
"width = (int) [ 1, MAX ], "
"height = (int) [ 1, MAX ]; "
GST_VAAPI_SURFACE_CAPS;
static GstStaticPadTemplate gst_vaapisink_sink_factory =
GST_STATIC_PAD_TEMPLATE(
"sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS(GST_VAAPI_SURFACE_CAPS));
GST_STATIC_CAPS(gst_vaapisink_sink_caps_str));
static void
gst_vaapisink_implements_iface_init(GstImplementsInterfaceClass *iface);
@ -228,6 +234,7 @@ gst_vaapisink_destroy(GstVaapiSink *sink)
gst_buffer_replace(&sink->video_buffer, NULL);
g_clear_object(&sink->texture);
g_clear_object(&sink->display);
g_clear_object(&sink->uploader);
gst_caps_replace(&sink->caps, NULL);
}
@ -561,7 +568,13 @@ gst_vaapisink_start(GstBaseSink *base_sink)
{
GstVaapiSink * const sink = GST_VAAPISINK(base_sink);
return gst_vaapisink_ensure_display(sink);
if (!gst_vaapisink_ensure_display(sink))
return FALSE;
sink->uploader = gst_vaapi_uploader_new(sink->display);
if (!sink->uploader)
return FALSE;
return TRUE;
}
static gboolean
@ -572,6 +585,7 @@ gst_vaapisink_stop(GstBaseSink *base_sink)
gst_buffer_replace(&sink->video_buffer, NULL);
g_clear_object(&sink->window);
g_clear_object(&sink->display);
g_clear_object(&sink->uploader);
return TRUE;
}
@ -598,6 +612,9 @@ gst_vaapisink_set_caps(GstBaseSink *base_sink, GstCaps *caps)
sink->video_width = video_width;
sink->video_height = video_height;
if (gst_structure_has_name(structure, "video/x-raw-yuv"))
sink->use_video_raw = TRUE;
gst_video_parse_caps_pixel_aspect_ratio(caps, &video_par_n, &video_par_d);
sink->video_par_n = video_par_n;
sink->video_par_d = video_par_d;
@ -808,26 +825,45 @@ static GstFlowReturn
gst_vaapisink_show_frame(GstBaseSink *base_sink, GstBuffer *buffer)
{
GstVaapiSink * const sink = GST_VAAPISINK(base_sink);
GstVaapiVideoBuffer * const vbuffer = GST_VAAPI_VIDEO_BUFFER(buffer);
GstVaapiVideoBuffer *vbuffer;
GstVaapiSurface *surface;
guint flags;
gboolean success;
GstVideoOverlayComposition * const composition =
gst_video_buffer_get_overlay_composition(buffer);
if (!sink->use_video_raw)
buffer = gst_buffer_ref(buffer);
else {
GstBuffer * const src_buffer = buffer;
if (GST_VAAPI_IS_VIDEO_BUFFER(buffer))
buffer = gst_buffer_ref(src_buffer);
else if (GST_VAAPI_IS_VIDEO_BUFFER(buffer->parent))
buffer = gst_buffer_ref(src_buffer->parent);
else {
buffer = gst_vaapi_uploader_get_buffer(sink->uploader);
if (!buffer)
return GST_FLOW_UNEXPECTED;
}
if (!gst_vaapi_uploader_process(sink->uploader, src_buffer, buffer))
goto error;
}
vbuffer = GST_VAAPI_VIDEO_BUFFER(buffer);
g_return_val_if_fail(vbuffer != NULL, GST_FLOW_UNEXPECTED);
if (sink->display != gst_vaapi_video_buffer_get_display (vbuffer)) {
g_clear_object(&sink->display);
sink->display = g_object_ref (gst_vaapi_video_buffer_get_display (vbuffer));
}
if (!sink->window)
return GST_FLOW_UNEXPECTED;
goto error;
gst_vaapisink_ensure_rotation(sink, TRUE);
surface = gst_vaapi_video_buffer_get_surface(vbuffer);
if (!surface)
return GST_FLOW_UNEXPECTED;
goto error;
GST_DEBUG("render surface %" GST_VAAPI_ID_FORMAT,
GST_VAAPI_ID_ARGS(gst_vaapi_surface_get_id(surface)));
@ -865,11 +901,50 @@ gst_vaapisink_show_frame(GstBaseSink *base_sink, GstBuffer *buffer)
break;
}
if (!success)
return GST_FLOW_UNEXPECTED;
goto error;
/* Retain VA surface until the next one is displayed */
if (sink->use_overlay)
gst_buffer_replace(&sink->video_buffer, buffer);
gst_buffer_unref(buffer);
return GST_FLOW_OK;
error:
gst_buffer_unref(buffer);
return GST_FLOW_UNEXPECTED;
}
static GstFlowReturn
gst_vaapisink_buffer_alloc(
GstBaseSink *base_sink,
guint64 offset,
guint size,
GstCaps *caps,
GstBuffer **pbuf
)
{
GstVaapiSink * const sink = GST_VAAPISINK(base_sink);
GstStructure *structure;
GstBuffer *buf;
*pbuf = NULL;
structure = gst_caps_get_structure(caps, 0);
if (!gst_structure_has_name(structure, "video/x-raw-yuv"))
return GST_FLOW_OK;
if (!gst_vaapi_uploader_ensure_display(sink->uploader, sink->display))
return GST_FLOW_NOT_SUPPORTED;
if (!gst_vaapi_uploader_ensure_caps(sink->uploader, caps, NULL))
return GST_FLOW_NOT_SUPPORTED;
buf = gst_vaapi_uploader_get_buffer(sink->uploader);
if (!buf) {
GST_WARNING("failed to allocate resources for raw YUV buffer");
return GST_FLOW_NOT_SUPPORTED;
}
*pbuf = buf;
return GST_FLOW_OK;
}
@ -974,6 +1049,7 @@ gst_vaapisink_class_init(GstVaapiSinkClass *klass)
basesink_class->preroll = gst_vaapisink_show_frame;
basesink_class->render = gst_vaapisink_show_frame;
basesink_class->query = gst_vaapisink_query;
basesink_class->buffer_alloc = gst_vaapisink_buffer_alloc;
gst_element_class_set_details_simple(
element_class,

View file

@ -30,6 +30,7 @@
#include <gst/vaapi/gstvaapitexture.h>
#endif
#include "gstvaapipluginutil.h"
#include "gstvaapiuploader.h"
G_BEGIN_DECLS
@ -67,6 +68,7 @@ struct _GstVaapiSink {
/*< private >*/
GstVideoSink parent_instance;
GstVaapiUploader *uploader;
GstCaps *caps;
GstVaapiDisplay *display;
GstVaapiDisplayType display_type;
@ -88,6 +90,7 @@ struct _GstVaapiSink {
guint use_reflection : 1;
guint use_overlay : 1;
guint use_rotation : 1;
guint use_video_raw : 1;
};
struct _GstVaapiSinkClass {

View file

@ -0,0 +1,394 @@
/*
* gstvaapiuploader.c - VA-API video upload helper
*
* Copyright (C) 2010-2011 Splitted-Desktop Systems
* Copyright (C) 2011-2012 Intel Corporation
*
* 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 "gst/vaapi/sysdeps.h"
#include <gst/video/video.h>
#include <gst/vaapi/gstvaapisurface.h>
#include <gst/vaapi/gstvaapiimagepool.h>
#include <gst/vaapi/gstvaapisurfacepool.h>
#include <gst/vaapi/gstvaapivideobuffer.h>
#include "gstvaapiuploader.h"
#include "gstvaapipluginbuffer.h"
#define GST_HELPER_NAME "vaapiupload"
#define GST_HELPER_DESC "VA-API video uploader"
GST_DEBUG_CATEGORY_STATIC(gst_debug_vaapi_uploader);
#define GST_CAT_DEFAULT gst_debug_vaapi_uploader
G_DEFINE_TYPE(GstVaapiUploader, gst_vaapi_uploader, G_TYPE_OBJECT)
#define GST_VAAPI_UPLOADER_CAST(obj) \
((GstVaapiUploader *)(obj))
#define GST_VAAPI_UPLOADER_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE((obj), \
GST_VAAPI_TYPE_UPLOADER, \
GstVaapiUploaderPrivate))
struct _GstVaapiUploaderPrivate {
GstVaapiDisplay *display;
GstVaapiVideoPool *images;
GstCaps *image_caps;
guint image_width;
guint image_height;
GstVaapiVideoPool *surfaces;
guint surface_width;
guint surface_height;
guint direct_rendering;
};
enum {
PROP_0,
PROP_DISPLAY,
};
static void
gst_vaapi_uploader_destroy(GstVaapiUploader *uploader)
{
GstVaapiUploaderPrivate * const priv = uploader->priv;
gst_caps_replace(&priv->image_caps, NULL);
g_clear_object(&priv->images);
g_clear_object(&priv->surfaces);
g_clear_object(&priv->display);
}
static gboolean
ensure_display(GstVaapiUploader *uploader, GstVaapiDisplay *display)
{
GstVaapiUploaderPrivate * const priv = uploader->priv;
if (priv->display == display)
return TRUE;
g_clear_object(&priv->display);
if (display)
priv->display = g_object_ref(display);
return TRUE;
}
static gboolean
ensure_image_pool(GstVaapiUploader *uploader, GstCaps *caps)
{
GstVaapiUploaderPrivate * const priv = uploader->priv;
GstStructure * const structure = gst_caps_get_structure(caps, 0);
gint width, height;
gst_structure_get_int(structure, "width", &width);
gst_structure_get_int(structure, "height", &height);
if (width != priv->image_width || height != priv->image_height) {
priv->image_width = width;
priv->image_height = height;
g_clear_object(&priv->images);
priv->images = gst_vaapi_image_pool_new(priv->display, caps);
if (!priv->images)
return FALSE;
gst_caps_replace(&priv->image_caps, caps);
}
return TRUE;
}
static gboolean
ensure_surface_pool(GstVaapiUploader *uploader, GstCaps *caps)
{
GstVaapiUploaderPrivate * const priv = uploader->priv;
GstStructure * const structure = gst_caps_get_structure(caps, 0);
gint width, height;
gst_structure_get_int(structure, "width", &width);
gst_structure_get_int(structure, "height", &height);
if (width != priv->surface_width || height != priv->surface_height) {
priv->surface_width = width;
priv->surface_height = height;
g_clear_object(&priv->surfaces);
priv->surfaces = gst_vaapi_surface_pool_new(priv->display, caps);
if (!priv->surfaces)
return FALSE;
}
return TRUE;
}
static void
gst_vaapi_uploader_finalize(GObject *object)
{
gst_vaapi_uploader_destroy(GST_VAAPI_UPLOADER_CAST(object));
G_OBJECT_CLASS(gst_vaapi_uploader_parent_class)->finalize(object);
}
static void
gst_vaapi_uploader_set_property(GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
GstVaapiUploader * const uploader = GST_VAAPI_UPLOADER_CAST(object);
switch (prop_id) {
case PROP_DISPLAY:
ensure_display(uploader, g_value_get_object(value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
}
}
static void
gst_vaapi_uploader_get_property(GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
GstVaapiUploader * const uploader = GST_VAAPI_UPLOADER_CAST(object);
switch (prop_id) {
case PROP_DISPLAY:
g_value_set_object(value, uploader->priv->display);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
}
}
static void
gst_vaapi_uploader_class_init(GstVaapiUploaderClass *klass)
{
GObjectClass * const object_class = G_OBJECT_CLASS(klass);
GST_DEBUG_CATEGORY_INIT(gst_debug_vaapi_uploader,
GST_HELPER_NAME, 0, GST_HELPER_DESC);
g_type_class_add_private(klass, sizeof(GstVaapiUploaderPrivate));
object_class->finalize = gst_vaapi_uploader_finalize;
object_class->set_property = gst_vaapi_uploader_set_property;
object_class->get_property = gst_vaapi_uploader_get_property;
g_object_class_install_property(
object_class,
PROP_DISPLAY,
g_param_spec_object(
"display",
"Display",
"The GstVaapiDisplay this object is bound to",
GST_VAAPI_TYPE_DISPLAY,
G_PARAM_READWRITE));
}
static void
gst_vaapi_uploader_init(GstVaapiUploader *uploader)
{
GstVaapiUploaderPrivate *priv;
priv = GST_VAAPI_UPLOADER_GET_PRIVATE(uploader);
uploader->priv = priv;
}
GstVaapiUploader *
gst_vaapi_uploader_new(GstVaapiDisplay *display)
{
return g_object_new(GST_VAAPI_TYPE_UPLOADER, "display", display, NULL);
}
gboolean
gst_vaapi_uploader_ensure_display(
GstVaapiUploader *uploader,
GstVaapiDisplay *display
)
{
g_return_val_if_fail(GST_VAAPI_IS_UPLOADER(uploader), FALSE);
g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), FALSE);
return ensure_display(uploader,display);
}
gboolean
gst_vaapi_uploader_ensure_caps(
GstVaapiUploader *uploader,
GstCaps *src_caps,
GstCaps *out_caps
)
{
GstVaapiUploaderPrivate *priv;
GstVaapiImage *image;
GstVaapiImageFormat vaformat;
GstVideoFormat vformat;
GstStructure *structure;
gint width, height;
g_return_val_if_fail(GST_VAAPI_IS_UPLOADER(uploader), FALSE);
g_return_val_if_fail(src_caps != NULL, FALSE);
if (!ensure_image_pool(uploader, src_caps))
return FALSE;
if (!ensure_surface_pool(uploader, out_caps ? out_caps : src_caps))
return FALSE;
priv = uploader->priv;
structure = gst_caps_get_structure(src_caps, 0);
if (!structure)
return FALSE;
gst_structure_get_int(structure, "width", &width);
gst_structure_get_int(structure, "height", &height);
/* Translate from Gst video format to VA image format */
if (!gst_video_format_parse_caps(src_caps, &vformat, NULL, NULL))
return FALSE;
if (!gst_video_format_is_yuv(vformat))
return FALSE;
vaformat = gst_vaapi_image_format_from_video(vformat);
if (!vaformat)
return FALSE;
/* Check if we can alias source and output buffers (same data_size) */
image = gst_vaapi_video_pool_get_object(priv->images);
if (image) {
if (gst_vaapi_image_get_format(image) == vaformat &&
gst_vaapi_image_is_linear(image) &&
(gst_vaapi_image_get_data_size(image) ==
gst_video_format_get_size(vformat, width, height)))
priv->direct_rendering = 1;
gst_vaapi_video_pool_put_object(priv->images, image);
}
return TRUE;
}
gboolean
gst_vaapi_uploader_process(
GstVaapiUploader *uploader,
GstBuffer *src_buffer,
GstBuffer *out_buffer
)
{
GstVaapiVideoBuffer *out_vbuffer;
GstVaapiSurface *surface;
GstVaapiImage *image;
g_return_val_if_fail(GST_VAAPI_IS_UPLOADER(uploader), FALSE);
if (GST_VAAPI_IS_VIDEO_BUFFER(out_buffer))
out_vbuffer = GST_VAAPI_VIDEO_BUFFER(out_buffer);
else if (GST_VAAPI_IS_VIDEO_BUFFER(out_buffer->parent))
out_vbuffer = GST_VAAPI_VIDEO_BUFFER(out_buffer->parent);
else {
GST_WARNING("expected an output video buffer");
return FALSE;
}
surface = gst_vaapi_video_buffer_get_surface(out_vbuffer);
g_return_val_if_fail(surface != NULL, FALSE);
if (GST_VAAPI_IS_VIDEO_BUFFER(src_buffer)) {
/* GstVaapiVideoBuffer with mapped VA image */
image = gst_vaapi_video_buffer_get_image(
GST_VAAPI_VIDEO_BUFFER(src_buffer));
if (!image || !gst_vaapi_image_unmap(image))
return FALSE;
}
else if (GST_VAAPI_IS_VIDEO_BUFFER(src_buffer->parent)) {
/* Sub-buffer from GstVaapiVideoBuffer with mapped VA image */
image = gst_vaapi_video_buffer_get_image(
GST_VAAPI_VIDEO_BUFFER(src_buffer->parent));
if (!image || !gst_vaapi_image_unmap(image))
return FALSE;
}
else {
/* Regular GstBuffer that needs to be uploaded to a VA image */
image = gst_vaapi_video_buffer_get_image(out_vbuffer);
if (!image) {
image = gst_vaapi_video_pool_get_object(uploader->priv->images);
if (!image)
return FALSE;
gst_vaapi_video_buffer_set_image(out_vbuffer, image);
}
if (!gst_vaapi_image_update_from_buffer(image, src_buffer, NULL))
return FALSE;
}
g_return_val_if_fail(image != NULL, FALSE);
if (!gst_vaapi_surface_put_image(surface, image)) {
GST_WARNING("failed to upload YUV buffer to VA surface");
return FALSE;
}
/* Map again for next uploads */
if (!gst_vaapi_image_map(image))
return FALSE;
return TRUE;
}
GstBuffer *
gst_vaapi_uploader_get_buffer(GstVaapiUploader *uploader)
{
GstVaapiUploaderPrivate *priv;
GstVaapiSurface *surface;
GstVaapiImage *image;
GstVaapiVideoBuffer *vbuffer;
GstBuffer *buffer = NULL;
g_return_val_if_fail(GST_VAAPI_IS_UPLOADER(uploader), NULL);
priv = uploader->priv;
buffer = gst_vaapi_video_buffer_new_from_pool(priv->images);
if (!buffer) {
GST_WARNING("failed to allocate video buffer");
goto error;
}
vbuffer = GST_VAAPI_VIDEO_BUFFER(buffer);
surface = gst_vaapi_video_pool_get_object(priv->surfaces);
if (!surface) {
GST_WARNING("failed to allocate VA surface");
goto error;
}
gst_vaapi_video_buffer_set_surface(vbuffer, surface);
image = gst_vaapi_video_buffer_get_image(vbuffer);
if (!gst_vaapi_image_map(image)) {
GST_WARNING("failed to map VA image");
goto error;
}
GST_BUFFER_DATA(buffer) = gst_vaapi_image_get_plane(image, 0);
GST_BUFFER_SIZE(buffer) = gst_vaapi_image_get_data_size(image);
gst_buffer_set_caps(buffer, priv->image_caps);
return buffer;
error:
gst_buffer_unref(buffer);
return buffer;
}
gboolean
gst_vaapi_uploader_has_direct_rendering(GstVaapiUploader *uploader)
{
g_return_val_if_fail(GST_VAAPI_IS_UPLOADER(uploader), FALSE);
return uploader->priv->direct_rendering;
}

View file

@ -0,0 +1,111 @@
/*
* gstvaapiuploader.h - VA-API video upload helper
*
* Copyright (C) 2010-2011 Splitted-Desktop Systems
* Copyright (C) 2011-2012 Intel Corporation
*
* This program 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 program 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 program; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA
*/
#ifndef GST_VAAPIUPLOADER_H
#define GST_VAAPIUPLOADER_H
#include <gst/vaapi/gstvaapidisplay.h>
G_BEGIN_DECLS
#define GST_VAAPI_TYPE_UPLOADER \
(gst_vaapi_uploader_get_type())
#define GST_VAAPI_UPLOADER(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj), \
GST_VAAPI_TYPE_UPLOADER, \
GstVaapiUploader))
#define GST_VAAPI_UPLOADER_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass), \
GST_VAAPI_TYPE_UPLOADER, \
GstVaapiUploaderClass))
#define GST_VAAPI_IS_UPLOADER(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_UPLOADER))
#define GST_VAAPI_IS_UPLOADER_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_UPLOADER))
#define GST_VAAPI_UPLOADER_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS((obj), \
GST_VAAPI_TYPE_UPLOADER, \
GstVaapiUploaderClass))
typedef struct _GstVaapiUploader GstVaapiUploader;
typedef struct _GstVaapiUploaderPrivate GstVaapiUploaderPrivate;
typedef struct _GstVaapiUploaderClass GstVaapiUploaderClass;
struct _GstVaapiUploader {
/*< private >*/
GObject parent_instance;
GstVaapiUploaderPrivate *priv;
};
struct _GstVaapiUploaderClass {
/*< private >*/
GObjectClass parent_class;
};
G_GNUC_INTERNAL
GType
gst_vaapi_uploader_get_type(void) G_GNUC_CONST;
G_GNUC_INTERNAL
GstVaapiUploader *
gst_vaapi_uploader_new(GstVaapiDisplay *display);
G_GNUC_INTERNAL
gboolean
gst_vaapi_uploader_ensure_display(
GstVaapiUploader *uploader,
GstVaapiDisplay *display
);
G_GNUC_INTERNAL
gboolean
gst_vaapi_uploader_ensure_caps(
GstVaapiUploader *uploader,
GstCaps *src_caps,
GstCaps *out_caps
);
G_GNUC_INTERNAL
gboolean
gst_vaapi_uploader_process(
GstVaapiUploader *uploader,
GstBuffer *src_buffer,
GstBuffer *out_buffer
);
G_GNUC_INTERNAL
GstBuffer *
gst_vaapi_uploader_get_buffer(GstVaapiUploader *uploader);
G_GNUC_INTERNAL
gboolean
gst_vaapi_uploader_has_direct_rendering(GstVaapiUploader *uploader);
G_END_DECLS
#endif /* GST_VAAPI_UPLOADER_H */