From: Sebastian Dröge Date: Tue, 26 May 2009 13:23:45 +0000 (+0200) Subject: videoscale: Add support for 16 bit grayscale in native endianness X-Git-Tag: RELEASE-0.10.24~222 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=2e5c9465015fabd6baf358194b0463d6a59280eb;p=platform%2Fupstream%2Fgst-plugins-base.git videoscale: Add support for 16 bit grayscale in native endianness --- diff --git a/gst/videoscale/gstvideoscale.c b/gst/videoscale/gstvideoscale.c index bceae21..252d8ae 100644 --- a/gst/videoscale/gstvideoscale.c +++ b/gst/videoscale/gstvideoscale.c @@ -106,6 +106,12 @@ static GstStaticCaps gst_video_scale_format_caps[] = { "bpp = 8, " "depth = 8, " "width = " GST_VIDEO_SIZE_RANGE ", " + "height = " GST_VIDEO_SIZE_RANGE ", " "framerate = " GST_VIDEO_FPS_RANGE), + GST_STATIC_CAPS ("video/x-raw-gray, " + "bpp = 16, " + "depth = 16, " + "endianness = BYTE_ORDER, " + "width = " GST_VIDEO_SIZE_RANGE ", " "height = " GST_VIDEO_SIZE_RANGE ", " "framerate = " GST_VIDEO_FPS_RANGE) }; @@ -131,7 +137,8 @@ enum GST_VIDEO_SCALE_YV12, GST_VIDEO_SCALE_RGB565, GST_VIDEO_SCALE_RGB555, - GST_VIDEO_SCALE_GRAY8 + GST_VIDEO_SCALE_GRAY8, + GST_VIDEO_SCALE_GRAY16 }; #define GST_TYPE_VIDEO_SCALE_METHOD (gst_video_scale_method_get_type()) @@ -445,6 +452,10 @@ gst_video_scale_prepare_size (GstVideoScale * videoscale, gint format, img->stride = GST_ROUND_UP_4 (img->width); *size = img->stride * img->height; break; + case GST_VIDEO_SCALE_GRAY16: + img->stride = GST_ROUND_UP_4 (img->width * 2); + *size = img->stride * img->height; + break; case GST_VIDEO_SCALE_I420: case GST_VIDEO_SCALE_YV12: { @@ -768,6 +779,9 @@ gst_video_scale_transform (GstBaseTransform * trans, GstBuffer * in, case GST_VIDEO_SCALE_GRAY8: vs_image_scale_nearest_Y (dest, src, videoscale->tmp_buf); break; + case GST_VIDEO_SCALE_GRAY16: + vs_image_scale_nearest_Y16 (dest, src, videoscale->tmp_buf); + break; case GST_VIDEO_SCALE_I420: case GST_VIDEO_SCALE_YV12: vs_image_scale_nearest_Y (dest, src, videoscale->tmp_buf); @@ -814,6 +828,9 @@ gst_video_scale_transform (GstBaseTransform * trans, GstBuffer * in, case GST_VIDEO_SCALE_GRAY8: vs_image_scale_linear_Y (dest, src, videoscale->tmp_buf); break; + case GST_VIDEO_SCALE_GRAY16: + vs_image_scale_linear_Y16 (dest, src, videoscale->tmp_buf); + break; case GST_VIDEO_SCALE_I420: case GST_VIDEO_SCALE_YV12: vs_image_scale_linear_Y (dest, src, videoscale->tmp_buf); @@ -860,6 +877,9 @@ gst_video_scale_transform (GstBaseTransform * trans, GstBuffer * in, case GST_VIDEO_SCALE_GRAY8: vs_image_scale_4tap_Y (dest, src, videoscale->tmp_buf); break; + case GST_VIDEO_SCALE_GRAY16: + vs_image_scale_4tap_Y16 (dest, src, videoscale->tmp_buf); + break; case GST_VIDEO_SCALE_I420: case GST_VIDEO_SCALE_YV12: vs_image_scale_4tap_Y (dest, src, videoscale->tmp_buf); diff --git a/gst/videoscale/vs_4tap.c b/gst/videoscale/vs_4tap.c index e5ffef5..c41419a 100644 --- a/gst/videoscale/vs_4tap.c +++ b/gst/videoscale/vs_4tap.c @@ -210,6 +210,123 @@ vs_image_scale_4tap_Y (const VSImage * dest, const VSImage * src, } void +vs_scanline_resample_4tap_Y16 (uint8_t * dest, uint8_t * src, + int n, int src_width, int *xacc, int increment) +{ + int i; + int j; + int acc; + int x; + int y; + uint16_t *d = (uint16_t *) dest, *s = (uint16_t *) src; + + acc = *xacc; + for (i = 0; i < n; i++) { + j = acc >> 16; + x = (acc & 0xff00) >> 8; + if (j - 1 >= 0 && j + 2 < src_width) { + y = vs_4tap_taps[x][0] * s[MAX (j - 1, 0)]; + y += vs_4tap_taps[x][1] * s[j]; + y += vs_4tap_taps[x][2] * s[j + 1]; + y += vs_4tap_taps[x][3] * s[j + 2]; + } else { + y = vs_4tap_taps[x][0] * s[CLAMP (j - 1, 0, src_width - 1)]; + y += vs_4tap_taps[x][1] * s[CLAMP (j, 0, src_width - 1)]; + y += vs_4tap_taps[x][2] * s[CLAMP (j + 1, 0, src_width - 1)]; + y += vs_4tap_taps[x][3] * s[CLAMP (j + 2, 0, src_width - 1)]; + } + y += (1 << (SHIFT - 1)); + d[i] = CLAMP (y >> SHIFT, 0, 65535); + acc += increment; + } + *xacc = acc; +} + +void +vs_scanline_merge_4tap_Y16 (uint8_t * dest, uint8_t * src1, uint8_t * src2, + uint8_t * src3, uint8_t * src4, int n, int acc) +{ + int i; + int y; + int a, b, c, d; + uint16_t *de = (uint16_t *) dest, *s1 = (uint16_t *) src1; + uint16_t *s2 = (uint16_t *) src2, *s3 = (uint16_t *) src3; + uint16_t *s4 = (uint16_t *) src4; + + acc = (acc >> 8) & 0xff; + a = vs_4tap_taps[acc][0]; + b = vs_4tap_taps[acc][1]; + c = vs_4tap_taps[acc][2]; + d = vs_4tap_taps[acc][3]; + for (i = 0; i < n; i++) { + y = a * s1[i]; + y += b * s2[i]; + y += c * s3[i]; + y += d * s4[i]; + y += (1 << (SHIFT - 1)); + de[i] = CLAMP (y >> SHIFT, 0, 65535); + } +} + + +void +vs_image_scale_4tap_Y16 (const VSImage * dest, const VSImage * src, + uint8_t * tmpbuf) +{ + int yacc; + int y_increment; + int x_increment; + int i; + int j; + int xacc; + int k; + + if (dest->height == 1) + y_increment = 0; + else + y_increment = ((src->height - 1) << 16) / (dest->height - 1); + + if (dest->width == 1) + x_increment = 0; + else + x_increment = ((src->width - 1) << 16) / (dest->width - 1); + + k = 0; + for (i = 0; i < 4; i++) { + xacc = 0; + vs_scanline_resample_4tap_Y16 (tmpbuf + i * dest->stride, + src->pixels + i * src->stride, dest->width, src->width, + &xacc, x_increment); + } + + yacc = 0; + for (i = 0; i < dest->height; i++) { + uint8_t *t0, *t1, *t2, *t3; + + j = yacc >> 16; + + while (j > k) { + k++; + if (k + 3 < src->height) { + xacc = 0; + vs_scanline_resample_4tap_Y16 (tmpbuf + ((k + 3) & 3) * dest->stride, + src->pixels + (k + 3) * src->stride, + dest->width, src->width, &xacc, x_increment); + } + } + + t0 = tmpbuf + (CLAMP (j - 1, 0, src->height - 1) & 3) * dest->stride; + t1 = tmpbuf + (CLAMP (j, 0, src->height - 1) & 3) * dest->stride; + t2 = tmpbuf + (CLAMP (j + 1, 0, src->height - 1) & 3) * dest->stride; + t3 = tmpbuf + (CLAMP (j + 2, 0, src->height - 1) & 3) * dest->stride; + vs_scanline_merge_4tap_Y16 (dest->pixels + i * dest->stride, + t0, t1, t2, t3, dest->width, yacc & 0xffff); + + yacc += y_increment; + } +} + +void vs_scanline_resample_4tap_RGBA (uint8_t * dest, uint8_t * src, int n, int src_width, int *xacc, int increment) { diff --git a/gst/videoscale/vs_4tap.h b/gst/videoscale/vs_4tap.h index fd370f1..3b13662 100644 --- a/gst/videoscale/vs_4tap.h +++ b/gst/videoscale/vs_4tap.h @@ -82,5 +82,12 @@ void vs_scanline_merge_4tap_RGB555 (uint8_t *dest, uint8_t *src1, uint8_t *src2, void vs_image_scale_4tap_RGB555 (const VSImage * dest, const VSImage * src, uint8_t * tmpbuf); +void vs_scanline_resample_4tap_Y16 (uint8_t *dest, uint8_t *src, + int n, int src_width, int *xacc, int increment); +void vs_scanline_merge_4tap_Y16 (uint8_t *dest, uint8_t *src1, uint8_t *src2, + uint8_t *src3, uint8_t *src4, int n, int acc); +void vs_image_scale_4tap_Y16 (const VSImage * dest, const VSImage * src, + uint8_t * tmpbuf); + #endif diff --git a/gst/videoscale/vs_image.c b/gst/videoscale/vs_image.c index 5840183..4991d73 100644 --- a/gst/videoscale/vs_image.c +++ b/gst/videoscale/vs_image.c @@ -692,6 +692,136 @@ vs_image_scale_linear_Y (const VSImage * dest, const VSImage * src, } } +void +vs_image_scale_nearest_Y16 (const VSImage * dest, const VSImage * src, + uint8_t * tmpbuf) +{ + int acc; + int y_increment; + int x_increment; + int i; + int j; + int x; + int xacc; + + if (dest->height == 1) + y_increment = 0; + else + y_increment = ((src->height - 1) << 16) / (dest->height - 1); + + if (dest->width == 1) + x_increment = 0; + else + x_increment = ((src->width - 1) << 16) / (dest->width - 1); + + acc = 0; + for (i = 0; i < dest->height; i++) { + j = acc >> 16; + x = acc & 0xffff; + + xacc = 0; + vs_scanline_resample_nearest_Y16 (dest->pixels + i * dest->stride, + src->pixels + j * src->stride, src->width, dest->width, &xacc, + x_increment); + + acc += y_increment; + } +} + +void +vs_image_scale_linear_Y16 (const VSImage * dest, const VSImage * src, + uint8_t * tmpbuf) +{ + int acc; + int y_increment; + int x_increment; + uint8_t *tmp1; + uint8_t *tmp2; + int y1; + int y2; + int i; + int j; + int x; + int dest_size; + int xacc; + + if (dest->height == 1) + y_increment = 0; + else + y_increment = ((src->height - 1) << 16) / (dest->height - 1); + + if (dest->width == 1) + x_increment = 0; + else + x_increment = ((src->width - 1) << 16) / (dest->width - 1); + + dest_size = 2 * dest->width; + + tmp1 = tmpbuf; + tmp2 = tmpbuf + dest_size; + + acc = 0; + xacc = 0; + y2 = -1; + vs_scanline_resample_linear_Y16 (tmp1, src->pixels, src->width, dest->width, + &xacc, x_increment); + y1 = 0; + for (i = 0; i < dest->height; i++) { + j = acc >> 16; + x = acc & 0xffff; + + if (x == 0) { + if (j == y1) { + memcpy (dest->pixels + i * dest->stride, tmp1, dest_size); + } else if (j == y2) { + memcpy (dest->pixels + i * dest->stride, tmp2, dest_size); + } else { + xacc = 0; + vs_scanline_resample_linear_Y16 (tmp1, src->pixels + j * src->stride, + src->width, dest->width, &xacc, x_increment); + y1 = j; + memcpy (dest->pixels + i * dest->stride, tmp1, dest_size); + } + } else { + if (j == y1) { + if (j + 1 != y2) { + xacc = 0; + vs_scanline_resample_linear_Y16 (tmp2, + src->pixels + (j + 1) * src->stride, src->width, dest->width, + &xacc, x_increment); + y2 = j + 1; + } + vs_scanline_merge_linear_Y16 (dest->pixels + i * dest->stride, + tmp1, tmp2, dest->width, x); + } else if (j == y2) { + if (j + 1 != y1) { + xacc = 0; + vs_scanline_resample_linear_Y16 (tmp1, + src->pixels + (j + 1) * src->stride, src->width, dest->width, + &xacc, x_increment); + y1 = j + 1; + } + vs_scanline_merge_linear_Y16 (dest->pixels + i * dest->stride, + tmp2, tmp1, dest->width, x); + } else { + xacc = 0; + vs_scanline_resample_linear_Y16 (tmp1, src->pixels + j * src->stride, + src->width, dest->width, &xacc, x_increment); + y1 = j; + xacc = 0; + vs_scanline_resample_linear_Y16 (tmp2, + src->pixels + (j + 1) * src->stride, src->width, dest->width, &xacc, + x_increment); + y2 = (j + 1); + vs_scanline_merge_linear_Y16 (dest->pixels + i * dest->stride, + tmp1, tmp2, dest->width, x); + } + } + + acc += y_increment; + } +} + /* RGB565 */ void diff --git a/gst/videoscale/vs_image.h b/gst/videoscale/vs_image.h index ba912f9..9771c77 100644 --- a/gst/videoscale/vs_image.h +++ b/gst/videoscale/vs_image.h @@ -74,5 +74,10 @@ void vs_image_scale_nearest_RGB555 (const VSImage *dest, const VSImage *src, void vs_image_scale_linear_RGB555 (const VSImage *dest, const VSImage *src, uint8_t *tmpbuf); +void vs_image_scale_nearest_Y16 (const VSImage *dest, const VSImage *src, + uint8_t *tmpbuf); +void vs_image_scale_linear_Y16 (const VSImage *dest, const VSImage *src, + uint8_t *tmpbuf); + #endif diff --git a/gst/videoscale/vs_scanline.c b/gst/videoscale/vs_scanline.c index 7cebef5..d524e73 100644 --- a/gst/videoscale/vs_scanline.c +++ b/gst/videoscale/vs_scanline.c @@ -95,6 +95,76 @@ vs_scanline_merge_linear_Y (uint8_t * dest, uint8_t * src1, uint8_t * src2, oil_merge_linear_u8 (dest, src1, src2, &value, n); } +void +vs_scanline_downsample_Y16 (uint8_t * dest, uint8_t * src, int n) +{ + int i; + uint16_t *d = (uint16_t *) dest, *s = (uint16_t *) src; + + for (i = 0; i < n; i++) { + d[i] = (s[i * 2] + s[i * 2 + 1]) / 2; + } +} + +void +vs_scanline_resample_nearest_Y16 (uint8_t * dest, uint8_t * src, int src_width, + int n, int *accumulator, int increment) +{ + int acc = *accumulator; + int i; + int j; + int x; + uint16_t *d = (uint16_t *) dest, *s = (uint16_t *) src; + + for (i = 0; i < n; i++) { + j = acc >> 16; + x = acc & 0xffff; + d[i] = (x < 32768 || j + 1 >= src_width) ? s[j] : s[j + 1]; + + acc += increment; + } + + *accumulator = acc; +} + +#include +void +vs_scanline_resample_linear_Y16 (uint8_t * dest, uint8_t * src, int src_width, + int n, int *accumulator, int increment) +{ + int acc = *accumulator; + int i; + int j; + int x; + uint16_t *d = (uint16_t *) dest, *s = (uint16_t *) src; + + for (i = 0; i < n; i++) { + j = acc >> 16; + x = acc & 0xffff; + + if (j + 1 < src_width) + d[i] = (s[j] * (65536 - x) + s[j + 1] * x) >> 16; + else + d[i] = s[j]; + + acc += increment; + } + + *accumulator = acc; +} + +void +vs_scanline_merge_linear_Y16 (uint8_t * dest, uint8_t * src1, uint8_t * src2, + int n, int x) +{ + int i; + uint16_t *d = (uint16_t *) dest, *s1 = (uint16_t *) src1, *s2 = + (uint16_t *) src2; + + for (i = 0; i < n; i++) { + d[i] = (s1[i] * (65536 - x) + s2[i] * x) >> 16; + } +} /* RGBA */ diff --git a/gst/videoscale/vs_scanline.h b/gst/videoscale/vs_scanline.h index 655a17d..2e0b179 100644 --- a/gst/videoscale/vs_scanline.h +++ b/gst/videoscale/vs_scanline.h @@ -65,6 +65,10 @@ void vs_scanline_resample_nearest_RGB555 (uint8_t *dest, uint8_t *src, int src_w void vs_scanline_resample_linear_RGB555 (uint8_t *dest, uint8_t *src, int src_width, int n, int *accumulator, int increment); void vs_scanline_merge_linear_RGB555 (uint8_t *dest, uint8_t *src1, uint8_t *src2, int n, int x); +void vs_scanline_downsample_Y16 (uint8_t *dest, uint8_t *src, int n); +void vs_scanline_resample_nearest_Y16 (uint8_t *dest, uint8_t *src, int n, int src_width, int *accumulator, int increment); +void vs_scanline_resample_linear_Y16 (uint8_t *dest, uint8_t *src, int n, int src_width, int *accumulator, int increment); +void vs_scanline_merge_linear_Y16 (uint8_t *dest, uint8_t *src1, uint8_t *src2, int n, int x); #endif