update GstVaapiUpload to use GstVaapiUploader 16/1716/1
authorZhao Halley <halley.zhao@intel.com>
Tue, 11 Sep 2012 07:36:14 +0000 (15:36 +0800)
committerZhao Halley <halley.zhao@intel.com>
Thu, 13 Sep 2012 06:18:40 +0000 (14:18 +0800)
gst-libs/gst/vaapi/gstvaapiuploader.c
gst-libs/gst/vaapi/gstvaapiuploader.h
gst/vaapi/gstvaapiupload.c [changed mode: 0644->0755]
gst/vaapi/gstvaapiupload.h [changed mode: 0644->0755]

index 77c07ed..c780155 100755 (executable)
@@ -221,25 +221,63 @@ gst_vaapiuploader_upload_raw_yuv(
     if (!surface)
         return NULL;
 
-    if (priv->direct_rendering == 1) {
-        image   = gst_vaapi_video_buffer_get_image(vbuffer);
-        g_assert(image);
+    if (gst_vaapiuploader_upload_raw_yuv_to_surface(uploader, inbuf, surface)) {
+        return surface;
     }
-    else if (priv->direct_rendering == 0) {
-        image = gst_vaapi_video_pool_get_object(priv->images);
-        gst_vaapi_image_update_from_buffer(image, inbuf, NULL);
+    else {
+        gst_vaapi_video_pool_put_object(priv->surfaces, surface);
+        return NULL;
+    }        
+
+}
+
+gboolean 
+gst_vaapiuploader_upload_raw_yuv_to_surface(
+    GstVaapiUploader    *uploader,
+    GstBuffer           *inbuf, 
+    GstVaapiSurface     *surface)
+{
+    GstVaapiUploaderPrivate * const priv  = uploader->priv;
+    GstVaapiVideoBuffer *vbuffer;
+    GstVaapiImage *image;
+    gboolean success;
+
+    g_assert(surface);
+    if (priv->direct_rendering) {
+        if (!GST_VAAPI_IS_VIDEO_BUFFER(inbuf)) {
+            GST_DEBUG("GstVaapiVideoBuffer was expected");
+            return FALSE;
+        }
+
+        vbuffer = GST_VAAPI_VIDEO_BUFFER(inbuf);
+        image   = gst_vaapi_video_buffer_get_image(vbuffer);
+        if (!image)
+            return FALSE;
+    #if 0 
+        if (!gst_vaapi_image_unmap(image))
+            return FALSE;
+    #else 
+        // one frame could be uploaded more than once, in either preroll or playing state, or in pause state
+        // unmap can be fail without harm
+        gst_vaapi_image_unmap(image);
+    #endif
+        if (priv->direct_rendering < 2) {
+            if (!gst_vaapi_surface_put_image(surface, image))
+                goto error_put_image;
+        }
+        return TRUE;
     }
-    gst_vaapi_image_unmap(image);
 
+    image = gst_vaapi_video_pool_get_object(priv->images);
+    if (!image)
+        return FALSE;
+
+    gst_vaapi_image_update_from_buffer(image, inbuf, NULL);
     success = gst_vaapi_surface_put_image(surface, image);
-    
-    if (priv->direct_rendering = 0) {
-        gst_vaapi_video_pool_put_object(priv->images, image);
-    }
-       
+    gst_vaapi_video_pool_put_object(priv->images, image);
     if (!success)
         goto error_put_image;
-    return surface;
+    return TRUE;
 
 error_put_image:
     {
@@ -247,8 +285,9 @@ error_put_image:
                     "to surface 0x%08x",
                     GST_FOURCC_ARGS(gst_vaapi_image_get_format(image)),
                     gst_vaapi_surface_get_id(surface));
-        return GST_FLOW_OK;
+        return FALSE;
     }
+
 }
 
 gboolean 
@@ -325,6 +364,40 @@ gst_vaapiuploader_buffer_request(
     return uploader_buffer;
 }
 
+GstVaapiSurface * 
+gst_vaapiuploader_pool_get_surface(GstVaapiUploader    *uploader)
+{
+    GstVaapiUploaderPrivate * priv = uploader->priv;
+    g_assert (priv->surfaces);
+    GstVaapiSurface *surface = gst_vaapi_video_pool_get_object(priv->surfaces);
+    return surface;
+}
+
+void  
+gst_vaapiuploader_pool_put_surface(GstVaapiUploader    *uploader, GstVaapiSurface *surface)
+{
+    GstVaapiUploaderPrivate * priv = uploader->priv;
+    g_assert (priv->surfaces);
+    gst_vaapi_video_pool_put_object(priv->surfaces, surface);
+    return;
+}
+
+GstVaapiImage * 
+gst_vaapiuploader_pool_get_image(GstVaapiUploader    *uploader)
+{
+    GstVaapiUploaderPrivate * priv = uploader->priv;
+    g_assert (priv->images);
+    return gst_vaapi_video_pool_get_object(priv->images);
+}
+
+void  
+gst_vaapiuploader_pool_put_image(GstVaapiUploader    *uploader, GstVaapiImage *image)
+{
+    GstVaapiUploaderPrivate * priv = uploader->priv;
+    g_assert (priv->images);
+    return gst_vaapi_video_pool_put_object(priv->images, image);
+}
+
 static void
 gst_vaapi_uploader_destroy(GstVaapiUploader *uploader)
 {
@@ -351,6 +424,16 @@ gst_vaapi_uploader_set_property(
 {
     GstVaapiUploader        * const uploader = GST_VAAPI_UPLOADER(object);
     GstVaapiUploaderPrivate * const priv  = uploader->priv;
+    switch (prop_id) {
+    case PROP_DIRECT_RENDERING:
+        GST_OBJECT_LOCK(uploader);
+        priv->direct_rendering = g_value_get_uint(value);
+        GST_OBJECT_UNLOCK(uploader);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
 
 }
 
@@ -364,6 +447,15 @@ gst_vaapi_uploader_get_property(
 {
     GstVaapiUploader        * const uploader = GST_VAAPI_UPLOADER(object);
     GstVaapiUploaderPrivate * const priv  = uploader->priv;
+
+    switch (prop_id) {
+    case PROP_DIRECT_RENDERING:
+        g_value_set_uint(value, priv->direct_rendering);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
 }
 
 static void
@@ -389,6 +481,34 @@ gst_vaapi_uploader_class_init(GstVaapiUploaderClass *klass)
     object_class->get_property = gst_vaapi_uploader_get_property;
     object_class->constructed  = gst_vaapi_uploader_constructed;
 
+    /**
+     * GstVaapiUploader:direct-rendering:
+     *
+     * Selects the direct rendering level.
+     * <orderedlist>
+     * <listitem override="0">
+     *   Disables direct rendering.
+     * </listitem>
+     * <listitem>
+     *   Enables direct rendering to the output buffer. i.e. this
+     *   tries to use a single buffer for both sink and src pads.
+     * </listitem>
+     * <listitem>
+     *   Enables direct rendering to the underlying surface. i.e. with
+     *   drivers supporting vaDeriveImage(), the output surface pixels
+     *   will be modified directly.
+     * </listitem>
+     * </orderedlist>
+     */
+    g_object_class_install_property
+        (object_class,
+         PROP_DIRECT_RENDERING,
+         g_param_spec_uint("direct-rendering",
+                           "Direct rendering",
+                           "Direct rendering level",
+                           0, 2,
+                           DIRECT_RENDERING_DEFAULT,
+                           G_PARAM_READWRITE));
 }
 
 static void
index 9442a7e..f6b692c 100755 (executable)
 #include <gst/vaapi/gstvaapipluginbuffer.h>
 
 G_BEGIN_DECLS
+    
+/*
+ * Direct rendering levels (direct-rendering)
+ * 0: upstream allocated YUV pixels
+ * 1: vaapiupload allocated YUV pixels (mapped from VA image)
+ * 2: vaapiupload allocated YUV pixels (mapped from VA surface)
+ */
+
+#define DIRECT_RENDERING_DEFAULT 2
+    
+enum {
+    PROP_UPLOADER_0,
+
+    PROP_DIRECT_RENDERING,
+};
+
 
 #define GST_VAAPI_TYPE_UPLOADER \
     (gst_vaapi_uploader_get_type())
@@ -112,6 +128,22 @@ gst_vaapiuploader_buffer_request(
     GstCaps          *caps,
     GstVaapiDisplay  *display);
 
+GstVaapiSurface * 
+gst_vaapiuploader_pool_get_surface(GstVaapiUploader    *uploader);
+
+void  
+gst_vaapiuploader_pool_put_surface(GstVaapiUploader    *uploader, GstVaapiSurface *surface);
+
+GstVaapiImage * 
+gst_vaapiuploader_pool_get_image(GstVaapiUploader    *uploader);
+
+void 
+gst_vaapiuploader_pool_put_image(GstVaapiUploader    *uploader, GstVaapiImage *image);
+
+gboolean 
+gst_vaapiuploader_upload_raw_yuv_to_surface(    GstVaapiUploader    *uploader,
+    GstBuffer           *inbuf,     GstVaapiSurface     *surface);
+
 G_END_DECLS
 
 #endif /* GST_VAAPI_UPLOADER_H */
old mode 100644 (file)
new mode 100755 (executable)
index b4bc9fd..7ddaaad
@@ -93,20 +93,6 @@ G_DEFINE_TYPE_WITH_CODE(
     G_IMPLEMENT_INTERFACE(GST_TYPE_VIDEO_CONTEXT,
                           gst_video_context_interface_init));
 
-/*
- * Direct rendering levels (direct-rendering)
- * 0: upstream allocated YUV pixels
- * 1: vaapiupload allocated YUV pixels (mapped from VA image)
- * 2: vaapiupload allocated YUV pixels (mapped from VA surface)
- */
-#define DIRECT_RENDERING_DEFAULT 2
-
-enum {
-    PROP_0,
-
-    PROP_DIRECT_RENDERING,
-};
-
 static gboolean
 gst_vaapiupload_start(GstBaseTransform *trans);
 
@@ -201,8 +187,6 @@ gst_video_context_interface_init(GstVideoContextInterface *iface)
 static void
 gst_vaapiupload_destroy(GstVaapiUpload *upload)
 {
-    g_clear_object(&upload->images);
-    g_clear_object(&upload->surfaces);
     g_clear_object(&upload->display);
 }
 
@@ -230,6 +214,7 @@ gst_vaapiupload_set_property(
         GST_OBJECT_LOCK(upload);
         upload->direct_rendering = g_value_get_uint(value);
         GST_OBJECT_UNLOCK(upload);
+        g_object_set(G_OBJECT(upload->uploader), "direct-rendering", upload->direct_rendering, NULL);
         break;
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
@@ -249,6 +234,7 @@ gst_vaapiupload_get_property(
 
     switch (prop_id) {
     case PROP_DIRECT_RENDERING:
+        g_object_get(G_OBJECT(upload->uploader), "direct-rendering", &upload->direct_rendering, NULL);
         g_value_set_uint(value, upload->direct_rendering);
         break;
     default:
@@ -333,17 +319,9 @@ gst_vaapiupload_init(GstVaapiUpload *upload)
 {
     GstPad *sinkpad, *srcpad;
 
-    upload->display                     = NULL;
-    upload->images                      = NULL;
-    upload->images_reset                = FALSE;
-    upload->image_width                 = 0;
-    upload->image_height                = 0;
-    upload->surfaces                    = NULL;
-    upload->surfaces_reset              = FALSE;
-    upload->surface_width               = 0;
-    upload->surface_height              = 0;
-    upload->direct_rendering_caps       = 0;
-    upload->direct_rendering            = G_MAXUINT32;
+    upload->display             = NULL;
+    upload->direct_rendering    = G_MAXUINT32;
+    upload->uploader            = gst_vaapi_uploader_new();
 
     /* Override buffer allocator on sink pad */
     sinkpad = gst_element_get_static_pad(GST_ELEMENT(upload), "sink");
@@ -405,45 +383,13 @@ gst_vaapiupload_transform(
     if (!surface)
         return GST_FLOW_UNEXPECTED;
 
-    if (upload->direct_rendering) {
-        if (!GST_VAAPI_IS_VIDEO_BUFFER(inbuf)) {
-            GST_DEBUG("GstVaapiVideoBuffer was expected");
-            return GST_FLOW_UNEXPECTED;
-        }
-
-        vbuffer = GST_VAAPI_VIDEO_BUFFER(inbuf);
-        image   = gst_vaapi_video_buffer_get_image(vbuffer);
-        if (!image)
-            return GST_FLOW_UNEXPECTED;
-        if (!gst_vaapi_image_unmap(image))
-            return GST_FLOW_UNEXPECTED;
-
-        if (upload->direct_rendering < 2) {
-            if (!gst_vaapi_surface_put_image(surface, image))
-                goto error_put_image;
-        }
+    if (gst_vaapiuploader_upload_raw_yuv_to_surface(upload->uploader, inbuf, surface)) {
         return GST_FLOW_OK;
     }
-
-    image = gst_vaapi_video_pool_get_object(upload->images);
-    if (!image)
+    else {
         return GST_FLOW_UNEXPECTED;
-
-    gst_vaapi_image_update_from_buffer(image, inbuf, NULL);
-    success = gst_vaapi_surface_put_image(surface, image);
-    gst_vaapi_video_pool_put_object(upload->images, image);
-    if (!success)
-        goto error_put_image;
-    return GST_FLOW_OK;
-
-error_put_image:
-    {
-        GST_WARNING("failed to upload %" GST_FOURCC_FORMAT " image "
-                    "to surface 0x%08x",
-                    GST_FOURCC_ARGS(gst_vaapi_image_get_format(image)),
-                    gst_vaapi_surface_get_id(surface));
-        return GST_FLOW_OK;
     }
+    
 }
 
 static GstCaps *
@@ -498,139 +444,6 @@ gst_vaapiupload_transform_caps(
 }
 
 static gboolean
-gst_vaapiupload_ensure_image_pool(GstVaapiUpload *upload, GstCaps *caps)
-{
-    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 != upload->image_width || height != upload->image_height) {
-        upload->image_width  = width;
-        upload->image_height = height;
-        g_clear_object(&upload->images);
-        upload->images = gst_vaapi_image_pool_new(upload->display, caps);
-        if (!upload->images)
-            return FALSE;
-        upload->images_reset = TRUE;
-    }
-    return TRUE;
-}
-
-static gboolean
-gst_vaapiupload_ensure_surface_pool(GstVaapiUpload *upload, GstCaps *caps)
-{
-    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 != upload->surface_width || height != upload->surface_height) {
-        upload->surface_width  = width;
-        upload->surface_height = height;
-        g_clear_object(&upload->surfaces);
-        upload->surfaces = gst_vaapi_surface_pool_new(upload->display, caps);
-        if (!upload->surfaces)
-            return FALSE;
-        upload->surfaces_reset = TRUE;
-    }
-    return TRUE;
-}
-
-static void
-gst_vaapiupload_ensure_direct_rendering_caps(
-    GstVaapiUpload *upload,
-    GstCaps         *caps
-)
-{
-    GstVaapiSurface *surface;
-    GstVaapiImage *image;
-    GstVaapiImageFormat vaformat;
-    GstVideoFormat vformat;
-    GstStructure *structure;
-    gint width, height;
-
-    if (!upload->images_reset && !upload->surfaces_reset)
-        return;
-
-    upload->images_reset          = FALSE;
-    upload->surfaces_reset        = FALSE;
-    upload->direct_rendering_caps = 0;
-
-    structure = gst_caps_get_structure(caps, 0);
-    if (!structure)
-        return;
-    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(caps, &vformat, NULL, NULL))
-        return;
-    if (!gst_video_format_is_yuv(vformat))
-        return;
-    vaformat = gst_vaapi_image_format_from_video(vformat);
-    if (!vaformat)
-        return;
-
-    /* Check if we can alias sink & output buffers (same data_size) */
-    image = gst_vaapi_video_pool_get_object(upload->images);
-    if (image) {
-        if (upload->direct_rendering_caps == 0 &&
-            (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))))
-            upload->direct_rendering_caps = 1;
-        gst_vaapi_video_pool_put_object(upload->images, image);
-    }
-
-    /* Check if we can access to the surface pixels directly */
-    surface = gst_vaapi_video_pool_get_object(upload->surfaces);
-    if (surface) {
-        image = gst_vaapi_surface_derive_image(surface);
-        if (image) {
-            if (gst_vaapi_image_map(image)) {
-                if (upload->direct_rendering_caps == 1 &&
-                    (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))))
-                    upload->direct_rendering_caps = 2;
-                gst_vaapi_image_unmap(image);
-            }
-            g_object_unref(image);
-        }
-        gst_vaapi_video_pool_put_object(upload->surfaces, surface);
-    }
-}
-
-static gboolean
-gst_vaapiupload_negotiate_buffers(
-    GstVaapiUpload  *upload,
-    GstCaps          *incaps,
-    GstCaps          *outcaps
-)
-{
-    guint dr;
-
-    if (!gst_vaapiupload_ensure_image_pool(upload, incaps))
-        return FALSE;
-
-    if (!gst_vaapiupload_ensure_surface_pool(upload, outcaps))
-        return FALSE;
-
-    gst_vaapiupload_ensure_direct_rendering_caps(upload, incaps);
-    dr = MIN(upload->direct_rendering, upload->direct_rendering_caps);
-    if (upload->direct_rendering != dr) {
-        upload->direct_rendering = dr;
-        GST_DEBUG("direct-rendering level: %d", dr);
-    }
-    return TRUE;
-}
-
-static gboolean
 gst_vaapiupload_set_caps(
     GstBaseTransform *trans,
     GstCaps          *incaps,
@@ -639,9 +452,11 @@ gst_vaapiupload_set_caps(
 {
     GstVaapiUpload * const upload = GST_VAAPIUPLOAD(trans);
 
-    if (!gst_vaapiupload_negotiate_buffers(upload, incaps, outcaps))
+    if (!gst_vaapiuploader_negotiate_buffers(upload->uploader, incaps, outcaps, upload->display))
         return FALSE;
 
+    g_object_get(G_OBJECT(upload->uploader), "direct-rendering", &upload->direct_rendering, NULL);
+
     return TRUE;
 }
 
@@ -676,52 +491,29 @@ gst_vaapiupload_buffer_alloc(
 {
     GstVaapiUpload * const upload = GST_VAAPIUPLOAD(trans);
     GstBuffer *buffer = NULL;
-    GstVaapiImage *image = NULL;
     GstVaapiSurface *surface = NULL;
     GstVaapiVideoBuffer *vbuffer;
 
-    /* Check if we can use direct-rendering */
-    if (!gst_vaapiupload_negotiate_buffers(upload, caps, caps))
-        goto error;
-    if (!upload->direct_rendering)
-        return GST_FLOW_OK;
+    *pbuf = NULL;
 
-    switch (upload->direct_rendering) {
-    case 2:
-        buffer  = gst_vaapi_video_buffer_new_from_pool(upload->surfaces);
-        if (!buffer)
-            goto error;
-        vbuffer = GST_VAAPI_VIDEO_BUFFER(buffer);
+    GstVaapiUploaderBuffer uploader_buffer = 
+        gst_vaapiuploader_buffer_request(upload->uploader, size, caps, upload->display);
 
-        surface = gst_vaapi_video_buffer_get_surface(vbuffer);
-        image   = gst_vaapi_surface_derive_image(surface);
-        if (image && gst_vaapi_image_get_data_size(image) == size) {
-            gst_vaapi_video_buffer_set_image(vbuffer, image);
-            g_object_unref(image); /* video buffer owns an extra reference */
-            break;
-        }
-
-        /* We can't use the derive-image optimization. Disable it. */
-        upload->direct_rendering = 1;
-        gst_buffer_unref(buffer);
-        buffer = NULL;
-
-    case 1:
-        buffer  = gst_vaapi_video_buffer_new_from_pool(upload->images);
-        if (!buffer)
-            goto error;
+    if (!uploader_buffer.image) return GST_FLOW_OK;
+    
+    if (uploader_buffer.surface) {
+        buffer = gst_vaapi_video_buffer_new_with_surface (uploader_buffer.surface);
+        g_assert(uploader_buffer.image);
+        
         vbuffer = GST_VAAPI_VIDEO_BUFFER(buffer);
-
-        image   = gst_vaapi_video_buffer_get_image(vbuffer);
-        break;
+        gst_vaapi_video_buffer_set_image(vbuffer, uploader_buffer.image);
+    }
+    else if (uploader_buffer.image) {
+        buffer = gst_vaapi_video_buffer_new_with_image (uploader_buffer.image);
     }
-    g_assert(image);
-
-    if (!gst_vaapi_image_map(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_DATA(buffer) = gst_vaapi_image_get_plane(uploader_buffer.image, 0);
+    GST_BUFFER_SIZE(buffer) = gst_vaapi_image_get_data_size(uploader_buffer.image);
 
     gst_buffer_set_caps(buffer, caps);
     *pbuf = buffer;
@@ -769,6 +561,8 @@ gst_vaapiupload_prepare_output_buffer(
     GstVaapiUpload * const upload = GST_VAAPIUPLOAD(trans);
     GstBuffer *buffer = NULL;
 
+    *poutbuf = NULL;
+
     if (upload->direct_rendering == 2) {
         if (GST_VAAPI_IS_VIDEO_BUFFER(inbuf)) {
             buffer = gst_vaapi_video_buffer_new_from_buffer(inbuf);
@@ -781,7 +575,8 @@ gst_vaapiupload_prepare_output_buffer(
     }
 
     if (!buffer) {
-        buffer = gst_vaapi_video_buffer_new_from_pool(upload->surfaces);
+        GstVaapiSurface *surface = gst_vaapiuploader_pool_get_surface(upload->uploader);
+        buffer = gst_vaapi_video_buffer_new_with_surface(surface);
         if (!buffer)
             return GST_FLOW_UNEXPECTED;
         gst_buffer_set_caps(buffer, caps);
old mode 100644 (file)
new mode 100755 (executable)
index 386a62c..a136d24
@@ -29,6 +29,7 @@
 #include <gst/vaapi/gstvaapiimagepool.h>
 #include <gst/vaapi/gstvaapisurfacepool.h>
 #include <gst/vaapi/gstvaapivideobuffer.h>
+#include "gst-libs/gst/vaapi/gstvaapiuploader.h"
 
 G_BEGIN_DECLS
 
@@ -67,16 +68,8 @@ struct _GstVaapiUpload {
     GstBaseTransform    parent_instance;
 
     GstVaapiDisplay    *display;
-    GstVaapiVideoPool  *images;
-    guint               image_width;
-    guint               image_height;
-    GstVaapiVideoPool  *surfaces;
-    guint               surface_width;
-    guint               surface_height;
-    guint               direct_rendering_caps;
     guint               direct_rendering;
-    unsigned int        images_reset    : 1;
-    unsigned int        surfaces_reset  : 1;
+    GstVaapiUploader   *uploader;
 };
 
 struct _GstVaapiUploadClass {