Commit 9d12fa3b authored by Rocky Bernstein's avatar Rocky Bernstein

Add RV16 rendering. With transparancy, but still only Y plane is done.

parent 310e183d
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* render.c : Philips OGT (SVCD Subtitle) renderer * render.c : Philips OGT (SVCD Subtitle) renderer
***************************************************************************** *****************************************************************************
* Copyright (C) 2003 VideoLAN * Copyright (C) 2003 VideoLAN
* $Id: render.c,v 1.5 2003/12/29 04:47:44 rocky Exp $ * $Id: render.c,v 1.6 2004/01/01 13:51:38 rocky Exp $
* *
* Author: Rocky Bernstein * Author: Rocky Bernstein
* based on code from: * based on code from:
...@@ -36,11 +36,12 @@ ...@@ -36,11 +36,12 @@
#include "render.h" #include "render.h"
/* We use 4 bits for an alpha value: 0..15, 15 is completely transparent and /* We use 4 bits for an alpha value: 0..15, 15 is completely transparent and
0 completely opaque. Note that SVCD allow 8-bits, it should be 0 completely opaque. Note that although SVCD allow 8-bits, pixels
scaled down to use these routines. previously should be scaled down to 4 bits to use these routines.
*/ */
#define ALPHA_BITS (4) #define ALPHA_BITS (4)
#define MAX_ALPHA ((1<<ALPHA_BITS) - 1) #define MAX_ALPHA ((1<<ALPHA_BITS) - 1)
#define ALPHA_SCALEDOWN (8-ALPHA_BITS)
/* Horrible hack to get dbg_print to do the right thing */ /* Horrible hack to get dbg_print to do the right thing */
#define p_dec p_vout #define p_dec p_vout
...@@ -50,6 +51,8 @@ ...@@ -50,6 +51,8 @@
*****************************************************************************/ *****************************************************************************/
static void RenderI420( vout_thread_t *, picture_t *, const subpicture_t *, static void RenderI420( vout_thread_t *, picture_t *, const subpicture_t *,
vlc_bool_t ); vlc_bool_t );
static void RenderRV16( vout_thread_t *p_vout, picture_t *p_pic,
const subpicture_t *p_spu, vlc_bool_t b_crop );
/***************************************************************************** /*****************************************************************************
* RenderSPU: draw an SPU on a picture * RenderSPU: draw an SPU on a picture
...@@ -81,7 +84,7 @@ void VCDSubRender( vout_thread_t *p_vout, picture_t *p_pic, ...@@ -81,7 +84,7 @@ void VCDSubRender( vout_thread_t *p_vout, picture_t *p_pic,
/* RV16 target, scaling */ /* RV16 target, scaling */
case VLC_FOURCC('R','V','1','6'): case VLC_FOURCC('R','V','1','6'):
msg_Err( p_vout, "RV16 not implimented yet" ); RenderRV16( p_vout, p_pic, p_spu, p_spu->p_sys->b_crop );
break; break;
/* RV32 target, scaling */ /* RV32 target, scaling */
...@@ -107,13 +110,11 @@ static void RenderI420( vout_thread_t *p_vout, picture_t *p_pic, ...@@ -107,13 +110,11 @@ static void RenderI420( vout_thread_t *p_vout, picture_t *p_pic,
const subpicture_t *p_spu, vlc_bool_t b_crop ) const subpicture_t *p_spu, vlc_bool_t b_crop )
{ {
/* Common variables */ /* Common variables */
uint8_t *p_dest; uint8_t *p_pixel_base;
uint8_t *p_destptr;
ogt_yuvt_t *p_source; ogt_yuvt_t *p_source;
unsigned int i_plane; unsigned int i_plane;
int i_x, i_y; int i_x, i_y;
uint16_t i_colprecomp, i_destalpha;
/* Crop-specific */ /* Crop-specific */
int i_x_start, i_y_start, i_x_end, i_y_end; int i_x_start, i_y_start, i_x_end, i_y_end;
...@@ -127,18 +128,97 @@ static void RenderI420( vout_thread_t *p_vout, picture_t *p_pic, ...@@ -127,18 +128,97 @@ static void RenderI420( vout_thread_t *p_vout, picture_t *p_pic,
p_pic->Y_PITCH, p_pic->U_PITCH, p_pic->V_PITCH ); p_pic->Y_PITCH, p_pic->U_PITCH, p_pic->V_PITCH );
/*for ( i_plane = 0; i_plane < p_pic->i_planes ; i_plane++ )*/ p_pixel_base = p_pic->p[Y_PLANE].p_pixels + p_spu->i_x + p_spu->i_width
for ( i_plane = 0; i_plane < 1 ; i_plane++ ) + p_pic->p[Y_PLANE].i_pitch * ( p_spu->i_y + p_spu->i_height );
i_x_start = p_spu->i_width - p_sys->i_x_end;
i_y_start = p_pic->p[Y_PLANE].i_pitch
* (p_spu->i_height - p_sys->i_y_end );
i_x_end = p_spu->i_width - p_sys->i_x_start;
i_y_end = p_pic->p[Y_PLANE].i_pitch
* (p_spu->i_height - p_sys->i_y_start );
p_source = (ogt_yuvt_t *)p_sys->p_data;
/* Draw until we reach the bottom of the subtitle */
for( i_y = p_spu->i_height * p_pic->p[Y_PLANE].i_pitch ;
i_y ;
i_y -= p_pic->p[Y_PLANE].i_pitch )
{
/* printf("+++begin line: %d,\n", i++); */
/* Draw until we reach the end of the line */
for( i_x = p_spu->i_width ; i_x ; i_x--, p_source++ )
{
if( b_crop
&& ( i_x < i_x_start || i_x > i_x_end
|| i_y < i_y_start || i_y > i_y_end ) )
{
continue;
}
/* printf( "t: %x, y: %x, u: %x, v: %x\n",
p_source->s.t, p_source->y, p_source->u, p_source->v ); */
switch( p_source->s.t )
{
case 0x00:
/* Completely transparent. Don't change pixel. */
break;
case MAX_ALPHA:
{
/* Completely opaque. Completely overwrite underlying
pixel with subtitle pixel. */
uint8_t *p_pixel = p_pixel_base - i_x - i_y;
uint16_t i_colprecomp =
(uint16_t) ( p_source->plane[Y_PLANE] * MAX_ALPHA );
*p_pixel = i_colprecomp >> ALPHA_SCALEDOWN;
break;
}
default:
{
/* Blend in underlying pixel subtitle pixel. */
/* To be able to scale correctly for full opaqueness, we
add 1 to the alpha. This means alpha value 0 won't
be completely transparent and is not correct, but
that's handled in a special case above anyway. */
uint8_t *p_pixel = p_pixel_base - i_x - i_y;
uint16_t i_colprecomp =
(uint16_t) ( p_source->plane[Y_PLANE]
* (uint16_t) (p_source->s.t+1) );
uint16_t i_destalpha = MAX_ALPHA - p_source->s.t;
*p_pixel = ( i_colprecomp +
(uint16_t) (*p_pixel) * i_destalpha )
>> ALPHA_SCALEDOWN;
break;
}
}
}
}
#if FIXED
for ( i_plane = U_PLANE; i_plane <= U_PLANE ; i_plane++ )
{ {
p_dest = p_pic->p[i_plane].p_pixels + p_spu->i_x + p_spu->i_width p_pixel_base = p_pic->p[i_plane].p_pixels
+ p_pic->p[i_plane].i_pitch * ( p_spu->i_y + p_spu->i_height ); + ( p_spu->i_x + p_spu->i_width
+ p_pic->p[i_plane].i_pitch * (p_spu->i_y + p_spu->i_height) )/2 ;
i_x_start = p_spu->i_width - p_sys->i_x_end; i_x_start = (p_spu->i_width - p_sys->i_x_end) >> 1;
i_y_start = p_pic->p[i_plane].i_pitch i_y_start = p_pic->p[i_plane].i_pitch
* (p_spu->i_height - p_sys->i_y_end ); * (p_spu->i_height - p_sys->i_y_end );
i_x_end = p_spu->i_width - p_sys->i_x_start; i_x_end = (p_spu->i_width - p_sys->i_x_start ) >> 1;
i_y_end = p_pic->p[i_plane].i_pitch i_y_end = p_pic->p[i_plane].i_pitch
* (p_spu->i_height - p_sys->i_y_start ); * (p_spu->i_height - p_sys->i_y_start );
...@@ -146,14 +226,18 @@ static void RenderI420( vout_thread_t *p_vout, picture_t *p_pic, ...@@ -146,14 +226,18 @@ static void RenderI420( vout_thread_t *p_vout, picture_t *p_pic,
/* Draw until we reach the bottom of the subtitle */ /* Draw until we reach the bottom of the subtitle */
for( i_y = p_spu->i_height * p_pic->p[i_plane].i_pitch ; for( i_y = p_spu->i_height * p_pic->p[i_plane].i_pitch ;
i_y ; i_y > 0;
i_y -= p_pic->p[i_plane].i_pitch ) i_y -= p_pic->p[i_plane].i_pitch )
{ {
vlc_bool_t high_nibble = VLC_TRUE;
/* printf("+++begin line: %d,\n", i++); */ /* printf("+++begin line: %d,\n", i++); */
/* Draw until we reach the end of the line */ /* Draw until we reach the end of the line */
for( i_x = p_spu->i_width ; i_x ; i_x--, p_source++ ) for( i_x = p_spu->i_width / 2 ; i_x > 0 ; i_x--, p_source ++ )
{ {
high_nibble = !high_nibble;
if( b_crop if( b_crop
&& ( i_x < i_x_start || i_x > i_x_end && ( i_x < i_x_start || i_x > i_x_end
|| i_y < i_y_start || i_y > i_y_end ) ) || i_y < i_y_start || i_y > i_y_end ) )
...@@ -167,41 +251,208 @@ static void RenderI420( vout_thread_t *p_vout, picture_t *p_pic, ...@@ -167,41 +251,208 @@ static void RenderI420( vout_thread_t *p_vout, picture_t *p_pic,
switch( p_source->s.t ) switch( p_source->s.t )
{ {
case 0x00: case 0x00:
/* Completely transparent. Don't change underlying pixel */ /* Completely transparent. Don't change pixel. */
break; break;
case MAX_ALPHA: case MAX_ALPHA:
/* Completely opaque. Completely overwrite underlying {
pixel with subtitle pixel. */
/* Completely opaque. Completely overwrite underlying
p_destptr = p_dest - i_x - i_y; pixel with subtitle pixel. */
i_colprecomp = uint8_t *p_pixel = p_pixel_base - (i_x - i_y) / 2;
(uint16_t) ( p_source->plane[i_plane] * MAX_ALPHA ); uint16_t i_colprecomp =
*p_destptr = i_colprecomp >> ALPHA_BITS; (uint16_t) (p_source->plane[i_plane] >> 4);
break; if (high_nibble)
*p_pixel = (i_colprecomp << 4) | ((*p_pixel) & 0x0f);
else
*p_pixel = (i_colprecomp) | ((*p_pixel) & 0xf0);
break;
}
default: default:
/* Blend in underlying pixel subtitle pixel. */ {
/* Blend in underlying pixel subtitle pixel. */
/* To be able to ALPHA_BITS, we add 1 to the alpha.
* This means Alpha 0 won't be completely transparent, but /* To be able to scale correctly for full
* that's handled in a special case above anyway. */ opaqueness, we add 1 to the alpha. This means
alpha value 0 won't be completely transparent and
p_destptr = p_dest - i_x - i_y; is not correct, but that's handled in a special
case above anyway. */
i_colprecomp = (uint16_t) (p_source->plane[i_plane] uint8_t *p_pixel = p_pixel_base - (i_x - i_y) / 2;
* (uint16_t) (p_source->s.t+1) ); uint16_t i_colprecomp = (uint16_t)
i_destalpha = MAX_ALPHA - p_source->s.t; (p_source->plane[i_plane]
* (uint16_t) (p_source->s.t+1)) >> (4+4);
*p_destptr = ( i_colprecomp + uint16_t i_destalpha = (MAX_ALPHA - p_source->s.t) >> 4;
(uint16_t)*p_destptr * i_destalpha )
>> ALPHA_BITS; if (high_nibble)
break; *p_pixel =
(( (i_colprecomp) +
(((uint16_t) *p_pixel * i_destalpha) & 0x0f) ) <<4)
| ((*p_pixel) & 0x0f);
else
*p_pixel =
( (i_colprecomp) +
(((uint16_t) *p_pixel * i_destalpha) & 0x0f) )
| ((*p_pixel) & 0xf0);
break;
}
} }
} }
} }
} }
#endif
}
#define Y2RV16(val) ((uint16_t) (0x111 * (uint16_t) ( (val) >> 4 )))
static void RenderRV16( vout_thread_t *p_vout, picture_t *p_pic,
const subpicture_t *p_spu, vlc_bool_t b_crop )
{
/* Common variables */
uint8_t *p_pixel_base;
ogt_yuvt_t *p_source = (ogt_yuvt_t *)p_spu->p_sys->p_data;
int i_x, i_y;
/* RGB-specific */
int i_xscale, i_yscale, i_width, i_height, i_ytmp, i_yreal, i_ynext;
/* Crop-specific */
int i_x_start, i_y_start, i_x_end, i_y_end;
i_xscale = ( p_vout->output.i_width << 6 ) / p_vout->render.i_width;
i_yscale = ( p_vout->output.i_height << 6 ) / p_vout->render.i_height;
i_width = p_spu->i_width * i_xscale;
i_height = p_spu->i_height * i_yscale;
p_pixel_base = p_pic->p->p_pixels + ( i_width >> 6 ) * 2
/* Add the picture coordinates and the SPU coordinates */
+ ( (p_spu->i_x * i_xscale) >> 6 ) * 2
+ ( (p_spu->i_y * i_yscale) >> 6 ) * p_pic->p->i_pitch;
i_x_start = i_width - i_xscale * p_spu->p_sys->i_x_end;
i_y_start = i_yscale * p_spu->p_sys->i_y_start;
i_x_end = i_width - i_xscale * p_spu->p_sys->i_x_start;
i_y_end = i_yscale * p_spu->p_sys->i_y_end;
/* Draw until we reach the bottom of the subtitle */
for( i_y = 0 ; i_y < i_height ; )
{
i_ytmp = i_y >> 6;
i_y += i_yscale;
/* Check whether we need to draw one line or more than one */
if( i_ytmp + 1 >= ( i_y >> 6 ) )
{
/* Just one line : we precalculate i_y >> 6 */
i_yreal = p_pic->p->i_pitch * i_ytmp;
/* Draw until we reach the end of the line */
for( i_x = i_width ; i_x ; i_x--, p_source++ )
{
if( b_crop
&& ( i_x < i_x_start || i_x > i_x_end
|| i_y < i_y_start || i_y > i_y_end ) )
{
continue;
}
switch( p_source->s.t )
{
case 0x00:
/* Completely transparent. Don't change pixel. */
break;
case MAX_ALPHA:
{
uint16_t i_colprecomp = Y2RV16(p_source->plane[Y_PLANE]);
uint8_t *p_pixel = p_pixel_base + i_yreal;
*p_pixel = i_colprecomp;
break;
}
default:
{
/* Blend in underlying pixel subtitle pixel. */
/* To be able to scale correctly for full opaqueness, we
add 1 to the alpha. This means alpha value 0 won't
be completely transparent and is not correct, but
that's handled in a special case above anyway. */
uint8_t *p_pixel = p_pixel_base + i_yreal;
uint16_t i_colprecomp = Y2RV16(p_source->plane[Y_PLANE])
* ( (uint16_t) (p_source->s.t+1) );
uint16_t i_destalpha = MAX_ALPHA - p_source->s.t;
p_pixel = p_pixel_base + i_yreal;
*p_pixel = ( i_colprecomp +
(uint16_t) (*p_pixel) * i_destalpha )
>> ALPHA_SCALEDOWN;
break;
}
}
}
}
else
{
i_yreal = p_pic->p->i_pitch * i_ytmp;
i_ynext = p_pic->p->i_pitch * i_y >> 6;
/* Draw until we reach the end of the line */
for( i_x = i_width ; i_x ; i_x--, p_source++ )
{
if( b_crop
&& ( i_x < i_x_start || i_x > i_x_end
|| i_y < i_y_start || i_y > i_y_end ) )
{
continue;
}
switch( p_source->s.t )
{
case 0x00:
/* Completely transparent. Don't change pixel. */
break;
case MAX_ALPHA:
for( i_ytmp = i_yreal ; i_ytmp < i_ynext ;
i_ytmp += p_pic->p->i_pitch )
{
uint8_t *p_pixel = p_pixel_base + i_ytmp;
uint16_t i_colprecomp = Y2RV16(p_source->plane[Y_PLANE]);
*p_pixel = i_colprecomp;
}
break;
default:
for( i_ytmp = i_yreal ; i_ytmp < i_ynext ;
i_ytmp += p_pic->p->i_pitch )
{
/* Blend in underlying pixel subtitle pixel. */
/* To be able to scale correctly for full opaqueness, we
add 1 to the alpha. This means alpha value 0 won't
be completely transparent and is not correct, but
that's handled in a special case above anyway. */
uint8_t *p_pixel = p_pixel_base + i_ytmp;
uint16_t i_colprecomp = Y2RV16(p_source->plane[Y_PLANE])
* ( (uint16_t) (p_source->s.t+1) );
uint16_t i_destalpha = MAX_ALPHA - p_source->s.t;
*p_pixel = ( i_colprecomp +
(uint16_t) (*p_pixel) * i_destalpha )
>> ALPHA_SCALEDOWN;
}
break;
}
}
}
}
} }
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