diff options
author | Benjamin Otte <otte@gnome.org> | 2009-09-23 11:25:21 +0200 |
---|---|---|
committer | Benjamin Otte <otte@gnome.org> | 2009-11-02 12:59:54 +0100 |
commit | 679b9029a24cbabba0b25d46efb7a94fcf0f0f53 (patch) | |
tree | c3e88a1ba8eec6ae67746c0dbfbec72495d363f1 | |
parent | b4a073b1bf13dc57af1c97d6d622c780163a5c5c (diff) |
Add NV12 and NV21yuv
-rw-r--r-- | pixman/pixman-access.c | 250 | ||||
-rw-r--r-- | pixman/pixman-bits-image.c | 6 | ||||
-rw-r--r-- | pixman/pixman.c | 5 | ||||
-rw-r--r-- | pixman/pixman.h | 4 |
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), |