summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Otte <otte@gnome.org>2009-09-23 11:25:21 +0200
committerBenjamin Otte <otte@gnome.org>2009-11-02 12:59:54 +0100
commit679b9029a24cbabba0b25d46efb7a94fcf0f0f53 (patch)
treec3e88a1ba8eec6ae67746c0dbfbec72495d363f1
parentb4a073b1bf13dc57af1c97d6d622c780163a5c5c (diff)
Add NV12 and NV21yuv
-rw-r--r--pixman/pixman-access.c250
-rw-r--r--pixman/pixman-bits-image.c6
-rw-r--r--pixman/pixman.c5
-rw-r--r--pixman/pixman.h4
4 files changed, 263 insertions, 2 deletions
diff --git a/pixman/pixman-access.c b/pixman/pixman-access.c
index 3da5304..5f67257 100644
--- a/pixman/pixman-access.c
+++ b/pixman/pixman-access.c
@@ -1231,6 +1231,64 @@ fetch_scanline_i420 (pixman_image_t *image,
}
}
+static void
+fetch_scanline_nv12 (pixman_image_t *image,
+ int x,
+ int line,
+ int width,
+ uint32_t * buffer,
+ const uint32_t *mask,
+ uint32_t mask_bits)
+{
+ const uint8_t *ybits = (const uint8_t *)
+ (image->bits.bits + image->bits.rowstride * line);
+ const uint8_t *cbits =
+ image->bits.planes[0].bits + image->bits.planes[0].rowstride * (line >> 1);
+ int i;
+
+ for (i = 0; i < width; i++)
+ {
+ int32_t y, u, v, r, g, b;
+
+ y = ybits[ x + i];
+ u = cbits[(x + i) & ~1];
+ v = cbits[(x + i) | 1];
+
+ YUV2RGB_CHROMA (r, g, b, u, v);
+ YUV2RGB_ADD (r, g, b, y);
+ YUV2RGB_STORE (buffer[i], r, g, b);
+ }
+}
+
+static void
+fetch_scanline_nv21 (pixman_image_t *image,
+ int x,
+ int line,
+ int width,
+ uint32_t * buffer,
+ const uint32_t *mask,
+ uint32_t mask_bits)
+{
+ const uint8_t *ybits = (const uint8_t *)
+ (image->bits.bits + image->bits.rowstride * line);
+ const uint8_t *cbits =
+ image->bits.planes[0].bits + image->bits.planes[0].rowstride * (line >> 1);
+ int i;
+
+ for (i = 0; i < width; i++)
+ {
+ int32_t y, u, v, r, g, b;
+
+ y = ybits[ x + i];
+ u = cbits[(x + i) | 1];
+ v = cbits[(x + i) & ~1];
+
+ YUV2RGB_CHROMA (r, g, b, u, v);
+ YUV2RGB_ADD (r, g, b, y);
+ YUV2RGB_STORE (buffer[i], r, g, b);
+ }
+}
+
/**************************** Pixel wise fetching *****************************/
/* Despite the type, expects a uint64_t buffer */
@@ -1970,6 +2028,52 @@ fetch_pixel_i420 (bits_image_t *image,
return pixel;
}
+static uint32_t
+fetch_pixel_nv12 (bits_image_t *image,
+ int offset,
+ int line)
+{
+ const uint8_t *ybits = (const uint8_t *)
+ (image->bits + image->rowstride * line);
+ const uint8_t *cbits =
+ image->planes[0].bits + image->planes[0].rowstride * (line >> 1);
+ int32_t y, u, v, r, g, b;
+ uint32_t pixel;
+
+ y = ybits[offset];
+ u = cbits[offset & ~1];
+ v = cbits[offset | 1];
+
+ YUV2RGB_CHROMA (r, g, b, u, v);
+ YUV2RGB_ADD (r, g, b, y);
+ YUV2RGB_STORE (pixel, r, g, b);
+
+ return pixel;
+}
+
+static uint32_t
+fetch_pixel_nv21 (bits_image_t *image,
+ int offset,
+ int line)
+{
+ const uint8_t *ybits = (const uint8_t *)
+ (image->bits + image->rowstride * line);
+ const uint8_t *cbits =
+ image->planes[0].bits + image->planes[0].rowstride * (line >> 1);
+ int32_t y, u, v, r, g, b;
+ uint32_t pixel;
+
+ y = ybits[offset];
+ u = cbits[offset | 1];
+ v = cbits[offset & ~1];
+
+ YUV2RGB_CHROMA (r, g, b, u, v);
+ YUV2RGB_ADD (r, g, b, y);
+ YUV2RGB_STORE (pixel, r, g, b);
+
+ return pixel;
+}
+
/*********************************** Store ************************************/
#define SPLIT_A(v) \
@@ -3043,6 +3147,150 @@ store_scanline_i420 (bits_image_t * image,
}
}
+static void
+store_scanline_nv12 (bits_image_t * image,
+ int x,
+ int y,
+ int width,
+ const uint32_t *values)
+{
+ uint8_t *ybits = (uint8_t *) (image->bits + image->rowstride * y);
+ uint8_t *cbits = image->planes[0].bits + image->planes[0].rowstride * (y >> 1);
+ int i, end;
+ int32_t u, v;
+
+ end = x + width;
+ u = cbits[x & ~1] * ((x & 1) << 16);
+ v = cbits[x | 1] * ((x & 1) << 16);
+
+ for (i = x; i < end; i++)
+ {
+ SPLIT(values[i - x]);
+
+ ybits[i] = RGB2Y (r, g, b) >> 16;
+ u += RGB2U (r, g, b);
+ v += RGB2V (r, g, b);
+
+ if (i & 1)
+ {
+ /* This is a cheat we use until a better way is figured out:
+ * Set the full chroma values for even rows and update half the
+ * value for odd rows. This way a solid fill gets the proper chroma
+ * values set.
+ */
+ if (y & 1)
+ {
+ cbits[i & ~1] = (u + (cbits[i & ~1] << 17)) >> 18;
+ cbits[i | 1] = (v + (cbits[i | 1] << 17)) >> 18;
+ }
+ else
+ {
+ cbits[i & ~1] = u >> 17;
+ cbits[i | 1] = v >> 17;
+ }
+ u = 0;
+ v = 0;
+ }
+ }
+
+ if (end & 1)
+ {
+ if (image->width == end)
+ {
+ u *= 2;
+ v *= 2;
+ }
+ else
+ {
+ u += cbits[i & ~1] << 16;
+ v += cbits[i | 1] << 16;
+ }
+ /* see reasoning in for loop above */
+ if (y & 1)
+ {
+ cbits[i & ~1] = (u + (cbits[i & ~1] << 17)) >> 18;
+ cbits[i | 1] = (v + (cbits[i | 1] << 17)) >> 18;
+ }
+ else
+ {
+ cbits[i & ~1] = u >> 17;
+ cbits[i | 1] = v >> 17;
+ }
+ }
+}
+
+static void
+store_scanline_nv21 (bits_image_t * image,
+ int x,
+ int y,
+ int width,
+ const uint32_t *values)
+{
+ uint8_t *ybits = (uint8_t *) (image->bits + image->rowstride * y);
+ uint8_t *cbits = image->planes[0].bits + image->planes[0].rowstride * (y >> 1);
+ int i, end;
+ int32_t u, v;
+
+ end = x + width;
+ u = cbits[x | 1] * ((x & 1) << 16);
+ v = cbits[x & ~1] * ((x & 1) << 16);
+
+ for (i = x; i < end; i++)
+ {
+ SPLIT(values[i - x]);
+
+ ybits[i] = RGB2Y (r, g, b) >> 16;
+ u += RGB2U (r, g, b);
+ v += RGB2V (r, g, b);
+
+ if (i & 1)
+ {
+ /* This is a cheat we use until a better way is figured out:
+ * Set the full chroma values for even rows and update half the
+ * value for odd rows. This way a solid fill gets the proper chroma
+ * values set.
+ */
+ if (y & 1)
+ {
+ cbits[i | 1] = (u + (cbits[i | 1] << 17)) >> 18;
+ cbits[i & ~1] = (v + (cbits[i & ~1] << 17)) >> 18;
+ }
+ else
+ {
+ cbits[i | 1] = u >> 17;
+ cbits[i & ~1] = v >> 17;
+ }
+ u = 0;
+ v = 0;
+ }
+ }
+
+ if (end & 1)
+ {
+ if (image->width == end)
+ {
+ u *= 2;
+ v *= 2;
+ }
+ else
+ {
+ u += cbits[i | 1] << 16;
+ v += cbits[i & ~1] << 16;
+ }
+ /* see reasoning in for loop above */
+ if (y & 1)
+ {
+ cbits[i | 1] = (u + (cbits[i | 1] << 17)) >> 18;
+ cbits[i & ~1] = (v + (cbits[i & ~1] << 17)) >> 18;
+ }
+ else
+ {
+ cbits[i | 1] = u >> 17;
+ cbits[i & ~1] = v >> 17;
+ }
+ }
+}
+
#define YVYU_FORMAT(NAME, Y1, Y2, U, V) \
static void \
fetch_scanline_ ## NAME (pixman_image_t *image, \
@@ -3394,6 +3642,8 @@ static const format_info_t accessors[] =
FORMAT_INFO (y42b),
FORMAT_INFO (y41b),
FORMAT_INFO (i420),
+ FORMAT_INFO (nv12),
+ FORMAT_INFO (nv21),
{ PIXMAN_null },
};
diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
index ffb9bdd..8283984 100644
--- a/pixman/pixman-bits-image.c
+++ b/pixman/pixman-bits-image.c
@@ -1054,6 +1054,12 @@ create_bits (bits_image_t *image)
image->planes[1].bits = image->planes[0].bits + (((image->height + 1) >> 1) * image->planes[0].rowstride);
image->planes[1].rowstride = image->planes[0].rowstride;
break;
+ case PIXMAN_nv12:
+ case PIXMAN_nv21:
+ image->bits = do_create_bits (8, (image->width + 7) & ~7, (image->height * 3 + 1) >> 1, &image->rowstride);
+ image->planes[0].bits = (uint8_t *) (image->bits + image->height * image->rowstride);
+ image->planes[0].rowstride = image->rowstride;
+ break;
/* non-planar formats */
case PIXMAN_a2b10g10r10:
case PIXMAN_x2b10g10r10:
diff --git a/pixman/pixman.c b/pixman/pixman.c
index 2cca3a9..608063b 100644
--- a/pixman/pixman.c
+++ b/pixman/pixman.c
@@ -466,6 +466,9 @@ pixman_format_n_planes (pixman_format_code_t format)
case PIXMAN_y42b:
case PIXMAN_i420:
return 3;
+ case PIXMAN_nv12:
+ case PIXMAN_nv21:
+ return 2;
/* 32 bpp formats */
case PIXMAN_a2b10g10r10:
case PIXMAN_x2b10g10r10:
@@ -600,6 +603,8 @@ pixman_format_supported_source (pixman_format_code_t format)
case PIXMAN_y41b:
case PIXMAN_y42b:
case PIXMAN_i420:
+ case PIXMAN_nv12:
+ case PIXMAN_nv21:
return TRUE;
default:
diff --git a/pixman/pixman.h b/pixman/pixman.h
index 958cd6b..5fb5b2c 100644
--- a/pixman/pixman.h
+++ b/pixman/pixman.h
@@ -692,8 +692,8 @@ typedef enum {
/* YUV formats */
PIXMAN_ayuv = PIXMAN_FORMAT(32,PIXMAN_TYPE_YUV_PACKED,8,8,8,8),
PIXMAN_i420 = PIXMAN_FORMAT(32,PIXMAN_TYPE_YUV_PLANAR,0,8,4,0),
-// PIXMAN_nv12 = PIXMAN_FORMAT(32,PIXMAN_TYPE_YUV_PLANAR,0,0,0,0),
-// PIXMAN_nv21 = PIXMAN_FORMAT(32,PIXMAN_TYPE_YUV_PLANAR,0,0,0,0),
+ PIXMAN_nv12 = PIXMAN_FORMAT(32,PIXMAN_TYPE_YUV_PLANAR,0,8,4,1),
+ PIXMAN_nv21 = PIXMAN_FORMAT(32,PIXMAN_TYPE_YUV_PLANAR,0,8,4,2),
// PIXMAN_iyu1 = PIXMAN_FORMAT(32,PIXMAN_TYPE_YUV_PACKED,0,0,0,0),
// PIXMAN_iyu2 = PIXMAN_FORMAT(32,PIXMAN_TYPE_YUV_PACKED,0,0,0,0),
// PIXMAN_v210 = PIXMAN_FORMAT(32,PIXMAN_TYPE_YUV_PACKED,0,0,0,0),