summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGwenole Beauchesne <gwenole.beauchesne@intel.com>2012-11-20 14:28:55 +0100
committerGwenole Beauchesne <gwenole.beauchesne@intel.com>2012-11-20 16:04:51 +0100
commit499e0dd981fb5ef770d25fe98d791e764f1089c9 (patch)
tree2fbd0d2957c3ff4e807b2dced464716841116d2f
parentc38c0853ebf2979f1321892d42217afb1b9b88fa (diff)
downloadgst-vaapi-499e0dd981fb5ef770d25fe98d791e764f1089c9.tar.gz
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>
-rw-r--r--NEWS1
-rw-r--r--gst/vaapi/Makefile.am2
-rw-r--r--gst/vaapi/gstvaapisink.c88
-rw-r--r--gst/vaapi/gstvaapisink.h3
-rw-r--r--gst/vaapi/gstvaapiuploader.c394
-rw-r--r--gst/vaapi/gstvaapiuploader.h111
6 files changed, 593 insertions, 6 deletions
diff --git a/NEWS b/NEWS
index 64b58ffe..621c5500 100644
--- a/NEWS
+++ b/NEWS
@@ -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
diff --git a/gst/vaapi/Makefile.am b/gst/vaapi/Makefile.am
index 0c1097ca..4da267e3 100644
--- a/gst/vaapi/Makefile.am
+++ b/gst/vaapi/Makefile.am
@@ -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 = \
diff --git a/gst/vaapi/gstvaapisink.c b/gst/vaapi/gstvaapisink.c
index 72513981..916cd8e1 100644
--- a/gst/vaapi/gstvaapisink.c
+++ b/gst/vaapi/gstvaapisink.c
@@ -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,
diff --git a/gst/vaapi/gstvaapisink.h b/gst/vaapi/gstvaapisink.h
index a2e8bff6..b8b082a9 100644
--- a/gst/vaapi/gstvaapisink.h
+++ b/gst/vaapi/gstvaapisink.h
@@ -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 {
diff --git a/gst/vaapi/gstvaapiuploader.c b/gst/vaapi/gstvaapiuploader.c
new file mode 100644
index 00000000..d7ba1f97
--- /dev/null
+++ b/gst/vaapi/gstvaapiuploader.c
@@ -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;
+}
diff --git a/gst/vaapi/gstvaapiuploader.h b/gst/vaapi/gstvaapiuploader.h
new file mode 100644
index 00000000..06f62d39
--- /dev/null
+++ b/gst/vaapi/gstvaapiuploader.h
@@ -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 */