vaapidownload: add new plugin to download pixels from VA surfaces.
authorGwenole Beauchesne <gwenole.beauchesne@intel.com>
Thu, 5 Jan 2012 09:50:59 +0000 (10:50 +0100)
committerGwenole Beauchesne <gwenole.beauchesne@intel.com>
Thu, 5 Jan 2012 10:04:29 +0000 (11:04 +0100)
README
docs/reference/plugins/plugins-docs.xml.in
docs/reference/plugins/plugins-sections.txt
docs/reference/plugins/plugins.types
gst/vaapi/Makefile.am
gst/vaapi/gstvaapi.c
gst/vaapi/gstvaapidownload.c [new file with mode: 0644]
gst/vaapi/gstvaapidownload.h [new file with mode: 0644]

diff --git a/README b/README
index 3aa80aa..6c10464 100644 (file)
--- 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.
 
index b02060f..550355e 100644 (file)
@@ -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>
index 9db963a..48cd444 100644 (file)
@@ -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>
index a6b5ab9..72cb6a4 100644 (file)
@@ -1,3 +1,4 @@
 gst_vaapisink_get_type
 gst_vaapidecode_get_type
+gst_vaapidownload_get_type
 gst_vaapiupload_get_type
index 3ff3b4a..5be0076 100644 (file)
@@ -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        \
index 44fb2e8..89db5e7 100644 (file)
@@ -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 (file)
index 0000000..2c02535
--- /dev/null
@@ -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 (file)
index 0000000..b15235a
--- /dev/null
@@ -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 */