summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGwenole Beauchesne <gwenole.beauchesne@intel.com>2012-01-05 10:50:59 +0100
committerGwenole Beauchesne <gwenole.beauchesne@intel.com>2012-01-05 11:04:29 +0100
commit6ca190b4c5143f9218eb078a61cb21cd0cb8e863 (patch)
treef11e53ce179b3608b557d0f8db970484bff2b2d5
parent872694fda58a725890fc8ff9f0a3f5bf9aabc88d (diff)
downloadgstreamer-vaapi-6ca190b4c5143f9218eb078a61cb21cd0cb8e863.tar.gz
vaapidownload: add new plugin to download pixels from VA surfaces.
-rw-r--r--README3
-rw-r--r--docs/reference/plugins/plugins-docs.xml.in1
-rw-r--r--docs/reference/plugins/plugins-sections.txt14
-rw-r--r--docs/reference/plugins/plugins.types1
-rw-r--r--gst/vaapi/Makefile.am2
-rw-r--r--gst/vaapi/gstvaapi.c4
-rw-r--r--gst/vaapi/gstvaapidownload.c614
-rw-r--r--gst/vaapi/gstvaapidownload.h66
8 files changed, 705 insertions, 0 deletions
diff --git a/README b/README
index 3aa80aa2..6c104645 100644
--- a/README
+++ b/README
@@ -26,6 +26,9 @@ GStreamer and helper libraries.
* `vaapiupload' is used to convert from video/x-raw-yuv pixels to
video/x-vaapi-surface surfaces.
+ * `vaapidownload' is used to convert from video-x-vaapi-surface
+ surfaces to video/x-raw-yuv pixels.
+
* `vaapisink' is used to display video/x-vaapi-surface surfaces to
screen.
diff --git a/docs/reference/plugins/plugins-docs.xml.in b/docs/reference/plugins/plugins-docs.xml.in
index b02060fd..550355ec 100644
--- a/docs/reference/plugins/plugins-docs.xml.in
+++ b/docs/reference/plugins/plugins-docs.xml.in
@@ -12,6 +12,7 @@
<chapter>
<title>gst-plugins-vaapi Plugins</title>
<xi:include href="xml/gstvaapidecode.xml"/>
+ <xi:include href="xml/gstvaapidownload.xml"/>
<xi:include href="xml/gstvaapiupload.xml"/>
<xi:include href="xml/gstvaapisink.xml"/>
</chapter>
diff --git a/docs/reference/plugins/plugins-sections.txt b/docs/reference/plugins/plugins-sections.txt
index 9db963af..48cd4445 100644
--- a/docs/reference/plugins/plugins-sections.txt
+++ b/docs/reference/plugins/plugins-sections.txt
@@ -39,3 +39,17 @@ GST_VAAPIUPLOAD_CLASS
GST_IS_VAAPIUPLOAD_CLASS
GST_VAAPIUPLOAD_GET_CLASS
</SECTION>
+
+<SECTION>
+<FILE>gstvaapidownload</FILE>
+<TITLE>GstVaapiDownload</TITLE>
+GstVaapiDownload
+<SUBSECTION Standard>
+GST_VAAPIDOWNLOAD
+GST_IS_VAAPIDOWNLOAD
+GST_TYPE_VAAPIDOWNLOAD
+gst_vaapidownload_get_type
+GST_VAAPIDOWNLOAD_CLASS
+GST_IS_VAAPIDOWNLOAD_CLASS
+GST_VAAPIDOWNLOAD_GET_CLASS
+</SECTION>
diff --git a/docs/reference/plugins/plugins.types b/docs/reference/plugins/plugins.types
index a6b5ab9c..72cb6a40 100644
--- a/docs/reference/plugins/plugins.types
+++ b/docs/reference/plugins/plugins.types
@@ -1,3 +1,4 @@
gst_vaapisink_get_type
gst_vaapidecode_get_type
+gst_vaapidownload_get_type
gst_vaapiupload_get_type
diff --git a/gst/vaapi/Makefile.am b/gst/vaapi/Makefile.am
index 3ff3b4ac..5be00766 100644
--- a/gst/vaapi/Makefile.am
+++ b/gst/vaapi/Makefile.am
@@ -18,6 +18,7 @@ endif
libgstvaapi_la_SOURCES = \
gstvaapi.c \
gstvaapidecode.c \
+ gstvaapidownload.c \
gstvaapipluginutil.c \
gstvaapisink.c \
gstvaapiupload.c \
@@ -25,6 +26,7 @@ libgstvaapi_la_SOURCES = \
noinst_HEADERS = \
gstvaapidecode.h \
+ gstvaapidownload.h \
gstvaapipluginutil.h \
gstvaapisink.h \
gstvaapiupload.h \
diff --git a/gst/vaapi/gstvaapi.c b/gst/vaapi/gstvaapi.c
index 44fb2e89..89db5e76 100644
--- a/gst/vaapi/gstvaapi.c
+++ b/gst/vaapi/gstvaapi.c
@@ -27,6 +27,7 @@
#include <gst/gst.h>
+#include "gstvaapidownload.h"
#include "gstvaapiupload.h"
#include "gstvaapidecode.h"
#include "gstvaapisink.h"
@@ -34,6 +35,9 @@
static gboolean
plugin_init (GstPlugin *plugin)
{
+ gst_element_register(plugin, "vaapidownload",
+ GST_RANK_SECONDARY,
+ GST_TYPE_VAAPIDOWNLOAD);
gst_element_register(plugin, "vaapiupload",
GST_RANK_PRIMARY,
GST_TYPE_VAAPIUPLOAD);
diff --git a/gst/vaapi/gstvaapidownload.c b/gst/vaapi/gstvaapidownload.c
new file mode 100644
index 00000000..2c025355
--- /dev/null
+++ b/gst/vaapi/gstvaapidownload.c
@@ -0,0 +1,614 @@
+/*
+ * gstvaapidownload.c - VA-API video downloader
+ *
+ * gstreamer-vaapi (C) 2010-2011 Splitted-Desktop Systems
+ * Copyright (C) 2011 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
+ */
+
+/**
+ * SECTION:gstvaapidownload
+ * @short_description: A VA to video flow filter
+ *
+ * vaapidownload converts from VA surfaces to raw YUV pixels.
+ */
+
+#include "config.h"
+
+#include <gst/gst.h>
+#include <gst/video/video.h>
+#include <gst/video/videocontext.h>
+#include <gst/vaapi/gstvaapivideosink.h>
+#include <gst/vaapi/gstvaapivideobuffer.h>
+
+#if USE_VAAPI_GLX
+#include <gst/vaapi/gstvaapivideobuffer_glx.h>
+#define gst_vaapi_video_buffer_new_from_pool(pool) \
+ gst_vaapi_video_buffer_glx_new_from_pool(pool)
+#define gst_vaapi_video_buffer_new_from_buffer(buffer) \
+ gst_vaapi_video_buffer_glx_new_from_buffer(buffer)
+#endif
+
+#include "gstvaapipluginutil.h"
+#include "gstvaapidownload.h"
+
+#define GST_PLUGIN_NAME "vaapidownload"
+#define GST_PLUGIN_DESC "A VA to video flow filter"
+
+GST_DEBUG_CATEGORY_STATIC(gst_debug_vaapidownload);
+#define GST_CAT_DEFAULT gst_debug_vaapidownload
+
+/* ElementFactory information */
+static const GstElementDetails gst_vaapidownload_details =
+ GST_ELEMENT_DETAILS(
+ "VA-API colorspace converter",
+ "Filter/Converter/Video",
+ GST_PLUGIN_DESC,
+ "Gwenole Beauchesne <gwenole.beauchesne@intel.com>");
+
+/* Default templates */
+static const char gst_vaapidownload_yuv_caps_str[] =
+ "video/x-raw-yuv, "
+ "width = (int) [ 1, MAX ], "
+ "height = (int) [ 1, MAX ]; ";
+
+static const char gst_vaapidownload_vaapi_caps_str[] =
+ GST_VAAPI_SURFACE_CAPS;
+
+static GstStaticPadTemplate gst_vaapidownload_sink_factory =
+ GST_STATIC_PAD_TEMPLATE(
+ "sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS(gst_vaapidownload_vaapi_caps_str));
+
+static GstStaticPadTemplate gst_vaapidownload_src_factory =
+ GST_STATIC_PAD_TEMPLATE(
+ "src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS(gst_vaapidownload_yuv_caps_str));
+
+typedef struct _TransformSizeCache TransformSizeCache;
+struct _TransformSizeCache {
+ GstCaps *caps;
+ guint size;
+};
+
+struct _GstVaapiDownload {
+ /*< private >*/
+ GstBaseTransform parent_instance;
+
+ GstVaapiDisplay *display;
+ GstCaps *allowed_caps;
+ TransformSizeCache transform_size_cache[2];
+ GstVaapiVideoPool *images;
+ GstVaapiImageFormat image_format;
+ guint image_width;
+ guint image_height;
+ unsigned int images_reset : 1;
+};
+
+struct _GstVaapiDownloadClass {
+ /*< private >*/
+ GstBaseTransformClass parent_class;
+};
+
+#define GstVideoContextClass GstVideoContextInterface
+GST_BOILERPLATE_WITH_INTERFACE(
+ GstVaapiDownload,
+ gst_vaapidownload,
+ GstBaseTransform,
+ GST_TYPE_BASE_TRANSFORM,
+ GstVideoContext,
+ GST_TYPE_VIDEO_CONTEXT,
+ gst_video_context);
+
+static gboolean
+gst_vaapidownload_start(GstBaseTransform *trans);
+
+static gboolean
+gst_vaapidownload_stop(GstBaseTransform *trans);
+
+static void
+gst_vaapidownload_before_transform(GstBaseTransform *trans, GstBuffer *buffer);
+
+static GstFlowReturn
+gst_vaapidownload_transform(
+ GstBaseTransform *trans,
+ GstBuffer *inbuf,
+ GstBuffer *outbuf
+);
+
+static GstCaps *
+gst_vaapidownload_transform_caps(
+ GstBaseTransform *trans,
+ GstPadDirection direction,
+ GstCaps *caps
+);
+
+static gboolean
+gst_vaapidownload_transform_size(
+ GstBaseTransform *trans,
+ GstPadDirection direction,
+ GstCaps *caps,
+ guint size,
+ GstCaps *othercaps,
+ guint *othersize
+);
+
+static gboolean
+gst_vaapidownload_set_caps(
+ GstBaseTransform *trans,
+ GstCaps *incaps,
+ GstCaps *outcaps
+);
+
+static gboolean
+gst_vaapidownload_query(
+ GstPad *pad,
+ GstQuery *query
+);
+
+/* GstVideoContext interface */
+
+static void
+gst_vaapidownload_set_video_context(GstVideoContext *context, const gchar *type,
+ const GValue *value)
+{
+ GstVaapiDownload *download = GST_VAAPIDOWNLOAD (context);
+ gst_vaapi_set_display (type, value, &download->display);
+}
+
+static gboolean
+gst_video_context_supported (GstVaapiDownload *download, GType iface_type)
+{
+ return (iface_type == GST_TYPE_VIDEO_CONTEXT);
+}
+
+static void
+gst_video_context_interface_init(GstVideoContextInterface *iface)
+{
+ iface->set_context = gst_vaapidownload_set_video_context;
+}
+
+static void
+gst_vaapidownload_destroy(GstVaapiDownload *download)
+{
+ guint i;
+
+ for (i = 0; i < G_N_ELEMENTS(download->transform_size_cache); i++) {
+ TransformSizeCache * const tsc = &download->transform_size_cache[i];
+ if (tsc->caps) {
+ gst_caps_unref(tsc->caps);
+ tsc->caps = NULL;
+ tsc->size = 0;
+ }
+ }
+
+ if (download->allowed_caps) {
+ gst_caps_unref(download->allowed_caps);
+ download->allowed_caps = NULL;
+ }
+
+ if (download->images) {
+ g_object_unref(download->images);
+ download->images = NULL;
+ }
+
+ if (download->display) {
+ g_object_unref(download->display);
+ download->display = NULL;
+ }
+}
+
+static void
+gst_vaapidownload_base_init(gpointer klass)
+{
+ GstElementClass * const element_class = GST_ELEMENT_CLASS(klass);
+
+ gst_element_class_set_details(element_class, &gst_vaapidownload_details);
+
+ /* sink pad */
+ gst_element_class_add_pad_template(
+ element_class,
+ gst_static_pad_template_get(&gst_vaapidownload_sink_factory)
+ );
+
+ /* src pad */
+ gst_element_class_add_pad_template(
+ element_class,
+ gst_static_pad_template_get(&gst_vaapidownload_src_factory)
+ );
+}
+
+static void
+gst_vaapidownload_finalize(GObject *object)
+{
+ gst_vaapidownload_destroy(GST_VAAPIDOWNLOAD(object));
+
+ G_OBJECT_CLASS(parent_class)->finalize(object);
+}
+
+static void
+gst_vaapidownload_class_init(GstVaapiDownloadClass *klass)
+{
+ GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+ GstBaseTransformClass * const trans_class = GST_BASE_TRANSFORM_CLASS(klass);
+
+ GST_DEBUG_CATEGORY_INIT(gst_debug_vaapidownload,
+ GST_PLUGIN_NAME, 0, GST_PLUGIN_DESC);
+
+ object_class->finalize = gst_vaapidownload_finalize;
+ trans_class->start = gst_vaapidownload_start;
+ trans_class->stop = gst_vaapidownload_stop;
+ trans_class->before_transform = gst_vaapidownload_before_transform;
+ trans_class->transform = gst_vaapidownload_transform;
+ trans_class->transform_caps = gst_vaapidownload_transform_caps;
+ trans_class->transform_size = gst_vaapidownload_transform_size;
+ trans_class->set_caps = gst_vaapidownload_set_caps;
+}
+
+static void
+gst_vaapidownload_init(GstVaapiDownload *download, GstVaapiDownloadClass *klass)
+{
+ GstPad *sinkpad, *srcpad;
+
+ download->display = NULL;
+ download->allowed_caps = NULL;
+ download->images = NULL;
+ download->images_reset = FALSE;
+ download->image_format = (GstVaapiImageFormat)0;
+ download->image_width = 0;
+ download->image_height = 0;
+
+ /* Override buffer allocator on sink pad */
+ sinkpad = gst_element_get_static_pad(GST_ELEMENT(download), "sink");
+ gst_pad_set_query_function(sinkpad, gst_vaapidownload_query);
+ gst_object_unref(sinkpad);
+
+ /* Override query on src pad */
+ srcpad = gst_element_get_static_pad(GST_ELEMENT(download), "src");
+ gst_pad_set_query_function(srcpad, gst_vaapidownload_query);
+ gst_object_unref(srcpad);
+}
+
+static gboolean
+gst_vaapidownload_start(GstBaseTransform *trans)
+{
+ GstVaapiDownload * const download = GST_VAAPIDOWNLOAD(trans);
+
+ if (!gst_vaapi_ensure_display(download, &download->display))
+ return FALSE;
+ return TRUE;
+}
+
+static gboolean
+gst_vaapidownload_stop(GstBaseTransform *trans)
+{
+ GstVaapiDownload * const download = GST_VAAPIDOWNLOAD(trans);
+
+ if (download->display) {
+ g_object_unref(download->display);
+ download->display = NULL;
+ }
+ return TRUE;
+}
+
+static GstVaapiImageFormat
+get_surface_format(GstVaapiSurface *surface)
+{
+ GstVaapiImage *image;
+ GstVaapiImageFormat format = GST_VAAPI_IMAGE_NV12;
+
+ /* XXX: NV12 is assumed by default */
+ image = gst_vaapi_surface_derive_image(surface);
+ if (image) {
+ format = gst_vaapi_image_get_format(image);
+ g_object_unref(image);
+ }
+ return format;
+}
+
+static gboolean
+gst_vaapidownload_update_src_caps(GstVaapiDownload *download, GstBuffer *buffer)
+{
+ GstVaapiVideoBuffer *vbuffer;
+ GstVaapiSurface *surface;
+ GstVaapiImageFormat format;
+ GstPad *srcpad;
+ GstCaps *in_caps, *out_caps;
+
+ vbuffer = GST_VAAPI_VIDEO_BUFFER(buffer);
+ surface = gst_vaapi_video_buffer_get_surface(vbuffer);
+ if (!surface) {
+ GST_WARNING("failed to retrieve VA surface from buffer");
+ return FALSE;
+ }
+
+ format = get_surface_format(surface);
+ if (format == download->image_format)
+ return TRUE;
+
+ in_caps = GST_BUFFER_CAPS(buffer);
+ if (!in_caps) {
+ GST_WARNING("failed to retrieve caps from buffer");
+ return FALSE;
+ }
+
+ out_caps = gst_vaapi_image_format_get_caps(format);
+ if (!out_caps) {
+ GST_WARNING("failed to create caps from format %" GST_FOURCC_FORMAT,
+ GST_FOURCC_ARGS(format));
+ return FALSE;
+ }
+
+ if (!gst_vaapi_append_surface_caps(out_caps, in_caps)) {
+ gst_caps_unref(out_caps);
+ return FALSE;
+ }
+
+ /* Try to renegotiate downstream caps */
+ srcpad = gst_element_get_static_pad(GST_ELEMENT(download), "src");
+ gst_pad_set_caps(srcpad, out_caps);
+ gst_object_unref(srcpad);
+
+ gst_vaapidownload_set_caps(GST_BASE_TRANSFORM(download), in_caps, out_caps);
+ gst_caps_replace(&download->allowed_caps, out_caps);
+ gst_caps_unref(out_caps);
+ return TRUE;
+}
+
+static void
+gst_vaapidownload_before_transform(GstBaseTransform *trans, GstBuffer *buffer)
+{
+ GstVaapiDownload * const download = GST_VAAPIDOWNLOAD(trans);
+
+ gst_vaapidownload_update_src_caps(download, buffer);
+}
+
+static GstFlowReturn
+gst_vaapidownload_transform(
+ GstBaseTransform *trans,
+ GstBuffer *inbuf,
+ GstBuffer *outbuf
+)
+{
+ GstVaapiDownload * const download = GST_VAAPIDOWNLOAD(trans);
+ GstVaapiVideoBuffer *vbuffer;
+ GstVaapiSurface *surface;
+ GstVaapiImage *image = NULL;
+ gboolean success;
+
+ vbuffer = GST_VAAPI_VIDEO_BUFFER(inbuf);
+ surface = gst_vaapi_video_buffer_get_surface(vbuffer);
+ if (!surface)
+ return GST_FLOW_UNEXPECTED;
+
+ image = gst_vaapi_video_pool_get_object(download->images);
+ if (!image)
+ return GST_FLOW_UNEXPECTED;
+ if (!gst_vaapi_surface_get_image(surface, image))
+ goto error_get_image;
+
+ success = gst_vaapi_image_get_buffer(image, outbuf, NULL);
+ gst_vaapi_video_pool_put_object(download->images, image);
+ if (!success)
+ goto error_get_buffer;
+ return GST_FLOW_OK;
+
+error_get_image:
+ {
+ GST_WARNING("failed to download %" GST_FOURCC_FORMAT " image "
+ "from surface 0x%08x",
+ GST_FOURCC_ARGS(gst_vaapi_image_get_format(image)),
+ gst_vaapi_surface_get_id(surface));
+ gst_vaapi_video_pool_put_object(download->images, image);
+ return GST_FLOW_UNEXPECTED;
+ }
+
+error_get_buffer:
+ {
+ GST_WARNING("failed to transfer image to output video buffer");
+ return GST_FLOW_UNEXPECTED;
+ }
+}
+
+static GstCaps *
+gst_vaapidownload_transform_caps(
+ GstBaseTransform *trans,
+ GstPadDirection direction,
+ GstCaps *caps
+)
+{
+ GstVaapiDownload * const download = GST_VAAPIDOWNLOAD(trans);
+ GstPad *srcpad;
+ GstCaps *allowed_caps, *inter_caps, *out_caps = NULL;
+ GstStructure *structure;
+
+ g_return_val_if_fail(GST_IS_CAPS(caps), NULL);
+
+ structure = gst_caps_get_structure(caps, 0);
+
+ if (direction == GST_PAD_SINK) {
+ if (!gst_structure_has_name(structure, GST_VAAPI_SURFACE_CAPS_NAME))
+ return NULL;
+ if (!gst_vaapi_ensure_display(download, &download->display))
+ return NULL;
+ out_caps = gst_caps_from_string(gst_vaapidownload_yuv_caps_str);
+
+ /* Build up allowed caps */
+ /* XXX: we don't know the decoded surface format yet so we
+ expose whatever VA images we support */
+ if (download->allowed_caps)
+ allowed_caps = gst_caps_ref(download->allowed_caps);
+ else {
+ allowed_caps = gst_vaapi_display_get_image_caps(download->display);
+ if (!allowed_caps)
+ return NULL;
+ }
+ inter_caps = gst_caps_intersect(out_caps, allowed_caps);
+ gst_caps_unref(allowed_caps);
+ gst_caps_unref(out_caps);
+ out_caps = inter_caps;
+
+ /* Intersect with allowed caps from the peer, if any */
+ srcpad = gst_element_get_static_pad(GST_ELEMENT(download), "src");
+ allowed_caps = gst_pad_peer_get_caps(srcpad);
+ if (allowed_caps) {
+ inter_caps = gst_caps_intersect(out_caps, allowed_caps);
+ gst_caps_unref(allowed_caps);
+ gst_caps_unref(out_caps);
+ out_caps = inter_caps;
+ }
+ }
+ else {
+ if (!gst_structure_has_name(structure, "video/x-raw-yuv"))
+ return NULL;
+ out_caps = gst_caps_from_string(gst_vaapidownload_vaapi_caps_str);
+
+ structure = gst_caps_get_structure(out_caps, 0);
+ gst_structure_set(
+ structure,
+ "type", G_TYPE_STRING, "vaapi",
+ "opengl", G_TYPE_BOOLEAN, USE_VAAPI_GLX,
+ NULL
+ );
+ }
+
+ if (!gst_vaapi_append_surface_caps(out_caps, caps)) {
+ gst_caps_unref(out_caps);
+ return NULL;
+ }
+ return out_caps;
+}
+
+static gboolean
+gst_vaapidownload_ensure_image_pool(GstVaapiDownload *download, GstCaps *caps)
+{
+ GstStructure * const structure = gst_caps_get_structure(caps, 0);
+ GstVaapiImageFormat format;
+ gint width, height;
+
+ format = gst_vaapi_image_format_from_caps(caps);
+ gst_structure_get_int(structure, "width", &width);
+ gst_structure_get_int(structure, "height", &height);
+
+ if (format != download->image_format ||
+ width != download->image_width ||
+ height != download->image_height) {
+ download->image_format = format;
+ download->image_width = width;
+ download->image_height = height;
+ if (download->images)
+ g_object_unref(download->images);
+ download->images = gst_vaapi_image_pool_new(download->display, caps);
+ if (!download->images)
+ return FALSE;
+ download->images_reset = TRUE;
+ }
+ return TRUE;
+}
+
+static inline gboolean
+gst_vaapidownload_negotiate_buffers(
+ GstVaapiDownload *download,
+ GstCaps *incaps,
+ GstCaps *outcaps
+)
+{
+ if (!gst_vaapidownload_ensure_image_pool(download, outcaps))
+ return FALSE;
+ return TRUE;
+}
+
+static gboolean
+gst_vaapidownload_set_caps(
+ GstBaseTransform *trans,
+ GstCaps *incaps,
+ GstCaps *outcaps
+)
+{
+ GstVaapiDownload * const download = GST_VAAPIDOWNLOAD(trans);
+
+ if (!gst_vaapidownload_negotiate_buffers(download, incaps, outcaps))
+ return FALSE;
+ return TRUE;
+}
+
+static gboolean
+gst_vaapidownload_transform_size(
+ GstBaseTransform *trans,
+ GstPadDirection direction,
+ GstCaps *caps,
+ guint size,
+ GstCaps *othercaps,
+ guint *othersize
+)
+{
+ GstVaapiDownload * const download = GST_VAAPIDOWNLOAD(trans);
+ GstStructure * const structure = gst_caps_get_structure(othercaps, 0);
+ GstVideoFormat format;
+ gint width, height;
+ guint i;
+
+ /* Lookup in cache */
+ for (i = 0; i < G_N_ELEMENTS(download->transform_size_cache); i++) {
+ TransformSizeCache * const tsc = &download->transform_size_cache[i];
+ if (tsc->caps && tsc->caps == othercaps) {
+ *othersize = tsc->size;
+ return TRUE;
+ }
+ }
+
+ /* Compute requested buffer size */
+ if (gst_structure_has_name(structure, GST_VAAPI_SURFACE_CAPS_NAME))
+ *othersize = 0;
+ else {
+ if (!gst_video_format_parse_caps(othercaps, &format, &width, &height))
+ return FALSE;
+ *othersize = gst_video_format_get_size(format, width, height);
+ }
+
+ /* Update cache */
+ for (i = 0; i < G_N_ELEMENTS(download->transform_size_cache); i++) {
+ TransformSizeCache * const tsc = &download->transform_size_cache[i];
+ if (!tsc->caps) {
+ gst_caps_replace(&tsc->caps, othercaps);
+ tsc->size = *othersize;
+ }
+ }
+ return TRUE;
+}
+
+static gboolean
+gst_vaapidownload_query(GstPad *pad, GstQuery *query)
+{
+ GstVaapiDownload * const download = GST_VAAPIDOWNLOAD(gst_pad_get_parent_element(pad));
+ gboolean res;
+
+ GST_DEBUG("sharing display %p", download->display);
+
+ if (gst_vaapi_reply_to_query(query, download->display))
+ res = TRUE;
+ else
+ res = gst_pad_query_default(pad, query);
+
+ g_object_unref(download);
+ return res;
+
+}
diff --git a/gst/vaapi/gstvaapidownload.h b/gst/vaapi/gstvaapidownload.h
new file mode 100644
index 00000000..b15235aa
--- /dev/null
+++ b/gst/vaapi/gstvaapidownload.h
@@ -0,0 +1,66 @@
+/*
+ * gstvaapidownload.h - VA-API video downloader
+ *
+ * gstreamer-vaapi (C) 2010-2011 Splitted-Desktop Systems
+ *
+ * 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_VAAPIDOWNLOAD_H
+#define GST_VAAPIDOWNLOAD_H
+
+#include <gst/base/gstbasetransform.h>
+#include <gst/vaapi/gstvaapidisplay.h>
+#include <gst/vaapi/gstvaapisurface.h>
+#include <gst/vaapi/gstvaapiimagepool.h>
+#include <gst/vaapi/gstvaapisurfacepool.h>
+#include <gst/vaapi/gstvaapivideobuffer.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_VAAPIDOWNLOAD \
+ (gst_vaapidownload_get_type())
+
+#define GST_VAAPIDOWNLOAD(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), \
+ GST_TYPE_VAAPIDOWNLOAD, \
+ GstVaapiDownload))
+
+#define GST_VAAPIDOWNLOAD_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), \
+ GST_TYPE_VAAPIDOWNLOAD, \
+ GstVaapiDownloadClass))
+
+#define GST_IS_VAAPIDOWNLOAD(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_VAAPIDOWNLOAD))
+
+#define GST_IS_VAAPIDOWNLOAD_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_VAAPIDOWNLOAD))
+
+#define GST_VAAPIDOWNLOAD_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj), \
+ GST_TYPE_VAAPIDOWNLOAD, \
+ GstVaapiDownloadClass))
+
+typedef struct _GstVaapiDownload GstVaapiDownload;
+typedef struct _GstVaapiDownloadClass GstVaapiDownloadClass;
+
+GType
+gst_vaapidownload_get_type(void);
+
+G_END_DECLS
+
+#endif /* GST_VAAPIDOWNLOAD_H */