From 2faf51032f01e3c62bc07cdd3ba2d4073642510d Mon Sep 17 00:00:00 2001 From: Vincent Seguin Date: Mon, 17 Jan 2000 16:43:04 +0000 Subject: [PATCH] =?UTF-8?q?Nettoyage,=20ajout=20du=20gamma,=20pr=EF=BF=BDp?= =?UTF-8?q?aration=20de=20la=20yuv=20walken.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 5 +- include/config.h | 8 + include/video.h | 2 +- include/video_output.h | 25 +- include/video_sys.h | 2 +- src/video_output/video_ggi.c | 2 +- src/video_output/video_output.c | 352 ++++---- src/video_output/video_x11.c | 6 +- src/video_output/video_yuv_c.c | 837 ++++++++++++++++++ .../{yuv_mmx.S => video_yuv_mmx.S} | 2 +- 10 files changed, 1043 insertions(+), 198 deletions(-) create mode 100644 src/video_output/video_yuv_c.c rename src/video_output/{yuv_mmx.S => video_yuv_mmx.S} (99%) diff --git a/Makefile b/Makefile index 0164579c24..ea5907f08f 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,7 @@ VIDEO=X11 # Target architecture and optimization #ARCH= -ARCH=MMX +#ARCH=MMX #ARCH=PPC # Decoder choice - ?? old decoder will be removed soon @@ -64,6 +64,7 @@ endif # Libraries # LIB += -lpthread +LIB += -lm ifeq ($(VIDEO),X11) LIB += -L/usr/X11R6/lib @@ -211,7 +212,7 @@ misc_obj = misc/mtime.o \ ifeq ($(ARCH),MMX) ASM_OBJ = video_decoder_ref/idctmmx.o \ - video_output/yuv_mmx.o + video_output/video_yuv_mmx.o endif C_OBJ = $(interface_obj) \ diff --git a/include/config.h b/include/config.h index 7160bbd089..5779c166a7 100644 --- a/include/config.h +++ b/include/config.h @@ -119,6 +119,11 @@ /* Base delay in micro second for interface sleeps */ #define INTF_IDLE_SLEEP 100000 +/* Factor for changing gamma, and minimum and maximum values */ +#define INTF_GAMMA_FACTOR 1.1 +#define INTF_GAMMA_MIN 0.1 +#define INTF_GAMMA_MAX 10 + /* * X11 settings */ @@ -241,6 +246,9 @@ #define VOUT_GRAYSCALE_VAR "vlc_grayscale" #define VOUT_GRAYSCALE_DEFAULT 0 +/* Default gamma */ +#define VOUT_GAMMA 1. + /* * Time settings */ diff --git a/include/video.h b/include/video.h index e1cdc88116..7e056168dd 100644 --- a/include/video.h +++ b/include/video.h @@ -57,7 +57,7 @@ typedef struct * (the pointer) should NEVER be modified. In YUV format, the p_y, p_u and * p_v data pointers refers to different areas of p_data, and should not * be freed */ - byte_t * p_data; /* picture data */ + void * p_data; /* picture data */ yuv_data_t * p_y; /* pointer to beginning of Y image in p_data */ yuv_data_t * p_u; /* pointer to beginning of U image in p_data */ yuv_data_t * p_v; /* pointer to beginning of V image in p_data */ diff --git a/include/video_output.h b/include/video_output.h index 1599ef75c2..e01c4cbde0 100644 --- a/include/video_output.h +++ b/include/video_output.h @@ -34,9 +34,11 @@ typedef struct vout_thread_s int i_bytes_per_pixel; /* real screen depth */ float f_x_ratio; /* horizontal display ratio */ float f_y_ratio; /* vertical display ratio */ + float f_gamma; /* gamma */ - /* New size for resizeable windows - they may be ignored or handled by - * vout_SysManage */ + /* Changed properties values - some of them are treated directly by the + * thread, the over may be ignored or handled by vout_SysManage */ + boolean_t b_gamma_change; /* gamma change indicator */ int i_new_width; /* new width */ int i_new_height; /* new height */ @@ -59,15 +61,16 @@ typedef struct vout_thread_s /* Video heap */ picture_t p_picture[VOUT_MAX_PICTURES]; /* pictures */ - /* YUV translation tables, for 15,16 and 24/32 bpp displays. 16 bits and 32 - * bits pointers points on the same data. - * CAUTION: these tables are translated: their origin is -384 */ - u16 * pi_trans16_red; - u16 * pi_trans16_green; - u16 * pi_trans16_blue; - u32 * pi_trans32_red; - u32 * pi_trans32_green; - u32 * pi_trans32_blue; + /* YUV translation tables - they have to be casted to the appropriate width + * on use. All tables are allocated in the same memory block, based at + * p_trans_base, and shifted depending of the output thread configuration */ + byte_t * p_trans_base; /* base for all translation tables */ + void * p_trans_red; + void * p_trans_green; + void * p_trans_blue; + void * p_trans_gray; + + /* YUV translation tables, for optimized C YUV transform ?? */ } vout_thread_t; /******************************************************************************* diff --git a/include/video_sys.h b/include/video_sys.h index 090390c7d0..1807f5c20f 100644 --- a/include/video_sys.h +++ b/include/video_sys.h @@ -16,7 +16,7 @@ void vout_SysEnd ( p_vout_thread_t p_vout ); void vout_SysDestroy ( p_vout_thread_t p_vout ); int vout_SysManage ( p_vout_thread_t p_vout ); void vout_SysDisplay ( p_vout_thread_t p_vout ); -byte_t * vout_SysGetPicture ( p_vout_thread_t p_vout ); +void * vout_SysGetPicture ( p_vout_thread_t p_vout ); void vout_SysPrint ( p_vout_thread_t p_vout, int i_x, int i_y, int i_halign, int i_valign, unsigned char *psz_text ); diff --git a/src/video_output/video_ggi.c b/src/video_output/video_ggi.c index e4205b4a8d..2f90586e56 100644 --- a/src/video_output/video_ggi.c +++ b/src/video_output/video_ggi.c @@ -166,7 +166,7 @@ void vout_SysDisplay( vout_thread_t *p_vout ) ******************************************************************************* * This function returns the address of the current display buffer. *******************************************************************************/ -byte_t * vout_SysGetPicture( vout_thread_t *p_vout ) +void * vout_SysGetPicture( vout_thread_t *p_vout ) { return( p_vout->p_sys->p_buffer[ p_vout->p_sys->i_buffer_index ]->write ); } diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c index 6e37473173..95562ff30c 100644 --- a/src/video_output/video_output.c +++ b/src/video_output/video_output.c @@ -10,7 +10,8 @@ /******************************************************************************* * Preamble *******************************************************************************/ -#include +#include +#include #include #include #include @@ -43,14 +44,29 @@ * not change much for two different loops. This macro allows to change slightly * the content of the loop without having to copy and paste code. It is used in * RenderYUVPicture function. */ -#define YUV_GRAYSCALE( TRANS_RED, TRANS_GREEN, TRANS_BLUE, P_PIC ) \ +#define YUV_GRAYSCALE( TRANS_GRAY, P_PIC ) \ /* Main loop */ \ for (i_pic_y=0; i_pic_y < p_pic->i_height ; i_pic_y++) \ { \ - for (i_pic_x=0; i_pic_x< p_pic->i_width; i_pic_x++) \ + for (i_pic_x=0; i_pic_x< p_pic->i_width; i_pic_x+=16) \ { \ - i_y = *p_y++; \ - *P_PIC++ = TRANS_RED[i_y] | TRANS_GREEN[i_y] | TRANS_BLUE[i_y]; \ + /* Convert 16 pixels (width is always multiple of 16 */ \ + *P_PIC++ = TRANS_GRAY[ *p_y++ ]; \ + *P_PIC++ = TRANS_GRAY[ *p_y++ ]; \ + *P_PIC++ = TRANS_GRAY[ *p_y++ ]; \ + *P_PIC++ = TRANS_GRAY[ *p_y++ ]; \ + *P_PIC++ = TRANS_GRAY[ *p_y++ ]; \ + *P_PIC++ = TRANS_GRAY[ *p_y++ ]; \ + *P_PIC++ = TRANS_GRAY[ *p_y++ ]; \ + *P_PIC++ = TRANS_GRAY[ *p_y++ ]; \ + *P_PIC++ = TRANS_GRAY[ *p_y++ ]; \ + *P_PIC++ = TRANS_GRAY[ *p_y++ ]; \ + *P_PIC++ = TRANS_GRAY[ *p_y++ ]; \ + *P_PIC++ = TRANS_GRAY[ *p_y++ ]; \ + *P_PIC++ = TRANS_GRAY[ *p_y++ ]; \ + *P_PIC++ = TRANS_GRAY[ *p_y++ ]; \ + *P_PIC++ = TRANS_GRAY[ *p_y++ ]; \ + *P_PIC++ = TRANS_GRAY[ *p_y++ ]; \ } \ /* Skip until beginning of next line */ \ P_PIC += i_eol_offset; \ @@ -66,7 +82,7 @@ for (i_pic_y=0; i_pic_y < p_pic->i_height ; i_pic_y++) \ /* Main loop */ \ for (i_pic_y=0; i_pic_y < p_pic->i_height ; i_pic_y++) \ { \ - for (i_pic_x=0; i_pic_x< p_pic->i_width; i_pic_x+=2) \ + for (i_pic_x=0; i_pic_x< p_pic->i_width; i_pic_x+=2 ) \ { \ /* First sample (complete) */ \ i_y = 76309 * *p_y++ - 1188177; \ @@ -123,7 +139,7 @@ const int MATRIX_COEFFICIENTS_TABLE[8][4] = * i_width, i_height: frames dimensions (pixels) * i_ypitch, i_vpitch: Y and V lines sizes (bytes) * i_aspect: vertical aspect factor - * pi_pic: RGB frame + * p_pic: RGB frame * i_dci_offset: ?? x offset for left image border * i_offset_to_line_0: ?? x offset for left image border * i_pitch: RGB line size (bytes) @@ -131,7 +147,7 @@ const int MATRIX_COEFFICIENTS_TABLE[8][4] = void vout_YUV420_16_MMX( u8* p_y, u8* p_u, u8 *p_v, unsigned int i_width, unsigned int i_height, unsigned int i_ypitch, unsigned int i_vpitch, - unsigned int i_aspect, u8 *pi_pic, + unsigned int i_aspect, u8 *p_pic, u32 i_dci_offset, u32 i_offset_to_line_0, int CCOPitch, int i_colortype ); #endif @@ -143,6 +159,7 @@ static int InitThread ( vout_thread_t *p_vout ); static void RunThread ( vout_thread_t *p_vout ); static void ErrorThread ( vout_thread_t *p_vout ); static void EndThread ( vout_thread_t *p_vout ); +static void BuildTables ( vout_thread_t *p_vout ); static void RenderPicture ( vout_thread_t *p_vout, picture_t *p_pic ); static void RenderYUVGrayPicture ( vout_thread_t *p_vout, picture_t *p_pic ); static void RenderYUV16Picture ( vout_thread_t *p_vout, picture_t *p_pic ); @@ -192,6 +209,7 @@ vout_thread_t * vout_CreateThread ( p_vout->i_bytes_per_pixel = 2; p_vout->f_x_ratio = 1; p_vout->f_y_ratio = 1; + p_vout->f_gamma = VOUT_GAMMA; intf_DbgMsg("wished configuration: %dx%d,%d (%d bytes/pixel, %d bytes/line), ratio %.2f:%.2f, gray=%d\n", p_vout->i_width, p_vout->i_height, p_vout->i_screen_depth, p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line, @@ -224,6 +242,9 @@ vout_thread_t * vout_CreateThread ( p_vout->c_idle_loops = 0; p_vout->c_fps_samples = 0; #endif + p_vout->b_gamma_change = 0; + p_vout->i_new_width = p_vout->i_width; + p_vout->i_new_height = p_vout->i_height; /* Create thread and set locks */ vlc_mutex_init( &p_vout->lock ); @@ -516,7 +537,6 @@ void vout_UnlinkPicture( vout_thread_t *p_vout, picture_t *p_pic ) static int InitThread( vout_thread_t *p_vout ) { int i_index; /* generic index */ - int i_pixel_size; /* pixel size, in bytes, for translations tables */ /* Update status */ *p_vout->pi_status = THREAD_START; @@ -536,94 +556,19 @@ static int InitThread( vout_thread_t *p_vout ) } /* Allocate translation tables */ - switch( p_vout->i_bytes_per_pixel ) + p_vout->p_trans_base = malloc( 4 * 1024 * p_vout->i_bytes_per_pixel ); + if( p_vout->p_trans_base == NULL ) { - case 2: /* 15 or 16 bpp, use 16 bits translations tables */ - i_pixel_size = sizeof( u16 ); - break; - case 3: /* 24 or 32 bpp, use 32 bits translations tables */ - case 4: -#ifndef DEBUG - default: -#endif - i_pixel_size = sizeof( u32 ); - break; -#ifdef DEBUG - default: - intf_DbgMsg("error: invalid bytes_per_pixel %d\n", p_vout->i_bytes_per_pixel ); - i_pixel_size = sizeof( u32 ); - break; -#endif + intf_ErrMsg("error: %s\n", strerror(ENOMEM)); + return( 1 ); } - p_vout->pi_trans32_red = (u32 *)p_vout->pi_trans16_red = - (u16 *)malloc( 1024 * i_pixel_size ); - p_vout->pi_trans32_green = (u32 *)p_vout->pi_trans16_green = - (u16 *)malloc( 1024 * i_pixel_size ); - p_vout->pi_trans32_blue = (u32 *)p_vout->pi_trans16_blue = - (u16 *)malloc( 1024 * i_pixel_size ); - if( (p_vout->pi_trans16_red == NULL) || - (p_vout->pi_trans16_green == NULL ) || - (p_vout->pi_trans16_blue == NULL ) ) - { - intf_ErrMsg("error: %s\n", strerror(ENOMEM) ); - *p_vout->pi_status = THREAD_ERROR; - if( p_vout->pi_trans16_red != NULL ) - { - free( p_vout->pi_trans16_red ); - } - if( p_vout->pi_trans16_green != NULL ) - { - free( p_vout->pi_trans16_green ); - } - if( p_vout->pi_trans16_blue != NULL ) - { - free( p_vout->pi_trans16_blue ); - } - return( 1 ); - } + p_vout->p_trans_red = p_vout->p_trans_base + 384 *p_vout->i_bytes_per_pixel; + p_vout->p_trans_green = p_vout->p_trans_base + ( 1024 + 384)*p_vout->i_bytes_per_pixel; + p_vout->p_trans_blue = p_vout->p_trans_base + (2*1024 + 384)*p_vout->i_bytes_per_pixel; + p_vout->p_trans_gray = p_vout->p_trans_base + (3*1024 + 384)*p_vout->i_bytes_per_pixel; - /* Translate translation tables */ - p_vout->pi_trans16_red += 384; - p_vout->pi_trans16_green += 384; - p_vout->pi_trans16_blue += 384; - p_vout->pi_trans32_red += 384; - p_vout->pi_trans32_green += 384; - p_vout->pi_trans32_blue += 384; - /* Build translation tables */ - switch( p_vout->i_screen_depth ) - { - case 15: - for( i_index = -384; i_index < 640; i_index++) - { - p_vout->pi_trans16_red[i_index] = (CLIP_BYTE( i_index ) & 0xf8)<<7; - p_vout->pi_trans16_green[i_index] = (CLIP_BYTE( i_index ) & 0xf8)<<2; - p_vout->pi_trans16_blue[i_index] = CLIP_BYTE( i_index ) >> 3; - } - break; - case 16: - for( i_index = -384; i_index < 640; i_index++) - { - p_vout->pi_trans16_red[i_index] = (CLIP_BYTE( i_index ) & 0xf8)<<8; - p_vout->pi_trans16_green[i_index] = (CLIP_BYTE( i_index ) & 0xfc)<<3; - p_vout->pi_trans16_blue[i_index] = CLIP_BYTE( i_index ) >> 3; - } - break; - case 24: - case 32: - for( i_index = -384; i_index < 640; i_index++) - { - p_vout->pi_trans32_red[i_index] = CLIP_BYTE( i_index ) <<16; - p_vout->pi_trans32_green[i_index] = CLIP_BYTE( i_index ) <<8; - p_vout->pi_trans32_blue[i_index] = CLIP_BYTE( i_index ) ; - } - break; -#ifdef DEBUG - default: - intf_DbgMsg("error: invalid screen depth %d\n", p_vout->i_screen_depth ); - break; -#endif - } + BuildTables( p_vout ); /* Mark thread as running and return */ p_vout->b_active = 1; @@ -725,6 +670,15 @@ static void RunThread( vout_thread_t *p_vout) } } + /* + * Rebuild tables if gamma has changed + */ + if( p_vout->b_gamma_change ) + { + p_vout->b_gamma_change = 0; + BuildTables( p_vout ); + } + /* * Check events, sleep and display picture */ @@ -844,10 +798,8 @@ static void EndThread( vout_thread_t *p_vout ) } } - /* Destroy translation tables - remeber these tables are translated */ - free( p_vout->pi_trans16_red - 384 ); - free( p_vout->pi_trans16_green - 384 ); - free( p_vout->pi_trans16_blue - 384 ); + /* Destroy translation tables */ + free( p_vout->p_trans_base ); /* Destroy thread structures allocated by InitThread */ vout_SysEnd( p_vout ); @@ -858,6 +810,72 @@ static void EndThread( vout_thread_t *p_vout ) *pi_status = THREAD_OVER; } +/******************************************************************************* + * BuildTables: build YUV translation tables + ******************************************************************************* + * This function will build translations tables according to pixel width and + * gamma. + *******************************************************************************/ +static void BuildTables( vout_thread_t *p_vout ) +{ + u16 * p_trans16_red = (u16 *) p_vout->p_trans_red; + u16 * p_trans16_green = (u16 *) p_vout->p_trans_green; + u16 * p_trans16_blue = (u16 *) p_vout->p_trans_blue; + u16 * p_trans16_gray = (u16 *) p_vout->p_trans_gray; + u32 * p_trans32_red = (u32 *) p_vout->p_trans_red; + u32 * p_trans32_green = (u32 *) p_vout->p_trans_green; + u32 * p_trans32_blue = (u32 *) p_vout->p_trans_blue; + u32 * p_trans32_gray = (u32 *) p_vout->p_trans_gray; + u8 i_gamma[256]; /* gamma table */ + int i_index; /* index in tables */ + + /* Build gamma table */ + for( i_index = 0; i_index < 256; i_index++ ) + { + i_gamma[i_index] = 255. * pow( (double)i_index / 255., p_vout->f_gamma ); + } + + /* Build red, green, blue and gray tables */ + switch( p_vout->i_screen_depth ) + { + case 15: + for( i_index = -384; i_index < 640; i_index++) + { + p_trans16_red[i_index] = (i_gamma[CLIP_BYTE( i_index )] & 0xf8)<<7; + p_trans16_green[i_index] = (i_gamma[CLIP_BYTE( i_index )] & 0xf8)<<2; + p_trans16_blue[i_index] = i_gamma[CLIP_BYTE( i_index )] >> 3; + p_trans16_gray[i_index] = p_trans16_red[i_index] | + p_trans16_green[i_index] | p_trans16_blue[i_index]; + } + break; + case 16: + for( i_index = -384; i_index < 640; i_index++) + { + p_trans16_red[i_index] = (i_gamma[CLIP_BYTE( i_index )] & 0xf8)<<8; + p_trans16_green[i_index] = (i_gamma[CLIP_BYTE( i_index )] & 0xfc)<<3; + p_trans16_blue[i_index] = i_gamma[CLIP_BYTE( i_index )] >> 3; + p_trans16_gray[i_index] = p_trans16_red[i_index] | + p_trans16_green[i_index] | p_trans16_blue[i_index]; + } + break; + case 32: + for( i_index = -384; i_index < 640; i_index++) + { + p_trans32_red[i_index] = i_gamma[CLIP_BYTE( i_index )] <<16; + p_trans32_green[i_index] = i_gamma[CLIP_BYTE( i_index )] <<8; + p_trans32_blue[i_index] = i_gamma[CLIP_BYTE( i_index )] ; + p_trans32_gray[i_index] = p_trans32_red[i_index] | + p_trans32_green[i_index] | p_trans32_blue[i_index]; + } + break; +#ifdef DEBUG + default: + intf_DbgMsg("error: invalid screen depth %d\n", p_vout->i_screen_depth ); + break; +#endif + } +} + /******************************************************************************* * RenderPicture: render a picture ******************************************************************************* @@ -890,7 +908,7 @@ static void RenderPicture( vout_thread_t *p_vout, picture_t *p_pic ) { RenderYUV16Picture( p_vout, p_pic ); } - else /* color 24 or 32 bpp */ + else if( p_vout->i_bytes_per_pixel == 4 ) /* color 32 bpp */ { RenderYUV32Picture( p_vout, p_pic ); } @@ -909,7 +927,7 @@ static void RenderPicture( vout_thread_t *p_vout, picture_t *p_pic ) } /******************************************************************************* - * RenderYUVGrayPicture: render a 15, 16, 24 or 32 bpp YUV picture in grayscale + * RenderYUVGrayPicture: render YUV picture in grayscale ******************************************************************************* * Performs the YUV convertion. The picture sent to this function should only * have YUV_420, YUV_422 or YUV_444 types. @@ -920,15 +938,10 @@ static void RenderYUVGrayPicture( vout_thread_t *p_vout, picture_t *p_pic ) int i_width, i_height; /* picture size */ int i_eol_offset; /* pixels from end of line to next line */ yuv_data_t *p_y; /* Y data base adress */ - yuv_data_t i_y; /* Y sample */ - u16 * pi_pic16; /* destination picture, 15 or 16 bpp */ - u32 * pi_pic32; /* destination picture, 24 or 32 bpp */ - u16 * pi_trans16_red; /* red transformation table */ - u16 * pi_trans16_green; /* green transformation table */ - u16 * pi_trans16_blue; /* blue transformation table */ - u32 * pi_trans32_red; /* red transformation table */ - u32 * pi_trans32_green; /* green transformation table */ - u32 * pi_trans32_blue; /* blue transformation table */ + u16 * p_pic16; /* destination picture, 15 or 16 bpp */ + u32 * p_pic32; /* destination picture, 32 bpp */ + u16 * p_trans16_gray; /* transformation table, 15 or 16 bpp */ + u32 * p_trans32_gray; /* transformation table, 32 bpp */ /* Set the base pointers and transformation parameters */ p_y = p_pic->p_y; @@ -942,23 +955,14 @@ static void RenderYUVGrayPicture( vout_thread_t *p_vout, picture_t *p_pic ) { case 15: case 16: - pi_trans16_red = p_vout->pi_trans16_red; - pi_trans16_green = p_vout->pi_trans16_green; - pi_trans16_blue = p_vout->pi_trans16_blue; - pi_pic16 = (u16 *) vout_SysGetPicture( p_vout ); - - YUV_GRAYSCALE( pi_trans16_red, pi_trans16_green, pi_trans16_blue, - pi_pic16 ); + p_trans16_gray = (u16 *) p_vout->p_trans_gray; + p_pic16 = (u16 *) vout_SysGetPicture( p_vout ); + YUV_GRAYSCALE( p_trans16_gray, p_pic16 ); break; - case 24: case 32: - pi_trans32_red = p_vout->pi_trans32_red; - pi_trans32_green = p_vout->pi_trans32_green; - pi_trans32_blue = p_vout->pi_trans32_blue; - pi_pic32 = (u32 *) vout_SysGetPicture( p_vout ); - - YUV_GRAYSCALE( pi_trans32_red, pi_trans32_green, pi_trans32_blue, - pi_pic32 ); + p_trans32_gray = (u32 *) p_vout->p_trans_gray; + p_pic32 = (u32 *) vout_SysGetPicture( p_vout ); + YUV_GRAYSCALE( p_trans32_gray, p_pic32 ); break; #ifdef DEBUG default: @@ -986,10 +990,10 @@ static void RenderYUV16Picture( vout_thread_t *p_vout, picture_t *p_pic ) yuv_data_t *p_y; /* Y data base adress */ yuv_data_t *p_u; /* U data base adress */ yuv_data_t *p_v; /* V data base adress */ - u16 * pi_pic; /* base adress for destination picture */ - u16 * pi_trans_red; /* red transformation table */ - u16 * pi_trans_green; /* green transformation table */ - u16 * pi_trans_blue; /* blue transformation table */ + u16 * p_data; /* base adress for destination picture */ + u16 * p_trans_red; /* red transformation table */ + u16 * p_trans_green; /* green transformation table */ + u16 * p_trans_blue; /* blue transformation table */ /* Choose transformation matrix coefficients */ i_crv = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][0]; @@ -997,10 +1001,11 @@ static void RenderYUV16Picture( vout_thread_t *p_vout, picture_t *p_pic ) i_cgu = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][2]; i_cgv = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][3]; - /* Choose the conversions tables */ - pi_trans_red = p_vout->pi_trans16_red; - pi_trans_green = p_vout->pi_trans16_green; - pi_trans_blue = p_vout->pi_trans16_blue; + /* Choose the conversions tables and picture address */ + p_trans_red = (u16 *) p_vout->p_trans_red; + p_trans_green = (u16 *) p_vout->p_trans_green; + p_trans_blue = (u16 *) p_vout->p_trans_blue; + p_data = (u16 *) vout_SysGetPicture( p_vout ); /* Set the base pointers and transformation parameters */ p_y = p_pic->p_y; @@ -1011,9 +1016,6 @@ static void RenderYUV16Picture( vout_thread_t *p_vout, picture_t *p_pic ) i_chroma_width = i_width / 2; i_eol_offset = p_vout->i_bytes_per_line / 2 - i_width; - /* Get base adress for destination image */ - pi_pic = (u16 *)vout_SysGetPicture( p_vout ); - /* Do YUV transformation - the loops are repeated for optimization */ switch( p_pic->i_type ) { @@ -1022,36 +1024,36 @@ static void RenderYUV16Picture( vout_thread_t *p_vout, picture_t *p_pic ) vout_YUV420_16_MMX( p_y, p_u, p_v, i_width, i_height, i_width, i_chroma_width, - 0, (u8 *) pi_pic, + 0, p_data, 0, 0, p_vout->i_bytes_per_line, p_vout->i_screen_depth == 15 ); #else YUV_TRANSFORM( 420, - pi_trans_red, - pi_trans_green, - pi_trans_blue, - pi_pic ); + p_trans_red, + p_trans_green, + p_trans_blue, + p_data ); #endif break; case YUV_422_PICTURE: /* 15 or 16 bpp 422 transformation */ YUV_TRANSFORM( 422, - pi_trans_red, - pi_trans_green, - pi_trans_blue, - pi_pic ); + p_trans_red, + p_trans_green, + p_trans_blue, + p_data ); break; case YUV_444_PICTURE: /* 15 or 16 bpp 444 transformation */ YUV_TRANSFORM( 444, - pi_trans_red, - pi_trans_green, - pi_trans_blue, - pi_pic ); + p_trans_red, + p_trans_green, + p_trans_blue, + p_data ); break; } } /******************************************************************************* - * RenderYUV32Picture: render a 24 or 32 bpp YUV picture + * RenderYUV32Picture: render a 32 bpp YUV picture ******************************************************************************* * Performs the YUV convertion. The picture sent to this function should only * have YUV_420, YUV_422 or YUV_444 types. @@ -1067,10 +1069,10 @@ static void RenderYUV32Picture( vout_thread_t *p_vout, picture_t *p_pic ) yuv_data_t *p_y; /* Y data base adress */ yuv_data_t *p_u; /* U data base adress */ yuv_data_t *p_v; /* V data base adress */ - u32 * pi_pic; /* base adress for destination picture */ - u32 * pi_trans_red; /* red transformation table */ - u32 * pi_trans_green; /* green transformation table */ - u32 * pi_trans_blue; /* blue transformation table */ + u32 * p_data; /* base adress for destination picture */ + u32 * p_trans_red; /* red transformation table */ + u32 * p_trans_green; /* green transformation table */ + u32 * p_trans_blue; /* blue transformation table */ /* Choose transformation matrix coefficients */ i_crv = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][0]; @@ -1078,10 +1080,11 @@ static void RenderYUV32Picture( vout_thread_t *p_vout, picture_t *p_pic ) i_cgu = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][2]; i_cgv = MATRIX_COEFFICIENTS_TABLE[p_pic->i_matrix_coefficients][3]; - /* Choose the conversions tables */ - pi_trans_red = p_vout->pi_trans32_red; - pi_trans_green = p_vout->pi_trans32_green; - pi_trans_blue = p_vout->pi_trans32_blue; + /* Choose the conversions tables and picture address */ + p_trans_red = (u32 *) p_vout->p_trans_red; + p_trans_green = (u32 *) p_vout->p_trans_green; + p_trans_blue = (u32 *) p_vout->p_trans_blue; + p_data = (u32 *) vout_SysGetPicture( p_vout ); /* Set the base pointers and transformation parameters */ p_y = p_pic->p_y; @@ -1092,32 +1095,29 @@ static void RenderYUV32Picture( vout_thread_t *p_vout, picture_t *p_pic ) i_chroma_width = i_width / 2; i_eol_offset = p_vout->i_bytes_per_line / p_vout->i_bytes_per_pixel - i_width; - /* Get base adress for destination image */ - pi_pic = (u32 *)vout_SysGetPicture( p_vout ); - /* Do YUV transformation - the loops are repeated for optimization */ switch( p_pic->i_type ) { - case YUV_420_PICTURE: /* 24 or 32 bpp 420 transformation */ + case YUV_420_PICTURE: /* 32 bpp 420 transformation */ YUV_TRANSFORM( 420, - pi_trans_red, - pi_trans_green, - pi_trans_blue, - pi_pic ); + p_trans_red, + p_trans_green, + p_trans_blue, + p_data ); break; - case YUV_422_PICTURE: /* 24 or 32 bpp 422 transformation */ + case YUV_422_PICTURE: /* 32 bpp 422 transformation */ YUV_TRANSFORM( 422, - pi_trans_red, - pi_trans_green, - pi_trans_blue, - pi_pic ); + p_trans_red, + p_trans_green, + p_trans_blue, + p_data ); break; - case YUV_444_PICTURE: /* 24 or 32 bpp 444 transformation */ + case YUV_444_PICTURE: /* 32 bpp 444 transformation */ YUV_TRANSFORM( 444, - pi_trans_red, - pi_trans_green, - pi_trans_blue, - pi_pic ); + p_trans_red, + p_trans_green, + p_trans_blue, + p_data ); break; } } @@ -1147,8 +1147,8 @@ static void RenderInfo( vout_thread_t *p_vout ) } /* Print statistics in upper left corner */ - sprintf( psz_buffer, "%ld frames (%.1f %% idle)", p_vout->c_fps_samples, - p_vout->c_loops ? + sprintf( psz_buffer, "gamma=%.2f %ld frames (%.1f %% idle)", + p_vout->f_gamma, p_vout->c_fps_samples, p_vout->c_loops ? (double ) p_vout->c_idle_loops * 100 / p_vout->c_loops : 100. ); vout_SysPrint( p_vout, 0, 0, -1, -1, psz_buffer ); #endif diff --git a/src/video_output/video_x11.c b/src/video_output/video_x11.c index 7415cb3fb1..b406e0a9e2 100644 --- a/src/video_output/video_x11.c +++ b/src/video_output/video_x11.c @@ -275,7 +275,7 @@ void vout_SysDisplay( vout_thread_t *p_vout ) ******************************************************************************* * This function returns the address of the current display buffer. *******************************************************************************/ -byte_t * vout_SysGetPicture( vout_thread_t *p_vout ) +void * vout_SysGetPicture( vout_thread_t *p_vout ) { return( p_vout->p_sys->p_ximage[ p_vout->p_sys->i_buffer_index ]->data ); } @@ -407,10 +407,6 @@ static int X11OpenDisplay( vout_thread_t *p_vout, char *psz_display, Window root return( 1 ); } - /* Store additionnal vout informations */ - p_vout->i_new_width = p_vout->i_width; - p_vout->i_new_height = p_vout->i_height; - /* Get font information */ if( X11GetFont( p_vout ) ) { diff --git a/src/video_output/video_yuv_c.c b/src/video_output/video_yuv_c.c new file mode 100644 index 0000000000..3573b3643f --- /dev/null +++ b/src/video_output/video_yuv_c.c @@ -0,0 +1,837 @@ +/******************************************************************************* + * video_yuv_c.c: YUV transformation, optimized + * (c)1999 VideoLAN + ******************************************************************************* + * Provides optimized functions to perform the YUV conversion. + *******************************************************************************/ + +#include /* malloc */ + +#include "convert.h" + +static int binaryLog (int i) +{ + int log; + + log = 0; + if (i & 0xffff0000) log = 16; + if (i & 0xff00ff00) log += 8; + if (i & 0xf0f0f0f0) log += 4; + if (i & 0xcccccccc) log += 2; + if (i & 0xaaaaaaaa) log++; + if (i != (1 << log)) + return -1; + + return log; +} + +static int colorMaskToShift (int * right, int * left, int mask) +{ + int low; + int high; + + low = mask & (- mask); /* lower bit of the mask */ + high = mask + low; /* higher bit of the mask */ + + low = binaryLog (low); + high = binaryLog (high); + if ((low == -1) || (high == -1)) + return 1; + + *left = low; + *right = (8 - high + low); + + return 0; +} + + +/* + * YUV to RGB routines. + * + * these routines calculate r, g and b values from each pixel's y, u and v. + * these r, g an b values are then passed thru a table lookup to take the + * gamma curve into account and find the corresponding pixel value. + * + * the table must store more than 3*256 values because of the possibility + * of overflow in the yuv->rgb calculation. actually the calculated r,g,b + * values are in the following intervals : + * -176 to 255+176 for red + * -133 to 255+133 for green + * -222 to 255+222 for blue + * + * If the input y,u,v values are right, the r,g,b results are not expected + * to move out of the 0 to 255 interval but who knows what will happen in + * real use... + * + * the red, green and blue conversion tables are stored in a single 1935-entry + * array. The respective positions of each component in the array have been + * calculated to minimize the cache interactions of the 3 tables. + */ + +static int rgbTable16 (short table [1935], + int redMask, int greenMask, int blueMask, + unsigned char gamma[256]) +{ + int redRight; + int redLeft; + int greenRight; + int greenLeft; + int blueRight; + int blueLeft; + short * redTable; + short * greenTable; + short * blueTable; + int i; + int y; + + if (colorMaskToShift (&redRight, &redLeft, redMask) || + colorMaskToShift (&greenRight, &greenLeft, greenMask) || + colorMaskToShift (&blueRight, &blueLeft, blueMask)) + return 1; + + /* + * green blue red +- 2 just to be sure + * green = 0-525 [151-370] + * blue = 594-1297 [834-1053] <834-29> + * red = 1323-1934 [1517-1736] <493-712> + */ + + redTable = table + 1501; + greenTable = table + 135; + blueTable = table + 818; + + for (i = 0; i < 178; i++) { + redTable[i-178] = 0; + redTable[i+256] = redMask; + } + for (i = 0; i < 135; i++) { + greenTable[i-135] = 0; + greenTable[i+256] = greenMask; + } + for (i = 0; i < 224; i++) { + blueTable[i-224] = 0; + blueTable[i+256] = blueMask; + } + + for (i = 0; i < 256; i++) { + y = gamma[i]; + redTable[i] = ((y >> redRight) << redLeft); + greenTable[i] = ((y >> greenRight) << greenLeft); + blueTable[i] = ((y >> blueRight) << blueLeft); + } + + return 0; +} + +static int rgbTable32 (int table [1935], + int redMask, int greenMask, int blueMask, + unsigned char gamma[256]) +{ + int redRight; + int redLeft; + int greenRight; + int greenLeft; + int blueRight; + int blueLeft; + int * redTable; + int * greenTable; + int * blueTable; + int i; + int y; + + if (colorMaskToShift (&redRight, &redLeft, redMask) || + colorMaskToShift (&greenRight, &greenLeft, greenMask) || + colorMaskToShift (&blueRight, &blueLeft, blueMask)) + return 1; + + /* + * green blue red +- 2 just to be sure + * green = 0-525 [151-370] + * blue = 594-1297 [834-1053] <834-29> + * red = 1323-1934 [1517-1736] <493-712> + */ + + redTable = table + 1501; + greenTable = table + 135; + blueTable = table + 818; + + for (i = 0; i < 178; i++) { + redTable[i-178] = 0; + redTable[i+256] = redMask; + } + for (i = 0; i < 135; i++) { + greenTable[i-135] = 0; + greenTable[i+256] = greenMask; + } + for (i = 0; i < 224; i++) { + blueTable[i-224] = 0; + blueTable[i+256] = blueMask; + } + + for (i = 0; i < 256; i++) { + y = gamma[i]; + redTable[i] = ((y >> redRight) << redLeft); + greenTable[i] = ((y >> greenRight) << greenLeft); + blueTable[i] = ((y >> blueRight) << blueLeft); + } + + return 0; +} + +#define SHIFT 20 +#define U_GREEN_COEF ((int)(-0.391 * (1<> 4; + while (i--) { + u = *(U++); + v = *(V++); + uvRed = (V_RED_COEF*v) >> SHIFT; + uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT; + uvBlue = (U_BLUE_COEF*u) >> SHIFT; + + tableY = table + *(Y++); + *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + + tableY = table + *(Y++); + *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + + u = *(U++); + v = *(V++); + uvRed = (V_RED_COEF*v) >> SHIFT; + uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT; + uvBlue = (U_BLUE_COEF*u) >> SHIFT; + + tableY = table + *(Y++); + *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + + tableY = table + *(Y++); + *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + + u = *(U++); + v = *(V++); + uvRed = (V_RED_COEF*v) >> SHIFT; + uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT; + uvBlue = (U_BLUE_COEF*u) >> SHIFT; + + tableY = table + *(Y++); + *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + + tableY = table + *(Y++); + *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + + u = *(U++); + v = *(V++); + uvRed = (V_RED_COEF*v) >> SHIFT; + uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT; + uvBlue = (U_BLUE_COEF*u) >> SHIFT; + + tableY = table + *(Y++); + *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + + tableY = table + *(Y++); + *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + + u = *(U++); + v = *(V++); + uvRed = (V_RED_COEF*v) >> SHIFT; + uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT; + uvBlue = (U_BLUE_COEF*u) >> SHIFT; + + tableY = table + *(Y++); + *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + + tableY = table + *(Y++); + *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + + u = *(U++); + v = *(V++); + uvRed = (V_RED_COEF*v) >> SHIFT; + uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT; + uvBlue = (U_BLUE_COEF*u) >> SHIFT; + + tableY = table + *(Y++); + *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + + tableY = table + *(Y++); + *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + + u = *(U++); + v = *(V++); + uvRed = (V_RED_COEF*v) >> SHIFT; + uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT; + uvBlue = (U_BLUE_COEF*u) >> SHIFT; + + tableY = table + *(Y++); + *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + + tableY = table + *(Y++); + *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + + u = *(U++); + v = *(V++); + uvRed = (V_RED_COEF*v) >> SHIFT; + uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT; + uvBlue = (U_BLUE_COEF*u) >> SHIFT; + + tableY = table + *(Y++); + *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + + tableY = table + *(Y++); + *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + } + + i = (width & 15) >> 1; + while (i--) { + u = *(U++); + v = *(V++); + uvRed = (V_RED_COEF*v) >> SHIFT; + uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT; + uvBlue = (U_BLUE_COEF*u) >> SHIFT; + + tableY = table + *(Y++); + *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + + tableY = table + *(Y++); + *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + } + + if (width & 1) { + u = *(U++); + v = *(V++); + uvRed = (V_RED_COEF*v) >> SHIFT; + uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT; + uvBlue = (U_BLUE_COEF*u) >> SHIFT; + + tableY = table + *(Y++); + *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + } +} + +static void yuvToRgb24 (unsigned char * Y, + unsigned char * U, unsigned char * V, + char * dest, int table[1935], int width) +{ + int i; + int u; + int v; + int uvRed; + int uvGreen; + int uvBlue; + int * tableY; + int tmp24; + + i = width >> 3; + while (i--) { + u = *(U++); + v = *(V++); + uvRed = (V_RED_COEF*v) >> SHIFT; + uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT; + uvBlue = (U_BLUE_COEF*u) >> SHIFT; + + tableY = table + *(Y++); + tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + *(dest++) = tmp24; + *(dest++) = tmp24 >> 8; + *(dest++) = tmp24 >> 16; + + tableY = table + *(Y++); + tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + *(dest++) = tmp24; + *(dest++) = tmp24 >> 8; + *(dest++) = tmp24 >> 16; + + u = *(U++); + v = *(V++); + uvRed = (V_RED_COEF*v) >> SHIFT; + uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT; + uvBlue = (U_BLUE_COEF*u) >> SHIFT; + + tableY = table + *(Y++); + tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + *(dest++) = tmp24; + *(dest++) = tmp24 >> 8; + *(dest++) = tmp24 >> 16; + + tableY = table + *(Y++); + tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + *(dest++) = tmp24; + *(dest++) = tmp24 >> 8; + *(dest++) = tmp24 >> 16; + + u = *(U++); + v = *(V++); + uvRed = (V_RED_COEF*v) >> SHIFT; + uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT; + uvBlue = (U_BLUE_COEF*u) >> SHIFT; + + tableY = table + *(Y++); + tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + *(dest++) = tmp24; + *(dest++) = tmp24 >> 8; + *(dest++) = tmp24 >> 16; + + tableY = table + *(Y++); + tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + *(dest++) = tmp24; + *(dest++) = tmp24 >> 8; + *(dest++) = tmp24 >> 16; + + u = *(U++); + v = *(V++); + uvRed = (V_RED_COEF*v) >> SHIFT; + uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT; + uvBlue = (U_BLUE_COEF*u) >> SHIFT; + + tableY = table + *(Y++); + tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + *(dest++) = tmp24; + *(dest++) = tmp24 >> 8; + *(dest++) = tmp24 >> 16; + + tableY = table + *(Y++); + tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + *(dest++) = tmp24; + *(dest++) = tmp24 >> 8; + *(dest++) = tmp24 >> 16; + } + + i = (width & 7) >> 1; + while (i--) { + u = *(U++); + v = *(V++); + uvRed = (V_RED_COEF*v) >> SHIFT; + uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT; + uvBlue = (U_BLUE_COEF*u) >> SHIFT; + + tableY = table + *(Y++); + tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + *(dest++) = tmp24; + *(dest++) = tmp24 >> 8; + *(dest++) = tmp24 >> 16; + + tableY = table + *(Y++); + tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + *(dest++) = tmp24; + *(dest++) = tmp24 >> 8; + *(dest++) = tmp24 >> 16; + } + + if (width & 1) { + u = *(U++); + v = *(V++); + uvRed = (V_RED_COEF*v) >> SHIFT; + uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT; + uvBlue = (U_BLUE_COEF*u) >> SHIFT; + + tableY = table + *(Y++); + tmp24 = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + *(dest++) = tmp24; + *(dest++) = tmp24 >> 8; + *(dest++) = tmp24 >> 16; + } +} + +static void yuvToRgb32 (unsigned char * Y, + unsigned char * U, unsigned char * V, + int * dest, int table[1935], int width) +{ + int i; + int u; + int v; + int uvRed; + int uvGreen; + int uvBlue; + int * tableY; + + i = width >> 4; + while (i--) { + u = *(U++); + v = *(V++); + uvRed = (V_RED_COEF*v) >> SHIFT; + uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT; + uvBlue = (U_BLUE_COEF*u) >> SHIFT; + + tableY = table + *(Y++); + *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + + tableY = table + *(Y++); + *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + + u = *(U++); + v = *(V++); + uvRed = (V_RED_COEF*v) >> SHIFT; + uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT; + uvBlue = (U_BLUE_COEF*u) >> SHIFT; + + tableY = table + *(Y++); + *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + + tableY = table + *(Y++); + *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + + u = *(U++); + v = *(V++); + uvRed = (V_RED_COEF*v) >> SHIFT; + uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT; + uvBlue = (U_BLUE_COEF*u) >> SHIFT; + + tableY = table + *(Y++); + *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + + tableY = table + *(Y++); + *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + + u = *(U++); + v = *(V++); + uvRed = (V_RED_COEF*v) >> SHIFT; + uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT; + uvBlue = (U_BLUE_COEF*u) >> SHIFT; + + tableY = table + *(Y++); + *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + + tableY = table + *(Y++); + *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + + u = *(U++); + v = *(V++); + uvRed = (V_RED_COEF*v) >> SHIFT; + uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT; + uvBlue = (U_BLUE_COEF*u) >> SHIFT; + + tableY = table + *(Y++); + *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + + tableY = table + *(Y++); + *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + + u = *(U++); + v = *(V++); + uvRed = (V_RED_COEF*v) >> SHIFT; + uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT; + uvBlue = (U_BLUE_COEF*u) >> SHIFT; + + tableY = table + *(Y++); + *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + + tableY = table + *(Y++); + *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + + u = *(U++); + v = *(V++); + uvRed = (V_RED_COEF*v) >> SHIFT; + uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT; + uvBlue = (U_BLUE_COEF*u) >> SHIFT; + + tableY = table + *(Y++); + *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + + tableY = table + *(Y++); + *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + + u = *(U++); + v = *(V++); + uvRed = (V_RED_COEF*v) >> SHIFT; + uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT; + uvBlue = (U_BLUE_COEF*u) >> SHIFT; + + tableY = table + *(Y++); + *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + + tableY = table + *(Y++); + *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + } + + i = (width & 15) >> 1; + while (i--) { + u = *(U++); + v = *(V++); + uvRed = (V_RED_COEF*v) >> SHIFT; + uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT; + uvBlue = (U_BLUE_COEF*u) >> SHIFT; + + tableY = table + *(Y++); + *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + + tableY = table + *(Y++); + *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + } + + if (width & 1) { + u = *(U++); + v = *(V++); + uvRed = (V_RED_COEF*v) >> SHIFT; + uvGreen = (U_GREEN_COEF*u + V_GREEN_COEF*v) >> SHIFT; + uvBlue = (U_BLUE_COEF*u) >> SHIFT; + + tableY = table + *(Y++); + *(dest++) = (tableY [1501 - ((V_RED_COEF*128)>>SHIFT) + uvRed] | + tableY [135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + + uvGreen] | + tableY [818 - ((U_BLUE_COEF*128)>>SHIFT) + uvBlue]); + } +} + +/* API routines */ + +int convertGrey (CONVERTER * convert, DISPLAY * disp) +{ + if ((convert == NULL) || (disp == NULL)) + return 1; + + if (greyRgbTable (disp)) + return 1; + + switch (disp->bytesPerPixel) { + case 2: + convert->convert = &greyToRgb16; + break; + case 3: + convert->convert = &greyToRgb24; + break; + case 4: + convert->convert = &greyToRgb32; + break; + default: + return 1; + } + convert->table = disp->greyRgbTable; + return 0; +} + +static void * greyRgbTable (DISP_COLORS * colors, unsigned char gamma[256]) +{ + /* FIXME could avoid recalculating the same table */ + void * table; + + for (i = 0; i < 16; i++) + gamma[i] = 0; +#define Y_COEF ((int)(1.164 * 65536)) + for (; i <= 235; i++) + gamma[i] = (Y_COEF * i - Y_COEF * 16) >> 16; +#undef Y_COEF + for (; i < 256; i++) + gamma[i] = 255; + } + + switch (colors->bytesPerPixel) { + case 2: + table = malloc (256 * sizeof (short)); + if (table == NULL) + break; + if (greyRgb16Table (table, + colors->redMask, + colors->greenMask, + colors->blueMask, + gamma)) + goto error; + return table; + case 3: + case 4: + table = malloc (256 * sizeof (int)); + if (table == NULL) + break; + if (greyRgb32Table (table, + colors->redMask, + colors->greenMask, + colors->blueMask, + gamma)) + goto error; + return table; + error: + free (table); + } + + return NULL; +} + +static void * rgbTable (DISP_COLORS * colors, unsigned char gamma[256]) +{ + /* FIXME could avoid recalculating the same table */ + void * table; + + switch (colors->bytesPerPixel) { + case 2: + table = malloc (1935 * sizeof (short)); + if (table == NULL) + break; + if (rgbTable16 (table, + colors->redMask, colors->greenMask, colors->blueMask, + gamma)) + goto error; + return table; + case 3: + case 4: + table = malloc (1935 * sizeof (int)); + if (table == NULL) + break; + if (rgbTable32 (table, + colors->redMask, colors->greenMask, colors->blueMask, + gamma)) + goto error; + return table; + error: + free (table); + } + + return NULL; +} diff --git a/src/video_output/yuv_mmx.S b/src/video_output/video_yuv_mmx.S similarity index 99% rename from src/video_output/yuv_mmx.S rename to src/video_output/video_yuv_mmx.S index 9b855153f4..0b3c9db7af 100644 --- a/src/video_output/yuv_mmx.S +++ b/src/video_output/video_yuv_mmx.S @@ -1,5 +1,5 @@ /******************************************************************************* - * yuv_mmx.S: YUV transformation, optimized for MMX processors + * video_yuv_mmx.S: YUV transformation, optimized for MMX processors * (c)1999 VideoLAN ******************************************************************************* * Following functions are defined: