Optimize gst_vaapi_image_is_linear() and simplify gst_vaapi_image_update_from_buffer().
authorgb <gb@5584edef-b1fe-4b99-b61b-dd2bab72e969>
Wed, 17 Mar 2010 10:43:02 +0000 (10:43 +0000)
committergb <gb@5584edef-b1fe-4b99-b61b-dd2bab72e969>
Wed, 17 Mar 2010 10:43:02 +0000 (10:43 +0000)
gst-libs/gst/vaapi/gstvaapiimage.c

index 7d9027b..1d793a8 100644 (file)
@@ -36,13 +36,15 @@ G_DEFINE_TYPE(GstVaapiImage, gst_vaapi_image, G_TYPE_OBJECT);
 
 struct _GstVaapiImagePrivate {
     GstVaapiDisplay    *display;
-    gboolean            is_constructed;
+    VAImage             internal_image;
     VAImage             image;
     guchar             *image_data;
     GstVaapiImageFormat internal_format;
     GstVaapiImageFormat format;
     guint               width;
     guint               height;
+    guint               is_constructed  : 1;
+    guint               is_linear       : 1;
 };
 
 enum {
@@ -69,16 +71,17 @@ gst_vaapi_image_destroy(GstVaapiImage *image)
 
     gst_vaapi_image_unmap(image);
 
-    if (priv->image.image_id != VA_INVALID_ID) {
+    if (priv->internal_image.image_id != VA_INVALID_ID) {
         GST_VAAPI_DISPLAY_LOCK(priv->display);
         status = vaDestroyImage(
             GST_VAAPI_DISPLAY_VADISPLAY(priv->display),
-            priv->image.image_id
+            priv->internal_image.image_id
         );
         GST_VAAPI_DISPLAY_UNLOCK(priv->display);
         if (!vaapi_check_status(status, "vaDestroyImage()"))
-            g_warning("failed to destroy image 0x%08x\n", priv->image.image_id);
-        priv->image.image_id = VA_INVALID_ID;
+            g_warning("failed to destroy image 0x%08x\n",
+                      priv->internal_image.image_id);
+        priv->internal_image.image_id = VA_INVALID_ID;
     }
 
     if (priv->display) {
@@ -107,40 +110,93 @@ _gst_vaapi_image_create(GstVaapiImage *image, GstVaapiImageFormat format)
         (VAImageFormat *)va_format,
         priv->width,
         priv->height,
-        &priv->image
+        &priv->internal_image
     );
     GST_VAAPI_DISPLAY_UNLOCK(priv->display);
-    return (status == VA_STATUS_SUCCESS &&
-            priv->image.format.fourcc == va_format->fourcc);
+    if (status != VA_STATUS_SUCCESS ||
+        priv->internal_image.format.fourcc != va_format->fourcc)
+        return FALSE;
+
+    priv->internal_format = format;
+    return TRUE;
 }
 
 static gboolean
-gst_vaapi_image_create(GstVaapiImage *image)
+_gst_vaapi_image_is_linear(GstVaapiImage *image)
 {
     GstVaapiImagePrivate * const priv = image->priv;
+    guint i, width, height, width2, height2, data_size;
 
-    if (_gst_vaapi_image_create(image, priv->format)) {
-        priv->internal_format = priv->format;
-        return TRUE;
-    }
+    for (i = 1; i < priv->image.num_planes; i++)
+        if (priv->image.offsets[i] < priv->image.offsets[i - 1])
+            return FALSE;
+
+    width   = priv->width;
+    height  = priv->height;
+    width2  = (width  + 1) / 2;
+    height2 = (height + 1) / 2;
 
-    switch (priv->format) {
+    switch (priv->internal_format) {
+    case GST_VAAPI_IMAGE_NV12:
+    case GST_VAAPI_IMAGE_YV12:
     case GST_VAAPI_IMAGE_I420:
-        priv->internal_format = GST_VAAPI_IMAGE_YV12;
+        data_size = width * height + 2 * width2 * height2;
         break;
-    case GST_VAAPI_IMAGE_YV12:
-        priv->internal_format = GST_VAAPI_IMAGE_I420;
+    case GST_VAAPI_IMAGE_ARGB:
+    case GST_VAAPI_IMAGE_RGBA:
+    case GST_VAAPI_IMAGE_ABGR:
+    case GST_VAAPI_IMAGE_BGRA:
+        data_size = 4 * width * height;
         break;
     default:
-        priv->internal_format = 0;
+        g_error("FIXME: incomplete formats");
         break;
     }
-    if (!priv->internal_format)
-        return FALSE;
-    if (!_gst_vaapi_image_create(image, priv->internal_format))
-        return FALSE;
+    return priv->image.data_size == data_size;
+}
+
+static gboolean
+gst_vaapi_image_create(GstVaapiImage *image)
+{
+    GstVaapiImagePrivate * const priv = image->priv;
+    GstVaapiImageFormat format = priv->format;
+    const VAImageFormat *va_format;
+
+    if (!_gst_vaapi_image_create(image, format)) {
+        switch (format) {
+        case GST_VAAPI_IMAGE_I420:
+            format = GST_VAAPI_IMAGE_YV12;
+            break;
+        case GST_VAAPI_IMAGE_YV12:
+            format = GST_VAAPI_IMAGE_I420;
+            break;
+        default:
+            format = 0;
+            break;
+        }
+        if (!format || !_gst_vaapi_image_create(image, format))
+            return FALSE;
+    }
+    priv->image = priv->internal_image;
+
+    if (priv->format != priv->internal_format) {
+        switch (priv->format) {
+        case GST_VAAPI_IMAGE_YV12:
+        case GST_VAAPI_IMAGE_I420:
+            va_format = gst_vaapi_image_format_get_va_format(priv->format);
+            if (!va_format)
+                return FALSE;
+            priv->image.format = *va_format;
+            SWAP_UINT(priv->image.offsets[1], priv->image.offsets[2]);
+            SWAP_UINT(priv->image.pitches[1], priv->image.pitches[2]);
+            break;
+        default:
+            break;
+        }
+    }
 
     GST_DEBUG("image 0x%08x", priv->image.image_id);
+    priv->is_linear = _gst_vaapi_image_is_linear(image);
     return TRUE;
 }
 
@@ -290,16 +346,23 @@ gst_vaapi_image_init(GstVaapiImage *image)
 {
     GstVaapiImagePrivate *priv = GST_VAAPI_IMAGE_GET_PRIVATE(image);
 
-    image->priv          = priv;
-    priv->display        = NULL;
-    priv->image_data     = NULL;
-    priv->width          = 0;
-    priv->height         = 0;
-    priv->format         = 0;
+    image->priv                   = priv;
+    priv->display                 = NULL;
+    priv->image_data              = NULL;
+    priv->width                   = 0;
+    priv->height                  = 0;
+    priv->internal_format         = 0;
+    priv->format                  = 0;
+    priv->is_constructed          = FALSE;
+    priv->is_linear               = FALSE;
+
+    memset(&priv->internal_image, 0, sizeof(priv->internal_image));
+    priv->internal_image.image_id = VA_INVALID_ID;
+    priv->internal_image.buf      = VA_INVALID_ID;
 
     memset(&priv->image, 0, sizeof(priv->image));
-    priv->image.image_id = VA_INVALID_ID;
-    priv->image.buf      = VA_INVALID_ID;
+    priv->image.image_id          = VA_INVALID_ID;
+    priv->image.buf               = VA_INVALID_ID;
 }
 
 GstVaapiImage *
@@ -340,20 +403,9 @@ gst_vaapi_image_get_image(GstVaapiImage *image, VAImage *va_image)
     g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
     g_return_val_if_fail(image->priv->is_constructed, FALSE);
 
-    if (!va_image)
-        return TRUE;
-
-    *va_image = image->priv->image;
+    if (va_image)
+        *va_image = image->priv->image;
 
-    if (image->priv->format != image->priv->internal_format) {
-        if (!(image->priv->format == GST_VAAPI_IMAGE_I420 &&
-              image->priv->internal_format == GST_VAAPI_IMAGE_YV12) &&
-            !(image->priv->format == GST_VAAPI_IMAGE_YV12 &&
-              image->priv->internal_format == GST_VAAPI_IMAGE_I420))
-            return FALSE;
-        SWAP_UINT(va_image->offsets[1], va_image->offsets[2]);
-        SWAP_UINT(va_image->pitches[1], va_image->pitches[2]);
-    }
     return TRUE;
 }
 
@@ -409,41 +461,10 @@ gst_vaapi_image_get_size(GstVaapiImage *image, guint *pwidth, guint *pheight)
 gboolean
 gst_vaapi_image_is_linear(GstVaapiImage *image)
 {
-    VAImage va_image;
-    guint i, width, height, width2, height2, data_size;
-
     g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
     g_return_val_if_fail(image->priv->is_constructed, FALSE);
 
-    if (!gst_vaapi_image_get_image(image, &va_image))
-        return FALSE;
-
-    for (i = 1; i < va_image.num_planes; i++)
-        if (va_image.offsets[i] < va_image.offsets[i - 1])
-            return FALSE;
-
-    width   = image->priv->width;
-    height  = image->priv->height;
-    width2  = (width  + 1) / 2;
-    height2 = (height + 1) / 2;
-
-    switch (image->priv->internal_format) {
-    case GST_VAAPI_IMAGE_NV12:
-    case GST_VAAPI_IMAGE_YV12:
-    case GST_VAAPI_IMAGE_I420:
-        data_size = width * height + 2 * width2 * height2;
-        break;
-    case GST_VAAPI_IMAGE_ARGB:
-    case GST_VAAPI_IMAGE_RGBA:
-    case GST_VAAPI_IMAGE_ABGR:
-    case GST_VAAPI_IMAGE_BGRA:
-        data_size = 4 * width * height;
-        break;
-    default:
-        g_error("FIXME: incomplete formats");
-        break;
-    }
-    return va_image.data_size == data_size;
+    return image->priv->is_linear;
 }
 
 static inline gboolean
@@ -564,7 +585,6 @@ gst_vaapi_image_update_from_buffer(GstVaapiImage *image, GstBuffer *buffer)
     guint i, j;
     guchar *data;
     guint32 data_size;
-    gboolean swap_YUV;
 
     g_return_val_if_fail(GST_VAAPI_IS_IMAGE(image), FALSE);
     g_return_val_if_fail(image->priv->is_constructed, FALSE);
@@ -582,12 +602,6 @@ gst_vaapi_image_update_from_buffer(GstVaapiImage *image, GstBuffer *buffer)
     if (format != priv->format)
         return FALSE;
 
-    swap_YUV = (priv->format != priv->internal_format &&
-                ((priv->format == GST_VAAPI_IMAGE_I420 &&
-                  priv->internal_format == GST_VAAPI_IMAGE_YV12) ||
-                 (priv->format == GST_VAAPI_IMAGE_YV12 &&
-                  priv->internal_format == GST_VAAPI_IMAGE_I420)));
-
     structure = gst_caps_get_structure(caps, 0);
     gst_structure_get_int(structure, "width",  &width);
     gst_structure_get_int(structure, "height", &height);
@@ -597,7 +611,7 @@ gst_vaapi_image_update_from_buffer(GstVaapiImage *image, GstBuffer *buffer)
     if (!gst_vaapi_image_map(image))
         return FALSE;
 
-    if (format == priv->internal_format && data_size == priv->image.data_size)
+    if (priv->is_linear && data_size == priv->image.data_size)
         memcpy(priv->image_data, data, data_size);
     else {
         /* XXX: copied from gst_video_format_get_row_stride() -- no NV12? */
@@ -649,20 +663,6 @@ gst_vaapi_image_update_from_buffer(GstVaapiImage *image, GstBuffer *buffer)
         }
         if (size2 != data_size)
             g_error("data_size mismatch %d / %u", size2, data_size);
-        if (swap_YUV) {
-            guint offset = offsets[1];
-            guint stride = pitches[1];
-            guint width  = widths [1];
-            guint height = heights[1];
-            offsets[1]   = offsets[2];
-            pitches[1]   = pitches[2];
-            widths [1]   = widths [2];
-            heights[1]   = heights[2];
-            offsets[2]   = offset;
-            pitches[2]   = stride;
-            widths [2]   = width;
-            heights[2]   = height;
-        }
         for (i = 0; i < priv->image.num_planes; i++) {
             guchar *src = data + offsets[i];
             guchar *dst = priv->image_data + priv->image.offsets[i];