vaapiconvert: change direct-rendering=0 to vaPutImage and support YUY2 colorspace...
authorWind Yuan <feng.yuan@intel.com>
Thu, 5 Jan 2012 03:17:33 +0000 (11:17 +0800)
committerZhong Cong <congx.zhong@intel.com>
Tue, 5 Feb 2013 07:37:10 +0000 (15:37 +0800)
gst-libs/gst/vaapi/gstvaapiimage.c
gst-libs/gst/vaapi/gstvaapiimage.h
gst/vaapi/gstvaapiupload.c
gst/vaapi/gstvaapiupload.h

index ba727c8..143ef8d 100644 (file)
@@ -1568,18 +1568,31 @@ _image_convert_to_yuv411(
 gboolean
 gst_vaapi_convert_buffer_to_image(
     GstVaapiImage *image,
-    GstBuffer *inbuf, // inbuf : I420
-    guint32 in_format)
+    GstBuffer *inbuf
+    )
 {
     GstVaapiImagePrivate *priv;
     guint width, height;
     GstVaapiImageFormat image_format;
     gboolean success = TRUE;
+    GstCaps *buffer_caps;
+    GstStructure *structure;
+    guint32 in_format = 0;
 
     priv = image->priv;
     gst_vaapi_image_get_size(image, &width, &height);
     image_format = gst_vaapi_image_get_format(image);
 
+    /* get buffer format */
+    buffer_caps = GST_BUFFER_CAPS(inbuf);
+    if (!buffer_caps)
+        return FALSE;
+    structure = gst_caps_get_structure(buffer_caps, 0);
+    if (!structure)
+        return FALSE;
+    if (!gst_structure_get_fourcc(structure, "format", &in_format))
+        return FALSE;
+
     /* currently only support YUV convert */
     if ( (in_format != GST_MAKE_FOURCC('N','V','1','2')
           && in_format != GST_MAKE_FOURCC('Y','V','1','2')
index 3b41f08..8cd1ad7 100644 (file)
@@ -207,9 +207,7 @@ gst_vaapi_image_update_from_raw(
 gboolean
 gst_vaapi_convert_buffer_to_image(
     GstVaapiImage *image,
-    GstBuffer *buffer,
-    guint32 in_format);
-
+    GstBuffer *buffer);
 
 G_END_DECLS
 
index 420695e..550d033 100644 (file)
@@ -332,17 +332,18 @@ 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->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->need_manual_upload        = FALSE;
 
     /* Override buffer allocator on sink pad */
     sinkpad = gst_element_get_static_pad(GST_ELEMENT(upload), "sink");
@@ -397,10 +398,7 @@ gst_vaapiupload_transform(
     GstVaapiVideoBuffer *vbuffer;
     GstVaapiSurface *surface;
     GstVaapiImage *image;
-    GstCaps *buffer_caps;
     gboolean success;
-    GstVaapiImageFormat buffer_format;
-    gboolean format_changed;
 
     vbuffer = GST_VAAPI_VIDEO_BUFFER(outbuf);
     surface = gst_vaapi_video_buffer_get_surface(vbuffer);
@@ -429,16 +427,23 @@ gst_vaapiupload_transform(
 
     image = gst_vaapi_video_pool_get_object(upload->images);
     if (!image)
-        return GST_FLOW_UNEXPECTED;
+        goto error_put_image;
+
+    if (!upload->need_manual_upload) {
+        gst_vaapi_image_update_from_buffer(image, inbuf, NULL);
+    } else { /* manually copy data to image*/
+        success = gst_vaapi_upload_buffer_to_image(image, inbuf);
+        if (!success)
+            goto error_put_image;
+    }
 
-    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;
 
 flow_ok:
-    FPS_CALCULATION(vaapiconvert);
+    FPS_CALCULATION(vaapiupload);
     return GST_FLOW_OK;
 
 error_put_image:
@@ -623,6 +628,83 @@ gst_vaapiupload_ensure_direct_rendering_caps(
     }
 }
 
+typedef enum YUV_TYPE {
+  YUV_UNKOWN = 0,
+  YUV_411    = 1,
+  YUV_422    = 2,
+  YUV_444    = 4
+} YUV_TYPE;
+
+static YUV_TYPE
+_image_format_to_yuv_type(guint32 fourcc)
+{
+    switch (fourcc) {
+        case GST_MAKE_FOURCC('N','V','1','2'):
+        case GST_MAKE_FOURCC('Y','V','1','2'):
+        case GST_MAKE_FOURCC('I','4','2','0'):
+        case GST_MAKE_FOURCC('N','V','2','1'):
+        return YUV_411;
+
+        case GST_MAKE_FOURCC('Y','U','Y','2'):
+        case GST_MAKE_FOURCC('Y','V','Y','U'):
+        return YUV_422;
+
+        case GST_MAKE_FOURCC('A','Y','U','V'):
+        return YUV_UNKOWN;
+
+        default:
+        return YUV_UNKOWN;
+    }
+}
+
+static GstCaps *
+_get_nearest_caps(GstCaps *caps_list, GstCaps *src_caps)
+{
+    GstCaps *ret = NULL;
+    GstStructure *cur_struct, *tmp_struct;
+    guint32 cur_format, dest_format, tmp_format;
+    YUV_TYPE cur_type, tmp_type;
+    const GValue*tmp_val;
+    guint  n_caps;
+    guint  i;
+    guint min_diff, tmp_diff;
+
+    cur_struct = gst_caps_get_structure(src_caps, 0);
+    tmp_val = gst_structure_get_value (cur_struct, "format");
+    if (!tmp_val)
+        return NULL;
+
+    cur_format = gst_value_get_fourcc(tmp_val);
+    if((cur_type = _image_format_to_yuv_type(cur_format)) == YUV_UNKOWN)
+        return NULL;
+
+    n_caps = gst_caps_get_size(caps_list);
+    min_diff = 100;
+    dest_format = 0;
+    for (i = 0; i < n_caps; ++i) {
+      tmp_struct = gst_caps_get_structure(caps_list, i);
+      tmp_val = gst_structure_get_value (tmp_struct, "format");
+      if (!tmp_val)
+          continue;
+      tmp_format = gst_value_get_fourcc(tmp_val);
+      if ((tmp_type = _image_format_to_yuv_type(tmp_format)) == YUV_UNKOWN)
+          continue;
+      tmp_diff = abs(tmp_type - cur_type);
+      if (tmp_diff < min_diff) {
+          min_diff = tmp_diff;
+          dest_format = tmp_format;
+      }
+    }
+
+    if (dest_format == 0)
+      return NULL;
+
+    ret = gst_caps_copy(src_caps);
+    tmp_struct = gst_caps_get_structure(ret, 0);
+    gst_structure_set(tmp_struct, "format", GST_TYPE_FOURCC, dest_format, NULL);
+    return ret;
+}
+
 static gboolean
 gst_vaapiupload_negotiate_buffers(
     GstVaapiUpload  *upload,
@@ -631,19 +713,42 @@ gst_vaapiupload_negotiate_buffers(
 )
 {
     guint dr;
+    gboolean ret = TRUE;
+    GstCaps *image_allowed_caps = NULL;
+    GstCaps *image_caps = NULL;
+
+    image_allowed_caps = gst_vaapi_display_get_image_caps(upload->display);
+    if (gst_caps_can_intersect(incaps, image_allowed_caps)) {
+        image_caps = gst_caps_ref(incaps);
+        upload->need_manual_upload = FALSE;
+    } else {
+        image_caps = _get_nearest_caps(image_allowed_caps, incaps);
+        upload->need_manual_upload = TRUE;
+    }
 
-    if (!gst_vaapiupload_ensure_image_pool(upload, incaps))
-        return FALSE;
+    if (!gst_vaapiupload_ensure_image_pool(upload, image_caps))
+        goto failed;
 
     if (!gst_vaapiupload_ensure_surface_pool(upload, outcaps))
-        return FALSE;
+        goto failed;
 
-    if (upload->direct_rendering)
-        gst_vaapiupload_ensure_direct_rendering_caps(upload, incaps);
+    if (upload->direct_rendering && !upload->need_manual_upload)
+      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;
-    return TRUE;
+        GST_DEBUG("direct-rendering level: %d", dr);
+    }
+    ret = TRUE;
+    goto end;
+
+  failed:
+    ret = FALSE;
+
+  end:
+    gst_caps_unref(image_caps);
+    gst_caps_unref(image_allowed_caps);
+    return ret;
 }
 
 static gboolean
@@ -698,6 +803,10 @@ gst_vaapiupload_buffer_alloc(
     GstVaapiSurface *surface = NULL;
     GstVaapiVideoBuffer *vbuffer;
 
+    /* already checked */
+    if (!upload->direct_rendering)
+        return GST_FLOW_OK;
+
     /* Check if we can use direct-rendering */
     if (!gst_vaapiupload_negotiate_buffers(upload, caps, caps))
         goto error;
index 386a62c..c5e37c4 100644 (file)
@@ -77,6 +77,7 @@ struct _GstVaapiUpload {
     guint               direct_rendering;
     unsigned int        images_reset    : 1;
     unsigned int        surfaces_reset  : 1;
+    unsigned int        need_manual_convert : 1;
 };
 
 struct _GstVaapiUploadClass {