diff options
author | Guenter Bartsch <guenter@users.sourceforge.net> | 2001-07-17 19:37:21 +0000 |
---|---|---|
committer | Guenter Bartsch <guenter@users.sourceforge.net> | 2001-07-17 19:37:21 +0000 |
commit | d433cfadf1ec1a6f042727d3818d86aecd513586 (patch) | |
tree | 47ce7536357ae6544efa5049aa7661a3ce92cb70 /src | |
parent | f071561aa3974d8d7ceba6fdab13668e92f624fd (diff) | |
download | xine-lib-d433cfadf1ec1a6f042727d3818d86aecd513586.tar.gz xine-lib-d433cfadf1ec1a6f042727d3818d86aecd513586.tar.bz2 |
yuy2 -> rgb conversion routines in C (no mlib/mmx yet)
CVS patchset: 299
CVS date: 2001/07/17 19:37:21
Diffstat (limited to 'src')
-rw-r--r-- | src/libw32dll/w32codec.c | 30 | ||||
-rw-r--r-- | src/video_out/video_out_xshm.c | 49 | ||||
-rw-r--r-- | src/video_out/yuv2rgb.c | 429 | ||||
-rw-r--r-- | src/video_out/yuv2rgb.h | 5 |
4 files changed, 471 insertions, 42 deletions
diff --git a/src/libw32dll/w32codec.c b/src/libw32dll/w32codec.c index 44030ce84..5e7b75856 100644 --- a/src/libw32dll/w32codec.c +++ b/src/libw32dll/w32codec.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: w32codec.c,v 1.10 2001/07/14 16:55:11 guenter Exp $ + * $Id: w32codec.c,v 1.11 2001/07/17 19:37:21 guenter Exp $ * * routines for using w32 codecs * @@ -325,21 +325,29 @@ static void w32v_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { img->bFrameBad = 0; if (img->copy) { -#warning: need to check 'dest' stuff for the YUY2 case /* note: dest stuff works with video_out_xshm & YV12 */ int height = abs(this->o_bih.biHeight); int stride = this->o_bih.biWidth; - uint8_t* dest[3]; + uint8_t* src[3]; - dest[0] = img->base[0]; - dest[2] = dest[0] + height * this->o_bih.biWidth; - dest[1] = dest[2] + height * this->o_bih.biWidth / 4; - while ((height -= 16) >= 0) { - img->copy(img, dest); - dest[0] += 16 * stride; - dest[1] += 4 * stride; - dest[2] += 4 * stride; + if (this->outfmt == IMGFMT_YUY2) { + src[0] = img->base[0]; + + while ((height -= 16) >= 0) { + img->copy(img, src); + src[0] += 32 * stride; + } + } else { + src[0] = img->base[0]; + src[2] = src[0] + height * this->o_bih.biWidth; + src[1] = src[2] + height * this->o_bih.biWidth / 4; + while ((height -= 16) >= 0) { + img->copy(img, src); + src[0] += 16 * stride; + src[1] += 4 * stride; + src[2] += 4 * stride; + } } } diff --git a/src/video_out/video_out_xshm.c b/src/video_out/video_out_xshm.c index 4f760eca9..485f4042a 100644 --- a/src/video_out/video_out_xshm.c +++ b/src/video_out/video_out_xshm.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: video_out_xshm.c,v 1.18 2001/07/16 09:18:24 jkeil Exp $ + * $Id: video_out_xshm.c,v 1.19 2001/07/17 19:37:21 guenter Exp $ * * video_out_xshm.c, X11 shared memory extension interface for xine * @@ -71,9 +71,9 @@ typedef struct xshm_frame_s { XImage *image; uint8_t *rgb_dst; int stripe_inc; - int y_off, uv_off; XShmSegmentInfo shminfo; + int format; } xshm_frame_t; typedef struct xshm_driver_s { @@ -320,7 +320,7 @@ static inline uint64_t rdtsc() */ static uint32_t xshm_get_capabilities (vo_driver_t *this_gen) { - return VO_CAP_COPIES_IMAGE | VO_CAP_YV12; + return VO_CAP_COPIES_IMAGE | VO_CAP_YV12 | VO_CAP_YUY2; } static void xshm_frame_copy (vo_frame_t *vo_img, uint8_t **src) { @@ -332,11 +332,15 @@ static void xshm_frame_copy (vo_frame_t *vo_img, uint8_t **src) { uint32_t cycles; #endif - - this->yuv2rgb->yuv2rgb_fun (this->yuv2rgb, frame->rgb_dst, - src[0]+frame->y_off, - src[1]+frame->uv_off, - src[2]+frame->uv_off); + if (frame->format == IMGFMT_YV12) { + this->yuv2rgb->yuv2rgb_fun (this->yuv2rgb, frame->rgb_dst, + src[0], src[1], src[2]); + } else { + + this->yuv2rgb->yuy22rgb_fun (this->yuv2rgb, frame->rgb_dst, + src[0]); + + } #ifdef DETAILED_TIMING cycles = rdtsc() - tsc; @@ -347,7 +351,7 @@ static void xshm_frame_copy (vo_frame_t *vo_img, uint8_t **src) { } static void xshm_frame_field (vo_frame_t *vo_img, int which_field) { - /* FIXME: implement */ + xshm_frame_t *frame = (xshm_frame_t *) vo_img ; xshm_driver_t *this = (xshm_driver_t *) vo_img->instance->driver; @@ -355,8 +359,6 @@ static void xshm_frame_field (vo_frame_t *vo_img, int which_field) { case 1: frame->rgb_dst = frame->image->data; frame->stripe_inc = 2*this->stripe_height * frame->image->bytes_per_line; - frame->y_off = 0; - frame->uv_off = 0; yuv2rgb_setup (this->yuv2rgb, this->delivered_width, 16, @@ -370,8 +372,6 @@ static void xshm_frame_field (vo_frame_t *vo_img, int which_field) { case 2: frame->rgb_dst = frame->image->data + frame->image->bytes_per_line ; frame->stripe_inc = 2*this->stripe_height * frame->image->bytes_per_line; - frame->y_off = 0; /* this->delivered_width; FIXME ?!*/ - frame->uv_off = 0; /* this->delivered_width/2; */ yuv2rgb_setup (this->yuv2rgb, this->delivered_width, 16, @@ -383,8 +383,6 @@ static void xshm_frame_field (vo_frame_t *vo_img, int which_field) { break; case 3: frame->rgb_dst = frame->image->data; - frame->y_off = 0; - frame->uv_off = 0; break; } } @@ -555,7 +553,8 @@ static void xshm_update_frame_format (vo_driver_t *this_gen, || (frame->rgb_height != this->output_height) || (frame->width != width) || (frame->height != height) - || (frame->ratio_code != ratio_code)) { + || (frame->ratio_code != ratio_code) + || (frame->format != format)) { int image_size; @@ -570,7 +569,7 @@ static void xshm_update_frame_format (vo_driver_t *this_gen, /* printf ("video_out_xshm: updating frame to %d x %d\n", this->output_width,this->output_height); - */ + */ XLockDisplay (this->display); @@ -593,11 +592,17 @@ static void xshm_update_frame_format (vo_driver_t *this_gen, XUnlockDisplay (this->display); - image_size = width * height; - frame->vo_frame.base[0] = xmalloc_aligned(16,image_size); - frame->vo_frame.base[1] = xmalloc_aligned(16,image_size/4); - frame->vo_frame.base[2] = xmalloc_aligned(16,image_size/4); - + if (format == IMGFMT_YV12) { + image_size = width * height; + frame->vo_frame.base[0] = xmalloc_aligned(16,image_size); + frame->vo_frame.base[1] = xmalloc_aligned(16,image_size/4); + frame->vo_frame.base[2] = xmalloc_aligned(16,image_size/4); + } else { + image_size = width * height; + frame->vo_frame.base[0] = xmalloc_aligned(16,image_size*2); + } + + frame->format = format; frame->width = width; frame->height = height; diff --git a/src/video_out/yuv2rgb.c b/src/video_out/yuv2rgb.c index 13459459b..9ef123542 100644 --- a/src/video_out/yuv2rgb.c +++ b/src/video_out/yuv2rgb.c @@ -141,6 +141,60 @@ static void scale_line (uint8_t *source, uint8_t *dest, } } + +static void scale_line_2 (uint8_t *source, uint8_t *dest, + int width, int step) { + int p1; + int p2; + int dx; + + p1 = *source; source+=2; + p2 = *source; source+=2; + dx = 0; + + while (width) { + + *dest = (p1 * (32768 - dx) + p2 * dx) / 32768; + + dx += step; + while (dx > 32768) { + dx -= 32768; + p1 = p2; + p2 = *source; + source+=2; + } + + dest ++; + width --; + } +} + +static void scale_line_4 (uint8_t *source, uint8_t *dest, + int width, int step) { + int p1; + int p2; + int dx; + + p1 = *source; source+=4; + p2 = *source; source+=4; + dx = 0; + + while (width) { + + *dest = (p1 * (32768 - dx) + p2 * dx) / 32768; + + dx += step; + while (dx > 32768) { + dx -= 32768; + p1 = p2; + p2 = *source; + source+=4; + } + + dest ++; + width --; + } +} #define RGB(i) \ @@ -151,7 +205,7 @@ static void scale_line (uint8_t *source, uint8_t *dest, b = this->table_bU[U]; #define DST1(i) \ - Y = py_1[2*i]; \ + Y = py_1[2*i]; \ dst_1[2*i] = r[Y] + g[Y] + b[Y]; \ Y = py_1[2*i+1]; \ dst_1[2*i+1] = r[Y] + g[Y] + b[Y]; @@ -695,8 +749,8 @@ static int div_round (int dividend, int divisor) return -((-dividend + (divisor>>1)) / divisor); } -static void yuv2rgb_c_init (yuv2rgb_t *this, int mode) -{ +static void yuv2rgb_setup_tables (yuv2rgb_t *this, int mode) +{ int i; uint8_t table_Y[1024]; uint32_t * table_32 = 0; @@ -721,8 +775,6 @@ static void yuv2rgb_c_init (yuv2rgb_t *this, int mode) switch (mode) { case MODE_32_RGB: case MODE_32_BGR: - this->yuv2rgb_fun = yuv2rgb_c_32; - table_32 = malloc ((197 + 2*682 + 256 + 132) * sizeof (uint32_t)); entry_size = sizeof (uint32_t); @@ -742,8 +794,6 @@ static void yuv2rgb_c_init (yuv2rgb_t *this, int mode) case MODE_24_RGB: case MODE_24_BGR: - this->yuv2rgb_fun = (mode==MODE_24_RGB) ? yuv2rgb_c_24_rgb : yuv2rgb_c_24_bgr; - table_8 = malloc ((256 + 2*232) * sizeof (uint8_t)); entry_size = sizeof (uint8_t); @@ -757,8 +807,6 @@ static void yuv2rgb_c_init (yuv2rgb_t *this, int mode) case MODE_16_BGR: case MODE_15_RGB: case MODE_16_RGB: - this->yuv2rgb_fun = yuv2rgb_c_16; - table_16 = malloc ((197 + 2*682 + 256 + 132) * sizeof (uint16_t)); entry_size = sizeof (uint16_t); @@ -809,6 +857,359 @@ static void yuv2rgb_c_init (yuv2rgb_t *this, int mode) } } +static void yuv2rgb_c_init (yuv2rgb_t *this, int mode) +{ + switch (mode) { + case MODE_32_RGB: + case MODE_32_BGR: + this->yuv2rgb_fun = yuv2rgb_c_32; + break; + + case MODE_24_RGB: + case MODE_24_BGR: + this->yuv2rgb_fun = (mode==MODE_24_RGB) ? yuv2rgb_c_24_rgb : yuv2rgb_c_24_bgr; + break; + + case MODE_15_BGR: + case MODE_16_BGR: + case MODE_15_RGB: + case MODE_16_RGB: + this->yuv2rgb_fun = yuv2rgb_c_16; + break; + + default: + fprintf (stderr, "mode %d not supported by yuv2rgb\n", mode); + exit (1); + } + +} + + +/* + * yuy2 stuff + */ + +static void yuy22rgb_c_32 (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p) +{ + int U, V, Y; + uint8_t * py_1, * pu, * pv; + uint32_t * r, * g, * b; + uint32_t * dst_1; + int width, height; + int dy; + + /* FIXME: implement unscaled version */ + + scale_line_4 (_p+1, this->u_buffer, + this->dest_width >> 1, this->step_dx); + scale_line_4 (_p+3, this->v_buffer, + this->dest_width >> 1, this->step_dx); + scale_line_2 (_p, this->y_buffer, + this->dest_width, this->step_dx); + + dy = 0; + height = this->source_height; + + for (;;) { + dst_1 = (uint32_t*)_dst; + py_1 = this->y_buffer; + pu = this->u_buffer; + pv = this->v_buffer; + + width = this->dest_width >> 3; + + do { + + RGB(0); + DST1(0); + + RGB(1); + DST1(1); + + RGB(2); + DST1(2); + + RGB(3); + DST1(3); + + pu += 4; + pv += 4; + py_1 += 8; + dst_1 += 8; + } while (--width); + + dy += this->step_dy; + _dst += this->rgb_stride; + + while (dy < 32768) { + + memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width*4); + + dy += this->step_dy; + _dst += this->rgb_stride; + } + + if (--height <= 0) + break; + + dy -= 32768; + _p += this->y_stride*2; + + scale_line_4 (_p+1, this->u_buffer, + this->dest_width >> 1, this->step_dx); + scale_line_4 (_p+3, this->v_buffer, + this->dest_width >> 1, this->step_dx); + scale_line_2 (_p, this->y_buffer, + this->dest_width, this->step_dx); + } +} + +static void yuy22rgb_c_24_rgb (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p) +{ + int U, V, Y; + uint8_t * py_1, * pu, * pv; + uint8_t * r, * g, * b; + uint8_t * dst_1; + int width, height; + int dy; + + /* FIXME: implement unscaled version */ + + scale_line_4 (_p+1, this->u_buffer, + this->dest_width >> 1, this->step_dx); + scale_line_4 (_p+3, this->v_buffer, + this->dest_width >> 1, this->step_dx); + scale_line_2 (_p, this->y_buffer, + this->dest_width, this->step_dx); + + dy = 0; + height = this->source_height; + + for (;;) { + dst_1 = _dst; + py_1 = this->y_buffer; + pu = this->u_buffer; + pv = this->v_buffer; + + width = this->dest_width >> 3; + + do { + RGB(0); + DST1RGB(0); + + RGB(1); + DST1RGB(1); + + RGB(2); + DST1RGB(2); + + RGB(3); + DST1RGB(3); + + pu += 4; + pv += 4; + py_1 += 8; + dst_1 += 24; + } while (--width); + + dy += this->step_dy; + _dst += this->rgb_stride; + + while (dy < 32768) { + + memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width*3); + + dy += this->step_dy; + _dst += this->rgb_stride; + } + + if (--height <= 0) + break; + + dy -= 32768; + _p += this->y_stride*2; + + scale_line_4 (_p+1, this->u_buffer, + this->dest_width >> 1, this->step_dx); + scale_line_4 (_p+3, this->v_buffer, + this->dest_width >> 1, this->step_dx); + scale_line_2 (_p, this->y_buffer, + this->dest_width, this->step_dx); + } +} + +static void yuy22rgb_c_24_bgr (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p) +{ + int U, V, Y; + uint8_t * py_1, * pu, * pv; + uint8_t * r, * g, * b; + uint8_t * dst_1; + int width, height; + int dy; + + /* FIXME: implement unscaled version */ + + scale_line_4 (_p+1, this->u_buffer, + this->dest_width >> 1, this->step_dx); + scale_line_4 (_p+3, this->v_buffer, + this->dest_width >> 1, this->step_dx); + scale_line_2 (_p, this->y_buffer, + this->dest_width, this->step_dx); + + dy = 0; + height = this->source_height; + + for (;;) { + dst_1 = _dst; + py_1 = this->y_buffer; + pu = this->u_buffer; + pv = this->v_buffer; + + width = this->dest_width >> 3; + + do { + RGB(0); + DST1BGR(0); + + RGB(1); + DST1BGR(1); + + RGB(2); + DST1BGR(2); + + RGB(3); + DST1BGR(3); + + pu += 4; + pv += 4; + py_1 += 8; + dst_1 += 24; + } while (--width); + + dy += this->step_dy; + _dst += this->rgb_stride; + + while (dy < 32768) { + + memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width*3); + + dy += this->step_dy; + _dst += this->rgb_stride; + } + + if (--height <= 0) + break; + + dy -= 32768; + _p += this->y_stride*2; + + scale_line_4 (_p+1, this->u_buffer, + this->dest_width >> 1, this->step_dx); + scale_line_4 (_p+3, this->v_buffer, + this->dest_width >> 1, this->step_dx); + scale_line_2 (_p, this->y_buffer, + this->dest_width, this->step_dx); + } +} + +static void yuy22rgb_c_16 (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p) +{ + int U, V, Y; + uint8_t * py_1, * pu, * pv; + uint16_t * r, * g, * b; + uint16_t * dst_1; + int width, height; + int dy; + + /* FIXME: implement unscaled version */ + + scale_line_4 (_p+1, this->u_buffer, + this->dest_width >> 1, this->step_dx); + scale_line_4 (_p+3, this->v_buffer, + this->dest_width >> 1, this->step_dx); + scale_line_2 (_p, this->y_buffer, + this->dest_width, this->step_dx); + + dy = 0; + height = this->source_height; + + for (;;) { + dst_1 = (uint16_t*)_dst; + py_1 = this->y_buffer; + pu = this->u_buffer; + pv = this->v_buffer; + + width = this->dest_width >> 3; + + do { + RGB(0); + DST1(0); + + RGB(1); + DST1(1); + + RGB(2); + DST1(2); + + RGB(3); + DST1(3); + + pu += 4; + pv += 4; + py_1 += 8; + dst_1 += 8; + } while (--width); + + dy += this->step_dy; + _dst += this->rgb_stride; + + while (dy < 32768) { + + memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width*2); + + dy += this->step_dy; + _dst += this->rgb_stride; + } + + if (--height <= 0) + break; + + dy -= 32768; + _p += this->y_stride*2; + + scale_line_4 (_p+1, this->u_buffer, + this->dest_width >> 1, this->step_dx); + scale_line_4 (_p+3, this->v_buffer, + this->dest_width >> 1, this->step_dx); + scale_line_2 (_p, this->y_buffer, + this->dest_width, this->step_dx); + } +} + +static void yuy22rgb_c_init (yuv2rgb_t *this, int mode) +{ + switch (mode) { + case MODE_32_RGB: + case MODE_32_BGR: + this->yuy22rgb_fun = yuy22rgb_c_32; + break; + + case MODE_24_RGB: + case MODE_24_BGR: + this->yuv2rgb_fun = (mode==MODE_24_RGB) ? yuy22rgb_c_24_rgb : yuy22rgb_c_24_bgr; + break; + case MODE_15_BGR: + case MODE_16_BGR: + case MODE_15_RGB: + case MODE_16_RGB: + this->yuy22rgb_fun = yuy22rgb_c_16; + break; + + default: + printf ("yuv2rgb: mode %d not supported for yuy2\n", mode); + } +} + yuv2rgb_t *yuv2rgb_init (int mode) { #ifdef ARCH_X86 @@ -823,6 +1224,8 @@ yuv2rgb_t *yuv2rgb_init (int mode) { this->y_chunk = this->u_buffer = NULL; this->y_chunk = this->v_buffer = NULL; + yuv2rgb_setup_tables(this, mode); + /* * auto-probe for the best yuv2rgb function */ @@ -851,5 +1254,13 @@ yuv2rgb_t *yuv2rgb_init (int mode) { printf ("yuv2rgb: no accelerated colorspace conversion found\n"); yuv2rgb_c_init (this, mode); } + + /* + * auto-probe for the best yuy22rgb function + */ + + /* FIXME: implement mmx/mlib functions */ + yuy22rgb_c_init (this, mode); + return this; } diff --git a/src/video_out/yuv2rgb.h b/src/video_out/yuv2rgb.h index 8ff6fbc9c..6e84bd923 100644 --- a/src/video_out/yuv2rgb.h +++ b/src/video_out/yuv2rgb.h @@ -27,6 +27,11 @@ struct yuv2rgb_s { void (*yuv2rgb_fun) (yuv2rgb_t *this, uint8_t * image, uint8_t * py, uint8_t * pu, uint8_t * pv) ; + /* + * this is the function to call for the yuy2->rgb and scaling process + */ + void (*yuy22rgb_fun) (yuv2rgb_t *this, uint8_t * image, uint8_t * p); + /* private stuff below */ uint32_t matrix_coefficients; |