Commit 6ed1e2d8 authored by Vincent Seguin's avatar Vincent Seguin

YUV 15,16 et 32 bits integr�e au vout (sans le MMX pour le moment).

En 24bpp, � vos risques et perils...
parent e4263587
......@@ -26,10 +26,18 @@
/* Program options */
#if defined(VIDEO_X11)
#define PROGRAM_OPTIONS "X11"
#define VIDEO_OPTIONS "X11"
#elif defined(VIDEO_FB)
#define PROGRAM_OPTIONS "Framebuffer"
#define VIDEO_OPTIONS "Framebuffer"
#else
#define VIDEO_OPTIONS ""
#endif
#if defined(HAVE_MMX)
#define ARCH_OPTIONS "MMX"
#else
#define ARCH_OPTIONS ""
#endif
#define PROGRAM_OPTIONS VIDEO_OPTIONS " " ARCH_OPTIONS
/* Program version and copyright message */
#define PROGRAM_VERSION "DR 2.1"
......
......@@ -29,6 +29,7 @@ typedef struct
/* Type and flags - should NOT be modified except by the vout thread */
int i_type; /* picture type */
int i_status; /* picture flags */
int i_matrix_coefficients; /* in YUV type, encoding type */
/* Picture properties - those properties are fixed at initialization and
* should NOT be modified. Note that for YUV pictures, i_bytes_per_line is
......
......@@ -7,14 +7,15 @@
* Prototypes
*******************************************************************************/
#if defined(VIDEO_X11)
int vout_SysCreate ( p_vout_thread_t p_vout, char *psz_display, Window root_window );
int vout_SysCreate ( p_vout_thread_t p_vout, char *psz_display, Window root_window );
#elif defined(VIDEO_FB)
int vout_SysCreate ( p_vout_thread_t p_vout );
int vout_SysCreate ( p_vout_thread_t p_vout );
#endif
int vout_SysInit ( p_vout_thread_t p_vout );
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 );
int vout_SysInit ( p_vout_thread_t p_vout );
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, int *pi_eol_offset );
......@@ -155,6 +155,20 @@ void vout_SysDisplay( vout_thread_t *p_vout )
//?? p_vout->p_sys->i_buffer_index = ++p_vout->p_sys->i_buffer_index & 1;
}
/*******************************************************************************
* vout_SysGetPicture: get current display buffer informations
*******************************************************************************
* This function returns the address of the current display buffer, and the
* number of samples per line. For 15, 16 and 32 bits displays, this value is
* the number of pixels in a line.
*******************************************************************************/
byte_t * vout_SysGetPicture( vout_thread_t *p_vout, int *pi_eol_offset )
{
*pi_eol_offset = p_vout->i_width;
//????
// return( p_vout->p_sys->p_ximage[ p_vout->p_sys->i_buffer_index ].data );
}
/* following functions are local */
/*******************************************************************************
......@@ -219,10 +233,30 @@ static int FBOpenDisplay( vout_thread_t *p_vout )
p_vout->i_width = var_info.xres;
p_vout->i_height = var_info.yres;
p_vout->i_screen_depth = var_info.bits_per_pixel;
p_vout->p_sys->i_page_size = var_info.xres *
var_info.yres * var_info.bits_per_pixel / 8;
p_vout->i_screen_depth = var_info.bits_per_pixel;
switch( p_vout->i_screen_depth )
{
case 15: /* 15 bpp (16bpp with a missing green bit) */
case 16: /* 16 bpp (65536 colors) */
p_vout->i_bytes_per_pixel = 2;
break;
case 24: /* 24 bpp (millions of colors) */
p_vout->i_bytes_per_pixel = 3;
break;
case 32: /* 32 bpp (millions of colors) */
p_vout->i_bytes_per_pixel = 4;
break;
default: /* unsupported screen depth */
intf_ErrMsg("vout error: screen depth %i is not supported\n",
p_vout->i_screen_depth);
return( 1 );
break;
}
p_vout->p_sys->i_page_size = var_info.xres *
var_info.yres * p_vout->i_bytes_per_pixel;
/* Map two framebuffers a the very beginning of the fb */
p_vout->p_sys->p_video = mmap(0, p_vout->p_sys->i_page_size * 2,
......
......@@ -31,14 +31,58 @@
/*******************************************************************************
* Macros
*******************************************************************************/
/* CLIP_BYTE: return value if between 0 and 255, else return nearest boundary
* (0 or 255) */
#define CLIP_BYTE( i_val ) ( (i_val < 0) ? 0 : ((i_val > 255) ? 255 : i_val) )
/* YUV_TRANSFORM_16: parametric macro. Due to the high performance need of this
* loop, all possible conditions evaluations are made outside the transformation
* loop. However, the code does 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_TRANSFORM( CHROMA, TRANS_RED, TRANS_GREEN, TRANS_BLUE, 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+=2) \
{ \
/* First sample (complete) */ \
i_y = 76309 * *p_y++ - 1188177; \
i_u = *p_u++ - 128; \
i_v = *p_v++ - 128; \
*P_PIC++ = \
TRANS_RED [(i_y+i_crv*i_v) >>16] | \
TRANS_GREEN [(i_y-i_cgu*i_u-i_cgv*i_v) >>16] | \
TRANS_BLUE [(i_y+i_cbu*i_u) >>16]; \
i_y = 76309 * *p_y++ - 1188177; \
/* Second sample (partial) */ \
if( CHROMA == 444 ) \
{ \
i_u = *p_u++ - 128; \
i_v = *p_v++ - 128; \
} \
*P_PIC++ = \
TRANS_RED [(i_y+i_crv*i_v) >>16] | \
TRANS_GREEN [(i_y-i_cgu*i_u-i_cgv*i_v) >>16] | \
TRANS_BLUE [(i_y+i_cbu*i_u) >>16]; \
} \
if( (CHROMA == 420) && !(i_pic_y & 0x1) ) \
{ \
p_u -= p_pic->i_width; \
p_v -= p_pic->i_width; \
} \
/* Skip until beginning of next line */ \
P_PIC += i_pic_eol_offset - p_pic->i_width; \
}
/*******************************************************************************
* Constants
*******************************************************************************/
/* RGB/YUV inversion matrix (ISO/IEC 13818-2 section 6.3.6, table 6.9) */
int matrix_coefficients[8][4] =
int matrix_coefficients_table[8][4] =
{
{117504, 138453, 13954, 34903}, /* no sequence_display_extension */
{117504, 138453, 13954, 34903}, /* ITU-R Rec. 709 (1990) */
......@@ -59,6 +103,7 @@ static void ErrorThread ( vout_thread_t *p_vout );
static void EndThread ( vout_thread_t *p_vout );
static void RenderPicture ( vout_thread_t *p_vout, picture_t *p_pic );
static void RenderYUVPicture( vout_thread_t *p_vout, picture_t *p_pic );
/*******************************************************************************
* vout_CreateThread: creates a new video output thread
......@@ -94,7 +139,7 @@ vout_thread_t * vout_CreateThread (
{
return( NULL );
}
intf_DbgMsg( "0x%x\n", p_vout );
intf_DbgMsg( "%p\n", p_vout );
if( vout_SysCreate( p_vout
#if defined(VIDEO_X11)
, psz_display, root_window
......@@ -156,7 +201,7 @@ void vout_DestroyThread( vout_thread_t *p_vout, int *pi_status )
{
int i_status; /* thread status */
intf_DbgMsg( "0x%x\n", p_vout );
intf_DbgMsg( "%p\n", p_vout );
/* Set status */
p_vout->pi_status = (pi_status != NULL) ? pi_status : &i_status;
......@@ -278,7 +323,7 @@ picture_t *vout_CreatePicture( vout_thread_t *p_vout, int i_type,
break;
#ifdef DEBUG
default:
intf_DbgMsg("0x%x error: unknown picture type %d\n", p_vout, i_type );
intf_DbgMsg("%p error: unknown picture type %d\n", p_vout, i_type );
p_free_picture->p_data = NULL;
#endif
}
......@@ -292,6 +337,7 @@ picture_t *vout_CreatePicture( vout_thread_t *p_vout, int i_type,
p_free_picture->i_height = i_height;
p_free_picture->i_bytes_per_line = i_bytes_per_line;
p_free_picture->i_refcount = 0;
p_free_picture->i_matrix_coefficients = 1; // ?? default value
}
else
{
......@@ -299,7 +345,7 @@ picture_t *vout_CreatePicture( vout_thread_t *p_vout, int i_type,
p_free_picture->i_type = EMPTY_PICTURE;
p_free_picture->i_status = FREE_PICTURE;
p_free_picture = NULL;
intf_DbgMsg("0x%x malloc for new picture failed\n");
intf_DbgMsg("%p malloc for new picture failed\n", p_vout );
}
vlc_mutex_unlock( &p_vout->lock );
......@@ -307,7 +353,7 @@ picture_t *vout_CreatePicture( vout_thread_t *p_vout, int i_type,
}
// No free or destroyed picture could be found
intf_DbgMsg("0x%x no picture available\n");
intf_DbgMsg("%p no picture available\n", p_vout );
vlc_mutex_unlock( &p_vout->lock );
return( NULL );
}
......@@ -325,7 +371,7 @@ void vout_DestroyPicture( vout_thread_t *p_vout, picture_t *p_pic )
/* Mark picture for destruction */
p_pic->i_status = DESTROYED_PICTURE;
intf_DbgMsg("%p -> picture %p destroyed\n", p_vout, p_pic );
intf_DbgMsg("%p picture %p destroyed\n", p_vout, p_pic );
vlc_mutex_unlock( &p_vout->lock );
}
......@@ -408,16 +454,22 @@ static int InitThread( vout_thread_t *p_vout )
break;
case 3: /* 24 or 32 bpp, use 32 bits translations tables */
case 4:
default:
i_pixel_size = sizeof( u32 );
break;
}
p_vout->pi_trans16_red = p_vout->pi_trans32_red = malloc( 1024 * i_pixel_size );
p_vout->pi_trans16_green = p_vout->pi_trans32_green = malloc( 1024 * i_pixel_size );
p_vout->pi_trans16_blue = p_vout->pi_trans32_blue = malloc( 1024 * i_pixel_size );
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("vout error: %s\n", strerror(ENOMEM) );
*p_vout->pi_status = THREAD_ERROR;
if( p_vout->pi_trans16_red != NULL )
{
free( p_vout->pi_trans16_red );
......@@ -430,10 +482,8 @@ static int InitThread( vout_thread_t *p_vout )
{
free( p_vout->pi_trans16_blue );
}
intf_ErrMsg("vout error: %s\n", strerror(ENOMEM) );
*p_vout->pi_status = THREAD_ERROR;
return( 1 );
}
}
/* Translate translation tables */
p_vout->pi_trans16_red += 384;
......@@ -461,6 +511,7 @@ static int InitThread( vout_thread_t *p_vout )
p_vout->pi_trans16_green[i_index] = (CLIP_BYTE( i_index ) & 0xf8)<<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++)
......@@ -472,8 +523,6 @@ static int InitThread( vout_thread_t *p_vout )
break;
}
//????
/* Mark thread as running and return */
*p_vout->pi_status = THREAD_READY;
intf_DbgMsg("%p -> succeeded\n", p_vout);
......@@ -500,7 +549,7 @@ static void RunThread( vout_thread_t *p_vout)
/*
* Initialize thread and free configuration
*/
intf_DbgMsg( "0x%x begin\n", p_vout );
intf_DbgMsg( "%p begin\n", p_vout );
p_vout->b_error = InitThread( p_vout );
if( p_vout->b_error )
{
......@@ -634,7 +683,7 @@ static void RunThread( vout_thread_t *p_vout)
/* End of thread */
EndThread( p_vout );
intf_DbgMsg( "0x%x end\n", p_vout );
intf_DbgMsg( "%p end\n", p_vout );
}
/*******************************************************************************
......@@ -703,9 +752,147 @@ static void EndThread( vout_thread_t *p_vout )
*******************************************************************************/
static void RenderPicture( vout_thread_t *p_vout, picture_t *p_pic )
{
intf_DbgMsg("0x%x Picture 0x%x type=%d, %dx%d\n",
switch( p_pic->i_type )
{
case YUV_420_PICTURE: /* YUV picture: YUV transformation */
case YUV_422_PICTURE:
case YUV_444_PICTURE:
RenderYUVPicture( p_vout, p_pic );
break;
}
intf_DbgMsg("%p Picture %p type=%d, %dx%d\n",
p_vout, p_pic, p_pic->i_type, p_pic->i_width, p_pic->i_height );
/*???*/
}
/*******************************************************************************
* RenderYUVPicture: render a YUV picture
*******************************************************************************
* Performs the YUV convertion.
*******************************************************************************/
static void RenderYUVPicture( vout_thread_t *p_vout, picture_t *p_pic )
{
int i_crv;
int i_cbu;
int i_cgu;
int i_cgv;
int i_pic_x; /* x coordinate in picture */
int i_pic_y; /* y coordinate in picture */
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 */
yuv_data_t i_y; /* Y sample */
yuv_data_t i_u; /* U sample */
yuv_data_t i_v; /* V sample */
u16 *pi_pic16; /* base adress for destination picture */
u32 *pi_pic32; /* base adress for destination picture */
int i_pic_eol_offset; /* end of line offset */
/* Choose transformation matrix coefficients */
i_crv = matrix_coefficients_table[p_pic->i_matrix_coefficients][0];
i_cbu = matrix_coefficients_table[p_pic->i_matrix_coefficients][1];
i_cgu = matrix_coefficients_table[p_pic->i_matrix_coefficients][2];
i_cgv = matrix_coefficients_table[p_pic->i_matrix_coefficients][3];
/* Set the base pointers */
p_y = p_pic->p_y;
p_u = p_pic->p_u;
p_v = p_pic->p_v;
/* Get base adress for destination image */
pi_pic32 = (u32 *)pi_pic16 =
(u16 *)vout_SysGetPicture( p_vout, &i_pic_eol_offset );
//?? copy used values (translation, height, width) to local variables ?
/* Do YUV transformation - the loops are repeated for optimization */
switch( p_vout->i_screen_depth )
{
case 15:
case 16:
switch( p_pic->i_type )
{
case YUV_420_PICTURE: /* 15 or 16 bpp 420 transformation */
//#ifdef HAVE_MMX
// ?? MMX
//#else
YUV_TRANSFORM( 420,
p_vout->pi_trans16_red,
p_vout->pi_trans16_green,
p_vout->pi_trans16_blue,
pi_pic16 );
//#endif
break;
case YUV_422_PICTURE: /* 15 or 16 bpp 422 transformation */
YUV_TRANSFORM( 422,
p_vout->pi_trans16_red,
p_vout->pi_trans16_green,
p_vout->pi_trans16_blue,
pi_pic16 );
break;
case YUV_444_PICTURE: /* 15 or 16 bpp 444 transformation */
YUV_TRANSFORM( 444,
p_vout->pi_trans16_red,
p_vout->pi_trans16_green,
p_vout->pi_trans16_blue,
pi_pic16 );
break;
}
break;
case 24: // ?? probably wrong !
switch( p_pic->i_type )
{
case YUV_420_PICTURE: /* 24 bpp 420 transformation */
YUV_TRANSFORM( 420,
p_vout->pi_trans32_red,
p_vout->pi_trans32_green,
p_vout->pi_trans32_blue,
pi_pic32 );
break;
case YUV_422_PICTURE: /* 24 bpp 422 transformation */
YUV_TRANSFORM( 422,
p_vout->pi_trans32_red,
p_vout->pi_trans32_green,
p_vout->pi_trans32_blue,
pi_pic32 );
break;
case YUV_444_PICTURE: /* 24 bpp 444 transformation */
YUV_TRANSFORM( 444,
p_vout->pi_trans32_red,
p_vout->pi_trans32_green,
p_vout->pi_trans32_blue,
pi_pic32 );
break;
}
break;
case 32:
switch( p_pic->i_type )
{
case YUV_420_PICTURE: /* 32 bpp 420 transformation */
YUV_TRANSFORM( 420,
p_vout->pi_trans32_red,
p_vout->pi_trans32_green,
p_vout->pi_trans32_blue,
pi_pic32 );
break;
case YUV_422_PICTURE: /* 32 bpp 422 transformation */
YUV_TRANSFORM( 422,
p_vout->pi_trans32_red,
p_vout->pi_trans32_green,
p_vout->pi_trans32_blue,
pi_pic32 );
break;
case YUV_444_PICTURE: /* 32 bpp 444 transformation */
YUV_TRANSFORM( 444,
p_vout->pi_trans32_red,
p_vout->pi_trans32_green,
p_vout->pi_trans32_blue,
pi_pic32 );
break;
}
break;
}
}
......@@ -58,8 +58,6 @@ typedef struct vout_sys_s
int i_buffer_index; /* buffer index */
XImage * p_ximage[2]; /* XImage pointer */
XShmSegmentInfo shm_info[2]; /* shared memory zone information */
int i_completion_type; /* ?? */
} vout_sys_t;
/*******************************************************************************
......@@ -234,6 +232,20 @@ void vout_SysDisplay( vout_thread_t *p_vout )
p_vout->p_sys->i_buffer_index = ++p_vout->p_sys->i_buffer_index & 1;
}
/*******************************************************************************
* vout_SysGetPicture: get current display buffer informations
*******************************************************************************
* This function returns the address of the current display buffer, and the
* number of samples per line. For 15, 16 and 32 bits displays, this value is
* the number of pixels in a line.
*******************************************************************************/
byte_t * vout_SysGetPicture( vout_thread_t *p_vout, int *pi_eol_offset )
{
*pi_eol_offset = p_vout->i_width;
return( p_vout->p_sys->p_ximage[ p_vout->p_sys->i_buffer_index ]->data );
}
/* following functions are local */
/*******************************************************************************
......@@ -256,40 +268,16 @@ static int X11GetProperties( vout_thread_t *p_vout )
switch( p_vout->i_screen_depth )
{
case 15: /* 15 bpp (16bpp with a missing green bit) */
p_vout->i_bytes_per_pixel = 2;
/*
?? */
break;
case 16: /* 16 bpp (65536 colors) */
p_vout->i_bytes_per_pixel = 2;
/*
Process_Frame=Translate_Frame;
Process_Top_Field=Translate_Top_Field;
Process_Bottom_Field=Translate_Bottom_Field;
Process_Top_Field420=Translate_Top_Field420;
Process_Bottom_Field420=Translate_Bottom_Field420; ?? */
break;
case 24: /* 24 bpp (millions of colors) */
p_vout->i_bytes_per_pixel = 3;
/*
Process_Frame=Translate_Frame;
Process_Top_Field=Translate_Top_Field;
Process_Bottom_Field=Translate_Bottom_Field;
Process_Top_Field420=Translate_Top_Field420;
Process_Bottom_Field420=Translate_Bottom_Field420; ?? */
break;
case 32: /* 32 bpp (millions of colors) */
p_vout->i_bytes_per_pixel = 4;
/*
Process_Frame=Translate_Frame;
Process_Top_Field=Translate_Top_Field;
Process_Bottom_Field=Translate_Bottom_Field;
Process_Top_Field420=Translate_Top_Field420;
Process_Bottom_Field420=Translate_Bottom_Field420; ?? */
break;
default: /* unsupported screen depth */
......@@ -579,11 +567,6 @@ static int X11CreateShmImage( vout_thread_t *p_vout, XImage **pp_ximage,
XDestroyImage( *pp_ximage );
return( -1 );
}
/* ?? don't know what it is. Function XShmGetEventBase prototype is defined
* in mit-shm document, but does not appears in any header. */
p_vout->p_sys->i_completion_type = XShmGetEventBase(p_vout->p_sys->p_display) + ShmCompletion;
return( 0 );
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment