/*******************************************************************************
* 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) */
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
{
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
{
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;
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
}
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
{
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 );
}
// 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 );
}
/* 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 );
}
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 );
{
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;
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++)
break;
}
- //????
-
/* Mark thread as running and return */
*p_vout->pi_status = THREAD_READY;
intf_DbgMsg("%p -> succeeded\n", 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 )
{
/* End of thread */
EndThread( p_vout );
- intf_DbgMsg( "0x%x end\n", p_vout );
+ intf_DbgMsg( "%p end\n", 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;
+ }
+}
+
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;
/*******************************************************************************
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 */
/*******************************************************************************
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 */
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 );
}