vaapiconvert support multiple YUV colorspace
authorWind Yuan <feng.yuan@intel.com>
Thu, 22 Dec 2011 06:41:42 +0000 (14:41 +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/vaapi/gstvaapiupload.c

index cc0ba02..ba727c8 100644 (file)
@@ -1305,125 +1305,263 @@ gst_vaapi_image_update_from_raw(
     return success;
 }
 
-static gboolean
-_image_convert_to_nv12(
-  guint8 *src,
-  guint32 width,
-  guint32 height,
-  guint32 src_format,
-  guint8 *dest,
-  VAImage *va_image)
+static void
+_yuv411_to_nv12(
+    const guint8 *y_src,
+    guint32 y_src_stride,
+    const guint8 *u_src,
+    guint32 u_src_stride,
+    const guint8 *v_src,
+    guint32 v_src_stride,
+    guint8 *y_dest,
+    guint32 y_dest_stride,
+    guint8 *uv_dest,
+    guint32 uv_dest_stride,
+    guint32 width,
+    guint32 height
+)
 {
-  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 */
-  if (GST_VAAPI_IMAGE_NV12 == src_format
-        || GST_VAAPI_IMAGE_I420 == src_format
-        || GST_VAAPI_IMAGE_YV12 == src_format)
-  {
-     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;
+    guint32 row, column;
+    guint32 uv_height;
 
-      for (row = 0; row < GST_ROUND_UP_2(height)/2; row++) {
+    memcpy_pic(y_dest, y_dest_stride, y_src, y_src_stride, width, height);
+    uv_height = GST_ROUND_UP_2(height)/2;
+    for (row = 0; row < uv_height; row++) {
         for (column = 0; column < width/2; column++) {
-          uv_dest[column*2] = u_src[column];
-          uv_dest[column*2+1] = v_src[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];
-      }
+        u_src += u_src_stride;
+        v_src += v_src_stride;
+        uv_dest += uv_dest_stride;
     }
-    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;
+static void
+_nv12_to_yuv411(
+    const guint8 *y_src,
+    guint32 y_src_stride,
+    const guint8 *uv_src,
+    guint32 uv_src_stride,
+    guint8 *y_dest,
+    guint32 y_dest_stride,
+    guint8 *u_dest,
+    guint32 u_dest_stride,
+    guint8 *v_dest,
+    guint32 v_dest_stride,
+    guint32 width,
+    guint32 height
+)
+{
+    guint32 row, column;
+    guint32 uv_height;
 
-      for (row = 0; row < GST_ROUND_UP_2(height)/2; row++) {
+    memcpy_pic(y_dest, y_dest_stride, y_src, y_src_stride, width, height);
+    uv_height = GST_ROUND_UP_2(height)/2;
+    for (row = 0; row < uv_height; row++) {
         for (column = 0; column < width/2; column++) {
-          uv_dest[column*2] = u_src[column];
-          uv_dest[column*2+1] = v_src[column];
+            u_dest[column] = uv_src[column*2];
+            v_dest[column] = uv_src[column*2+1];
         }
-        u_src += ustride;
-        v_src += vstride;
-        uv_dest += va_image->pitches[1];
-      }
+        uv_src += uv_src_stride;
+        u_dest += u_dest_stride;
+        v_dest += v_dest_stride;
     }
-    break;
-
-    case GST_MAKE_FOURCC('Y', 'U', 'Y', '2'): {
-      const guint8 *y_next_src;
-      guint8 *y_next_dest;
-      ystride = GST_ROUND_UP_2(width)*2;
-      for (row = 0; row < height/2; row++) {
-        y_next_src = y_src + ystride;
-        y_next_dest = y_dest + va_image->pitches[0];
+}
+
+static void
+_yuy2_to_yuv411(
+    const guint8 *yuv_src,
+    guint32 yuv_src_stride,
+    guint8 *y_dest,
+    guint32 y_dest_stride,
+    guint8 *u_dest,
+    guint32 u_dest_stride,
+    guint8 *v_dest,
+    guint32 v_dest_stride,
+    gboolean uv_interlaced,
+    guint32 width,
+    guint32 height
+)
+{
+    guint32 row, column;
+    const guint8 *yuv_next_src;
+    guint8 *y_next_dest;
+    guint32 interval;
+
+    interval = uv_interlaced ? 2 : 1;
+    for (row = 0; row < height/2; row++) {
+        yuv_next_src = yuv_src + yuv_src_stride;
+        y_next_dest = y_dest + y_dest_stride;
         for (column = 0; column < width/2; column++) {
-          y_dest[column*2] = y_src[column*4];
-          y_dest[column*2+1] = y_src[column*4+2];
-          y_next_dest[column*2] = y_next_src[column*4];
-          y_next_dest[column*2+1] = y_next_src[column*4+2];
-          uv_dest[column*2] = (y_src[column*4+1] + y_next_src[column*4+1])>>1;
-          uv_dest[column*2+1] = (y_src[column*4+3] + y_next_src[column*4+3])>>1;
+            y_dest[column*2] = yuv_src[column*4];
+            y_dest[column*2+1] = yuv_src[column*4+2];
+            y_next_dest[column*2] = yuv_next_src[column*4];
+            y_next_dest[column*2+1] = yuv_next_src[column*4+2];
+            u_dest[column*interval] = ((yuv_src[column*4+1] + yuv_next_src[column*4+1])>>1);
+            v_dest[column*interval] = ((yuv_src[column*4+3] + yuv_next_src[column*4+3])>>1);
         }
-        y_src = y_next_src + ystride;
-        y_dest = y_next_dest + va_image->pitches[0];
-        uv_dest += va_image->pitches[1];
-      }
-      /*  odd line */
-      if (height%2) {
-        y_next_dest = y_dest + va_image->pitches[0];
+        yuv_src = yuv_next_src + yuv_src_stride;
+        y_dest = y_next_dest + y_dest_stride;
+        u_dest += u_dest_stride;
+        v_dest += v_dest_stride;
+    }
+
+    /*  odd line */
+    if (height%2) {
         for (column = 0; column < width/2; column++) {
-          y_dest[column*2] = y_src[column*4];
-          y_dest[column*2+1] = y_src[column*4+2];
-          y_next_dest[column*2] = y_src[column*4];
-          y_next_dest[column*2+1] = y_src[column*4+2];
-          uv_dest[column*2] = y_src[column*4+1];
-          uv_dest[column*2+1] = y_src[column*4+3];
+          y_dest[column*2] = yuv_src[column*4];
+          y_dest[column*2+1] = yuv_src[column*4+2];
+          u_dest[column*interval] = yuv_src[column*4+1];
+          v_dest[column*interval] = yuv_src[column*4+3];
         }
-      }
     }
-    break;
 
-    default:
-      return FALSE;
-  }
-  return TRUE;
+}
+
+static gboolean
+_image_convert_to_nv12(
+    const guint8 *src,
+    guint32 width,
+    guint32 height,
+    guint32 src_format,
+    guint8 *y_dest,
+    guint32 y_dest_stride,
+    guint8 *uv_dest,
+    guint32 uv_dest_stride
+)
+{
+    const guint8 *y_src, *u_src, *v_src, *uv_src;
+    guint32 ystride, ustride, vstride, uv_stride;
+
+    switch (src_format) {
+        case GST_MAKE_FOURCC('N','V','1','2'): {
+            y_src = src;
+            ystride = GST_ROUND_UP_4(width);
+            uv_src = src + ystride*GST_ROUND_UP_2(height);
+            uv_stride = ystride;
+            memcpy_pic(y_dest, y_dest_stride, y_src, ystride, width, height);
+            memcpy_pic(uv_dest, uv_dest_stride, uv_src, uv_stride,
+                       width, GST_ROUND_UP_2(height)/2);
+            break;
+        }
+
+        case GST_MAKE_FOURCC('I','4','2','0'): {
+            y_src = src;
+            ystride = GST_ROUND_UP_4(width);
+            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;
+
+            _yuv411_to_nv12(y_src, ystride, u_src, ustride, v_src, vstride,
+                            y_dest, y_dest_stride,
+                            uv_dest, uv_dest_stride,
+                            width, height);
+            break;
+        }
+
+        case GST_MAKE_FOURCC('Y','V','1','2'):{
+            y_src = src;
+            ystride = GST_ROUND_UP_4(width);
+            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;
+
+            _yuv411_to_nv12(y_src, ystride, u_src, ustride, v_src, vstride,
+                            y_dest, y_dest_stride, uv_dest, uv_dest_stride,
+                            width, height);
+            break;
+        }
+
+        case GST_MAKE_FOURCC('Y', 'U', 'Y', '2'): {
+            y_src = src;
+            ystride = GST_ROUND_UP_2(width)*2;
+            _yuy2_to_yuv411(y_src, ystride,
+                            y_dest, y_dest_stride,
+                            uv_dest, uv_dest_stride,
+                            uv_dest+1, uv_dest_stride,
+                            TRUE,
+                            width, height);
+            break;
+        }
+
+        default:
+          return FALSE;
+    }
+    return TRUE;
+}
+
+static gboolean
+_image_convert_to_yuv411(
+    const guint8 *src,
+    guint32 width,
+    guint32 height,
+    guint32 src_format,
+    guint8 *y_dest,
+    guint32 y_dest_stride,
+    guint8 *u_dest,
+    guint32 u_dest_stride,
+    guint8 *v_dest,
+    guint32 v_dest_stride
+)
+{
+    const guint8 *y_src, *u_src, *v_src, *uv_src;
+    guint32 ystride, ustride, vstride, uv_stride;
+
+    switch (src_format) {
+        case GST_MAKE_FOURCC('N','V','1','2'): {
+            y_src = src;
+            ystride = GST_ROUND_UP_4(width);
+            uv_src = src + ystride*GST_ROUND_UP_2(height);
+            uv_stride = ystride;
+            _nv12_to_yuv411(y_src, ystride, uv_src, uv_stride,
+                            y_dest, y_dest_stride,
+                            u_dest, u_dest_stride,
+                            v_dest, v_dest_stride,
+                            width, height);
+            break;
+        }
+
+        case GST_MAKE_FOURCC('I','4','2','0'):
+        case GST_MAKE_FOURCC('Y','V','1','2'):{
+            y_src = src;
+            ystride = GST_ROUND_UP_4(width);
+            if (GST_MAKE_FOURCC('I','4','2','0') == src_format) {
+                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;
+            } else {
+                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;
+            }
+
+            memcpy_pic(y_dest, y_dest_stride, y_src, ystride, width, height);
+            memcpy_pic(u_dest, u_dest_stride, u_src, ustride, width/2, GST_ROUND_UP_2(height)/2);
+            memcpy_pic(v_dest, v_dest_stride, v_src, vstride, width/2, GST_ROUND_UP_2(height)/2);
+            break;
+        }
+
+        case GST_MAKE_FOURCC('Y', 'U', 'Y', '2'): {
+            y_src = src;
+            ystride = GST_ROUND_UP_2(width)*2;
+            _yuy2_to_yuv411(y_src, ystride,
+                            y_dest, y_dest_stride,
+                            u_dest, u_dest_stride,
+                            v_dest, v_dest_stride,
+                            FALSE,
+                            width, height);
+            break;
+        }
+
+        default:
+          return FALSE;
+    }
+    return TRUE;
 }
 
 
@@ -1433,49 +1571,73 @@ gst_vaapi_convert_buffer_to_image(
     GstBuffer *inbuf, // inbuf : I420
     guint32 in_format)
 {
-  GstVaapiImagePrivate *priv;
-  guint width, height;
-  GstVaapiImageFormat image_format;
-  gboolean success = TRUE;
-
-  priv = image->priv;
-  gst_vaapi_image_get_size(image, &width, &height);
-  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
-        && in_format != GST_MAKE_FOURCC('Y', 'U', 'Y', '2'))
-      || (image_format != GST_VAAPI_IMAGE_NV12
-        && image_format != GST_VAAPI_IMAGE_YV12
-        && image_format != GST_VAAPI_IMAGE_I420)
-      )
-  {
-      return FALSE;
-  }
-
-
-  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;
+    GstVaapiImagePrivate *priv;
+    guint width, height;
+    GstVaapiImageFormat image_format;
+    gboolean success = TRUE;
 
-    case GST_VAAPI_IMAGE_I420:
-    case GST_VAAPI_IMAGE_YV12:
-      success = FALSE;
-      break;
+    priv = image->priv;
+    gst_vaapi_image_get_size(image, &width, &height);
+    image_format = gst_vaapi_image_get_format(image);
+
+    /* currently only support YUV convert */
+    if ( (in_format != GST_MAKE_FOURCC('N','V','1','2')
+          && in_format != GST_MAKE_FOURCC('Y','V','1','2')
+          && in_format != GST_MAKE_FOURCC('I','4','2','0')
+          && in_format != GST_MAKE_FOURCC('Y', 'U', 'Y', '2'))
+        || (image_format != GST_VAAPI_IMAGE_NV12
+          && image_format != GST_VAAPI_IMAGE_YV12
+          && image_format != GST_VAAPI_IMAGE_I420)
+        )
+    {
+        return FALSE;
+    }
 
-    default:
-      success = FALSE;
-      break;
-  }
-  gst_vaapi_image_unmap(image);
 
-  return success;
+    gst_vaapi_image_map(image);
+    switch (image_format) {
+      case GST_VAAPI_IMAGE_NV12: {
+          g_assert(priv->image.num_planes == 2);
+          success = _image_convert_to_nv12(GST_BUFFER_DATA(inbuf),
+                                           width, height, in_format,
+                                           priv->image_data+priv->image.offsets[0],
+                                           priv->image.pitches[0],
+                                           priv->image_data+priv->image.offsets[1],
+                                           priv->image.pitches[1]);
+          break;
+      }
+
+      case GST_VAAPI_IMAGE_I420: {
+          g_assert(priv->image.num_planes == 3);
+          success = _image_convert_to_yuv411(GST_BUFFER_DATA(inbuf),
+                                           width, height, in_format,
+                                           priv->image_data+priv->image.offsets[0],
+                                           priv->image.pitches[0],
+                                           priv->image_data+priv->image.offsets[1],
+                                           priv->image.pitches[1],
+                                           priv->image_data+priv->image.offsets[2],
+                                           priv->image.pitches[2]);
+          break;
+      }
+      case GST_VAAPI_IMAGE_YV12:{
+          g_assert(priv->image.num_planes == 3);
+          success = _image_convert_to_yuv411(GST_BUFFER_DATA(inbuf),
+                                           width, height, in_format,
+                                           priv->image_data+priv->image.offsets[0],
+                                           priv->image.pitches[0],
+                                           priv->image_data+priv->image.offsets[2],
+                                           priv->image.pitches[2],
+                                           priv->image_data+priv->image.offsets[1],
+                                           priv->image.pitches[1]);
+          break;
+      }
+
+      default:
+        success = FALSE;
+        break;
+    }
+    gst_vaapi_image_unmap(image);
+
+    return success;
 }
 
index 5a07ba5..420695e 100644 (file)
@@ -33,6 +33,7 @@
 #include <gst/video/video.h>
 #include <gst/video/videocontext.h>
 #include <gst/vaapi/gstvaapivideobuffer.h>
+#include <gst/vaapi/gstvaapidebug.h>
 
 #include "gstvaapiupload.h"
 #include "gstvaapipluginutil.h"