Commit 3a45b93f authored by Vincent Seguin's avatar Vincent Seguin

Scaling horizontal >=1

parent 01fcd5af
......@@ -293,8 +293,11 @@
#define VPAR_IDLE_SLEEP 100000
/* Time to sleep when waiting for a buffer (from vout or the video fifo). */
#define VPAR_OUTMEM_SLEEP 100000
/* Time to sleep when waiting for a buffer (from vout or the video fifo).
* It should be approximately the time needed to perform a complete picture
* loop. Since it only happens when the video heap is full, it does not need
* to be too low, even if it blocks the decoder. */
#define VPAR_OUTMEM_SLEEP 50000
/* Optimization level, from 0 to 2 - 1 is generally a good compromise. Remember
* that raising this level dramatically lengthens the compilation time. */
......
......@@ -20,6 +20,7 @@
* i_pic_width, i_pic_height picture extension
* i_pic_line_width picture total line width
* i_matrix_coefficients matrix coefficients
* Picture width and source dimensions must be multiples of 16.
*******************************************************************************/
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,
......
......@@ -396,13 +396,13 @@ void vout_DestroySubPicture( vout_thread_t *p_vout, subpicture_t *p_subpic )
#endif
}
/******************************************************************************
/*******************************************************************************
* vout_DisplayPicture: display a picture
******************************************************************************
*******************************************************************************
* Remove the reservation flag of a picture, which will cause it to be ready for
* display. The picture won't be displayed until vout_DatePicture has been
* called.
******************************************************************************/
*******************************************************************************/
void vout_DisplayPicture( vout_thread_t *p_vout, picture_t *p_pic )
{
vlc_mutex_lock( &p_vout->picture_lock );
......@@ -422,21 +422,24 @@ void vout_DisplayPicture( vout_thread_t *p_vout, picture_t *p_pic )
}
#ifdef DEBUG_VIDEO
intf_DbgMsg("picture %p\n", p_pic );
intf_DbgMsg("picture %p\n", p_pic);
#endif
vlc_mutex_unlock( &p_vout->picture_lock );
}
/******************************************************************************
/*******************************************************************************
* vout_DatePicture: date a picture
******************************************************************************
*******************************************************************************
* Remove the reservation flag of a picture, which will cause it to be ready for
* display. The picture won't be displayed until vout_DisplayPicture has been
* called.
******************************************************************************/
*******************************************************************************/
void vout_DatePicture( vout_thread_t *p_vout, picture_t *p_pic, mtime_t date )
{
#ifdef DEBUG_VIDEO
char psz_date[MSTRTIME_MAX_SIZE]; /* date */
#endif
vlc_mutex_lock( &p_vout->picture_lock );
p_pic->date = date;
switch( p_pic->i_status )
......@@ -455,9 +458,8 @@ void vout_DatePicture( vout_thread_t *p_vout, picture_t *p_pic, mtime_t date )
}
#ifdef DEBUG_VIDEO
intf_DbgMsg("picture %p\n", p_pic);
intf_DbgMsg("picture %p, display date: %s\n", p_pic, mstrtime( psz_date, p_pic->date) );
#endif
vlc_mutex_unlock( &p_vout->picture_lock );
}
......@@ -1265,10 +1267,9 @@ static void SetBufferPicture( vout_thread_t *p_vout, picture_t *p_pic )
*/
if( p_pic != NULL )
{
/* 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;
/* Try horizontal scaling first - width must be a mutiple of 16 */
i_pic_width = (( p_vout->b_scale || (p_pic->i_width > i_vout_width)) ?
i_vout_width : p_pic->i_width) & ~0xf;
switch( p_pic->i_aspect_ratio )
{
case AR_3_4_PICTURE:
......@@ -1287,7 +1288,8 @@ static void SetBufferPicture( vout_thread_t *p_vout, picture_t *p_pic )
}
/* If picture dimensions using horizontal scaling are too large, use
* vertical scaling */
* vertical scaling. Since width must be a multiple of 16, height is
* adjusted again after. */
if( i_pic_height > i_vout_height )
{
i_pic_height = ( p_vout->b_scale || (p_pic->i_height > i_vout_height)) ?
......@@ -1295,20 +1297,23 @@ static void SetBufferPicture( vout_thread_t *p_vout, picture_t *p_pic )
switch( p_pic->i_aspect_ratio )
{
case AR_3_4_PICTURE:
i_pic_width = i_pic_height * 4 / 3;
i_pic_width = (i_pic_height * 4 / 3) & ~0xf;
i_pic_height = i_pic_width * 3 / 4;
break;
case AR_16_9_PICTURE:
i_pic_width = i_pic_height * 16 / 9;
i_pic_width = (i_pic_height * 16 / 9) & ~0xf;
i_pic_height = i_pic_width * 9 / 16;
break;
case AR_221_1_PICTURE:
i_pic_width = i_pic_height * 221 / 100;
i_pic_width = (i_pic_height * 221 / 100) & ~0xf;
i_pic_height = i_pic_width * 100 / 221;
break;
case AR_SQUARE_PICTURE:
default:
i_pic_width = p_pic->i_width * i_pic_height / p_pic->i_height;
i_pic_width = (p_pic->i_width * i_pic_height / p_pic->i_height) & ~0xf;
i_pic_height = p_pic->i_height * i_pic_width / p_pic->i_width;
break;
}
i_pic_width = i_pic_width;
}
/* Set picture position */
......@@ -1386,7 +1391,7 @@ static void SetBufferPicture( vout_thread_t *p_vout, picture_t *p_pic )
#ifdef DEBUG_VIDEO
/*
* In DEBUG_VIDEO_MODE, draw white pixels at the beginning and the end of
* In DEBUG_VIDEO mode, draw white pixels at the beginning and the end of
* the picture area. These pixels should not be erased by rendering functions,
* otherwise segmentation fault is menacing !
*/
......@@ -1423,6 +1428,10 @@ static void SetBufferPicture( vout_thread_t *p_vout, picture_t *p_pic )
******************************************************************************/
static void RenderPicture( vout_thread_t *p_vout, picture_t *p_pic )
{
#ifdef DEBUG_VIDEO
char psz_date[MSTRTIME_MAX_SIZE]; /* picture date */
mtime_t render_time; /* picture rendering time */
#endif
vout_buffer_t * p_buffer; /* rendering buffer */
byte_t * p_pic_data; /* convertion destination */
......@@ -1431,6 +1440,9 @@ static void RenderPicture( vout_thread_t *p_vout, picture_t *p_pic )
p_pic_data = p_buffer->p_data +
p_buffer->i_pic_x * p_vout->i_bytes_per_pixel +
p_buffer->i_pic_y * p_vout->i_bytes_per_line;
#ifdef DEBUG_VIDEO
render_time = mdate();
#endif
/*
* Choose appropriate rendering function and render picture
......@@ -1467,6 +1479,12 @@ static void RenderPicture( vout_thread_t *p_vout, picture_t *p_pic )
break;
#endif
}
#ifdef DEBUG_VIDEO
/* Print picture date and rendering time */
intf_DbgMsg("picture %p rendered (%ld us), display date: %s\n", p_pic,
(long) (mdate() - render_time), mstrtime( psz_date, p_pic->date ));
#endif
}
/******************************************************************************
......
......@@ -194,13 +194,12 @@ for (i_y = 0; i_y < i_height ; i_y++) \
* CONVERT_YUV_PIXEL, CONVERT_Y_PIXEL: pixel convertion blocks
*******************************************************************************
* These convertion routines are used by YUV convertion functions.
* Convertion are made from p_y, p_u, p_v, which are modified, to p_pic, which
* is also modified.
* Convertion are made from p_y, p_u, p_v, which are modified, to i_dst. ??
*******************************************************************************/
#define CONVERT_Y_PIXEL \
/* Only Y sample is present */ \
p_ybase = p_yuv + *(p_y++); \
*(p_pic++) = p_ybase[1501 - ((V_RED_COEF*128)>>SHIFT) + i_red] | \
*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]; \
......@@ -213,6 +212,14 @@ for (i_y = 0; i_y < i_height ; i_y++) \
i_blue = (U_BLUE_COEF * i_uval) >> SHIFT; \
CONVERT_Y_PIXEL \
#define COPY_PIXEL \
/* Pixel may be copied, but only once */ \
while( (i_width_count -= i_width) > 0 ) \
{ \
*p_pic++ = *(p_pic - 1); \
} \
i_width_count += i_pic_width; \
/*******************************************************************************
* vout_InitYUV: allocate and initialize translations tables
*******************************************************************************
......@@ -386,7 +393,7 @@ static void SetYUV( vout_thread_t *p_vout )
switch( p_vout->i_screen_depth )
{
case 15:
MaskToShift( &i_red_right, &i_red_left, 0x7c00 );
MaskToShift( &i_red_right, &i_red_left, 0xf800 );
MaskToShift( &i_green_right, &i_green_left, 0x03e0 );
MaskToShift( &i_blue_right, &i_blue_left, 0x001f );
break;
......@@ -625,51 +632,141 @@ static void ConvertYUV420RGB16( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *
CONVERT_YUV_RGB( 420, i_crv, i_cgv, i_cbu, i_cgu );
#else
boolean_t b_inc_width, b_inc_height; /* width/heidth are increased */
int i_horizontal_scaling; /* horizontal scaling type */
int i_vertical_scaling; /* vertical scaling type */
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_width_count; /* width modulo counter */
int i_height_count; /* height modulo counter */
u16 * p_yuv; /* base convertion table */
u16 * p_ybase; /* Y dependant convertion table */
u16 * p_pic_start; /* beginning of the current line */
/* Initialize values */
b_inc_width = i_width < i_pic_width;
b_inc_height = i_height < i_pic_height;
i_height_count = i_pic_height;
i_chroma_width = i_width / 2;
p_yuv = p_vout->yuv.yuv2.p_rgb16;
/* Set scalings */
if( i_pic_width - i_width > 0 )
{
i_horizontal_scaling = 1;
}
else if( i_pic_width - i_width < 0 )
{
i_horizontal_scaling = -1;
}
else
{
i_horizontal_scaling = 0;
}
if( i_pic_height - i_height > 0 )
{
i_vertical_scaling = 1;
}
else if( i_pic_height - i_height < 0 )
{
i_vertical_scaling = -1;
}
else
{
i_vertical_scaling = 0;
}
/*
* Perform convertion
*/
i_height_count = i_pic_height;
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 */
/* Convert line using 16 pixels blocks, since picture come from 16 pixels
* width macroblocks - several loops will be used, depending of the
* scaling type */
switch( i_horizontal_scaling )
{
case 1: /* horizontal scaling is > 1 */
i_width_count = i_pic_width;
for( i_x = i_width / 16; i_x--; )
{
CONVERT_YUV_PIXEL;
COPY_PIXEL;
CONVERT_Y_PIXEL;
COPY_PIXEL;
CONVERT_YUV_PIXEL;
COPY_PIXEL;
CONVERT_Y_PIXEL;
COPY_PIXEL;
CONVERT_YUV_PIXEL;
COPY_PIXEL;
CONVERT_Y_PIXEL;
COPY_PIXEL;
CONVERT_YUV_PIXEL;
COPY_PIXEL;
CONVERT_Y_PIXEL;
COPY_PIXEL;
CONVERT_YUV_PIXEL;
COPY_PIXEL;
CONVERT_Y_PIXEL;
COPY_PIXEL;
CONVERT_YUV_PIXEL;
COPY_PIXEL;
CONVERT_Y_PIXEL;
COPY_PIXEL;
CONVERT_YUV_PIXEL;
COPY_PIXEL;
CONVERT_Y_PIXEL;
COPY_PIXEL;
CONVERT_YUV_PIXEL;
COPY_PIXEL;
CONVERT_Y_PIXEL;
COPY_PIXEL;
}
break;
case 0:
for( i_x = i_width / 16; i_x--; )
{
CONVERT_YUV_PIXEL;
CONVERT_Y_PIXEL;
CONVERT_YUV_PIXEL;
CONVERT_Y_PIXEL;
CONVERT_YUV_PIXEL;
CONVERT_Y_PIXEL;
CONVERT_YUV_PIXEL;
CONVERT_Y_PIXEL;
CONVERT_YUV_PIXEL;
CONVERT_Y_PIXEL;
CONVERT_YUV_PIXEL;
CONVERT_Y_PIXEL;
CONVERT_YUV_PIXEL;
CONVERT_Y_PIXEL;
CONVERT_YUV_PIXEL;
CONVERT_Y_PIXEL;
}
break;
case -1:
i_width_count = i_width;
/* {
while( (i_width_count -= i_pic_width) > 0)
{
p_y++;
p_u++;
}
i_width_count += i_width;
}
CONVERT_Y_PIXEL;
while( (i_width_count -= i_width) > 0)
{
*p_pic++ = *(p_pic - 1);
}
i_width_count += i_pic_width;
break;
*/
break;
}
/* If line is odd, rewind U and V samples */
......@@ -686,8 +783,22 @@ static void ConvertYUV420RGB16( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *
* Handle vertical scaling. The current line is copied or next one
* is ignored.
*/
if( b_inc_height )
switch( i_vertical_scaling )
{
case -1: /* vertical scaling factor is < 1 */
while( (i_height_count -= i_pic_height) >= 0 )
{
/* Height reduction: skip next source line */
p_y += i_width;
if( ! (++i_y & 0x1) )
{
p_u += i_chroma_width;
p_v += i_chroma_width;
}
}
i_height_count += i_height;
break;
case 1: /* vertical scaling factor is > 1 */
while( (i_height_count -= i_height) > 0 )
{
/* Height increment: copy previous picture line */
......@@ -702,20 +813,7 @@ static void ConvertYUV420RGB16( p_vout_thread_t p_vout, u16 *p_pic, yuv_data_t *
p_pic_start += i_pic_line_width - i_pic_width;
}
i_height_count += i_pic_height;
}
else
{
while( (i_height_count -= i_pic_height) >= 0 )
{
/* Height reduction: skip next source line */
p_y += i_width;
if( ! (++i_y & 0x1) )
{
p_u += i_chroma_width;
p_v += i_chroma_width;
}
}
i_height_count += i_height;
break;
}
}
#endif
......@@ -826,60 +924,6 @@ static void ConvertYUV444RGB32( p_vout_thread_t p_vout, u32 *p_pic, yuv_data_t *
* calculated to minimize the cache interactions of the 3 tables.
*/
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;
MaskToShift (&redRight, &redLeft, redMask);
MaskToShift (&greenRight, &greenLeft, greenMask);
MaskToShift (&blueRight, &blueLeft, blueMask);
/*
* 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])
......
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