Commit d8fe284a authored by Vincent Seguin's avatar Vincent Seguin

Temporaire (�a segfaulte si on le chatouille un peu).

YUV walken avec resize. Y et + seulement pour le moment.
parent fc6b9b04
......@@ -97,15 +97,17 @@ typedef struct picture_s
typedef struct subpicture_s
{
/* Type and flags - should NOT be modified except by the vout thread */
int i_type; /* spu type */
int i_status; /* spu flags */
int i_type; /* type */
int i_status; /* flags */
int i_size; /* data size */
/* Other properties */
mtime_t begin_date; /* beginning of display date */
mtime_t end_date; /* end of display date */
/* Display properties - these properties are only indicative and may be
* changed by the video output thread */
* changed by the video output thread, or simply ignored depending of the
* subpicture type. */
int i_x; /* offset from alignment position */
int i_y; /* offset from alignment position */
int i_width; /* picture width */
......@@ -113,15 +115,30 @@ typedef struct subpicture_s
int i_horizontal_align; /* horizontal alignment */
int i_vertical_align; /* vertical alignment */
/* Sub picture unit data - data can always be freely modified. p_data itself
* (the pointer) should NEVER be modified. */
void * p_data; /* spu data */
/* Additionnal properties depending of the subpicture type */
union
{
/* Text subpictures properties - text is stored in data area, in ASCIIZ
* format */
struct
{
p_vout_font_t p_font; /* font, NULL for default */
int i_style; /* text style */
u32 i_char_color; /* character color */
u32 i_border_color; /* border color */
u32 i_bg_color; /* background color */
} text;
} type;
/* Subpicture data, format depends of type - data can always be freely
* modified. p_data itself (the pointer) should NEVER be modified. */
void * p_data; /* subpicture data */
} subpicture_t;
/* Subpicture type */
#define EMPTY_SUBPICTURE 0 /* subtitle slot is empty and available */
#define RLE_SUBPICTURE 100 /* RLE encoded subtitle */
#define TEXT_SUBPICTURE 200 /* iso8859-1 text subtitle */
#define TEXT_SUBPICTURE 200 /* single line text */
/* Subpicture status */
#define FREE_SUBPICTURE 0 /* subpicture is free and not allocated */
......
......@@ -17,16 +17,13 @@
* p_pic picture address
* p_y, p_u, p_v Y,U,V samples addresses
* i_width, i_height Y samples extension
* i_skip Y pixels to skip at the end of a line
* i_pic_width, i_pic_height picture extension
* i_pic_skip pixels to skip at the end of a line
* i_pic_line_width picture total line width
* i_matrix_coefficients matrix coefficients
* Conditions:
* i_width % 16 == 0
*******************************************************************************/
typedef void (vout_yuv_convert_t)( p_vout_thread_t p_vout, void *p_pic,
yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
int i_width, int i_height, int i_skip,
int i_width, int i_height,
int i_pic_width, int i_pic_height, int i_pic_skip,
int i_matrix_coefficients );
......
......@@ -88,7 +88,7 @@ typedef struct video_synchro_s
} video_synchro_t;
#define SYNC_TOLERATE 10000 /* 10 ms */
#define SYNC_DELAY 100000
#define SYNC_DELAY 500000
#endif
/*****************************************************************************
......
......@@ -10,36 +10,21 @@
/*******************************************************************************
* Preamble
*******************************************************************************/
#include "vlc.h"
/*
#include <errno.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/soundcard.h>
#include <sys/uio.h>
#include "config.h"
#include "common.h"
#include "mtime.h"
#include "vlc_thread.h"
#include "input.h"
#include "input_vlan.h"
#include "audio_output.h"
#include "video.h"
#include "video_output.h"
#include "xconsole.h"
#include "interface.h"
#include "intf_msg.h"
#include "intf_cmd.h"
#include "intf_ctrl.h"
*/
#include "main.h"
/*
* Local prototypes
......
......@@ -264,7 +264,110 @@ void vout_DisplaySubPicture( vout_thread_t *p_vout, subpicture_t *p_subpic )
subpicture_t *vout_CreateSubPicture( vout_thread_t *p_vout, int i_type,
int i_size )
{
//??
int i_subpic; /* subpicture index */
subpicture_t * p_free_subpic = NULL; /* first free subpicture */
subpicture_t * p_destroyed_subpic = NULL; /* first destroyed subpic */
/* Get lock */
vlc_mutex_lock( &p_vout->subpicture_lock );
/*
* Look for an empty place
*/
for( i_subpic = 0; i_subpic < VOUT_MAX_PICTURES; i_subpic++ )
{
if( p_vout->p_subpicture[i_subpic].i_status == DESTROYED_SUBPICTURE )
{
/* Subpicture is marked for destruction, but is still allocated */
if( (p_vout->p_subpicture[i_subpic].i_type == i_type) &&
(p_vout->p_subpicture[i_subpic].i_size >= i_size) )
{
/* Memory size do match or is smaller : memory will not be reallocated,
* and function can end immediately - this is the best possible case,
* since no memory allocation needs to be done */
p_vout->p_subpicture[i_subpic].i_status = RESERVED_SUBPICTURE;
#ifdef DEBUG_VIDEO
intf_DbgMsg("subpicture %p (in destroyed subpicture slot)\n",
&p_vout->p_subpicture[i_subpic] );
#endif
vlc_mutex_unlock( &p_vout->subpicture_lock );
return( &p_vout->p_subpicture[i_subpic] );
}
else if( p_destroyed_subpic == NULL )
{
/* Memory size do not match, but subpicture index will be kept in
* case no other place are left */
p_destroyed_subpic = &p_vout->p_subpicture[i_subpic];
}
}
else if( (p_free_subpic == NULL) &&
(p_vout->p_subpicture[i_subpic].i_status == FREE_SUBPICTURE ))
{
/* Subpicture is empty and ready for allocation */
p_free_subpic = &p_vout->p_subpicture[i_subpic];
}
}
/* If no free subpicture is available, use a destroyed subpicture */
if( (p_free_subpic == NULL) && (p_destroyed_subpic != NULL ) )
{
/* No free subpicture or matching destroyed subpicture has been found, but
* a destroyed subpicture is still avalaible */
free( p_destroyed_subpic->p_data );
p_free_subpic = p_destroyed_subpic;
}
/*
* Prepare subpicture
*/
if( p_free_subpic != NULL )
{
/* Allocate memory */
switch( i_type )
{
case TEXT_SUBPICTURE: /* text subpicture */
p_free_subpic->p_data = malloc( i_size + 1 );
break;
#ifdef DEBUG
default:
intf_DbgMsg("error: unknown subpicture type %d\n", i_type );
p_free_subpic->p_data = NULL;
break;
#endif
}
if( p_free_subpic->p_data != NULL )
{ /* Copy subpicture informations, set some default values */
p_free_subpic->i_type = i_type;
p_free_subpic->i_status = RESERVED_SUBPICTURE;
p_free_subpic->i_size = i_size;
p_free_subpic->i_x = 0;
p_free_subpic->i_y = 0;
p_free_subpic->i_width = 0;
p_free_subpic->i_height = 0;
p_free_subpic->i_horizontal_align = CENTER_RALIGN;
p_free_subpic->i_vertical_align = CENTER_RALIGN;
}
else
{
/* Memory allocation failed : set subpicture as empty */
p_free_subpic->i_type = EMPTY_SUBPICTURE;
p_free_subpic->i_status = FREE_SUBPICTURE;
p_free_subpic = NULL;
intf_ErrMsg("warning: %s\n", strerror( ENOMEM ) );
}
#ifdef DEBUG_VIDEO
intf_DbgMsg("subpicture %p (in free subpicture slot)\n", p_free_subpic );
#endif
vlc_mutex_unlock( &p_vout->subpicture_lock );
return( p_free_subpic );
}
/* No free or destroyed subpicture could be found */
intf_DbgMsg( "warning: heap is full\n" );
vlc_mutex_unlock( &p_vout->subpicture_lock );
return( NULL );
}
/******************************************************************************
......@@ -380,9 +483,7 @@ picture_t *vout_CreatePicture( vout_thread_t *p_vout, int i_type,
/*
* Look for an empty place
*/
for( i_picture = 0;
i_picture < VOUT_MAX_PICTURES;
i_picture++ )
for( i_picture = 0; i_picture < VOUT_MAX_PICTURES; i_picture++ )
{
if( p_vout->p_picture[i_picture].i_status == DESTROYED_PICTURE )
{
......@@ -497,7 +598,7 @@ picture_t *vout_CreatePicture( vout_thread_t *p_vout, int i_type,
return( p_free_picture );
}
// No free or destroyed picture could be found
/* No free or destroyed picture could be found */
intf_DbgMsg( "warning: heap is full\n" );
vlc_mutex_unlock( &p_vout->picture_lock );
return( NULL );
......@@ -1167,7 +1268,7 @@ static void SetBufferPicture( vout_thread_t *p_vout, picture_t *p_pic )
/* Try horizontal scaling first */
i_pic_width = ( p_vout->b_scale || (p_pic->i_width > i_vout_width)) ?
i_vout_width : p_pic->i_width;
i_pic_width = i_pic_width / 16 * 16; //?? currently, width must be multiple of 16
i_pic_width = i_pic_width;
switch( p_pic->i_aspect_ratio )
{
case AR_3_4_PICTURE:
......@@ -1207,7 +1308,7 @@ static void SetBufferPicture( vout_thread_t *p_vout, picture_t *p_pic )
i_pic_width = p_pic->i_width * i_pic_height / p_pic->i_height;
break;
}
i_pic_width = i_pic_width / 16 * 16; //?? currently, width must be multiple of 16
i_pic_width = i_pic_width;
}
/* Set picture position */
......@@ -1311,25 +1412,25 @@ static void RenderPicture( vout_thread_t *p_vout, picture_t *p_pic )
case YUV_420_PICTURE:
p_vout->yuv.p_Convert420( p_vout, p_pic_data,
p_pic->p_y, p_pic->p_u, p_pic->p_v,
p_pic->i_width, p_pic->i_height, 0,
p_pic->i_width, p_pic->i_height,
p_buffer->i_pic_width, p_buffer->i_pic_height,
p_vout->i_bytes_per_line / p_vout->i_bytes_per_pixel - p_buffer->i_pic_width,
p_vout->i_bytes_per_line / p_vout->i_bytes_per_pixel,
p_pic->i_matrix_coefficients );
break;
case YUV_422_PICTURE:
p_vout->yuv.p_Convert422( p_vout, p_pic_data,
p_pic->p_y, p_pic->p_u, p_pic->p_v,
p_pic->i_width, p_pic->i_height, 0,
p_pic->i_width, p_pic->i_height,
p_buffer->i_pic_width, p_buffer->i_pic_height,
p_vout->i_bytes_per_line / p_vout->i_bytes_per_pixel - p_buffer->i_pic_width,
p_vout->i_bytes_per_line / p_vout->i_bytes_per_pixel,
p_pic->i_matrix_coefficients );
break;
case YUV_444_PICTURE:
p_vout->yuv.p_Convert444( p_vout, p_pic_data,
p_pic->p_y, p_pic->p_u, p_pic->p_v,
p_pic->i_width, p_pic->i_height, 0,
p_pic->i_width, p_pic->i_height,
p_buffer->i_pic_width, p_buffer->i_pic_height,
p_vout->i_bytes_per_line / p_vout->i_bytes_per_pixel - p_buffer->i_pic_width,
p_vout->i_bytes_per_line / p_vout->i_bytes_per_pixel,
p_pic->i_matrix_coefficients );
break;
#ifdef DEBUG
......@@ -1481,7 +1582,40 @@ static void RenderInfo( vout_thread_t *p_vout )
*******************************************************************************/
static void RenderSubPicture( vout_thread_t *p_vout, subpicture_t *p_subpic )
{
//??
p_vout_font_t p_font; /* text font */
int i_width, i_height; /* subpicture dimensions */
switch( p_subpic->i_type )
{
case TEXT_SUBPICTURE: /* single line text */
/* Select default font if not specified */
p_font = p_subpic->type.text.p_font;
if( p_font == NULL )
{
p_font = p_vout->p_default_font;
}
/* Computes text size (width and height fields are ignored) and print it */
vout_TextSize( p_font, p_subpic->type.text.i_style, p_subpic->p_data, &i_width, &i_height );
if( !Align( p_vout, &p_subpic->i_x, &p_subpic->i_y, i_width, i_height,
p_subpic->i_horizontal_align, p_subpic->i_vertical_align ) )
{
vout_Print( p_font, p_vout->p_buffer[ p_vout->i_buffer_index ].p_data +
p_subpic->i_x * p_vout->i_bytes_per_pixel +
p_subpic->i_y * p_vout->i_bytes_per_line,
p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line,
p_subpic->type.text.i_char_color, p_subpic->type.text.i_border_color,
p_subpic->type.text.i_bg_color, p_subpic->type.text.i_style,
p_subpic->p_data );
SetBufferArea( p_vout, p_subpic->i_x, p_subpic->i_y, i_width, i_height );
}
break;
#ifdef DEBUG
default:
intf_DbgMsg("error: unknown subpicture %p type %d\n", p_subpic, p_subpic->i_type );
#endif
}
}
/*******************************************************************************
......
......@@ -41,6 +41,12 @@ const int MATRIX_COEFFICIENTS_TABLE[8][4] =
{117579, 136230, 16907, 35559} /* SMPTE 240M (1987) */
};
#define SHIFT 20
#define U_GREEN_COEF ((int)(-0.391 * (1<<SHIFT) / 1.164))
#define U_BLUE_COEF ((int)(2.018 * (1<<SHIFT) / 1.164))
#define V_RED_COEF ((int)(1.596 * (1<<SHIFT) / 1.164))
#define V_GREEN_COEF ((int)(-0.813 * (1<<SHIFT) / 1.164))
/*******************************************************************************
* Local prototypes
*******************************************************************************/
......@@ -50,47 +56,42 @@ static void SetGammaTable ( int *pi_table, double f_gamma );
static void SetYUV ( vout_thread_t *p_vout );
static void ConvertY4Gray16 ( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
int i_width, int i_height, int i_skip, int i_pic_width, int i_pic_height, int i_pic_skip,
int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
int i_matrix_coefficients );
static void ConvertY4Gray24 ( p_vout_thread_t p_vout, void *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
int i_width, int i_height, int i_skip, int i_pic_width, int i_pic_height, int i_pic_skip,
int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
int i_matrix_coefficients );
static void ConvertY4Gray32 ( p_vout_thread_t p_vout, u32 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
int i_width, int i_height, int i_skip, int i_pic_width, int i_pic_height, int i_pic_skip,
int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
int i_matrix_coefficients );
static void ConvertYUV420RGB16( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
int i_width, int i_height, int i_skip, int i_pic_width, int i_pic_height, int i_pic_skip,
int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
int i_matrix_coefficients );
static void ConvertYUV422RGB16( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
int i_width, int i_height, int i_skip, int i_pic_width, int i_pic_height, int i_pic_skip,
int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
int i_matrix_coefficients );
static void ConvertYUV444RGB16( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
int i_width, int i_height, int i_skip, int i_pic_width, int i_pic_height, int i_pic_skip,
int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
int i_matrix_coefficients );
static void ConvertYUV420RGB24( p_vout_thread_t p_vout, void *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
int i_width, int i_height, int i_skip, int i_pic_width, int i_pic_height, int i_pic_skip,
int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
int i_matrix_coefficients );
static void ConvertYUV422RGB24( p_vout_thread_t p_vout, void *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
int i_width, int i_height, int i_skip, int i_pic_width, int i_pic_height, int i_pic_skip,
int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
int i_matrix_coefficients );
static void ConvertYUV444RGB24( p_vout_thread_t p_vout, void *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
int i_width, int i_height, int i_skip, int i_pic_width, int i_pic_height, int i_pic_skip,
int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
int i_matrix_coefficients );
static void ConvertYUV420RGB32( p_vout_thread_t p_vout, u32 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
int i_width, int i_height, int i_skip, int i_pic_width, int i_pic_height, int i_pic_skip,
int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
int i_matrix_coefficients );
static void ConvertYUV422RGB32( p_vout_thread_t p_vout, u32 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
int i_width, int i_height, int i_skip, int i_pic_width, int i_pic_height, int i_pic_skip,
int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
int i_matrix_coefficients );
static void ConvertYUV444RGB32( p_vout_thread_t p_vout, u32 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
int i_width, int i_height, int i_skip, int i_pic_width, int i_pic_height, int i_pic_skip,
int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
int i_matrix_coefficients );
//?? temporary prototypes, will be integrated to normal ones */
void yuv420ToRgb16_scaled (unsigned char * Y, unsigned char * U, unsigned char * V,
short * dest, short table[1935], int width , int dest_width,
int height, int dest_height, int skip, int dest_skip,short * buffer);
/*******************************************************************************
* CLIP_BYTE macro: boundary detection
*******************************************************************************
......@@ -99,36 +100,6 @@ void yuv420ToRgb16_scaled (unsigned char * Y, unsigned char * U, unsigned char *
*******************************************************************************/
#define CLIP_BYTE( i_val ) ( (i_val < 0) ? 0 : ((i_val > 255) ? 255 : i_val) )
/*******************************************************************************
* LINE_COPY macro: memcopy using 16 pixels blocks
*******************************************************************************
* Variables:
* p_pic destination pointer
* p_pic_src source pointer
* i_width width
* i_x index
*******************************************************************************/
#define LINE_COPY \
for( i_x = 0; i_x < i_width; i_x+=16 ) \
{ \
*p_pic++ = *p_pic_src++; \
*p_pic++ = *p_pic_src++; \
*p_pic++ = *p_pic_src++; \
*p_pic++ = *p_pic_src++; \
*p_pic++ = *p_pic_src++; \
*p_pic++ = *p_pic_src++; \
*p_pic++ = *p_pic_src++; \
*p_pic++ = *p_pic_src++; \
*p_pic++ = *p_pic_src++; \
*p_pic++ = *p_pic_src++; \
*p_pic++ = *p_pic_src++; \
*p_pic++ = *p_pic_src++; \
*p_pic++ = *p_pic_src++; \
*p_pic++ = *p_pic_src++; \
*p_pic++ = *p_pic_src++; \
*p_pic++ = *p_pic_src++; \
}
/*******************************************************************************
* CONVERT_YUV_GRAY macro: grayscale YUV convertion
*******************************************************************************
......@@ -137,38 +108,36 @@ for( i_x = 0; i_x < i_width; i_x+=16 ) \
*******************************************************************************/
#define CONVERT_YUV_GRAY \
/* Change boundaries according to picture size */ \
i_pic_skip += i_pic_width - MIN( i_width, i_pic_width ); \
i_skip += i_width - MIN( i_width, i_pic_width ); \
i_width = MIN( i_width, i_pic_width ); \
i_height = MIN( i_height, i_pic_height ); \
i_pic_line_width -= i_width; \
\
/* Loop */ \
for (i_y = 0; i_y < i_height ; i_y++) \
{ \
for (i_x = 0; i_x < i_width; i_x += 16) \
for (i_x = 0; i_x < i_width; ) \
{ \
/* Convert 16 pixels (width is always multiple of 16 */ \
*p_pic++ = p_gray[ *p_y++ ]; \
*p_pic++ = p_gray[ *p_y++ ]; \
*p_pic++ = p_gray[ *p_y++ ]; \
*p_pic++ = p_gray[ *p_y++ ]; \
*p_pic++ = p_gray[ *p_y++ ]; \
*p_pic++ = p_gray[ *p_y++ ]; \
*p_pic++ = p_gray[ *p_y++ ]; \
*p_pic++ = p_gray[ *p_y++ ]; \
*p_pic++ = p_gray[ *p_y++ ]; \
*p_pic++ = p_gray[ *p_y++ ]; \
*p_pic++ = p_gray[ *p_y++ ]; \
*p_pic++ = p_gray[ *p_y++ ]; \
*p_pic++ = p_gray[ *p_y++ ]; \
*p_pic++ = p_gray[ *p_y++ ]; \
*p_pic++ = p_gray[ *p_y++ ]; \
*p_pic++ = p_gray[ *p_y++ ]; \
p_pic[i_x++] = p_gray[ p_y[i_x] ]; \
p_pic[i_x++] = p_gray[ p_y[i_x] ]; \
p_pic[i_x++] = p_gray[ p_y[i_x] ]; \
p_pic[i_x++] = p_gray[ p_y[i_x] ]; \
p_pic[i_x++] = p_gray[ p_y[i_x] ]; \
p_pic[i_x++] = p_gray[ p_y[i_x] ]; \
p_pic[i_x++] = p_gray[ p_y[i_x] ]; \
p_pic[i_x++] = p_gray[ p_y[i_x] ]; \
p_pic[i_x++] = p_gray[ p_y[i_x] ]; \
p_pic[i_x++] = p_gray[ p_y[i_x] ]; \
p_pic[i_x++] = p_gray[ p_y[i_x] ]; \
p_pic[i_x++] = p_gray[ p_y[i_x] ]; \
p_pic[i_x++] = p_gray[ p_y[i_x] ]; \
p_pic[i_x++] = p_gray[ p_y[i_x] ]; \
p_pic[i_x++] = p_gray[ p_y[i_x] ]; \
p_pic[i_x++] = p_gray[ p_y[i_x] ]; \
} \
\
/* Skip until beginning of next line */ \
p_y += i_skip; \
p_pic += i_pic_skip; \
p_pic += i_pic_line_width; \
}
/*******************************************************************************
......@@ -177,39 +146,37 @@ for (i_y = 0; i_y < i_height ; i_y++) \
* This macro does not perform any scaling, but crops the picture. It is
* provided as a temporary way of implementing an YUV convertion function.
*******************************************************************************/
#define CONVERT_YUV_RGB( CHROMA ) \
#define CONVERT_YUV_RGB( CHROMA, CRV, CGV, CBU, CGU ) \
/* Change boundaries according to picture size */ \
i_pic_skip += i_pic_width - MIN( i_width, i_pic_width ); \
i_skip += i_width - MIN( i_width, i_pic_width ); \
i_width = MIN( i_width, i_pic_width ); \
i_height = MIN( i_height, i_pic_height ); \
i_chroma_skip = (CHROMA == 444) ? i_skip : i_skip / 2; \
i_chroma_width = (CHROMA == 444) ? i_width : i_width / 2; \
i_pic_line_width -= i_width; \
\
/* Loop */ \
for (i_y = 0; i_y < i_height ; i_y++) \
{ \
for (i_x = 0; i_x < i_width; i_x += 2 ) \
for (i_x = 0; i_x < i_width; ) \
{ \
/* First sample (complete) */ \
i_yval = 76309 * *p_y++ - 1188177; \
i_yval = 76309 * p_y[i_x] - 1188177; \
i_uval = *p_u++ - 128; \
i_vval = *p_v++ - 128; \
*p_pic++ = \
p_red [(i_yval+i_crv*i_vval) >>16] | \
p_green[(i_yval-i_cgu*i_uval-i_cgv*i_vval) >>16] | \
p_blue [(i_yval+i_cbu*i_uval) >>16]; \
i_yval = 76309 * *p_y++ - 1188177; \
p_pic[i_x++] = \
p_red [(i_yval+CRV*i_vval) >>16] | \
p_green[(i_yval-CGU*i_uval-CGV*i_vval) >>16] | \
p_blue [(i_yval+CBU*i_uval) >>16]; \
i_yval = 76309 * p_y[i_x] - 1188177; \
/* Second sample (partial) */ \
if( CHROMA == 444 ) \
{ \
i_uval = *p_u++ - 128; \
i_vval = *p_v++ - 128; \
} \
*p_pic++ = \
p_red [(i_yval+i_crv*i_vval) >>16] | \
p_green[(i_yval-i_cgu*i_uval-i_cgv*i_vval) >>16] | \
p_blue [(i_yval+i_cbu*i_uval) >>16]; \
p_pic[i_x++] = \
p_red [(i_yval+CRV*i_vval) >>16] | \
p_green[(i_yval-CGU*i_uval-CGV*i_vval) >>16] | \
p_blue [(i_yval+CBU*i_uval) >>16]; \
} \
\
/* Rewind in 4:2:0 */ \
......@@ -217,19 +184,12 @@ for (i_y = 0; i_y < i_height ; i_y++) \
{ \
p_u -= i_chroma_width; \
p_v -= i_chroma_width; \
} \
else \
{ \
p_u += i_chroma_skip; \
p_v += i_chroma_skip; \
} \
\
/* Skip until beginning of next line */ \
p_y += i_skip; \
p_pic += i_pic_skip; \
p_pic += i_pic_line_width; \
}
/*******************************************************************************
* vout_InitYUV: allocate and initialize translations tables
*******************************************************************************
......@@ -570,7 +530,7 @@ static void SetYUV( vout_thread_t *p_vout )
* ConvertY4Gray16: grayscale YUV 4:x:x to RGB 15 or 16 bpp
*******************************************************************************/
static void ConvertY4Gray16( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
int i_width, int i_height, int i_skip, int i_pic_width, int i_pic_height, int i_pic_skip,
int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
int i_matrix_coefficients )
{
u16 * p_gray; /* gray table */
......@@ -584,7 +544,7 @@ static void ConvertY4Gray16( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *p_y
* ConvertY4Gray24: grayscale YUV 4:x:x to RGB 24 bpp
*******************************************************************************/
static void ConvertY4Gray24( p_vout_thread_t p_vout, void *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
int i_width, int i_height, int i_skip, int i_pic_width, int i_pic_height, int i_pic_skip,
int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
int i_matrix_coefficients )
{
//??
......@@ -594,7 +554,7 @@ static void ConvertY4Gray24( p_vout_thread_t p_vout, void *p_pic, yuv_data_t *p_
* ConvertY4Gray32: grayscale YUV 4:x:x to RGB 32 bpp
*******************************************************************************/
static void ConvertY4Gray32( p_vout_thread_t p_vout, u32 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
int i_width, int i_height, int i_skip, int i_pic_width, int i_pic_height, int i_pic_skip,
int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
int i_matrix_coefficients )
{
u32 * p_gray; /* gray table */
......@@ -608,19 +568,12 @@ static void ConvertY4Gray32( p_vout_thread_t p_vout, u32 *p_pic, yuv_data_t *p_y
* ConvertYUV420RGB16: color YUV 4:2:0 to RGB 15 or 16 bpp
*******************************************************************************/
static void ConvertYUV420RGB16( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
int i_width, int i_height, int i_skip, int i_pic_width, int i_pic_height, int i_pic_skip,
int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
int i_matrix_coefficients )
{
//?? gloups: find a good one !
#if 0
intf_DbgMsg("%dx%d-%d -> %dx%d-%d\n", i_width, i_height, i_skip, i_pic_width, i_pic_height, i_pic_skip );
yuv420ToRgb16_scaled ( p_y, p_u, p_v, p_pic, p_vout->yuv.yuv2.p_rgb16,
i_width , i_pic_width, i_height, i_pic_height, i_skip, i_pic_skip,
p_vout->yuv.p_buffer);
#elif 0
//#ifdef HAVE_MMX
int i_chroma_width, i_chroma_skip; /* width and eol for chroma */
/* MMX version */
// int i_chroma_width, i_chroma_skip; /* width and eol for chroma */
/*
i_chroma_width = i_width / 2;
i_chroma_skip = i_skip / 2;
ConvertYUV420RGB16MMX( p_y, p_u, p_v, i_width, i_height,
......@@ -628,7 +581,9 @@ static void ConvertYUV420RGB16( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *
(i_chroma_width + i_chroma_skip) * sizeof( yuv_data_t),
i_scale, (u8 *)p_pic, 0, 0, (i_width + i_pic_eol) * sizeof( u16 ),
p_vout->i_screen_depth == 15 );
#else
*/
#if 0
u16 * p_red; /* red table */
u16 * p_green; /* green table */
u16 * p_blue; /* blue table */
......@@ -637,14 +592,191 @@ static void ConvertYUV420RGB16( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *
int i_chroma_width, i_chroma_skip; /* width and eol for chroma */
int i_crv, i_cbu, i_cgu, i_cgv; /* transformation coefficients */
p_red = p_vout->yuv.yuv.rgb16.p_red;
p_green = p_vout->yuv.yuv.rgb16.p_green;
p_blue = p_vout->yuv.yuv.rgb16.p_blue;
i_crv = MATRIX_COEFFICIENTS_TABLE[i_matrix_coefficients][0];
i_cbu = MATRIX_COEFFICIENTS_TABLE[i_matrix_coefficients][1];
i_cgu = MATRIX_COEFFICIENTS_TABLE[i_matrix_coefficients][2];
i_cgv = MATRIX_COEFFICIENTS_TABLE[i_matrix_coefficients][3];
p_red = p_vout->yuv.yuv.rgb16.p_red;
p_green = p_vout->yuv.yuv.rgb16.p_green;
p_blue = p_vout->yuv.yuv.rgb16.p_blue;
CONVERT_YUV_RGB( 420 )
CONVERT_YUV_RGB( 420, i_crv, i_cgv, i_cbu, i_cgu );
#else
int i_x, i_y; /* horizontal and vertical indexes */
int i_uval, i_vval; /* U and V samples */
int i_red, i_green, i_blue; /* U and V modified samples */
int i_chroma_width; /* chroma width */
int i_height_count; /* height modulo counter */
u16 * p_yuv; /* base convertion table */
u16 * p_ybase; /* Y dependant convertion table */
u16 * p_pic_start;
/* Initialize values */
i_height_count = i_pic_height;
i_chroma_width = i_width / 2;
p_yuv = p_vout->yuv.yuv2.p_rgb16;
/*?? temporary kludge to protect from segfault at startup */
i_height = MIN( i_height, i_pic_height );
/*
* Perform convertion
*/
for( i_y = 0; i_y < i_height; i_y++ )
{
/* Mark beginnning of line */
p_pic_start = p_pic;
/* Convert line using 16 pixels blocks, since picture come from 16 pixels width
* macroblocks */
for( i_x = i_width / 16; i_x--; )
{
i_uval = *p_u++;
i_vval = *p_v++;
i_red = (V_RED_COEF * i_vval) >> SHIFT;
i_green = (U_GREEN_COEF * i_uval + V_GREEN_COEF * i_vval) >> SHIFT;
i_blue = (U_BLUE_COEF * i_uval) >> SHIFT;
p_ybase = p_yuv + *(p_y++);
*(p_pic++) = p_ybase[1501 - ((V_RED_COEF*128)>>SHIFT) + i_red] |
p_ybase[135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + i_green ] |
p_ybase[818 - ((U_BLUE_COEF*128)>>SHIFT) + i_blue];
p_ybase = p_yuv + *(p_y++);
*(p_pic++) = p_ybase[1501 - ((V_RED_COEF*128)>>SHIFT) + i_red] |
p_ybase[135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + i_green ] |
p_ybase[818 - ((U_BLUE_COEF*128)>>SHIFT) + i_blue];
i_uval = *p_u++;
i_vval = *p_v++;
i_red = (V_RED_COEF * i_vval) >> SHIFT;
i_green = (U_GREEN_COEF * i_uval + V_GREEN_COEF * i_vval) >> SHIFT;
i_blue = (U_BLUE_COEF * i_uval) >> SHIFT;
p_ybase = p_yuv + *(p_y++);
*(p_pic++) = p_ybase[1501 - ((V_RED_COEF*128)>>SHIFT) + i_red] |
p_ybase[135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + i_green ] |
p_ybase[818 - ((U_BLUE_COEF*128)>>SHIFT) + i_blue];
p_ybase = p_yuv + *(p_y++);
*(p_pic++) = p_ybase[1501 - ((V_RED_COEF*128)>>SHIFT) + i_red] |
p_ybase[135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + i_green ] |
p_ybase[818 - ((U_BLUE_COEF*128)>>SHIFT) + i_blue];
i_uval = *p_u++;
i_vval = *p_v++;
i_red = (V_RED_COEF * i_vval) >> SHIFT;
i_green = (U_GREEN_COEF * i_uval + V_GREEN_COEF * i_vval) >> SHIFT;
i_blue = (U_BLUE_COEF * i_uval) >> SHIFT;
p_ybase = p_yuv + *(p_y++);
*(p_pic++) = p_ybase[1501 - ((V_RED_COEF*128)>>SHIFT) + i_red] |
p_ybase[135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + i_green ] |
p_ybase[818 - ((U_BLUE_COEF*128)>>SHIFT) + i_blue];
p_ybase = p_yuv + *(p_y++);
*(p_pic++) = p_ybase[1501 - ((V_RED_COEF*128)>>SHIFT) + i_red] |
p_ybase[135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + i_green ] |
p_ybase[818 - ((U_BLUE_COEF*128)>>SHIFT) + i_blue];
i_uval = *p_u++;
i_vval = *p_v++;
i_red = (V_RED_COEF * i_vval) >> SHIFT;
i_green = (U_GREEN_COEF * i_uval + V_GREEN_COEF * i_vval) >> SHIFT;
i_blue = (U_BLUE_COEF * i_uval) >> SHIFT;
p_ybase = p_yuv + *(p_y++);
*(p_pic++) = p_ybase[1501 - ((V_RED_COEF*128)>>SHIFT) + i_red] |
p_ybase[135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + i_green ] |
p_ybase[818 - ((U_BLUE_COEF*128)>>SHIFT) + i_blue];
p_ybase = p_yuv + *(p_y++);
*(p_pic++) = p_ybase[1501 - ((V_RED_COEF*128)>>SHIFT) + i_red] |
p_ybase[135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + i_green ] |
p_ybase[818 - ((U_BLUE_COEF*128)>>SHIFT) + i_blue];
i_uval = *p_u++;
i_vval = *p_v++;
i_red = (V_RED_COEF * i_vval) >> SHIFT;
i_green = (U_GREEN_COEF * i_uval + V_GREEN_COEF * i_vval) >> SHIFT;
i_blue = (U_BLUE_COEF * i_uval) >> SHIFT;
p_ybase = p_yuv + *(p_y++);
*(p_pic++) = p_ybase[1501 - ((V_RED_COEF*128)>>SHIFT) + i_red] |
p_ybase[135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + i_green ] |
p_ybase[818 - ((U_BLUE_COEF*128)>>SHIFT) + i_blue];
p_ybase = p_yuv + *(p_y++);
*(p_pic++) = p_ybase[1501 - ((V_RED_COEF*128)>>SHIFT) + i_red] |
p_ybase[135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + i_green ] |
p_ybase[818 - ((U_BLUE_COEF*128)>>SHIFT) + i_blue];
i_uval = *p_u++;
i_vval = *p_v++;
i_red = (V_RED_COEF * i_vval) >> SHIFT;
i_green = (U_GREEN_COEF * i_uval + V_GREEN_COEF * i_vval) >> SHIFT;
i_blue = (U_BLUE_COEF * i_uval) >> SHIFT;
p_ybase = p_yuv + *(p_y++);
*(p_pic++) = p_ybase[1501 - ((V_RED_COEF*128)>>SHIFT) + i_red] |
p_ybase[135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + i_green ] |
p_ybase[818 - ((U_BLUE_COEF*128)>>SHIFT) + i_blue];
p_ybase = p_yuv + *(p_y++);
*(p_pic++) = p_ybase[1501 - ((V_RED_COEF*128)>>SHIFT) + i_red] |
p_ybase[135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + i_green ] |
p_ybase[818 - ((U_BLUE_COEF*128)>>SHIFT) + i_blue];
i_uval = *p_u++;
i_vval = *p_v++;
i_red = (V_RED_COEF * i_vval) >> SHIFT;
i_green = (U_GREEN_COEF * i_uval + V_GREEN_COEF * i_vval) >> SHIFT;
i_blue = (U_BLUE_COEF * i_uval) >> SHIFT;
p_ybase = p_yuv + *(p_y++);
*(p_pic++) = p_ybase[1501 - ((V_RED_COEF*128)>>SHIFT) + i_red] |
p_ybase[135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + i_green ] |
p_ybase[818 - ((U_BLUE_COEF*128)>>SHIFT) + i_blue];
p_ybase = p_yuv + *(p_y++);
*(p_pic++) = p_ybase[1501 - ((V_RED_COEF*128)>>SHIFT) + i_red] |
p_ybase[135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + i_green ] |
p_ybase[818 - ((U_BLUE_COEF*128)>>SHIFT) + i_blue];
i_uval = *p_u++;
i_vval = *p_v++;
i_red = (V_RED_COEF * i_vval) >> SHIFT;
i_green = (U_GREEN_COEF * i_uval + V_GREEN_COEF * i_vval) >> SHIFT;
i_blue = (U_BLUE_COEF * i_uval) >> SHIFT;
p_ybase = p_yuv + *(p_y++);
*(p_pic++) = p_ybase[1501 - ((V_RED_COEF*128)>>SHIFT) + i_red] |
p_ybase[135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + i_green ] |
p_ybase[818 - ((U_BLUE_COEF*128)>>SHIFT) + i_blue];
p_ybase = p_yuv + *(p_y++);
*(p_pic++) = p_ybase[1501 - ((V_RED_COEF*128)>>SHIFT) + i_red] |
p_ybase[135 - (((U_GREEN_COEF+V_GREEN_COEF)*128)>>SHIFT) + i_green ] |
p_ybase[818 - ((U_BLUE_COEF*128)>>SHIFT) + i_blue];
}
/* If line is odd, rewind U and V samples */
if( i_y & 0x1 )
{
p_u -= i_chroma_width;
p_v -= i_chroma_width;
}
/* End of line: skip picture to reach beginning of next line */
p_pic += i_pic_line_width - i_pic_width;
/* Copy line if needed */
while( (i_height_count -= i_height) >= 0 )
{
for( i_x = i_pic_width / 16; i_x--; )
{
*(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ );
*(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ );
*(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ );
*(((u64 *) p_pic)++) = *(((u64 *) p_pic_start)++ );
}
p_pic += i_pic_line_width - i_pic_width;
p_pic_start += i_pic_line_width - i_pic_width;
}
i_height_count += i_pic_height;
}
#endif
}
......@@ -652,7 +784,7 @@ static void ConvertYUV420RGB16( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *
* ConvertYUV422RGB16: color YUV 4:2:2 to RGB 15 or 16 bpp
*******************************************************************************/
static void ConvertYUV422RGB16( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
int i_width, int i_height, int i_skip, int i_pic_width, int i_pic_height, int i_pic_skip,
int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
int i_matrix_coefficients )
{
//??
......@@ -662,7 +794,7 @@ static void ConvertYUV422RGB16( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *
* ConvertYUV444RGB16: color YUV 4:4:4 to RGB 15 or 16 bpp
*******************************************************************************/
static void ConvertYUV444RGB16( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
int i_width, int i_height, int i_skip, int i_pic_width, int i_pic_height, int i_pic_skip,
int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
int i_matrix_coefficients )
{
//??
......@@ -672,7 +804,7 @@ static void ConvertYUV444RGB16( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *
* ConvertYUV420RGB24: color YUV 4:2:0 to RGB 24 bpp
*******************************************************************************/
static void ConvertYUV420RGB24( p_vout_thread_t p_vout, void *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
int i_width, int i_height, int i_skip, int i_pic_width, int i_pic_height, int i_pic_skip,
int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
int i_matrix_coefficients )
{
//???
......@@ -682,7 +814,7 @@ static void ConvertYUV420RGB24( p_vout_thread_t p_vout, void *p_pic, yuv_data_t
* ConvertYUV422RGB24: color YUV 4:2:2 to RGB 24 bpp
*******************************************************************************/
static void ConvertYUV422RGB24( p_vout_thread_t p_vout, void *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
int i_width, int i_height, int i_skip, int i_pic_width, int i_pic_height, int i_pic_skip,
int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
int i_matrix_coefficients )
{
//???
......@@ -692,7 +824,7 @@ static void ConvertYUV422RGB24( p_vout_thread_t p_vout, void *p_pic, yuv_data_t
* ConvertYUV444RGB24: color YUV 4:4:4 to RGB 24 bpp
*******************************************************************************/
static void ConvertYUV444RGB24( p_vout_thread_t p_vout, void *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
int i_width, int i_height, int i_skip, int i_pic_width, int i_pic_height, int i_pic_skip,
int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
int i_matrix_coefficients )
{
//???
......@@ -702,7 +834,7 @@ static void ConvertYUV444RGB24( p_vout_thread_t p_vout, void *p_pic, yuv_data_t
* ConvertYUV420RGB32: color YUV 4:2:0 to RGB 32 bpp
*******************************************************************************/
static void ConvertYUV420RGB32( p_vout_thread_t p_vout, u32 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
int i_width, int i_height, int i_skip, int i_pic_width, int i_pic_height, int i_pic_skip,
int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
int i_matrix_coefficients )
{
//??
......@@ -712,7 +844,7 @@ static void ConvertYUV420RGB32( p_vout_thread_t p_vout, u32 *p_pic, yuv_data_t *
* ConvertYUV422RGB32: color YUV 4:2:2 to RGB 32 bpp
*******************************************************************************/
static void ConvertYUV422RGB32( p_vout_thread_t p_vout, u32 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
int i_width, int i_height, int i_skip, int i_pic_width, int i_pic_height, int i_pic_skip,
int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
int i_matrix_coefficients )
{
//??
......@@ -722,7 +854,7 @@ static void ConvertYUV422RGB32( p_vout_thread_t p_vout, u32 *p_pic, yuv_data_t *
* ConvertYUV444RGB32: color YUV 4:4:4 to RGB 32 bpp
*******************************************************************************/
static void ConvertYUV444RGB32( p_vout_thread_t p_vout, u32 *p_pic, yuv_data_t *p_y, yuv_data_t *p_u, yuv_data_t *p_v,
int i_width, int i_height, int i_skip, int i_pic_width, int i_pic_height, int i_pic_skip,
int i_width, int i_height, int i_pic_width, int i_pic_height, int i_pic_line_width,
int i_matrix_coefficients )
{
//??
......@@ -862,11 +994,6 @@ static int rgbTable32 (int table [1935],
return 0;
}
#define SHIFT 20
#define U_GREEN_COEF ((int)(-0.391 * (1<<SHIFT) / 1.164))
#define U_BLUE_COEF ((int)(2.018 * (1<<SHIFT) / 1.164))
#define V_RED_COEF ((int)(1.596 * (1<<SHIFT) / 1.164))
#define V_GREEN_COEF ((int)(-0.813 * (1<<SHIFT) / 1.164))
void yuvToRgb16 (unsigned char * Y,
unsigned char * U, unsigned char * V,
......
......@@ -380,9 +380,9 @@ mtime_t vpar_SynchroDate( vpar_thread_t * p_vpar )
{
mtime_t i_displaydate = p_vpar->synchro.i_last_display_pts;
#if 0
static mtime_t i_delta = 0;
static mtime_t i_delta = 0;
#if 0
fprintf( stderr,
"displaying type %i with delay %lli and delta %lli\n",
p_vpar->synchro.fifo[p_vpar->synchro.i_fifo_start].i_image_type,
......
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