vaapiconvert: try directly copy buffer to derived surface first
authorWind Yuan <feng.yuan@intel.com>
Thu, 1 Dec 2011 18:07:31 +0000 (13:07 -0500)
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

index 9d4c1a7..ea207de 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "sysdeps.h"
 #include <string.h>
+#include "gst/gstutils.h"
 #include "gstvaapicompat.h"
 #include "gstvaapiutils.h"
 #include "gstvaapiimage.h"
@@ -1304,48 +1305,137 @@ gst_vaapi_image_update_from_raw(
     return success;
 }
 
+static gboolean
+_image_convert_to_nv12(
+  guint8 *src,
+  guint32 width,
+  guint32 height,
+  GstVaapiImageFormat src_format,
+  guint8 *dest,
+  VAImage *va_image)
+{
+  guint8 *y_src, *u_src, *v_src, *uv_src;
+  guint8 *y_dest, *uv_dest;
+  guint32 ystride, ustride, vstride, uv_stride;
+  guint row, column;
+
+  y_src = src;
+  ystride = GST_ROUND_UP_4(width);
+
+  y_dest = dest + va_image->offsets[0];
+  uv_dest = dest + va_image->offsets[1];
+  g_assert(va_image->num_planes == 2);
+
+  /* copy Y first */
+  for (row = 0; row < height; row++) {
+    memcpy(y_dest, y_src, width);
+    y_src += ystride;
+    y_dest += va_image->pitches[0];
+  }
+
+  switch (src_format) {
+    case GST_VAAPI_IMAGE_NV12: {
+      uv_src = src + ystride*GST_ROUND_UP_2(height);
+      uv_stride = ystride;
+      for (row = 0; row < GST_ROUND_UP_2(height)/2; row++) {
+        memcpy(uv_dest, uv_src, width);
+        uv_src += uv_stride;
+        uv_dest += va_image->pitches[1];
+      }
+    }
+    break;
+
+    case GST_VAAPI_IMAGE_I420: {
+      u_src = src + ystride*GST_ROUND_UP_2(height);
+      ustride = GST_ROUND_UP_8(ystride)/2;
+      v_src = u_src + ustride*GST_ROUND_UP_2(height)/2;
+      vstride = GST_ROUND_UP_8(ystride)/2;
+
+      for (row = 0; row < GST_ROUND_UP_2(height)/2; row++) {
+        for (column = 0; column < width/2; column++) {
+          uv_dest[column*2] = u_src[column];
+          uv_dest[column*2+1] = v_src[column];
+        }
+        u_src += ustride;
+        v_src += vstride;
+        uv_dest += va_image->pitches[1];
+      }
+    }
+    break;
+
+    case GST_VAAPI_IMAGE_YV12:{
+      v_src = src + ystride*GST_ROUND_UP_2(height);
+      vstride = GST_ROUND_UP_8(ystride)/2;
+      u_src = v_src + vstride*GST_ROUND_UP_2(height)/2;
+      ustride = GST_ROUND_UP_8(ystride)/2;
+
+      for (row = 0; row < GST_ROUND_UP_2(height)/2; row++) {
+        for (column = 0; column < width/2; column++) {
+          uv_dest[column*2] = u_src[column];
+          uv_dest[column*2+1] = v_src[column];
+        }
+        u_src += ustride;
+        v_src += vstride;
+        uv_dest += va_image->pitches[1];
+      }
+    }
+    break;
+
+    default:
+      return FALSE;
+  }
+  return TRUE;
+}
+
+
 gboolean
 gst_vaapi_convert_buffer_to_image(
     GstVaapiImage *image,
-    GstBuffer *inbuf) // inbuf : I420
+    GstBuffer *inbuf, // inbuf : I420
+    GstVaapiImageFormat in_format)
 {
   GstVaapiImagePrivate *priv;
   guint width, height;
-  guint row, column;
-  GstVaapiImageFormat format;
-  guint8 *y_src, *u_src, *v_src;
-  guint8 *y_dest, *u_dest, *v_dest;
+  GstVaapiImageFormat image_format;
+  gboolean success = TRUE;
 
   priv = image->priv;
   gst_vaapi_image_get_size(image, &width, &height);
-  format = gst_vaapi_image_get_format(image);
-  gst_vaapi_image_map(image);
+  image_format = gst_vaapi_image_get_format(image);
+
+  /* currently only support YUV convert */
+  if ( (in_format != GST_VAAPI_IMAGE_NV12
+        && in_format != GST_VAAPI_IMAGE_YV12
+        && in_format != GST_VAAPI_IMAGE_I420)
+      || (image_format != GST_VAAPI_IMAGE_NV12
+        && image_format != GST_VAAPI_IMAGE_YV12
+        && image_format != GST_VAAPI_IMAGE_I420)
+      )
+  {
+      return FALSE;
+  }
 
-  y_src = GST_BUFFER_DATA(inbuf);
-  u_src = y_src + width*height;
-  v_src = u_src + (width/2)*(height/2);
 
-  y_dest = priv->image_data + priv->image.offsets[0];
-  u_dest = priv->image_data + priv->image.offsets[1];
-  v_dest = priv->image_data + priv->image.offsets[2];
+  gst_vaapi_image_map(image);
+  switch (image_format) {
+    case GST_VAAPI_IMAGE_NV12:
+      success = _image_convert_to_nv12(GST_BUFFER_DATA(inbuf),
+                                       width, height, in_format,
+                                       priv->image_data,
+                                       &priv->image);
+    break;
+
+    case GST_VAAPI_IMAGE_I420:
+    case GST_VAAPI_IMAGE_YV12:
+      success = FALSE;
+      break;
 
-  if (format == GST_VAAPI_IMAGE_NV12) {
-    for (row = 0; row < height; row++) {
-      memcpy(y_dest, y_src, width);
-      y_src += width;
-      y_dest += priv->image.pitches[0];
-    }
-    for (row = 0; row < height/2; row++) {
-      for (column = 0; column < width/2; column++) {
-        u_dest[column*2] = u_src[column];
-        u_dest[column*2+1] = v_src[column];
-      }
-      u_src += width/2;
-      v_src += width/2;
-      u_dest += priv->image.pitches[1];
-    }
+    default:
+      success = FALSE;
+      break;
   }
   gst_vaapi_image_unmap(image);
-  return TRUE;
+
+  return success;
 }
 
index 0c1e477..46bfb19 100644 (file)
@@ -205,7 +205,10 @@ gst_vaapi_image_update_from_raw(
 );
 
 gboolean
-gst_vaapi_convert_buffer_to_image(GstVaapiImage *image, GstBuffer *buffer);
+gst_vaapi_convert_buffer_to_image(
+    GstVaapiImage *image,
+    GstBuffer *buffer,
+    GstVaapiImageFormat in_format);
 
 
 G_END_DECLS
index 7863bf9..3116449 100644 (file)
@@ -396,7 +396,10 @@ 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);